1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032 |
- // Native Javascript for Bootstrap 3 v2.0.27 | © dnp_theme | MIT-License
- (function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD support:
- define([], factory);
- } else if (typeof module === 'object' && module.exports) {
- // CommonJS-like:
- module.exports = factory();
- } else {
- // Browser globals (root is window)
- var bsn = factory();
- root.Affix = bsn.Affix;
- root.Alert = bsn.Alert;
- root.Button = bsn.Button;
- root.Carousel = bsn.Carousel;
- root.Collapse = bsn.Collapse;
- root.Dropdown = bsn.Dropdown;
- root.Modal = bsn.Modal;
- root.Popover = bsn.Popover;
- root.ScrollSpy = bsn.ScrollSpy;
- root.Tab = bsn.Tab;
- root.Tooltip = bsn.Tooltip;
- }
- }(this, function () {
-
- /* Native Javascript for Bootstrap 3 | Internal Utility Functions
- ----------------------------------------------------------------*/
- "use strict";
-
- // globals
- var globalObject = typeof global !== 'undefined' ? global : this||window,
- DOC = document, HTML = DOC.documentElement, body = 'body', // allow the library to be used in <head>
-
- // Native Javascript for Bootstrap Global Object
- BSN = globalObject.BSN = {},
- supports = BSN.supports = [],
-
- // function toggle attributes
- dataToggle = 'data-toggle',
- dataDismiss = 'data-dismiss',
- dataSpy = 'data-spy',
- dataRide = 'data-ride',
-
- // components
- stringAffix = 'Affix',
- stringAlert = 'Alert',
- stringButton = 'Button',
- stringCarousel = 'Carousel',
- stringCollapse = 'Collapse',
- stringDropdown = 'Dropdown',
- stringModal = 'Modal',
- stringPopover = 'Popover',
- stringScrollSpy = 'ScrollSpy',
- stringTab = 'Tab',
- stringTooltip = 'Tooltip',
-
- // options DATA API
- databackdrop = 'data-backdrop',
- dataKeyboard = 'data-keyboard',
- dataTarget = 'data-target',
- dataInterval = 'data-interval',
- dataHeight = 'data-height',
- dataPause = 'data-pause',
- dataTitle = 'data-title',
- dataOriginalTitle = 'data-original-title',
- dataOriginalText = 'data-original-text',
- dataDismissible = 'data-dismissible',
- dataTrigger = 'data-trigger',
- dataAnimation = 'data-animation',
- dataContainer = 'data-container',
- dataPlacement = 'data-placement',
- dataDelay = 'data-delay',
- dataOffsetTop = 'data-offset-top',
- dataOffsetBottom = 'data-offset-bottom',
-
- // option keys
- backdrop = 'backdrop', keyboard = 'keyboard', delay = 'delay',
- content = 'content', target = 'target', currentTarget = 'currentTarget',
- interval = 'interval', pause = 'pause', animation = 'animation',
- placement = 'placement', container = 'container',
-
- // box model
- offsetTop = 'offsetTop', offsetBottom = 'offsetBottom',
- offsetLeft = 'offsetLeft',
- scrollTop = 'scrollTop', scrollLeft = 'scrollLeft',
- clientWidth = 'clientWidth', clientHeight = 'clientHeight',
- offsetWidth = 'offsetWidth', offsetHeight = 'offsetHeight',
- innerWidth = 'innerWidth', innerHeight = 'innerHeight',
- scrollHeight = 'scrollHeight', height = 'height',
-
- // aria
- ariaExpanded = 'aria-expanded',
- ariaHidden = 'aria-hidden',
-
- // event names
- clickEvent = 'click',
- focusEvent = 'focus',
- hoverEvent = 'hover',
- keydownEvent = 'keydown',
- keyupEvent = 'keyup',
- resizeEvent = 'resize', // passive
- scrollEvent = 'scroll', // passive
- mouseHover = ('onmouseleave' in DOC) ? [ 'mouseenter', 'mouseleave'] : [ 'mouseover', 'mouseout' ],
- // touch since 2.0.26
- touchEvents = { start: 'touchstart', end: 'touchend', move:'touchmove' }, // passive
- // originalEvents
- showEvent = 'show',
- shownEvent = 'shown',
- hideEvent = 'hide',
- hiddenEvent = 'hidden',
- closeEvent = 'close',
- closedEvent = 'closed',
- slidEvent = 'slid',
- slideEvent = 'slide',
- changeEvent = 'change',
-
- // other
- getAttribute = 'getAttribute',
- setAttribute = 'setAttribute',
- hasAttribute = 'hasAttribute',
- createElement = 'createElement',
- appendChild = 'appendChild',
- innerHTML = 'innerHTML',
- getElementsByTagName = 'getElementsByTagName',
- preventDefault = 'preventDefault',
- getBoundingClientRect = 'getBoundingClientRect',
- querySelectorAll = 'querySelectorAll',
- getElementsByCLASSNAME = 'getElementsByClassName',
- getComputedStyle = 'getComputedStyle',
-
- indexOf = 'indexOf',
- parentNode = 'parentNode',
- length = 'length',
- toLowerCase = 'toLowerCase',
- Transition = 'Transition',
- Duration = 'Duration',
- Webkit = 'Webkit',
- style = 'style',
- push = 'push',
- tabindex = 'tabindex',
- contains = 'contains',
-
- active = 'active',
- inClass = 'in',
- collapsing = 'collapsing',
- disabled = 'disabled',
- loading = 'loading',
- left = 'left',
- right = 'right',
- top = 'top',
- bottom = 'bottom',
-
- // IE8 browser detect
- isIE8 = !('opacity' in HTML[style]),
-
- // tooltip / popover
- tipPositions = /\b(top|bottom|left|right)+/,
-
- // modal
- modalOverlay = 0,
- fixedTop = 'navbar-fixed-top',
- fixedBottom = 'navbar-fixed-bottom',
-
- // transitionEnd since 2.0.4
- supportTransitions = Webkit+Transition in HTML[style] || Transition[toLowerCase]() in HTML[style],
- transitionEndEvent = Webkit+Transition in HTML[style] ? Webkit[toLowerCase]()+Transition+'End' : Transition[toLowerCase]()+'end',
- transitionDuration = Webkit+Duration in HTML[style] ? Webkit[toLowerCase]()+Transition+Duration : Transition[toLowerCase]()+Duration,
-
- // set new focus element since 2.0.3
- setFocus = function(element){
- element.focus ? element.focus() : element.setActive();
- },
-
- // class manipulation, since 2.0.0 requires polyfill.js
- addClass = function(element,classNAME) {
- element.classList.add(classNAME);
- },
- removeClass = function(element,classNAME) {
- element.classList.remove(classNAME);
- },
- hasClass = function(element,classNAME){ // since 2.0.0
- return element.classList[contains](classNAME);
- },
-
- // selection methods
- nodeListToArray = function(nodeList){
- var childItems = []; for (var i = 0, nll = nodeList[length]; i<nll; i++) { childItems[push]( nodeList[i] ) }
- return childItems;
- },
- getElementsByClassName = function(element,classNAME) { // getElementsByClassName IE8+
- var selectionMethod = isIE8 ? querySelectorAll : getElementsByCLASSNAME;
- return nodeListToArray(element[selectionMethod]( isIE8 ? '.' + classNAME.replace(/\s(?=[a-z])/g,'.') : classNAME ));
- },
- queryElement = function (selector, parent) {
- var lookUp = parent ? parent : DOC;
- return typeof selector === 'object' ? selector : lookUp.querySelector(selector);
- },
- getClosest = function (element, selector) { //element is the element and selector is for the closest parent element to find
- // source http://gomakethings.com/climbing-up-and-down-the-dom-tree-with-vanilla-javascript/
- var firstChar = selector.charAt(0), selectorSubstring = selector.substr(1);
- if ( firstChar === '.' ) {// If selector is a class
- for ( ; element && element !== DOC; element = element[parentNode] ) { // Get closest match
- if ( queryElement(selector,element[parentNode]) !== null && hasClass(element,selectorSubstring) ) { return element; }
- }
- } else if ( firstChar === '#' ) { // If selector is an ID
- for ( ; element && element !== DOC; element = element[parentNode] ) { // Get closest match
- if ( element.id === selectorSubstring ) { return element; }
- }
- }
- return false;
- },
-
- // event attach jQuery style / trigger since 1.2.0
- on = function (element, event, handler, options) {
- options = options || false;
- element.addEventListener(event, handler, options);
- },
- off = function(element, event, handler, options) {
- options = options || false;
- element.removeEventListener(event, handler, options);
- },
- one = function (element, event, handler, options) { // one since 2.0.4
- on(element, event, function handlerWrapper(e){
- handler(e);
- off(element, event, handlerWrapper, options);
- }, options);
- },
- // determine support for passive events
- supportPassive = (function(){
- // Test via a getter in the options object to see if the passive property is accessed
- var result = false;
- try {
- var opts = Object.defineProperty({}, 'passive', {
- get: function() {
- result = true;
- }
- });
- one(globalObject, 'testPassive', null, opts);
- } catch (e) {}
-
- return result;
- }()),
- // event options
- // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md#feature-detection
- passiveHandler = supportPassive ? { passive: true } : false,
- // transitions
- getTransitionDurationFromElement = function(element) {
- var duration = supportTransitions ? globalObject[getComputedStyle](element)[transitionDuration] : 0;
- duration = parseFloat(duration);
- duration = typeof duration === 'number' && !isNaN(duration) ? duration * 1000 : 0;
- return duration; // we take a short offset to make sure we fire on the next frame after animation
- },
- emulateTransitionEnd = function(element,handler){ // emulateTransitionEnd since 2.0.4
- var called = 0, duration = getTransitionDurationFromElement(element);
- duration ? one(element, transitionEndEvent, function(e){ !called && handler(e), called = 1; })
- : setTimeout(function() { !called && handler(), called = 1; }, 17);
- },
- bootstrapCustomEvent = function (eventName, componentName, related) {
- var OriginalCustomEvent = new CustomEvent( eventName + '.bs.' + componentName);
- OriginalCustomEvent.relatedTarget = related;
- this.dispatchEvent(OriginalCustomEvent);
- },
-
- // tooltip / popover stuff
- getScroll = function() { // also Affix and ScrollSpy uses it
- return {
- y : globalObject.pageYOffset || HTML[scrollTop],
- x : globalObject.pageXOffset || HTML[scrollLeft]
- }
- },
- styleTip = function(link,element,position,parent) { // both popovers and tooltips (target,tooltip/popover,placement,elementToAppendTo)
- var elementDimensions = { w : element[offsetWidth], h: element[offsetHeight] },
- windowWidth = (HTML[clientWidth] || DOC[body][clientWidth]),
- windowHeight = (HTML[clientHeight] || DOC[body][clientHeight]),
- rect = link[getBoundingClientRect](),
- scroll = parent === DOC[body] ? getScroll() : { x: parent[offsetLeft] + parent[scrollLeft], y: parent[offsetTop] + parent[scrollTop] },
- linkDimensions = { w: rect[right] - rect[left], h: rect[bottom] - rect[top] },
- arrow = queryElement('[class*="arrow"]',element),
- topPosition, leftPosition, arrowTop, arrowLeft,
-
- halfTopExceed = rect[top] + linkDimensions.h/2 - elementDimensions.h/2 < 0,
- halfLeftExceed = rect[left] + linkDimensions.w/2 - elementDimensions.w/2 < 0,
- halfRightExceed = rect[left] + elementDimensions.w/2 + linkDimensions.w/2 >= windowWidth,
- halfBottomExceed = rect[top] + elementDimensions.h/2 + linkDimensions.h/2 >= windowHeight,
- topExceed = rect[top] - elementDimensions.h < 0,
- leftExceed = rect[left] - elementDimensions.w < 0,
- bottomExceed = rect[top] + elementDimensions.h + linkDimensions.h >= windowHeight,
- rightExceed = rect[left] + elementDimensions.w + linkDimensions.w >= windowWidth;
-
- // recompute position
- position = (position === left || position === right) && leftExceed && rightExceed ? top : position; // first, when both left and right limits are exceeded, we fall back to top|bottom
- position = position === top && topExceed ? bottom : position;
- position = position === bottom && bottomExceed ? top : position;
- position = position === left && leftExceed ? right : position;
- position = position === right && rightExceed ? left : position;
-
- // apply styling to tooltip or popover
- if ( position === left || position === right ) { // secondary|side positions
- if ( position === left ) { // LEFT
- leftPosition = rect[left] + scroll.x - elementDimensions.w;
- } else { // RIGHT
- leftPosition = rect[left] + scroll.x + linkDimensions.w;
- }
-
- // adjust top and arrow
- if (halfTopExceed) {
- topPosition = rect[top] + scroll.y;
- arrowTop = linkDimensions.h/2;
- } else if (halfBottomExceed) {
- topPosition = rect[top] + scroll.y - elementDimensions.h + linkDimensions.h;
- arrowTop = elementDimensions.h - linkDimensions.h/2;
- } else {
- topPosition = rect[top] + scroll.y - elementDimensions.h/2 + linkDimensions.h/2;
- }
- } else if ( position === top || position === bottom ) { // primary|vertical positions
- if ( position === top) { // TOP
- topPosition = rect[top] + scroll.y - elementDimensions.h;
- } else { // BOTTOM
- topPosition = rect[top] + scroll.y + linkDimensions.h;
- }
- // adjust left | right and also the arrow
- if (halfLeftExceed) {
- leftPosition = 0;
- arrowLeft = rect[left] + linkDimensions.w/2;
- } else if (halfRightExceed) {
- leftPosition = windowWidth - elementDimensions.w*1.01;
- arrowLeft = elementDimensions.w - ( windowWidth - rect[left] ) + linkDimensions.w/2;
- } else {
- leftPosition = rect[left] + scroll.x - elementDimensions.w/2 + linkDimensions.w/2;
- }
- }
-
- // apply style to tooltip/popover and it's arrow
- element[style][top] = topPosition + 'px';
- element[style][left] = leftPosition + 'px';
-
- arrowTop && (arrow[style][top] = arrowTop + 'px');
- arrowLeft && (arrow[style][left] = arrowLeft + 'px');
-
- element.className[indexOf](position) === -1 && (element.className = element.className.replace(tipPositions,position));
- };
-
- BSN.version = '2.0.27';
-
- /* Native Javascript for Bootstrap 3 | Affix
- -------------------------------------------*/
-
- // AFFIX DEFINITION
- var Affix = function(element, options) {
-
- // initialization element
- element = queryElement(element);
-
- // set options
- options = options || {};
-
- // read DATA API
- var targetData = element[getAttribute](dataTarget),
- offsetTopData = element[getAttribute](dataOffsetTop),
- offsetBottomData = element[getAttribute](dataOffsetBottom),
-
- // component specific strings
- affix = 'affix', affixed = 'affixed', fn = 'function', update = 'update',
- affixTop = 'affix-top', affixedTop = 'affixed-top',
- affixBottom = 'affix-bottom', affixedBottom = 'affixed-bottom';
-
- this[target] = options[target] ? queryElement(options[target]) : queryElement(targetData) || null; // target is an object
- this[offsetTop] = options[offsetTop] ? options[offsetTop] : parseInt(offsetTopData) || 0; // offset option is an integer number or function to determine that number
- this[offsetBottom] = options[offsetBottom] ? options[offsetBottom]: parseInt(offsetBottomData) || 0;
-
- if ( !this[target] && !( this[offsetTop] || this[offsetBottom] ) ) { return; } // invalidate
-
- // internal bind
- var self = this,
-
- // constants
- pinOffsetTop, pinOffsetBottom, maxScroll, scrollY, pinnedTop, pinnedBottom,
- affixedToTop = false, affixedToBottom = false,
-
- // private methods
- getMaxScroll = function(){
- return Math.max( DOC[body][scrollHeight], DOC[body][offsetHeight], HTML[clientHeight], HTML[scrollHeight], HTML[offsetHeight] );
- },
- getOffsetTop = function () {
- if ( self[target] !== null ) {
- return self[target][getBoundingClientRect]()[top] + scrollY;
- } else if ( self[offsetTop] ) {
- return parseInt(typeof self[offsetTop] === fn ? self[offsetTop]() : self[offsetTop] || 0);
- }
- },
- getOffsetBottom = function () {
- if ( self[offsetBottom] ) {
- return maxScroll - element[offsetHeight] - parseInt( typeof self[offsetBottom] === fn ? self[offsetBottom]() : self[offsetBottom] || 0 );
- }
- },
- checkPosition = function () {
- maxScroll = getMaxScroll();
- scrollY = parseInt(getScroll().y,0);
- pinOffsetTop = getOffsetTop();
- pinOffsetBottom = getOffsetBottom();
- pinnedTop = ( parseInt(pinOffsetTop) - scrollY < 0) && (scrollY > parseInt(pinOffsetTop) );
- pinnedBottom = ( parseInt(pinOffsetBottom) - scrollY < 0) && (scrollY > parseInt(pinOffsetBottom) );
- },
- pinTop = function () {
- if ( !affixedToTop && !hasClass(element,affix) ) { // on loading a page halfway scrolled these events don't trigger in Chrome
- bootstrapCustomEvent.call(element, affix, affix);
- bootstrapCustomEvent.call(element, affixTop, affix);
- addClass(element,affix);
- affixedToTop = true;
- bootstrapCustomEvent.call(element, affixed, affix);
- bootstrapCustomEvent.call(element, affixedTop, affix);
- }
- },
- unPinTop = function () {
- if ( affixedToTop && hasClass(element,affix) ) {
- removeClass(element,affix);
- affixedToTop = false;
- }
- },
- pinBottom = function () {
- if ( !affixedToBottom && !hasClass(element, affixBottom) ) {
- bootstrapCustomEvent.call(element, affix, affix);
- bootstrapCustomEvent.call(element, affixBottom, affix);
- addClass(element,affixBottom);
- affixedToBottom = true;
- bootstrapCustomEvent.call(element, affixed, affix);
- bootstrapCustomEvent.call(element, affixedBottom, affix);
- }
- },
- unPinBottom = function () {
- if ( affixedToBottom && hasClass(element,affixBottom) ) {
- removeClass(element,affixBottom);
- affixedToBottom = false;
- }
- },
- updatePin = function () {
- if ( pinnedBottom ) {
- if ( pinnedTop ) { unPinTop(); }
- pinBottom();
- } else {
- unPinBottom();
- if ( pinnedTop ) { pinTop(); }
- else { unPinTop(); }
- }
- };
-
- // public method
- this[update] = function () {
- checkPosition();
- updatePin();
- };
-
- // init
- if ( !(stringAffix in element ) ) { // prevent adding event handlers twice
- on( globalObject, scrollEvent, self[update], passiveHandler );
- !isIE8 && on( globalObject, resizeEvent, self[update], passiveHandler );
- }
- element[stringAffix] = self;
-
- self[update]();
- };
-
- // AFFIX DATA API
- // =================
- supports[push]([stringAffix, Affix, '['+dataSpy+'="affix"]']);
-
-
-
- /* Native Javascript for Bootstrap 3 | Alert
- -------------------------------------------*/
-
- // ALERT DEFINITION
- // ================
- var Alert = function( element ) {
-
- // initialization element
- element = queryElement(element);
-
- // bind, target alert, duration and stuff
- var self = this, component = 'alert',
- alert = getClosest(element,'.'+component),
- triggerHandler = function(){ hasClass(alert,'fade') ? emulateTransitionEnd(alert,transitionEndHandler) : transitionEndHandler(); },
- // handlers
- clickHandler = function(e){
- alert = getClosest(e[target],'.'+component);
- element = queryElement('['+dataDismiss+'="'+component+'"]',alert);
- element && alert && (element === e[target] || element[contains](e[target])) && self.close();
- },
- transitionEndHandler = function(){
- bootstrapCustomEvent.call(alert, closedEvent, component);
- off(element, clickEvent, clickHandler); // detach it's listener
- alert[parentNode].removeChild(alert);
- };
-
- // public method
- this.close = function() {
- if ( alert && element && hasClass(alert,inClass) ) {
- bootstrapCustomEvent.call(alert, closeEvent, component);
- removeClass(alert,inClass);
- alert && triggerHandler();
- }
- };
-
- // init
- if ( !(stringAlert in element ) ) { // prevent adding event handlers twice
- on(element, clickEvent, clickHandler);
- }
- element[stringAlert] = self;
- };
-
- // ALERT DATA API
- // ==============
- supports[push]([stringAlert, Alert, '['+dataDismiss+'="alert"]']);
-
-
-
- /* Native Javascript for Bootstrap 3 | Button
- ---------------------------------------------*/
-
- // BUTTON DEFINITION
- // ===================
- var Button = function( element, option ) {
-
- // initialization element
- element = queryElement(element);
-
- // set option
- option = option || null;
-
- // constant
- var toggled = false, // toggled makes sure to prevent triggering twice the change.bs.button events
-
- // strings
- component = 'button',
- checked = 'checked',
- reset = 'reset',
- LABEL = 'LABEL',
- INPUT = 'INPUT',
-
- // private methods
- setState = function() {
- if ( !! option && option !== reset ) {
- if ( option === loading ) {
- addClass(element,disabled);
- element[setAttribute](disabled,disabled);
- element[setAttribute](dataOriginalText, element[innerHTML].trim()); // trim the text
- }
- element[innerHTML] = element[getAttribute]('data-'+option+'-text');
- }
- },
- resetState = function() {
- if (element[getAttribute](dataOriginalText)) {
- if ( hasClass(element,disabled) || element[getAttribute](disabled) === disabled ) {
- removeClass(element,disabled);
- element.removeAttribute(disabled);
- }
- element[innerHTML] = element[getAttribute](dataOriginalText);
- }
- },
- keyHandler = function(e){
- var key = e.which || e.keyCode;
- key === 32 && e[target] === DOC.activeElement && toggle(e);
- },
- preventScroll = function(e){
- var key = e.which || e.keyCode;
- key === 32 && e[preventDefault]();
- },
- toggle = function(e) {
- var label = e[target].tagName === LABEL ? e[target] : e[target][parentNode].tagName === LABEL ? e[target][parentNode] : null; // the .btn label
-
- if ( !label ) return; //react if a label or its immediate child is clicked
-
- var labels = getElementsByClassName(label[parentNode],'btn'), // all the button group buttons
- input = label[getElementsByTagName](INPUT)[0];
-
- if ( !input ) return; // return if no input found
-
- // manage the dom manipulation
- if ( input.type === 'checkbox' ) { //checkboxes
- if ( !input[checked] ) {
- addClass(label,active);
- input[getAttribute](checked);
- input[setAttribute](checked,checked);
- input[checked] = true;
- } else {
- removeClass(label,active);
- input[getAttribute](checked);
- input.removeAttribute(checked);
- input[checked] = false;
- }
-
- if (!toggled) { // prevent triggering the event twice
- toggled = true;
- bootstrapCustomEvent.call(input, changeEvent, component); //trigger the change for the input
- bootstrapCustomEvent.call(element, changeEvent, component); //trigger the change for the btn-group
- }
- }
-
- if ( input.type === 'radio' && !toggled ) { // radio buttons
- // don't trigger if already active (the OR condition is a hack to check if the buttons were selected with key press and NOT mouse click)
- if ( !input[checked] || (e.screenX === 0 && e.screenY == 0) ) {
- addClass(label,active);
- input[setAttribute](checked,checked);
- input[checked] = true;
- bootstrapCustomEvent.call(input, changeEvent, component); //trigger the change for the input
- bootstrapCustomEvent.call(element, changeEvent, component); //trigger the change for the btn-group
-
- toggled = true;
- for (var i = 0, ll = labels[length]; i<ll; i++) {
- var otherLabel = labels[i], otherInput = otherLabel[getElementsByTagName](INPUT)[0];
- if ( otherLabel !== label && hasClass(otherLabel,active) ) {
- removeClass(otherLabel,active);
- otherInput.removeAttribute(checked);
- otherInput[checked] = false;
- bootstrapCustomEvent.call(otherInput, changeEvent, component); // trigger the change
- }
- }
- }
- }
- setTimeout( function() { toggled = false; }, 50 );
- };
-
- // init
- if ( hasClass(element,'btn') ) { // when Button text is used we execute it as an instance method
- if ( option !== null ) {
- if ( option !== reset ) { setState(); }
- else { resetState(); }
- }
- } else { // if ( hasClass(element,'btn-group') ) // we allow the script to work outside btn-group component
-
- if ( !( stringButton in element ) ) { // prevent adding event handlers twice
- on( element, clickEvent, toggle );
- on( element, keyupEvent, keyHandler ), on( element, keydownEvent, preventScroll );
- }
-
- // activate items on load
- var labelsToACtivate = getElementsByClassName(element, 'btn'), lbll = labelsToACtivate[length];
- for (var i=0; i<lbll; i++) {
- !hasClass(labelsToACtivate[i],active) && queryElement('input',labelsToACtivate[i])[getAttribute](checked)
- && addClass(labelsToACtivate[i],active);
- }
- element[stringButton] = this;
- }
- };
-
- // BUTTON DATA API
- // =================
- supports[push]( [ stringButton, Button, '['+dataToggle+'="buttons"]' ] );
-
-
- /* Native Javascript for Bootstrap 3 | Carousel
- ----------------------------------------------*/
-
- // CAROUSEL DEFINITION
- // ===================
- var Carousel = function( element, options ) {
-
- // initialization element
- element = queryElement( element );
-
- // set options
- options = options || {};
-
- // DATA API
- var intervalAttribute = element[getAttribute](dataInterval),
- intervalOption = options[interval],
- intervalData = intervalAttribute === 'false' ? 0 : parseInt(intervalAttribute),
- pauseData = element[getAttribute](dataPause) === hoverEvent || false,
- keyboardData = element[getAttribute](dataKeyboard) === 'true' || false,
-
- // strings
- component = 'carousel',
- paused = 'paused',
- direction = 'direction',
- dataSlideTo = 'data-slide-to';
-
- this[keyboard] = options[keyboard] === true || keyboardData;
- this[pause] = (options[pause] === hoverEvent || pauseData) ? hoverEvent : false; // false / hover
-
- this[interval] = typeof intervalOption === 'number' ? intervalOption
- : intervalOption === false || intervalData === 0 || intervalData === false ? 0
- : isNaN(intervalData) ? 5000 // bootstrap carousel default interval
- : intervalData;
-
- // bind, event targets
- var self = this, index = element.index = 0, timer = element.timer = 0,
- isSliding = false, // isSliding prevents click event handlers when animation is running
- isTouch = false, startXPosition = null, currentXPosition = null, endXPosition = null, // touch and event coordinates
- slides = getElementsByClassName(element,'item'), total = slides[length],
- slideDirection = this[direction] = left,
- controls = getElementsByClassName(element,component+'-control'),
- leftArrow = controls[0], rightArrow = controls[1],
- indicator = queryElement( '.'+component+'-indicators', element ),
- indicators = indicator && indicator[getElementsByTagName]( "LI" ) || [];
-
- // invalidate when not enough items
- if (total < 2) { return; }
-
- // handlers
- var pauseHandler = function () {
- if ( self[interval] !==false && !hasClass(element,paused) ) {
- addClass(element,paused);
- !isSliding && ( clearInterval(timer), timer = null );
- }
- },
- resumeHandler = function() {
- if ( self[interval] !== false && hasClass(element,paused) ) {
- removeClass(element,paused);
- !isSliding && ( clearInterval(timer), timer = null );
- !isSliding && self.cycle();
- }
- },
- indicatorHandler = function(e) {
- e[preventDefault]();
- if (isSliding) return;
-
- var eventTarget = e[target]; // event target | the current active item
-
- if ( eventTarget && !hasClass(eventTarget,active) && eventTarget[getAttribute](dataSlideTo) ) {
- index = parseInt( eventTarget[getAttribute](dataSlideTo), 10 );
- } else { return false; }
-
- self.slideTo( index ); //Do the slide
- },
- controlsHandler = function (e) {
- e[preventDefault]();
- if (isSliding) return;
-
- var eventTarget = e.currentTarget || e.srcElement;
-
- if ( eventTarget === rightArrow ) {
- index++;
- } else if ( eventTarget === leftArrow ) {
- index--;
- }
-
- self.slideTo( index ); //Do the slide
- },
- keyHandler = function (e) {
- if (isSliding) return;
- switch (e.which) {
- case 39:
- index++;
- break;
- case 37:
- index--;
- break;
- default: return;
- }
- self.slideTo( index ); //Do the slide
- },
- // touch events
- toggleTouchEvents = function(toggle){
- toggle( element, touchEvents.move, touchMoveHandler, passiveHandler );
- toggle( element, touchEvents.end, touchEndHandler, passiveHandler );
- },
- touchDownHandler = function(e) {
- if ( isTouch ) { return; }
-
- startXPosition = parseInt(e.touches[0].pageX);
-
- if ( element.contains(e[target]) ) {
- isTouch = true;
- toggleTouchEvents(on);
- }
- },
- touchMoveHandler = function(e) {
- if ( !isTouch ) { e.preventDefault(); return; }
-
- currentXPosition = parseInt(e.touches[0].pageX);
-
- //cancel touch if more than one touches detected
- if ( e.type === 'touchmove' && e.touches[length] > 1 ) {
- e.preventDefault();
- return false;
- }
- },
- touchEndHandler = function(e) {
- if ( !isTouch || isSliding ) { return }
-
- endXPosition = currentXPosition || parseInt( e.touches[0].pageX );
-
- if ( isTouch ) {
- if ( (!element.contains(e[target]) || !element.contains(e.relatedTarget) ) && Math.abs(startXPosition - endXPosition) < 75 ) {
- return false;
- } else {
- if ( currentXPosition < startXPosition ) {
- index++;
- } else if ( currentXPosition > startXPosition ) {
- index--;
- }
- isTouch = false;
- self.slideTo(index);
- }
- toggleTouchEvents(off);
- }
- },
-
- // private methods
- isElementInScrollRange = function () {
- var rect = element[getBoundingClientRect](),
- viewportHeight = globalObject[innerHeight] || HTML[clientHeight]
- return rect[top] <= viewportHeight && rect[bottom] >= 0; // bottom && top
- },
- setActivePage = function( pageIndex ) { //indicators
- for ( var i = 0, icl = indicators[length]; i < icl; i++ ) {
- removeClass(indicators[i],active);
- }
- if (indicators[pageIndex]) addClass(indicators[pageIndex], active);
- };
-
-
- // public methods
- this.cycle = function() {
- if (timer) {
- clearInterval(timer);
- timer = null;
- }
-
- timer = setInterval(function() {
- isElementInScrollRange() && (index++, self.slideTo( index ) );
- }, this[interval]);
- };
- this.slideTo = function( next ) {
- if (isSliding) return; // when controled via methods, make sure to check again
-
- var activeItem = this.getActiveIndex(), // the current active
- orientation;
-
- // first return if we're on the same item #227
- if ( activeItem === next ) {
- return;
- // or determine slideDirection
- } else if ( (activeItem < next ) || (activeItem === 0 && next === total -1 ) ) {
- slideDirection = self[direction] = left; // next
- } else if ( (activeItem > next) || (activeItem === total - 1 && next === 0 ) ) {
- slideDirection = self[direction] = right; // prev
- }
-
- // find the right next index
- if ( next < 0 ) { next = total - 1; }
- else if ( next >= total ){ next = 0; }
-
- // update index
- index = next;
-
- orientation = slideDirection === left ? 'next' : 'prev'; //determine type
- bootstrapCustomEvent.call(element, slideEvent, component, slides[next]); // here we go with the slide
-
- isSliding = true;
- clearInterval(timer);
- timer = null;
- setActivePage( next );
-
- if ( supportTransitions && hasClass(element,'slide') ) {
-
- addClass(slides[next],orientation);
- slides[next][offsetWidth];
- addClass(slides[next],slideDirection);
- addClass(slides[activeItem],slideDirection);
-
- emulateTransitionEnd(slides[next], function(e) {
- var timeout = e && e[target] !== slides[next] ? e.elapsedTime*1000+100 : 20;
- isSliding && setTimeout(function(){
- isSliding = false;
-
- addClass(slides[next],active);
- removeClass(slides[activeItem],active);
-
- removeClass(slides[next],orientation);
- removeClass(slides[next],slideDirection);
- removeClass(slides[activeItem],slideDirection);
-
- bootstrapCustomEvent.call(element, slidEvent, component, slides[next]);
-
- if ( self[interval] && !hasClass(element,paused) ) {
- self.cycle();
- }
- }, timeout);
- });
-
- } else {
- addClass(slides[next],active);
- slides[next][offsetWidth];
- removeClass(slides[activeItem],active);
- setTimeout(function() {
- isSliding = false;
- if ( self[interval] && !hasClass(element,paused) ) {
- self.cycle();
- }
- bootstrapCustomEvent.call(element, slidEvent, component, slides[next]);
- }, 100 );
- }
- };
- this.getActiveIndex = function () {
- return slides[indexOf](getElementsByClassName(element,'item active')[0]) || 0;
- };
-
- // init
- if ( !(stringCarousel in element ) ) { // prevent adding event handlers twice
-
- if ( self[pause] && self[interval] ) {
- on( element, mouseHover[0], pauseHandler );
- on( element, mouseHover[1], resumeHandler );
- on( element, touchEvents.start, pauseHandler, passiveHandler );
- on( element, touchEvents.end, resumeHandler, passiveHandler );
- }
-
- slides[length] > 1 && on( element, touchEvents.start, touchDownHandler, passiveHandler );
-
- rightArrow && on( rightArrow, clickEvent, controlsHandler );
- leftArrow && on( leftArrow, clickEvent, controlsHandler );
-
- indicator && on( indicator, clickEvent, indicatorHandler );
- self[keyboard] && on( globalObject, keydownEvent, keyHandler );
-
- }
- if (self.getActiveIndex()<0) {
- slides[length] && addClass(slides[0],active);
- indicators[length] && setActivePage(0);
- }
-
- if ( self[interval] ){ self.cycle(); }
- element[stringCarousel] = self;
- };
-
- // CAROUSEL DATA API
- // =================
- supports[push]( [ stringCarousel, Carousel, '['+dataRide+'="carousel"]' ] );
-
-
- /* Native Javascript for Bootstrap 3 | Collapse
- -----------------------------------------------*/
-
- // COLLAPSE DEFINITION
- // ===================
- var Collapse = function( element, options ) {
-
- // initialization element
- element = queryElement(element);
-
- // set options
- options = options || {};
-
- // event targets and constants
- var accordion = null, collapse = null, self = this,
- accordionData = element[getAttribute]('data-parent'),
- activeCollapse, activeElement,
-
- // component strings
- component = 'collapse',
- collapsed = 'collapsed',
- isAnimating = 'isAnimating',
-
- // private methods
- openAction = function(collapseElement,toggle) {
- bootstrapCustomEvent.call(collapseElement, showEvent, component);
- collapseElement[isAnimating] = true;
- addClass(collapseElement,collapsing);
- removeClass(collapseElement,component);
- collapseElement[style][height] = collapseElement[scrollHeight] + 'px';
-
- emulateTransitionEnd(collapseElement, function() {
- collapseElement[isAnimating] = false;
- collapseElement[setAttribute](ariaExpanded,'true');
- toggle[setAttribute](ariaExpanded,'true');
- removeClass(collapseElement,collapsing);
- addClass(collapseElement, component);
- addClass(collapseElement, inClass);
- collapseElement[style][height] = '';
- bootstrapCustomEvent.call(collapseElement, shownEvent, component);
- });
- },
- closeAction = function(collapseElement,toggle) {
- bootstrapCustomEvent.call(collapseElement, hideEvent, component);
- collapseElement[isAnimating] = true;
- collapseElement[style][height] = collapseElement[scrollHeight] + 'px'; // set height first
- removeClass(collapseElement,component);
- removeClass(collapseElement, inClass);
- addClass(collapseElement, collapsing);
- collapseElement[offsetWidth]; // force reflow to enable transition
- collapseElement[style][height] = '0px';
-
- emulateTransitionEnd(collapseElement, function() {
- collapseElement[isAnimating] = false;
- collapseElement[setAttribute](ariaExpanded,'false');
- toggle[setAttribute](ariaExpanded,'false');
- removeClass(collapseElement,collapsing);
- addClass(collapseElement,component);
- collapseElement[style][height] = '';
- bootstrapCustomEvent.call(collapseElement, hiddenEvent, component);
- });
- },
- getTarget = function() {
- var href = element.href && element[getAttribute]('href'),
- parent = element[getAttribute](dataTarget),
- id = href || ( parent && parent.charAt(0) === '#' ) && parent;
- return id && queryElement(id);
- };
-
- // public methods
- this.toggle = function(e) {
- e[preventDefault]();
- if (!hasClass(collapse,inClass)) { self.show(); }
- else { self.hide(); }
- };
- this.hide = function() {
- if ( collapse[isAnimating] ) return;
- closeAction(collapse,element);
- addClass(element,collapsed);
- };
- this.show = function() {
- if ( accordion ) {
- activeCollapse = queryElement('.'+component+'.'+inClass,accordion);
- activeElement = activeCollapse && (queryElement('['+dataTarget+'="#'+activeCollapse.id+'"]', accordion)
- || queryElement('[href="#'+activeCollapse.id+'"]',accordion) );
- }
-
- if ( !collapse[isAnimating] || activeCollapse && !activeCollapse[isAnimating] ) {
- if ( activeElement && activeCollapse !== collapse ) {
- closeAction(activeCollapse,activeElement);
- addClass(activeElement,collapsed);
- }
- openAction(collapse,element);
- removeClass(element,collapsed);
- }
- };
-
- // init
- if ( !(stringCollapse in element ) ) { // prevent adding event handlers twice
- on(element, clickEvent, self.toggle);
- }
- collapse = getTarget();
- collapse[isAnimating] = false; // when true it will prevent click handlers
- accordion = queryElement(options.parent) || accordionData && getClosest(element, accordionData);
- element[stringCollapse] = self;
- };
-
- // COLLAPSE DATA API
- // =================
- supports[push]( [ stringCollapse, Collapse, '['+dataToggle+'="collapse"]' ] );
-
-
- /* Native Javascript for Bootstrap 3 | Dropdown
- ----------------------------------------------*/
-
- // DROPDOWN DEFINITION
- // ===================
- var Dropdown = function( element, option ) {
-
- // initialization element
- element = queryElement(element);
-
- // set option
- this.persist = option === true || element[getAttribute]('data-persist') === 'true' || false;
-
- // constants, event targets, strings
- var self = this, children = 'children',
- parent = element[parentNode],
- component = 'dropdown', open = 'open',
- relatedTarget = null,
- menu = queryElement('.dropdown-menu', parent),
- menuItems = (function(){
- var set = menu[children], newSet = [];
- for ( var i=0; i<set[length]; i++ ){
- set[i][children][length] && (set[i][children][0].tagName === 'A' && newSet[push](set[i]));
- }
- return newSet;
- })(),
-
- // preventDefault on empty anchor links
- preventEmptyAnchor = function(anchor){
- (anchor.href && anchor.href.slice(-1) === '#' || anchor[parentNode] && anchor[parentNode].href
- && anchor[parentNode].href.slice(-1) === '#') && this[preventDefault]();
- },
-
- // toggle dismissible events
- toggleDismiss = function(){
- var type = element[open] ? on : off;
- type(DOC, clickEvent, dismissHandler);
- type(DOC, keydownEvent, preventScroll);
- type(DOC, keyupEvent, keyHandler);
- type(DOC, focusEvent, dismissHandler, true);
- },
-
- // handlers
- dismissHandler = function(e) {
- var eventTarget = e[target], hasData = eventTarget && (eventTarget[getAttribute](dataToggle)
- || eventTarget[parentNode] && getAttribute in eventTarget[parentNode]
- && eventTarget[parentNode][getAttribute](dataToggle));
- if ( e.type === focusEvent && (eventTarget === element || eventTarget === menu || menu[contains](eventTarget) ) ) {
- return;
- }
- if ( (eventTarget === menu || menu[contains](eventTarget)) && (self.persist || hasData) ) { return; }
- else {
- relatedTarget = eventTarget === element || element[contains](eventTarget) ? element : null;
- hide();
- }
- preventEmptyAnchor.call(e,eventTarget);
- },
- clickHandler = function(e) {
- relatedTarget = element;
- show();
- preventEmptyAnchor.call(e,e[target]);
- },
- preventScroll = function(e){
- var key = e.which || e.keyCode;
- if( key === 38 || key === 40 ) { e[preventDefault](); }
- },
- keyHandler = function(e){
- var key = e.which || e.keyCode,
- activeItem = DOC.activeElement,
- idx = menuItems[indexOf](activeItem[parentNode]),
- isSameElement = activeItem === element,
- isInsideMenu = menu[contains](activeItem),
- isMenuItem = activeItem[parentNode][parentNode] === menu;
-
- if ( isMenuItem ) { // navigate up | down
- idx = isSameElement ? 0
- : key === 38 ? (idx>1?idx-1:0)
- : key === 40 ? (idx<menuItems[length]-1?idx+1:idx) : idx;
- menuItems[idx] && setFocus(menuItems[idx][children][0]);
- }
- if ( (menuItems[length] && isMenuItem // menu has items
- || !menuItems[length] && (isInsideMenu || isSameElement) // menu might be a form
- || !isInsideMenu ) // or the focused element is not in the menu at all
- && element[open] && key === 27 // menu must be open
- ) {
- self.toggle();
- relatedTarget = null;
- }
- },
-
- // private methods
- show = function() {
- bootstrapCustomEvent.call(parent, showEvent, component, relatedTarget);
- addClass(parent,open);
- element[setAttribute](ariaExpanded,true);
- bootstrapCustomEvent.call(parent, shownEvent, component, relatedTarget);
- element[open] = true;
- off(element, clickEvent, clickHandler);
- setTimeout(function(){
- setFocus( menu[getElementsByTagName]('INPUT')[0] || element ); // focus the first input item | element
- toggleDismiss();
- },1);
- },
- hide = function() {
- bootstrapCustomEvent.call(parent, hideEvent, component, relatedTarget);
- removeClass(parent,open);
- element[setAttribute](ariaExpanded,false);
- bootstrapCustomEvent.call(parent, hiddenEvent, component, relatedTarget);
- element[open] = false;
- toggleDismiss();
- setFocus(element);
- setTimeout(function(){ on(element, clickEvent, clickHandler); },1);
- };
-
- // set initial state to closed
- element[open] = false;
-
- // public methods
- this.toggle = function() {
- if (hasClass(parent,open) && element[open]) { hide(); }
- else { show(); }
- };
-
- // init
- if (!(stringDropdown in element)) { // prevent adding event handlers twice
- !tabindex in menu && menu[setAttribute](tabindex, '0'); // Fix onblur on Chrome | Safari
- on(element, clickEvent, clickHandler);
- }
-
- element[stringDropdown] = self;
- };
-
- // DROPDOWN DATA API
- // =================
- supports[push]( [stringDropdown, Dropdown, '['+dataToggle+'="dropdown"]'] );
-
-
- /* Native Javascript for Bootstrap 3 | Modal
- -------------------------------------------*/
-
- // MODAL DEFINITION
- // ===============
- var Modal = function(element, options) { // element can be the modal/triggering button
-
- // the modal (both JavaScript / DATA API init) / triggering button element (DATA API)
- element = queryElement(element);
-
- // strings
- var component = 'modal',
- staticString = 'static',
- modalTrigger = 'modalTrigger',
- paddingRight = 'paddingRight',
- modalBackdropString = 'modal-backdrop',
- isAnimating = 'isAnimating',
- // determine modal, triggering element
- btnCheck = element[getAttribute](dataTarget)||element[getAttribute]('href'),
- checkModal = queryElement( btnCheck ),
- modal = hasClass(element,component) ? element : checkModal;
-
- if ( hasClass(element, component) ) { element = null; } // modal is now independent of it's triggering element
-
- if ( !modal ) { return; } // invalidate
-
- // set options
- options = options || {};
-
- this[keyboard] = options[keyboard] === false || modal[getAttribute](dataKeyboard) === 'false' ? false : true;
- this[backdrop] = options[backdrop] === staticString || modal[getAttribute](databackdrop) === staticString ? staticString : true;
- this[backdrop] = options[backdrop] === false || modal[getAttribute](databackdrop) === 'false' ? false : this[backdrop];
- this[animation] = hasClass(modal, 'fade') ? true : false;
- this[content] = options[content]; // JavaScript only
-
- // set an initial state of the modal
- modal[isAnimating] = false;
-
- // bind, constants, event targets and other vars
- var self = this, relatedTarget = null,
- bodyIsOverflowing, scrollBarWidth, overlay, overlayDelay, modalTimer,
-
- // also find fixed-top / fixed-bottom items
- fixedItems = getElementsByClassName(HTML,fixedTop).concat(getElementsByClassName(HTML,fixedBottom)),
-
- // private methods
- getWindowWidth = function() {
- var htmlRect = HTML[getBoundingClientRect]();
- return globalObject[innerWidth] || (htmlRect[right] - Math.abs(htmlRect[left]));
- },
- setScrollbar = function () {
- var bodyStyle = DOC[body].currentStyle || globalObject[getComputedStyle](DOC[body]),
- bodyPad = parseInt((bodyStyle[paddingRight]), 10), itemPad;
- if (bodyIsOverflowing) {
- DOC[body][style][paddingRight] = (bodyPad + scrollBarWidth) + 'px';
- modal[style][paddingRight] = scrollBarWidth+'px';
- if (fixedItems[length]){
- for (var i = 0; i < fixedItems[length]; i++) {
- itemPad = (fixedItems[i].currentStyle || globalObject[getComputedStyle](fixedItems[i]))[paddingRight];
- fixedItems[i][style][paddingRight] = ( parseInt(itemPad) + scrollBarWidth) + 'px';
- }
- }
- }
- },
- resetScrollbar = function () {
- DOC[body][style][paddingRight] = '';
- modal[style][paddingRight] = '';
- if (fixedItems[length]){
- for (var i = 0; i < fixedItems[length]; i++) {
- fixedItems[i][style][paddingRight] = '';
- }
- }
- },
- measureScrollbar = function () { // thx walsh
- var scrollDiv = DOC[createElement]('div'), widthValue;
- scrollDiv.className = component+'-scrollbar-measure'; // this is here to stay
- DOC[body][appendChild](scrollDiv);
- widthValue = scrollDiv[offsetWidth] - scrollDiv[clientWidth];
- DOC[body].removeChild(scrollDiv);
- return widthValue;
- },
- checkScrollbar = function () {
- bodyIsOverflowing = DOC[body][clientWidth] < getWindowWidth();
- scrollBarWidth = measureScrollbar();
- },
- createOverlay = function() {
- var newOverlay = DOC[createElement]('div');
- overlay = queryElement('.'+modalBackdropString);
-
- if ( overlay === null ) {
- newOverlay[setAttribute]('class', modalBackdropString + (self[animation] ? ' fade' : ''));
- overlay = newOverlay;
- DOC[body][appendChild](overlay);
- }
- modalOverlay = 1;
- },
- removeOverlay = function() {
- overlay = queryElement('.'+modalBackdropString);
- if ( overlay && overlay !== null && typeof overlay === 'object' ) {
- modalOverlay = 0;
- DOC[body].removeChild(overlay); overlay = null;
- }
- },
- // triggers
- triggerShow = function() {
- setFocus(modal);
- modal[isAnimating] = false;
- bootstrapCustomEvent.call(modal, shownEvent, component, relatedTarget);
-
- on(globalObject, resizeEvent, self.update, passiveHandler);
- on(modal, clickEvent, dismissHandler);
- on(DOC, keydownEvent, keyHandler);
- },
- triggerHide = function() {
- modal[style].display = '';
- element && (setFocus(element));
- bootstrapCustomEvent.call(modal, hiddenEvent, component);
-
- (function(){
- if (!getElementsByClassName(DOC,component+' '+inClass)[0]) {
- resetScrollbar();
- removeClass(DOC[body],component+'-open');
- overlay && hasClass(overlay,'fade') ? (removeClass(overlay,inClass), emulateTransitionEnd(overlay,removeOverlay))
- : removeOverlay();
-
- off(globalObject, resizeEvent, self.update, passiveHandler);
- off(modal, clickEvent, dismissHandler);
- off(DOC, keydownEvent, keyHandler);
- }
- }());
- modal[isAnimating] = false;
- },
- // handlers
- clickHandler = function(e) {
- if ( modal[isAnimating] ) return;
-
- var clickTarget = e[target];
- clickTarget = clickTarget[hasAttribute](dataTarget) || clickTarget[hasAttribute]('href') ? clickTarget : clickTarget[parentNode];
- if ( clickTarget === element && !hasClass(modal,inClass) ) {
- modal[modalTrigger] = element;
- relatedTarget = element;
- self.show();
- e[preventDefault]();
- }
- },
- keyHandler = function(e) {
- if ( modal[isAnimating] ) return;
-
- var key = e.which || e.keyCode; // keyCode for IE8
- if (self[keyboard] && key == 27 && hasClass(modal,inClass)) {
- self.hide();
- }
- },
- dismissHandler = function(e) {
- if ( modal[isAnimating] ) return;
-
- var clickTarget = e[target];
- if ( hasClass(modal,inClass) && (clickTarget[parentNode][getAttribute](dataDismiss) === component
- || clickTarget[getAttribute](dataDismiss) === component
- || clickTarget === modal && self[backdrop] !== staticString) ) {
- self.hide(); relatedTarget = null;
- e[preventDefault]();
- }
- };
-
- // public methods
- this.toggle = function() {
- if ( hasClass(modal,inClass) ) {this.hide();} else {this.show();}
- };
- this.show = function() {
- if ( hasClass(modal,inClass) || modal[isAnimating] ) {return}
-
- clearTimeout(modalTimer);
- modalTimer = setTimeout(function(){
- modal[isAnimating] = true;
- bootstrapCustomEvent.call(modal, showEvent, component, relatedTarget);
-
- // we elegantly hide any opened modal
- var currentOpen = getElementsByClassName(DOC,component+' in')[0];
- if (currentOpen && currentOpen !== modal) {
- modalTrigger in currentOpen && currentOpen[modalTrigger][stringModal].hide();
- stringModal in currentOpen && currentOpen[stringModal].hide();
- }
-
- if ( self[backdrop] ) {
- !modalOverlay && !overlay && createOverlay();
- }
-
- if ( overlay && !hasClass(overlay,inClass)) {
- overlay[offsetWidth]; // force reflow to enable trasition
- overlayDelay = getTransitionDurationFromElement(overlay);
- addClass(overlay,inClass);
- }
-
- setTimeout( function() {
- modal[style].display = 'block';
-
- checkScrollbar();
- setScrollbar();
-
- addClass(DOC[body],component+'-open');
- addClass(modal,inClass);
- modal[setAttribute](ariaHidden, false);
-
- hasClass(modal,'fade') ? emulateTransitionEnd(modal, triggerShow) : triggerShow();
- }, supportTransitions && overlay && overlayDelay ? overlayDelay : 1);
- },1);
- };
- this.hide = function() {
- if ( modal[isAnimating] || !hasClass(modal,inClass) ) {return}
-
- clearTimeout(modalTimer);
- modalTimer = setTimeout(function(){
- modal[isAnimating] = true;
- bootstrapCustomEvent.call(modal, hideEvent, component);
- overlay = queryElement('.'+modalBackdropString);
- overlayDelay = overlay && getTransitionDurationFromElement(overlay);
-
- removeClass(modal,inClass);
- modal[setAttribute](ariaHidden, true);
-
- setTimeout(function(){
- hasClass(modal,'fade') ? emulateTransitionEnd(modal, triggerHide) : triggerHide();
- }, supportTransitions && overlay && overlayDelay ? overlayDelay : 2);
- },2)
- };
- this.setContent = function( content ) {
- queryElement('.'+component+'-content',modal)[innerHTML] = content;
- };
- this.update = function() {
- if (hasClass(modal,inClass)) {
- checkScrollbar();
- setScrollbar();
- }
- };
-
- // init
- // prevent adding event handlers over and over
- // modal is independent of a triggering element
- if ( !!element && !(stringModal in element) ) {
- on(element, clickEvent, clickHandler);
- }
- if ( !!self[content] ) { self.setContent( self[content] ); }
- if (element) { element[stringModal] = self; modal[modalTrigger] = element; }
- else { modal[stringModal] = self; }
- };
-
- // DATA API
- supports[push]( [ stringModal, Modal, '['+dataToggle+'="modal"]' ] );
-
- /* Native Javascript for Bootstrap 3 | Popover
- ----------------------------------------------*/
-
- // POPOVER DEFINITION
- // ==================
- var Popover = function( element, options ) {
-
- // initialization element
- element = queryElement(element);
-
- // set options
- options = options || {};
-
- // DATA API
- var triggerData = element[getAttribute](dataTrigger), // click / hover / focus
- animationData = element[getAttribute](dataAnimation), // true / false
- placementData = element[getAttribute](dataPlacement),
- dismissibleData = element[getAttribute](dataDismissible),
- delayData = element[getAttribute](dataDelay),
- containerData = element[getAttribute](dataContainer),
-
- // internal strings
- component = 'popover',
- template = 'template',
- trigger = 'trigger',
- classString = 'class',
- div = 'div',
- fade = 'fade',
- dataContent = 'data-content',
- dismissible = 'dismissible',
- closeBtn = '<button type="button" class="close">×</button>',
-
- // check container
- containerElement = queryElement(options[container]),
- containerDataElement = queryElement(containerData),
-
- // maybe the element is inside a modal
- modal = getClosest(element,'.modal'),
-
- // maybe the element is inside a fixed navbar
- navbarFixedTop = getClosest(element,'.'+fixedTop),
- navbarFixedBottom = getClosest(element,'.'+fixedBottom);
-
- // set instance options
- this[template] = options[template] ? options[template] : null; // JavaScript only
- this[trigger] = options[trigger] ? options[trigger] : triggerData || hoverEvent;
- this[animation] = options[animation] && options[animation] !== fade ? options[animation] : animationData || fade;
- this[placement] = options[placement] ? options[placement] : placementData || top;
- this[delay] = parseInt(options[delay] || delayData) || 200;
- this[dismissible] = options[dismissible] || dismissibleData === 'true' ? true : false;
- this[container] = containerElement ? containerElement
- : containerDataElement ? containerDataElement
- : navbarFixedTop ? navbarFixedTop
- : navbarFixedBottom ? navbarFixedBottom
- : modal ? modal : DOC[body];
-
- // bind, content
- var self = this,
- titleString = options.title || element[getAttribute](dataTitle) || null,
- contentString = options.content || element[getAttribute](dataContent) || null;
-
- if ( !contentString && !this[template] ) return; // invalidate
-
- // constants, vars
- var popover = null, timer = 0, placementSetting = this[placement],
-
- // handlers
- dismissibleHandler = function(e) {
- if (popover !== null && e[target] === queryElement('.close',popover)) {
- self.hide();
- }
- },
-
- // private methods
- removePopover = function() {
- self[container].removeChild(popover);
- timer = null; popover = null;
- },
- createPopover = function() {
- titleString = options.title || element[getAttribute](dataTitle);
- contentString = options.content || element[getAttribute](dataContent);
- // fixing https://github.com/thednp/bootstrap.native/issues/233
- contentString = !!contentString ? contentString.replace(/^\s+|\s+$/g, '') : null;
-
- popover = DOC[createElement](div);
-
- if ( contentString !== null && self[template] === null ) { //create the popover from data attributes
-
- popover[setAttribute]('role','tooltip');
-
- if (titleString !== null) {
- var popoverTitle = DOC[createElement]('h3');
- popoverTitle[setAttribute](classString,component+'-title');
-
- popoverTitle[innerHTML] = self[dismissible] ? titleString + closeBtn : titleString;
- popover[appendChild](popoverTitle);
- }
-
- var popoverArrow = DOC[createElement](div), popoverContent = DOC[createElement](div);
- popoverArrow[setAttribute](classString,'arrow'); popoverContent[setAttribute](classString,component+'-content');
- popover[appendChild](popoverArrow); popover[appendChild](popoverContent);
-
- //set popover content
- popoverContent[innerHTML] = self[dismissible] && titleString === null ? contentString + closeBtn : contentString;
-
- } else { // or create the popover from template
- var popoverTemplate = DOC[createElement](div);
- self[template] = self[template].replace(/^\s+|\s+$/g, '');
- popoverTemplate[innerHTML] = self[template];
- popover[innerHTML] = popoverTemplate.firstChild[innerHTML];
- }
-
- //append to the container
- self[container][appendChild](popover);
- popover[style].display = 'block';
- popover[setAttribute](classString, component+ ' ' + placementSetting + ' ' + self[animation]);
- },
- showPopover = function () {
- !hasClass(popover,inClass) && ( addClass(popover,inClass) );
- },
- updatePopover = function() {
- styleTip(element,popover,placementSetting,self[container]);
- },
-
- // event toggle
- dismissHandlerToggle = function(type){
- if (clickEvent == self[trigger] || 'focus' == self[trigger]) {
- !self[dismissible] && type( element, 'blur', self.hide );
- }
- self[dismissible] && type( DOC, clickEvent, dismissibleHandler );
- !isIE8 && type( globalObject, resizeEvent, self.hide, passiveHandler );
- },
-
- // triggers
- showTrigger = function() {
- dismissHandlerToggle(on);
- bootstrapCustomEvent.call(element, shownEvent, component);
- },
- hideTrigger = function() {
- dismissHandlerToggle(off);
- removePopover();
- bootstrapCustomEvent.call(element, hiddenEvent, component);
- };
-
- // public methods / handlers
- this.toggle = function() {
- if (popover === null) { self.show(); }
- else { self.hide(); }
- };
- this.show = function() {
- clearTimeout(timer);
- timer = setTimeout( function() {
- if (popover === null) {
- placementSetting = self[placement]; // we reset placement in all cases
- createPopover();
- updatePopover();
- showPopover();
- bootstrapCustomEvent.call(element, showEvent, component);
- !!self[animation] ? emulateTransitionEnd(popover, showTrigger) : showTrigger();
- }
- }, 20 );
- };
- this.hide = function() {
- clearTimeout(timer);
- timer = setTimeout( function() {
- if (popover && popover !== null && hasClass(popover,inClass)) {
- bootstrapCustomEvent.call(element, hideEvent, component);
- removeClass(popover,inClass);
- !!self[animation] ? emulateTransitionEnd(popover, hideTrigger) : hideTrigger();
- }
- }, self[delay] );
- };
-
- // init
- if ( !(stringPopover in element) ) { // prevent adding event handlers twice
- if (self[trigger] === hoverEvent) {
- on( element, mouseHover[0], self.show );
- if (!self[dismissible]) { on( element, mouseHover[1], self.hide ); }
- } else if (clickEvent == self[trigger] || 'focus' == self[trigger]) {
- on( element, self[trigger], self.toggle );
- }
- }
- element[stringPopover] = self;
- };
-
- // POPOVER DATA API
- // ================
- supports[push]( [ stringPopover, Popover, '['+dataToggle+'="popover"]' ] );
-
-
- /* Native Javascript for Bootstrap 3 | ScrollSpy
- -----------------------------------------------*/
-
- // SCROLLSPY DEFINITION
- // ====================
- var ScrollSpy = function(element, options) {
-
- // initialization element, the element we spy on
- element = queryElement(element);
-
- // DATA API
- var targetData = queryElement(element[getAttribute](dataTarget)),
- offsetData = element[getAttribute]('data-offset');
-
- // set options
- options = options || {};
-
- // invalidate
- if ( !options[target] && !targetData ) { return; }
-
- // event targets, constants
- var self = this, spyTarget = options[target] && queryElement(options[target]) || targetData,
- links = spyTarget && spyTarget[getElementsByTagName]('A'),
- offset = parseInt(options['offset'] || offsetData) || 10,
- items = [], targetItems = [], scrollOffset,
- scrollTarget = element[offsetHeight] < element[scrollHeight] ? element : globalObject, // determine which is the real scrollTarget
- isWindow = scrollTarget === globalObject;
-
- // populate items and targets
- for (var i=0, il=links[length]; i<il; i++) {
- var href = links[i][getAttribute]('href'),
- targetItem = href && href.charAt(0) === '#' && href.slice(-1) !== '#' && queryElement(href);
- if ( !!targetItem ) {
- items[push](links[i]);
- targetItems[push](targetItem);
- }
- }
-
- // private methods
- var updateItem = function(index) {
- var parent = items[index][parentNode], // item's parent LI element
- targetItem = targetItems[index], // the menu item targets this element
- dropdown = getClosest(parent,'.dropdown'),
- targetRect = isWindow && targetItem[getBoundingClientRect](),
-
- isActive = hasClass(parent,active) || false,
-
- topEdge = (isWindow ? targetRect[top] + scrollOffset : targetItem[offsetTop]) - offset,
- bottomEdge = isWindow ? targetRect[bottom] + scrollOffset - offset : targetItems[index+1] ? targetItems[index+1][offsetTop] - offset : element[scrollHeight],
-
- inside = scrollOffset >= topEdge && bottomEdge > scrollOffset;
-
- if ( !isActive && inside ) {
- if ( parent.tagName === 'LI' && !hasClass(parent,active) ) {
- addClass(parent,active);
- if (dropdown && !hasClass(dropdown,active) ) {
- addClass(dropdown,active);
- }
- bootstrapCustomEvent.call(element, 'activate', 'scrollspy', items[index]);
- }
- } else if ( !inside ) {
- if ( parent.tagName === 'LI' && hasClass(parent,active) ) {
- removeClass(parent,active);
- if (dropdown && hasClass(dropdown,active) && !getElementsByClassName(parent[parentNode],active).length ) {
- removeClass(dropdown,active);
- }
- }
- } else if ( !inside && !isActive || isActive && inside ) {
- return;
- }
- },
- updateItems = function(){
- scrollOffset = isWindow ? getScroll().y : element[scrollTop];
- for (var index=0, itl=items[length]; index<itl; index++) {
- updateItem(index)
- }
- };
-
- // public method
- this.refresh = function () {
- updateItems();
- }
-
- // init
- if ( !(stringScrollSpy in element) ) { // prevent adding event handlers twice
- on( scrollTarget, scrollEvent, self.refresh, passiveHandler );
- !isIE8 && on( globalObject, resizeEvent, self.refresh, passiveHandler );
- }
- self.refresh();
- element[stringScrollSpy] = self;
- };
-
- // SCROLLSPY DATA API
- // ==================
- supports[push]( [ stringScrollSpy, ScrollSpy, '['+dataSpy+'="scroll"]' ] );
-
-
- /* Native Javascript for Bootstrap 3 | Tab
- -----------------------------------------*/
-
- // TAB DEFINITION
- // ==============
- var Tab = function( element, options ) {
-
- // initialization element
- element = queryElement(element);
-
- // DATA API
- var heightData = element[getAttribute](dataHeight),
-
- // strings
- component = 'tab', height = 'height', float = 'float', isAnimating = 'isAnimating';
-
- // set options
- options = options || {};
- this[height] = supportTransitions ? (options[height] || heightData === 'true') : false; // filter legacy browsers
-
- // bind, event targets
- var self = this, next,
- tabs = getClosest(element,'.nav'),
- tabsContentContainer = false,
- dropdown = tabs && queryElement('.dropdown',tabs),
- activeTab, activeContent, nextContent, containerHeight, equalContents, nextHeight,
-
- // trigger
- triggerEnd = function(){
- tabsContentContainer[style][height] = '';
- removeClass(tabsContentContainer,collapsing);
- tabs[isAnimating] = false;
- },
- triggerShow = function() {
- if (tabsContentContainer) { // height animation
- if ( equalContents ) {
- triggerEnd();
- } else {
- setTimeout(function(){ // enables height animation
- tabsContentContainer[style][height] = nextHeight + 'px'; // height animation
- tabsContentContainer[offsetWidth];
- emulateTransitionEnd(tabsContentContainer, triggerEnd);
- },50);
- }
- } else {
- tabs[isAnimating] = false;
- }
- bootstrapCustomEvent.call(next, shownEvent, component, activeTab);
- },
- triggerHide = function() {
- if (tabsContentContainer) {
- activeContent[style][float] = left;
- nextContent[style][float] = left;
- containerHeight = activeContent[scrollHeight];
- }
-
- addClass(nextContent,active);
- bootstrapCustomEvent.call(next, showEvent, component, activeTab);
-
- removeClass(activeContent,active);
- bootstrapCustomEvent.call(activeTab, hiddenEvent, component, next);
-
- if (tabsContentContainer) {
- nextHeight = nextContent[scrollHeight];
- equalContents = nextHeight === containerHeight;
- addClass(tabsContentContainer,collapsing);
- tabsContentContainer[style][height] = containerHeight + 'px'; // height animation
- tabsContentContainer[offsetHeight];
- activeContent[style][float] = '';
- nextContent[style][float] = '';
- }
-
- if ( hasClass(nextContent, 'fade') ) {
- setTimeout(function(){
- addClass(nextContent,inClass);
- emulateTransitionEnd(nextContent,triggerShow);
- },20);
- } else { triggerShow(); }
- };
-
- if (!tabs) return; // invalidate
-
- // set default animation state
- tabs[isAnimating] = false;
-
- // private methods
- var getActiveTab = function() {
- var activeTabs = getElementsByClassName(tabs,active), activeTab;
- if ( activeTabs[length] === 1 && !hasClass(activeTabs[0],'dropdown') ) {
- activeTab = activeTabs[0];
- } else if ( activeTabs[length] > 1 ) {
- activeTab = activeTabs[activeTabs[length]-1];
- }
- return activeTab[getElementsByTagName]('A')[0];
- },
- getActiveContent = function() {
- return queryElement(getActiveTab()[getAttribute]('href'));
- },
- // handler
- clickHandler = function(e) {
- e[preventDefault]();
- next = e[currentTarget] || this; // IE8 needs to know who really currentTarget is
- !tabs[isAnimating] && !hasClass(next[parentNode],active) && self.show();
- };
-
- // public method
- this.show = function() { // the tab we clicked is now the next tab
- next = next || element;
- nextContent = queryElement(next[getAttribute]('href')); //this is the actual object, the next tab content to activate
- activeTab = getActiveTab();
- activeContent = getActiveContent();
-
- tabs[isAnimating] = true;
- removeClass(activeTab[parentNode],active);
- activeTab[setAttribute](ariaExpanded,'false');
- addClass(next[parentNode],active);
- next[setAttribute](ariaExpanded,'true');
-
- if ( dropdown ) {
- if ( !hasClass(element[parentNode][parentNode],'dropdown-menu') ) {
- if (hasClass(dropdown,active)) removeClass(dropdown,active);
- } else {
- if (!hasClass(dropdown,active)) addClass(dropdown,active);
- }
- }
-
- bootstrapCustomEvent.call(activeTab, hideEvent, component, next);
-
- if (hasClass(activeContent, 'fade')) {
- removeClass(activeContent,inClass);
- emulateTransitionEnd(activeContent, triggerHide);
- } else { triggerHide(); }
- };
-
- // init
- if ( !(stringTab in element) ) { // prevent adding event handlers twice
- on(element, clickEvent, clickHandler);
- }
- if (self[height]) { tabsContentContainer = getActiveContent()[parentNode]; }
- element[stringTab] = self;
- };
-
- // TAB DATA API
- // ============
- supports[push]( [ stringTab, Tab, '['+dataToggle+'="tab"]' ] );
-
-
- /* Native Javascript for Bootstrap 3 | Tooltip
- ---------------------------------------------*/
-
- // TOOLTIP DEFINITION
- // ==================
- var Tooltip = function( element,options ) {
-
- // initialization element
- element = queryElement(element);
-
- // set options
- options = options || {};
-
- // DATA API
- var animationData = element[getAttribute](dataAnimation),
- placementData = element[getAttribute](dataPlacement),
- delayData = element[getAttribute](dataDelay),
- containerData = element[getAttribute](dataContainer),
-
- // strings
- component = 'tooltip',
- classString = 'class',
- title = 'title',
- fade = 'fade',
- div = 'div',
-
- // check container
- containerElement = queryElement(options[container]),
- containerDataElement = queryElement(containerData),
-
- // maybe the element is inside a modal
- modal = getClosest(element,'.modal'),
-
- // maybe the element is inside a fixed navbar
- navbarFixedTop = getClosest(element,'.'+fixedTop),
- navbarFixedBottom = getClosest(element,'.'+fixedBottom);
-
- // set instance options
- this[animation] = options[animation] && options[animation] !== fade ? options[animation] : animationData || fade;
- this[placement] = options[placement] ? options[placement] : placementData || top;
- this[delay] = parseInt(options[delay] || delayData) || 200;
- this[container] = containerElement ? containerElement
- : containerDataElement ? containerDataElement
- : navbarFixedTop ? navbarFixedTop
- : navbarFixedBottom ? navbarFixedBottom
- : modal ? modal : DOC[body];
-
- // bind, event targets, title and constants
- var self = this, timer = 0, placementSetting = this[placement], tooltip = null,
- titleString = element[getAttribute](title) || element[getAttribute](dataTitle) || element[getAttribute](dataOriginalTitle);
-
- if ( !titleString || titleString == "" ) return; // invalidate
-
- // private methods
- var removeToolTip = function() {
- self[container].removeChild(tooltip);
- tooltip = null; timer = null;
- },
- createToolTip = function() {
- titleString = element[getAttribute](title) || element[getAttribute](dataTitle) || element[getAttribute](dataOriginalTitle); // read the title again
- if ( !titleString || titleString == "" ) return false; // invalidate
-
- tooltip = DOC[createElement](div);
- tooltip[setAttribute]('role',component);
-
- var tooltipArrow = DOC[createElement](div), tooltipInner = DOC[createElement](div);
- tooltipArrow[setAttribute](classString, component+'-arrow'); tooltipInner[setAttribute](classString,component+'-inner');
-
- tooltip[appendChild](tooltipArrow); tooltip[appendChild](tooltipInner);
-
- tooltipInner[innerHTML] = titleString;
-
- self[container][appendChild](tooltip);
- tooltip[setAttribute](classString, component + ' ' + placementSetting + ' ' + self[animation]);
- },
- updateTooltip = function () {
- styleTip(element,tooltip,placementSetting,self[container]);
- },
- showTooltip = function () {
- !hasClass(tooltip,inClass) && ( addClass(tooltip,inClass) );
- },
- // triggers
- showTrigger = function() {
- bootstrapCustomEvent.call(element, shownEvent, component);
- !isIE8 && on( globalObject, resizeEvent, self.hide, passiveHandler );
- },
- hideTrigger = function() {
- !isIE8 && off( globalObject, resizeEvent, self.hide, passiveHandler );
- removeToolTip();
- bootstrapCustomEvent.call(element, hiddenEvent, component);
- };
-
- // public methods
- this.show = function() {
- clearTimeout(timer);
- timer = setTimeout( function() {
- if (tooltip === null) {
- placementSetting = self[placement]; // we reset placement in all cases
- if(createToolTip() == false) return;
- updateTooltip();
- showTooltip();
- bootstrapCustomEvent.call(element, showEvent, component);
- !!self[animation] ? emulateTransitionEnd(tooltip, showTrigger) : showTrigger();
- }
- }, 20 );
- };
- this.hide = function() {
- clearTimeout(timer);
- timer = setTimeout( function() {
- if (tooltip && hasClass(tooltip,inClass)) {
- bootstrapCustomEvent.call(element, hideEvent, component);
- removeClass(tooltip,inClass);
- !!self[animation] ? emulateTransitionEnd(tooltip, hideTrigger) : hideTrigger();
- }
- }, self[delay]);
- };
- this.toggle = function() {
- if (!tooltip) { self.show(); }
- else { self.hide(); }
- };
-
- // init
- if ( !(stringTooltip in element) ) { // prevent adding event handlers twice
- element[setAttribute](dataOriginalTitle,titleString);
- element.removeAttribute(title);
- on(element, mouseHover[0], self.show);
- on(element, mouseHover[1], self.hide);
- }
- element[stringTooltip] = self;
- };
-
- // TOOLTIP DATA API
- // =================
- supports[push]( [ stringTooltip, Tooltip, '['+dataToggle+'="tooltip"]' ] );
-
-
-
- /* Native Javascript for Bootstrap | Initialize Data API
- --------------------------------------------------------*/
- var initializeDataAPI = function( constructor, collection ){
- for (var i=0, l=collection[length]; i<l; i++) {
- new constructor(collection[i]);
- }
- },
- initCallback = BSN.initCallback = function(lookUp){
- lookUp = lookUp || DOC;
- for (var i=0, l=supports[length]; i<l; i++) {
- initializeDataAPI( supports[i][1], lookUp[querySelectorAll] (supports[i][2]) );
- }
- };
-
- // bulk initialize all components
- DOC[body] ? initCallback() : on( DOC, 'DOMContentLoaded', function(){ initCallback(); } );
-
- return {
- Affix: Affix,
- Alert: Alert,
- Button: Button,
- Carousel: Carousel,
- Collapse: Collapse,
- Dropdown: Dropdown,
- Modal: Modal,
- Popover: Popover,
- ScrollSpy: ScrollSpy,
- Tab: Tab,
- Tooltip: Tooltip
- };
- }));
|