Project

General

Profile

1
// Native Javascript for Bootstrap 3
2
// by dnp_theme
3

    
4
(function(factory){
5

    
6
  // CommonJS/RequireJS and "native" compatibility
7
  if(typeof module !== "undefined" && typeof exports == "object") {
8
    // A commonJS/RequireJS environment
9
    if(typeof window != "undefined") {
10
      // Window and document exist, so return the factory's return value.
11
      module.exports = factory();
12
    } else {
13
      // Let the user give the factory a Window and Document.
14
      module.exports = factory;
15
    }
16
  } else {
17
    // Assume a traditional browser.
18
    window.Affix = factory();
19
  }
20

    
21
})(function(){
22

    
23
  //AFFIX DEFINITION
24
  var Affix = function(element,options) {
25
    options = options || {};
26

    
27
    this.element = typeof element === 'object' ? element : document.querySelector(element);
28
    this.options = {};
29
    this.options.target = options.target ? ((typeof(options.target) === 'object') ? options.target : document.querySelector(options.target)) : null; // target is an object
30
    this.options.offsetTop = options.offsetTop && options.offsetTop ? ( options.offsetTop === 'function' ? options.offsetTop() : parseInt(options.offsetTop,0) ) : 0; // offset option is an integer number or function to determine that number
31
    this.options.offsetBottom = options.offsetBottom && options.offsetBottom ? ( options.offsetBottom === 'function' ? options.offsetBottom() : parseInt(options.offsetBottom,0) ) : null;
32

    
33
    if (this.element && (this.options.target || this.options.offsetTop || this.options.offsetBottom ) ) { this.init(); }
34
  }
35

    
36
  //AFFIX METHODS
37
  Affix.prototype = {
38
    init: function () {
39
      this.affixed = false;
40
      this.affixedBottom = false;
41
      this.getPinOffsetTop = 0;
42
      this.getPinOffsetBottom = null;
43

    
44
      //actions
45
      this.checkPosition();
46
      this.updateAffix();
47
      this.scrollEvent();
48
      this.resizeEvent()
49
    },
50
    processOffsetTop: function () {
51
      if ( this.options.target !== null ) {
52
        return this.targetRect().top + this.scrollOffset();
53
      } else if ( this.options.offsetTop !== null ) {
54
        return this.options.offsetTop
55
      }
56
    },
57
    processOffsetBottom: function () {
58
      if ( this.options.offsetBottom !== null ) {
59
        var maxScroll = this.getMaxScroll();
60
        return maxScroll - this.elementHeight() - this.options.offsetBottom
61
      }
62
    },
63
    offsetTop: function () {
64
      return this.processOffsetTop()
65
    },
66
    offsetBottom: function () {
67
      return this.processOffsetBottom()
68
    },
69
    checkPosition: function () {
70
      this.getPinOffsetTop = this.offsetTop
71
      this.getPinOffsetBottom = this.offsetBottom
72
    },
73
    scrollOffset: function () {
74
      return window.pageYOffset || document.documentElement.scrollTop
75
    },
76
    pinTop: function () {
77
      if ( !/affix/.test(this.element.className) ) {
78
        this.element.className += ' affix';
79
        this.affixed = true
80
      }
81
    },
82
    unPinTop: function () {
83
      if ( /affix/.test(this.element.className) ) {
84
        this.element.className = this.element.className.replace(' affix','');
85
        this.affixed = false
86
      }
87
    },
88
    pinBottom: function () {
89
      if ( !/'affix-bottom'/.test(this.element.className) ) {
90
        this.element.className += ' affix-bottom';
91
        this.affixedBottom = true
92
      }
93
    },
94
    unPinBottom: function () {
95
      if ( /'affix-bottom'/.test(this.element.className) ) {
96
        this.element.className = this.element.className.replace(' affix-bottom','');
97
        this.affixedBottom = false
98
      }
99
    },
100
    updatePin: function () {
101
      if (this.affixed === false && (parseInt(this.offsetTop(),0) - parseInt(this.scrollOffset(),0) < 0)) {
102
        this.pinTop();
103
      } else if (this.affixed === true && (parseInt(this.scrollOffset(),0) <= parseInt(this.getPinOffsetTop(),0) )) {
104
        this.unPinTop()
105
      }
106

    
107
      if (this.affixedBottom === false && (parseInt(this.offsetBottom(),0) - parseInt(this.scrollOffset(),0) < 0)) {
108
        this.pinBottom();
109
      } else if (this.affixedBottom === true && (parseInt(this.scrollOffset(),0) <= parseInt(this.getPinOffsetBottom(),0) )) {
110
        this.unPinBottom()
111
      }
112
    },
113

    
114
    updateAffix : function () { // Unpin and check position again
115
      this.unPinTop();
116
      this.unPinBottom();
117
      this.checkPosition()
118

    
119
      this.updatePin() // If any case update values again
120
    },
121

    
122
    elementHeight : function(){
123
      return this.element.offsetHeight
124
    },
125

    
126
    targetRect : function(){
127
      return this.options.target.getBoundingClientRect()
128
    },
129

    
130
    getMaxScroll : function(){
131
      return Math.max( document.body.scrollHeight, document.body.offsetHeight,
132
        document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight )
133
    },
134

    
135
    scrollEvent : function(){
136
      var self = this;
137
      window.addEventListener('scroll', function() {
138
        self.updatePin()
139
      }, false);
140

    
141
    },
142
    resizeEvent : function(){
143
      var self = this,
144
        isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false,
145
        dl = (isIE && isIE < 10) ? 500 : 50;
146
      window.addEventListener('resize', function () {
147
        setTimeout(function(){
148
          self.updateAffix()
149
        },dl);
150
      }, false);
151

    
152
    }
153
  };
154

    
155
  // AFFIX DATA API
156
  // =================
157
  var Affixes = document.querySelectorAll('[data-spy="affix"]'), i = 0, afl = Affixes.length;
158
  for (i;i<afl;i++) {
159
    var item = Affixes[i], options = {};
160
      options.offsetTop    = item.getAttribute('data-offset-top');
161
      options.offsetBottom  = item.getAttribute('data-offset-bottom');
162
      options.target      = item.getAttribute('data-target');
163

    
164
    if ( item && (options.offsetTop !== null || options.offsetBottom !== null || options.target !== null) ) { //don't do anything unless we have something valid to pin
165
      new Affix(item, options);
166
    }
167
  }
168

    
169
  return Affix;
170
});
171

    
172

    
173
(function(factory){
174

    
175
  // CommonJS/RequireJS and "native" compatibility
176
  if(typeof module !== "undefined" && typeof exports == "object") {
177
    // A commonJS/RequireJS environment
178
    if(typeof window != "undefined") {
179
      // Window and document exist, so return the factory's return value.
180
      module.exports = factory();
181
    } else {
182
      // Let the user give the factory a Window and Document.
183
      module.exports = factory;
184
    }
185
  } else {
186
    // Assume a traditional browser.
187
    window.Alert = factory();
188
  }
189

    
190
})(function(root){
191

    
192
  // ALERT DEFINITION
193
  // ===================
194
  var Alert = function( element ) {
195
    this.btn = typeof element === 'object' ? element : document.querySelector(element);
196
    this.alert = null;
197
    this.duration = 150; // default alert transition duration
198
    this.init();
199
  }
200

    
201
  // ALERT METHODS
202
  // ================
203
  Alert.prototype = {
204

    
205
    init : function() {
206
      this.actions();
207
      document.addEventListener('click', this.close, false); //delegate to all alerts, including those inserted later into the DOM
208
    },
209

    
210
    actions : function() {
211
      var self = this;
212

    
213
      this.close = function(e) {
214
        var target = e.target;
215
        self.btn = target.getAttribute('data-dismiss') === 'alert' && target.className === 'close' ? target : target.parentNode;
216
        self.alert = self.btn.parentNode;
217

    
218
        if ( self.alert !== null && self.btn.getAttribute('data-dismiss') === 'alert' && /in/.test(self.alert.className) ) {
219
          self.alert.className = self.alert.className.replace(' in','');
220
          setTimeout(function() {
221
            self.alert && self.alert.parentNode.removeChild(self.alert);
222
          }, self.duration);
223
        }
224

    
225
      }
226
    }
227
    }
228

    
229
  // ALERT DATA API
230
  // =================
231
    var Alerts = document.querySelectorAll('[data-dismiss="alert"]'), i = 0, all = Alerts.length;
232
  for (i;i<all;i++) {
233
    new Alert(Alerts[i]);
234
  }
235

    
236
  return Alert;
237

    
238
});
239

    
240

    
241
(function(factory){
242

    
243
  // CommonJS/RequireJS and "native" compatibility
244
  if(typeof module !== "undefined" && typeof exports == "object") {
245
    // A commonJS/RequireJS environment
246
    if(typeof window != "undefined") {
247
      // Window and document exist, so return the factory's return value.
248
      module.exports = factory();
249
    } else {
250
      // Let the user give the factory a Window and Document.
251
      module.exports = factory;
252
    }
253
  } else {
254
    // Assume a traditional browser.
255
    window.Button = factory();
256
  }
257

    
258
})(function(){
259

    
260
  // BUTTON DEFINITION
261
  // ===================
262
  var Button = function( element, option ) {
263
    this.btn = typeof element === 'object' ? element : document.querySelector(element);
264
    this.option = typeof option === 'string' ? option : null;
265

    
266
    this.init();
267
  };
268

    
269
  // BUTTON METHODS
270
  // ================
271
  Button.prototype = {
272

    
273
    init : function() {
274
      var self = this;
275
      this.actions();
276

    
277
      if ( /btn/.test(this.btn.className) ) {
278
        if ( this.option && this.option !== 'reset' ) {
279

    
280
          this.state = this.btn.getAttribute('data-'+this.option+'-text') || null;
281

    
282
          !this.btn.getAttribute('data-original-text') && this.btn.setAttribute('data-original-text',self.btn.innerHTML.replace(/^\s+|\s+$/g, ''));
283
          this.setState();
284

    
285
        } else if ( this.option === 'reset' ) {
286
          this.reset();
287
        }
288
      }
289

    
290
      if ( /btn-group/.test(this.btn.className) ) {
291
        this.btn.addEventListener('click', this.toggle, false);
292
      }
293
    },
294

    
295
    actions : function() {
296
      var self = this,
297
        changeEvent = (('CustomEvent' in window) && window.dispatchEvent)
298
          ? new CustomEvent('bs.button.change') : null; // The custom event that will be triggered on demand
299

    
300
      // assign event to a trigger function
301
      function triggerChange(t) { if (changeEvent) { t.dispatchEvent(changeEvent); } }
302

    
303
      this.setState = function() {
304
        if ( this.option === 'loading' ) {
305
          this.addClass(this.btn,'disabled');
306
          this.btn.setAttribute('disabled','disabled');
307
        }
308
        this.btn.innerHTML = this.state;
309
      },
310

    
311
      this.reset = function() {
312
        if ( /disabled/.test(self.btn.className) || self.btn.getAttribute('disabled') === 'disabled' ) {
313
          this.removeClass(this.btn,'disabled');
314
          self.btn.removeAttribute('disabled');
315
        }
316
        self.btn.innerHTML = self.btn.getAttribute('data-original-text');
317
      },
318

    
319
      this.toggle = function(e) {
320
        var parent = e.target.parentNode,
321
          label = e.target.tagName === 'LABEL' ? e.target : parent.tagName === 'LABEL' ? parent : null; // the .btn label
322

    
323
        if ( !label ) return; //react if a label or its immediate child is clicked
324

    
325
        var target = this, //e.currentTarget || e.srcElement; // the button group, the target of the handler function
326
          labels = target.querySelectorAll('.btn'), ll = labels.length, i = 0, // all the button group buttons
327
          input = label.getElementsByTagName('INPUT')[0];
328

    
329
        if ( !input ) return; //return if no input found
330

    
331
        //manage the dom manipulation
332
        if ( input.type === 'checkbox' ) { //checkboxes
333
          if ( !input.checked ) {
334
            self.addClass(label,'active');
335
            input.getAttribute('checked');
336
            input.setAttribute('checked','checked');
337
            input.checked = true;
338
          } else {
339
            self.removeClass(label,'active');
340
            input.getAttribute('checked');
341
            input.removeAttribute('checked');
342
            input.checked = false;
343
          }
344
          triggerChange(input); //trigger the change for the input
345
          triggerChange(self.btn); //trigger the change for the btn-group
346
        }
347

    
348
        if ( input.type === 'radio' ) { // radio buttons
349
          if ( !input.checked ) { // don't trigger if already active
350
            self.addClass(label,'active');
351
            input.setAttribute('checked','checked');
352
            input.checked = true;
353
            triggerChange(self.btn);
354
            triggerChange(input); //trigger the change
355

    
356
            for (i;i<ll;i++) {
357
              var l = labels[i];
358
              if ( l !== label && /active/.test(l.className) )  {
359
                var inp = l.getElementsByTagName('INPUT')[0];
360
                self.removeClass(l,'active');
361
                inp.removeAttribute('checked');
362
                inp.checked = false;
363
                triggerChange(inp); // trigger the change
364
              }
365
            }
366
          }
367
        }
368
      },
369
      this.addClass = function(el,c) { // where modern browsers fail, use classList
370
        if (el.classList) { el.classList.add(c); } else { el.className += ' '+c; el.offsetWidth; }
371
      },
372
      this.removeClass = function(el,c) {
373
        if (el.classList) { el.classList.remove(c); } else { el.className = el.className.replace(c,'').replace(/^\s+|\s+$/g,''); el.offsetWidth; }
374
      }
375
    }
376
    }
377

    
378
  // BUTTON DATA API
379
  // =================
380
    var Buttons = document.querySelectorAll('[data-toggle=button]'), i = 0, btl = Buttons.length;
381
  for (i;i<btl;i++) {
382
    new Button(Buttons[i]);
383
  }
384

    
385
  var ButtonGroups = document.querySelectorAll('[data-toggle=buttons]'), j = 0, bgl = ButtonGroups.length;
386
  for (j;j<bgl;j++) {
387
    new Button(ButtonGroups[j]);
388
  }
389

    
390
  return Button;
391

    
392
});
393

    
394

    
395
(function(factory){
396

    
397
  // CommonJS/RequireJS and "native" compatibility
398
  if(typeof module !== "undefined" && typeof exports == "object") {
399
    // A commonJS/RequireJS environment
400
    if(typeof window != "undefined") {
401
      // Window and document exist, so return the factory's return value.
402
      module.exports = factory();
403
    } else {
404
      // Let the user give the factory a Window and Document.
405
      module.exports = factory;
406
    }
407
  } else {
408
    // Assume a traditional browser.
409
    window.Carousel = factory();
410
  }
411

    
412
})(function(){
413

    
414
  // CAROUSEL DEFINITION
415
  // ===================
416
  var Carousel = function( element, options ) {
417
    options = options || {};
418

    
419
    this.carousel = (typeof element === 'object') ? element : document.querySelector( element );
420
    this.options = {}; //replace extend
421
    this.options.keyboard = options.keyboard === 'true' ? true : false;
422
    this.options.pause = options.pause ? options.pause : 'hover'; // false / hover
423

    
424
    // bootstrap carousel default transition duration / option
425
    this.duration = 600;
426
    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false;
427
    this.options.duration = (this.isIE && this.isIE < 10) ? 0 : (options.duration || this.duration);
428

    
429
    var items = this.carousel.querySelectorAll('.item'), il=items.length; //this is an object
430
    this.controls = this.carousel.querySelectorAll('.carousel-control');
431
    this.prev = this.controls[0];
432
    this.next = this.controls[1];
433
    this.slides = []; for (var i = 0; i < il; i++) { this.slides.push(items[i]); } // this is an array
434
    this.indicator = this.carousel.querySelector( ".carousel-indicators" ); // object
435
    this.indicators = this.carousel.querySelectorAll( ".carousel-indicators li" ); // object
436
    this.total    = this.slides.length;
437
    this.timer    = null;
438
    this.direction  = null;
439
    this.index    = 0;
440

    
441
    if (options.interval === 'false' ) {
442
      this.options.interval = false;
443
    } else {
444
      this.options.interval = parseInt(options.interval) || 5000;
445
    }
446

    
447
    this.init();
448
  };
449

    
450
  // CAROUSEL METHODS
451
  // ================
452
  Carousel.prototype = {
453
    init: function() {
454
      if ( this.options.interval !== false ){
455
        this.cycle();
456
      }
457

    
458
      if ( this.options && this.options.pause === 'hover' && this.options.interval !== false ) {
459
        this.pause();
460
      }
461
      this.actions();
462
      this._addEventListeners();
463
    },
464
    cycle: function(e) {
465
      var self = this;
466

    
467
      self.direction = 'left';
468
      self.timer = setInterval(function() {
469
        self.index++;
470
        if( self.index == self.slides.length ) {
471
          self.index = 0;
472
        }
473
        self._slideTo( self.index, e );
474

    
475
      }, self.options.interval);
476
    },
477
    pause: function() {
478
      var self = this;
479
      var pauseHandler = function () {
480
        if ( self.options.interval !==false && !/paused/.test(self.carousel.className) ) {
481
          self.carousel.className += ' paused';
482
          clearInterval( self.timer );
483
          self.timer = null;
484
        }
485
      };
486
      var resumeHandler = function() {
487
        if ( self.options.interval !==false && /paused/.test(self.carousel.className) ) {
488
          self.cycle();
489
          self.carousel.className = self.carousel.className.replace(' paused','');
490
        }
491
      };
492
      self.carousel.addEventListener( "mouseenter", pauseHandler, false);
493
      self.carousel.addEventListener( "mouseleave", resumeHandler, false);
494
      self.carousel.addEventListener( "touchstart", pauseHandler, false);
495
      self.carousel.addEventListener( "touchend", resumeHandler, false);
496
    },
497
    _slideTo: function( next, e ) {
498
      var self = this;
499
      var active = self._getActiveIndex(); // the current active
500
      //determine type
501
      var direction = self.direction;
502
      var dr = direction === 'left' ? 'next' : 'prev';
503
      var slid = null, slide=null;
504

    
505
      //register events
506
      if (('CustomEvent' in window) && window.dispatchEvent) {
507
        slid =  new CustomEvent("slid.bs.carousel");
508
        slide = new CustomEvent("slide.bs.carousel");
509
      }
510
      if (slid) { self.carousel.dispatchEvent(slid); } //here we go with the slid
511

    
512
      self._removeEventListeners();
513
      clearInterval(self.timer);
514
      self.timer = null;
515
      self._curentPage( self.indicators[next] );
516

    
517
      if ( /slide/.test(this.carousel.className) && !(this.isIE && this.isIE < 10) ) {
518
        self.slides[next].className += (' '+dr);
519
        self.slides[next].offsetWidth;
520
        self.slides[next].className += (' '+direction);
521
        self.slides[active].className += (' '+direction);
522

    
523
        setTimeout(function() { //we're gonna fake waiting for the animation to finish, cleaner and better
524
          self._addEventListeners();
525

    
526
          self.slides[next].className += ' active';
527
          self.slides[active].className = self.slides[active].className.replace(' active','');
528

    
529
          self.slides[next].className = self.slides[next].className.replace(' '+dr,'');
530
          self.slides[next].className = self.slides[next].className.replace(' '+direction,'');
531
          self.slides[active].className = self.slides[active].className.replace(' '+direction,'');
532

    
533
          if ( self.options.interval !== false && !/paused/.test(self.carousel.className) ){
534
            clearInterval(self.timer); self.cycle();
535
          }
536
          if (slide) { self.carousel.dispatchEvent(slide); } //here we go with the slide
537
        }, self.options.duration + 100 );
538
      } else {
539
        self.slides[next].className += ' active';
540
        self.slides[next].offsetWidth;
541
        self.slides[active].className = self.slides[active].className.replace(' active','');
542
        setTimeout(function() {
543
          self._addEventListeners();
544
          if ( self.options.interval !== false && !/paused/.test(self.carousel.className) ){
545
            clearInterval(self.timer); self.cycle();
546
          }
547
          if (slide) { self.carousel.dispatchEvent(slide); } //here we go with the slide
548
        }, self.options.duration + 100 );
549
      }
550
    },
551
    _addEventListeners : function () {
552
      var self = this;
553

    
554
      self.next && self.next.addEventListener( "click", self.controlsHandler, false);
555
      self.prev && self.prev.addEventListener( "click", self.controlsHandler, false);
556

    
557
      self.indicator && self.indicator.addEventListener( "click", self.indicatorHandler, false);
558

    
559
      if (self.options.keyboard === true) {
560
        window.addEventListener('keydown', self.keyHandler, false);
561
      }
562
    },
563
    _removeEventListeners : function () { // prevent mouse bubbles while animating
564
      var self = this;
565

    
566
      self.next && self.next.removeEventListener( "click", self.controlsHandler, false);
567
      self.prev && self.prev.removeEventListener( "click", self.controlsHandler, false);
568

    
569
      self.indicator && self.indicator.removeEventListener( "click", self.indicatorHandler, false);
570

    
571
      if (self.options.keyboard === true) {
572
        window.removeEventListener('keydown', self.keyHandler, false);
573
      }
574
    },
575
    _getActiveIndex : function () {
576
      return this.slides.indexOf(this.carousel.querySelector('.item.active'))
577
    },
578
    _curentPage: function( p ) {
579
      for( var i = 0; i < this.indicators.length; ++i ) {
580
        var a = this.indicators[i];
581
        a.className = "";
582
      }
583
      if (p) p.className = "active";
584
    },
585
    actions: function() {
586
      var self = this;
587
      self.indicatorHandler = function(e) {
588
        e.preventDefault();
589
        var target = e.target;
590
        var active = self._getActiveIndex(); // the current active
591

    
592
        if ( target && !/active/.test(target.className) && target.getAttribute('data-slide-to') ) {
593
          var n = parseInt( target.getAttribute('data-slide-to'), 10 );
594

    
595
          self.index = n;
596

    
597
          if( self.index == 0 ) {
598
            self.index = 0;
599
          } else if ( self.index == self.total - 1 ) {
600
            self.index = self.total - 1;
601
          }
602

    
603
           //determine direction first
604
          if  ( (active < self.index ) || (active === self.total - 1 && self.index === 0 ) ) {
605
            self.direction = 'left'; // next
606
          } else if  ( (active > self.index) || (active === 0 && self.index === self.total -1 ) ) {
607
            self.direction = 'right'; // prev
608
          }
609
        } else { return false; }
610

    
611
        self._slideTo( self.index, e ); //Do the slide
612

    
613
      },
614

    
615
      self.controlsHandler = function (e) {
616
        var target = e.currentTarget || e.srcElement;
617
        e.preventDefault();
618

    
619
        if ( target === self.next ) {
620
          self.index++;
621
          self.direction = 'left'; //set direction first
622

    
623
          if( self.index == self.total - 1 ) {
624
            self.index = self.total - 1;
625
          } else if ( self.index == self.total ){
626
            self.index = 0
627
          }
628
        } else if ( target === self.prev ) {
629
          self.index--;
630
          self.direction = 'right'; //set direction first
631

    
632
          if( self.index == 0 ) {
633
            self.index = 0;
634
          } else if ( self.index < 0 ){
635
            self.index = self.total - 1
636
          }
637
        }
638

    
639
        self._slideTo( self.index, e ); //Do the slide
640
      }
641

    
642
      self.keyHandler = function (e) {
643

    
644
        switch (e.which) {
645
          case 39:
646
            e.preventDefault();
647
            self.index++;
648
            self.direction = 'left';
649
            if( self.index == self.total - 1 ) { self.index = self.total - 1; } else
650
            if ( self.index == self.total ){ self.index = 0 }
651
            break;
652
          case 37:
653
            e.preventDefault();
654
            self.index--;
655
            self.direction = 'right';
656
            if( self.index == 0 ) { self.index = 0; } else
657
            if ( self.index < 0 ){ self.index = self.total - 1 }
658
            break;
659
          default: return;
660
        }
661
        self._slideTo( self.index, e ); //Do the slide
662
      }
663
    }
664
  }
665

    
666
  // CAROUSEL DATA API
667
  // =================
668
  var Carousels = document.querySelectorAll('[data-ride="carousel"]'), i = 0, crl = Carousels.length;
669
  for (i;i<crl;i++) {
670
    var c = Carousels[i], options = {};
671
    options.interval = c.getAttribute('data-interval') && c.getAttribute('data-interval');
672
    options.pause = c.getAttribute('data-pause') && c.getAttribute('data-pause') || 'hover';
673
    options.keyboard = c.getAttribute('data-keyboard') && c.getAttribute('data-keyboard') || false;
674
    options.duration = c.getAttribute('data-duration') && c.getAttribute('data-duration') || false;
675
    new Carousel(c, options)
676
  }
677

    
678
  return Carousel;
679

    
680
});
681

    
682

    
683
// Native Javascript for Bootstrap 3 | Collapse
684
// by dnp_theme
685

    
686
(function(factory){
687

    
688
  // CommonJS/RequireJS and "native" compatibility
689
  if(typeof module !== "undefined" && typeof exports == "object") {
690
    // A commonJS/RequireJS environment
691
    if(typeof window != "undefined") {
692
      // Window and document exist, so return the factory's return value.
693
      module.exports = factory();
694
    } else {
695
      // Let the user give the factory a Window and Document.
696
      module.exports = factory;
697
    }
698
  } else {
699
    // Assume a traditional browser.
700
    window.Collapse = factory();
701
  }
702

    
703
})(function(){
704

    
705
  // COLLAPSE DEFINITION
706
  // ===================
707
  var Collapse = function( element, options ) {
708
    options = options || {};
709
    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false;
710
    this.btn = typeof element === 'object' ? element : document.querySelector(element);
711
    this.accordion = null;
712
    this.collapse = null;
713
    this.duration = 300; // default collapse transition duration
714
    this.options = {};
715
    this.options.duration = (this.isIE && this.isIE < 10) ? 0 : (options.duration || this.duration);
716
    this.init();
717
  };
718

    
719
  // COLLAPSE METHODS
720
  // ================
721
  Collapse.prototype = {
722

    
723
    init : function() {
724
      this.actions();
725
      this.addEvent();
726
    },
727

    
728
    actions : function() {
729
      var self = this;
730
      var getOuterHeight = function (el) {
731
        var s = el && el.currentStyle || window.getComputedStyle(el), // the getComputedStyle polyfill would do this for us, but we want to make sure it does
732
          btp = s.borderTopWidth || 0,
733
          mtp = /px/.test(s.marginTop)  ? Math.round(s.marginTop.replace('px',''))    : 0,
734
          mbp = /px/.test(s.marginBottom)  ? Math.round(s.marginBottom.replace('px',''))  : 0,
735
          mte = /em/.test(s.marginTop)  ? Math.round(s.marginTop.replace('em','')    * parseInt(s.fontSize)) : 0,
736
          mbe = /em/.test(s.marginBottom)  ? Math.round(s.marginBottom.replace('em','')  * parseInt(s.fontSize)) : 0;
737

    
738
        return el.clientHeight + parseInt( btp ) + parseInt( mtp ) + parseInt( mbp ) + parseInt( mte ) + parseInt( mbe ); //we need an accurate margin value
739
      };
740

    
741
      this.toggle = function(e) {
742
        self.btn = self.getTarget(e).btn;
743
        self.collapse = self.getTarget(e).collapse;
744

    
745
        if (!/\bin/.test(self.collapse.className)) {
746
          self.open(e);
747
        } else {
748
          self.close(e);
749
        }
750
      },
751
      this.close = function(e) {
752
        e.preventDefault();
753
        self.btn = self.getTarget(e).btn;
754
        self.collapse = self.getTarget(e).collapse;
755
        self._close(self.collapse);
756
        self.removeClass(self.btn,'collapsed');
757
      },
758
      this.open = function(e) {
759
        e.preventDefault();
760
        self.btn = self.getTarget(e).btn;
761
        self.collapse = self.getTarget(e).collapse;
762
        self.accordion = self.btn.getAttribute('data-parent') && self.getClosest(self.btn, self.btn.getAttribute('data-parent'));
763

    
764
        self._open(self.collapse);
765
        self.addClass(self.btn,'collapsed');
766

    
767
        if ( self.accordion !== null ) {
768
          var active = self.accordion.querySelectorAll('.collapse.in'), al = active.length, i = 0;
769
          for (i;i<al;i++) {
770
            if ( active[i] !== self.collapse) self._close(active[i]);
771
          }
772
        }
773
      },
774
      this._open = function(c) {
775
        self.removeEvent();
776
        self.addClass(c,'in');
777
        c.setAttribute('aria-expanded','true');
778
        self.addClass(c,'collapsing');
779
        setTimeout(function() {
780
          var h = self.getMaxHeight(c);
781
          c.style.height = h + 'px';
782
          c.style.overflowY = 'hidden';
783
        }, 0);
784
        setTimeout(function() {
785
          c.style.height = '';
786
          c.style.overflowY = '';
787
          self.removeClass(c,'collapsing');
788
          self.addEvent();
789
        }, self.options.duration);
790
      },
791
      this._close = function(c) {
792
        self.removeEvent();
793
        c.setAttribute('aria-expanded','false');
794
        c.style.height = self.getMaxHeight(c) + 'px';
795
        setTimeout(function() {
796
          c.style.height = '0px';
797
          c.style.overflowY = 'hidden';
798
          self.addClass(c,'collapsing');
799
        }, 0);
800

    
801
        setTimeout(function() {
802
          self.removeClass(c,'collapsing');
803
          self.removeClass(c,'in');
804
          c.style.overflowY = '';
805
          c.style.height = '';
806
          self.addEvent();
807
        }, self.options.duration);
808
      },
809
      this.getMaxHeight = function(l) { // get collapse trueHeight and border
810
        var h = 0;
811
        for (var k = 0, ll = l.children.length; k < ll; k++) {
812
          h += getOuterHeight(l.children[k]);
813
        }
814
        return h;
815
      },
816
      this.removeEvent = function() {
817
        this.btn.removeEventListener('click', this.toggle, false);
818
      },
819
      this.addEvent = function() {
820
        this.btn.addEventListener('click', this.toggle, false);
821
      },
822
      this.getTarget = function(e) {
823
        var t = e.currentTarget || e.srcElement,
824
          h = t.href && t.getAttribute('href').replace('#',''),
825
          d = t.getAttribute('data-target') && ( t.getAttribute('data-target') ),
826
          id = h || ( d && /#/.test(d)) && d.replace('#',''),
827
          cl = (d && d.charAt(0) === '.') && d, //the navbar collapse trigger targets a class
828
          c = id && document.getElementById(id) || cl && document.querySelector(cl);
829

    
830
        return {
831
          btn : t,
832
          collapse : c
833
        };
834
      },
835

    
836
      this.getClosest = function (el, s) { //el is the element and s the selector of the closest item to find
837
      // source http://gomakethings.com/climbing-up-and-down-the-dom-tree-with-vanilla-javascript/
838
        var f = s.charAt(0);
839
        for ( ; el && el !== document; el = el.parentNode ) {// Get closest match
840
          if ( f === '.' ) {// If selector is a class
841
            if ( document.querySelector(s) !== undefined ) { return el; }
842
          }
843
          if ( f === '#' ) { // If selector is an ID
844
            if ( el.id === s.substr(1) ) { return el; }
845
          }
846
        }
847
        return false;
848
      };
849
      this.addClass = function(el,c) {
850
        if (el.classList) { el.classList.add(c); } else { el.className += ' '+c; }
851
      };
852
      this.removeClass = function(el,c) {
853
        if (el.classList) { el.classList.remove(c); } else { el.className = el.className.replace(c,'').replace(/^\s+|\s+$/g,''); }
854
      };
855
    }
856
  };
857

    
858
  // COLLAPSE DATA API
859
  // =================
860
  var Collapses = document.querySelectorAll('[data-toggle="collapse"]'), i = 0, cll = Collapses.length;
861
  for (i;i<cll;i++) {
862
    var item = Collapses[i], options = {};
863
    options.duration = item.getAttribute('data-duration');
864
    new Collapse(item,options);
865
  }
866

    
867
  return Collapse;
868

    
869
});
870

    
871

    
872
(function(factory){
873

    
874
  // CommonJS/RequireJS and "native" compatibility
875
  if(typeof module !== "undefined" && typeof exports == "object") {
876
    // A commonJS/RequireJS environment
877
    if(typeof window != "undefined") {
878
      // Window and document exist, so return the factory's return value.
879
      module.exports = factory();
880
    } else {
881
      // Let the user give the factory a Window and Document.
882
      module.exports = factory;
883
    }
884
  } else {
885
    // Assume a traditional browser.
886
    window.Dropdown = factory();
887
  }
888

    
889
})(function(root){
890

    
891
  // DROPDOWN DEFINITION
892
  // ===================
893
  var Dropdown = function( element) {
894
    this.menu = typeof element === 'object' ? element : document.querySelector(element);
895
    this.init();
896
  }
897

    
898
  // DROPDOWN METHODS
899
  // ================
900
  Dropdown.prototype = {
901

    
902
    init : function() {
903
      this.actions();
904
      this.menu.setAttribute('tabindex', '0'); // Fix onblur on Chrome | Safari
905
      document.addEventListener('click', this.handle, false);
906
    },
907

    
908
    actions : function() {
909
      var self = this;
910

    
911
      this.handle = function(e) { // fix some Safari bug with <button>
912
        var target = e.target || e.currentTarget,
913
            children = [], c = self.menu.parentNode.getElementsByTagName('*');
914
        for ( var i=0, l = c.length||0; i<l; i++) { l && children.push(c[i]); }
915

    
916
        if ( target === self.menu || target.parentNode === self.menu ) {
917
          self.toggle(e);
918
        }  else if ( children && children.indexOf(target) > -1  ) {
919
          return;
920
        } else { self.close(); }
921
        /\#$/g.test(target.href) && e.preventDefault();
922
      }
923

    
924
      this.toggle = function(e) {
925
        if (/open/.test(this.menu.parentNode.className)) {
926
          this.close();
927
          document.removeEventListener('keydown', this.key, false);
928
        } else {
929
          this.menu.parentNode.className += ' open';
930
          this.menu.setAttribute('aria-expanded',true);
931
          document.addEventListener('keydown', this.key, false);
932
        }
933
      }
934

    
935
      this.key = function(e) {
936
        if (e.which == 27) {self.close();}
937
      }
938

    
939
      this.close = function() {
940
        self.menu.parentNode.className = self.menu.parentNode.className.replace(' open','');
941
        self.menu.setAttribute('aria-expanded',false);
942
      }
943
    }
944
  }
945

    
946
  // DROPDOWN DATA API
947
  // =================
948
  var Dropdowns = document.querySelectorAll('[data-toggle=dropdown]'), i = 0, ddl = Dropdowns.length;
949
  for (i;i<ddl;i++) {
950
    new Dropdown(Dropdowns[i]);
951
  }
952

    
953
  return Dropdown;
954

    
955
});
956

    
957

    
958
(function(factory){
959

    
960
  // CommonJS/RequireJS and "native" compatibility
961
  if(typeof module !== "undefined" && typeof exports == "object") {
962
    // A commonJS/RequireJS environment
963
    if(typeof window != "undefined") {
964
      // Window and document exist, so return the factory's return value.
965
      module.exports = factory();
966
    } else {
967
      // Let the user give the factory a Window and Document.
968
      module.exports = factory;
969
    }
970
  } else {
971
    // Assume a traditional browser.
972
    window.Modal = factory();
973
  }
974

    
975
})(function(){
976

    
977
  //MODAL DEFINITION
978
  var Modal = function(element, options) { // element is the trigger button / options.target is the modal
979
    options = options || {};
980
    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false;
981
    this.modal = typeof element === 'object' ? element : document.querySelector(element);
982
    this.options = {};
983
    this.options.backdrop = options.backdrop === 'false' ? false : true;
984
    this.options.keyboard = options.keyboard === 'false' ? false : true;
985
    this.options.content = options.content;
986
    this.duration = options.duration || 300; // the default modal fade duration option
987
    this.options.duration = (this.isIE && this.isIE < 10) ? 0 : this.duration;
988

    
989
    this.scrollbarWidth    = 0;
990
    this.dialog = this.modal.querySelector('.modal-dialog');
991
    this.timer = 0;
992

    
993
    this.init();
994
  };
995

    
996
  var getWindowWidth = function() {
997
    var htmlRect = document.documentElement.getBoundingClientRect(),
998
      fullWindowWidth = window.innerWidth || (htmlRect.right - Math.abs(htmlRect.left));
999
    return fullWindowWidth;
1000
  };
1001
  Modal.prototype = {
1002

    
1003
    init : function() {
1004

    
1005
      this.actions();
1006
      this.trigger();
1007
      if ( this.options.content && this.options.content !== undefined ) {
1008
        this.content( this.options.content );
1009
      }
1010
    },
1011

    
1012
    actions : function() {
1013
      var self = this;
1014
      this.open = function() {
1015
        this._open();
1016
      },
1017

    
1018
      this.close = function() {
1019
        this._close();
1020
      },
1021

    
1022
      this._open = function() {
1023
        var currentOpen = document.querySelector('.modal.in');
1024
        if (currentOpen){
1025
            clearTimeout(currentOpen.getAttribute('data-timer'));
1026
            this.removeClass(currentOpen,'in');
1027
            setTimeout( function() {
1028
              currentOpen.setAttribute('aria-hidden', true);
1029
              currentOpen.style.display = '';
1030
            }, self.options.duration/2);
1031
        }
1032

    
1033
        if ( this.options.backdrop ) {
1034
          this.createOverlay();
1035
        } else { this.overlay = null }
1036

    
1037
        if ( this.overlay ) {
1038
          setTimeout( function() {
1039
            self.addClass(self.overlay,'in');
1040
          }, 0);
1041
        }
1042

    
1043
        clearTimeout(self.modal.getAttribute('data-timer'));
1044
        this.timer = setTimeout( function() {
1045
          self.modal.style.display = 'block';
1046

    
1047
          self.checkScrollbar();
1048
          self.adjustDialog();
1049
          self.setScrollbar();
1050

    
1051
          self.resize();
1052
          self.dismiss();
1053
          self.keydown();
1054

    
1055
          self.addClass(document.body,'modal-open');
1056
          self.addClass(self.modal,'in');
1057
          self.modal.setAttribute('aria-hidden', false);
1058
        }, self.options.duration/2);
1059
        this.modal.setAttribute('data-timer',self.timer);
1060
      },
1061

    
1062
      this._close = function() {
1063

    
1064
        if ( this.overlay ) {
1065
          this.removeClass(this.overlay,'in');
1066
        }
1067
        this.removeClass(this.modal,'in');
1068
        this.modal.setAttribute('aria-hidden', true);
1069

    
1070
        clearTimeout(self.modal.getAttribute('data-timer'));
1071
        this.timer = setTimeout( function() {
1072
          self.removeClass(document.body,'modal-open');
1073
          self.resize();
1074
          self.resetAdjustments();
1075
          self.resetScrollbar();
1076

    
1077
          self.dismiss();
1078
          self.keydown();
1079
          self.modal.style.display = '';
1080
        }, self.options.duration/2);
1081
        this.modal.setAttribute('data-timer',self.timer);
1082

    
1083
        setTimeout( function() {
1084
          if (!document.querySelector('.modal.in')) {  self.removeOverlay(); }
1085
        }, self.options.duration);
1086
      },
1087

    
1088
      this.content = function( content ) {
1089
        return this.modal.querySelector('.modal-content').innerHTML = content;
1090
      },
1091

    
1092
      this.createOverlay = function() {
1093
        var backdrop = document.createElement('div'), overlay = document.querySelector('.modal-backdrop');
1094
        backdrop.setAttribute('class','modal-backdrop fade');
1095

    
1096
        if ( overlay ) {
1097
          this.overlay = overlay;
1098
        } else {
1099
          this.overlay = backdrop;
1100
          document.body.appendChild(backdrop);
1101
        }
1102
      },
1103

    
1104
      this.removeOverlay = function() {
1105
        var overlay = document.querySelector('.modal-backdrop');
1106
        if ( overlay !== null && overlay !== undefined ) {
1107
          document.body.removeChild(overlay)
1108
        }
1109
      },
1110

    
1111
      this.keydown = function() {
1112
        function keyHandler(e) {
1113
          if (self.options.keyboard && e.which == 27) {
1114
            self.close();
1115
          }
1116
        }
1117
        if (!/in/.test(this.modal.className)) {
1118
          document.addEventListener('keydown', keyHandler, false);
1119
        } else {
1120
          document.removeEventListener('keydown', keyHandler, false);
1121
        }
1122
      },
1123

    
1124
      this.trigger = function() {
1125
        var triggers = document.querySelectorAll('[data-toggle="modal"]'), tgl = triggers.length, i = 0;
1126
        for ( i;i<tgl;i++ ) {
1127
          triggers[i].addEventListener('click', function(e) {
1128
            var b = e.target,
1129
            s = b.getAttribute('data-target') && b.getAttribute('data-target').replace('#','')
1130
            || b.getAttribute('href') && b.getAttribute('href').replace('#','');
1131
            if ( document.getElementById( s ) === self.modal ) {
1132
              self.open()
1133
            }
1134
          })
1135
        }
1136
      },
1137

    
1138
      this._resize = function() {
1139
        var overlay = this.overlay||document.querySelector('.modal-backdrop'),
1140
          dim = { w: document.documentElement.clientWidth + 'px', h: document.documentElement.clientHeight + 'px' };
1141
        // setTimeout(function() {
1142
          if ( overlay !== null && /in/.test(overlay.className) ) {
1143
            overlay.style.height = dim.h; overlay.style.width = dim.w;
1144
          }
1145
        // }, self.options.duration/2)
1146
      },
1147

    
1148
      this.oneResize = function() {
1149
        function oneResize() {
1150
          self._resize();
1151
          self.handleUpdate();
1152
          window.removeEventListener('resize', oneResize, false);
1153
        }
1154
        window.addEventListener('resize', oneResize, false);
1155
      },
1156

    
1157
      this.resize = function() {
1158
        function resizeHandler() {
1159
          // setTimeout(function() {
1160
            self._resize();
1161
            self.handleUpdate();
1162
            // console.log('offresize')
1163
          // }, 100)
1164
        }
1165

    
1166
        if (!/in/.test(this.modal.className)) {
1167
          window.addEventListener('resize', this.oneResize, false);
1168
        } else {
1169
          window.removeEventListener('resize', this.oneResize, false);
1170
        }
1171

    
1172
      },
1173

    
1174
      this.dismiss = function() {
1175
        function dismissHandler(e) {
1176
          if ( e.target.parentNode.getAttribute('data-dismiss') === 'modal' || e.target.getAttribute('data-dismiss') === 'modal' || e.target === self.modal ) {
1177
            e.preventDefault(); self.close()
1178
          }
1179
        }
1180
        if (!/in/.test(this.modal.className)) {
1181
          this.modal.addEventListener('click', dismissHandler, false);
1182
        } else {
1183
          this.modal.removeEventListener('click', dismissHandler, false);
1184
        }
1185
      },
1186

    
1187
      // these following methods are used to handle overflowing modals
1188

    
1189
      this.handleUpdate = function () {
1190
        this.adjustDialog();
1191
      },
1192

    
1193
      this.adjustDialog = function () {
1194
        this.modal.style.paddingLeft = !this.bodyIsOverflowing && this.modalIsOverflowing ? this.scrollbarWidth + 'px' : '';
1195
        this.modal.style.paddingRight = this.bodyIsOverflowing && !this.modalIsOverflowing ? this.scrollbarWidth + 'px' : '';
1196
      },
1197

    
1198
      this.resetAdjustments = function () {
1199
        this.modal.style.paddingLeft = '';
1200
        this.modal.style.paddingRight = '';
1201
      },
1202

    
1203
      this.checkScrollbar = function () {
1204
        this.bodyIsOverflowing = document.body.clientWidth < getWindowWidth();
1205
        this.modalIsOverflowing = this.modal.scrollHeight > document.documentElement.clientHeight;
1206
        this.scrollbarWidth = this.measureScrollbar();
1207
      },
1208

    
1209
      this.setScrollbar = function () {
1210
        var bodyStyle = window.getComputedStyle(document.body), bodyPad = parseInt((bodyStyle.paddingRight), 10);
1211
        if (this.bodyIsOverflowing) { document.body.style.paddingRight = (bodyPad + this.scrollbarWidth) + 'px'; }
1212
        document.body.style.paddingRight = '';
1213
      },
1214

    
1215
      this.resetScrollbar = function () {
1216
        document.body.style.paddingRight = '';
1217
      },
1218

    
1219
      this.measureScrollbar = function () { // thx walsh
1220
        var scrollDiv = document.createElement('div');
1221
        scrollDiv.className = 'modal-scrollbar-measure';
1222
        document.body.appendChild(scrollDiv);
1223
        var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
1224
        document.body.removeChild(scrollDiv);
1225
        return scrollbarWidth;
1226
      },
1227

    
1228
      this.addClass = function(el,c) {
1229
        if (el.classList) { el.classList.add(c); } else { el.className += ' '+c; }
1230
      },
1231

    
1232
      this.removeClass = function(el,c) {
1233
        if (el.classList) { el.classList.remove(c); } else { el.className = el.className.replace(c,'').replace(/^\s+|\s+$/g,''); }
1234
      }
1235
    }
1236
  };
1237

    
1238
  // DATA API
1239
  var Modals = document.querySelectorAll('.modal'), mdl = Modals.length, i = 0;
1240
  for ( i;i<mdl;i++ ) {
1241
    var modal = Modals[i], options = {};
1242
    options.keyboard = modal.getAttribute('data-keyboard');
1243
    options.backdrop = modal.getAttribute('data-backdrop');
1244
    options.duration = modal.getAttribute('data-duration');
1245
    new Modal(modal,options)
1246
  }
1247

    
1248
  return Modal;
1249

    
1250
});
1251

    
1252

    
1253
(function(factory){
1254

    
1255
  // CommonJS/RequireJS and "native" compatibility
1256
  if(typeof module !== "undefined" && typeof exports == "object") {
1257
    // A commonJS/RequireJS environment
1258
    if(typeof window != "undefined") {
1259
      // Window and document exist, so return the factory's return value.
1260
      module.exports = factory();
1261
    } else {
1262
      // Let the user give the factory a Window and Document.
1263
      module.exports = factory;
1264
    }
1265
  } else {
1266
    // Assume a traditional browser.
1267
    window.Popover = factory();
1268
  }
1269

    
1270
})(function(){
1271

    
1272
  // POPOVER DEFINITION
1273
  // ===================
1274
  var Popover = function( element,options ) {
1275
    options = options || {};
1276
    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false;
1277
    this.link = typeof element === 'object' ? element : document.querySelector(element);
1278
    this.title = this.link.getAttribute('data-title') || null;
1279
    this.content = this.link.getAttribute('data-content') || null;
1280
    this.popover = null;
1281
    this.options = {};
1282
    this.options.template = options.template ? options.template : null;
1283
    this.options.trigger = options.trigger ? options.trigger : 'hover';
1284
    this.options.animation = options.animation && options.animation !== 'true' ? options.animation : 'true';
1285
    this.options.placement = options.placement ? options.placement : 'top';
1286
    this.options.delay = parseInt(options.delay) || 100;
1287
    this.options.dismiss = options.dismiss && options.dismiss === 'true' ? true : false;
1288
    this.duration = 150;
1289
    this.options.duration = (this.isIE && this.isIE < 10) ? 0 : (options.duration || this.duration);
1290
    this.options.container = document.body;
1291
    if ( this.content || this.options.template ) this.init();
1292
    this.timer = 0 // the link own event timer
1293
    this.rect = null;
1294
  }
1295

    
1296
  // POPOVER METHODS
1297
  // ================
1298
  Popover.prototype = {
1299

    
1300
    init : function() {
1301
      this.actions();
1302
      var events = ('onmouseleave' in this.link) ? [ 'mouseenter', 'mouseleave'] : [ 'mouseover', 'mouseout' ];
1303
      if (this.options.trigger === 'hover') {
1304
        this.link.addEventListener(events[0], this.open, false);
1305
        if (!this.options.dismiss) { this.link.addEventListener(events[1], this.close, false); }
1306
      } else if (this.options.trigger === 'click') {
1307
        this.link.addEventListener('click', this.toggle, false);
1308
        if (!this.options.dismiss) { this.link.addEventListener('blur', this.close, false); }
1309
      } else if (this.options.trigger === 'focus') {
1310
        this.link.addEventListener('focus', this.toggle, false);
1311
        if (!this.options.dismiss) { this.link.addEventListener('blur', this.close, false);  }
1312
      }
1313

    
1314
      if (this.options.dismiss) {  document.addEventListener('click', this.dismiss, false); }
1315

    
1316
      if (!(this.isIE && this.isIE < 9) ) { // dismiss on window resize
1317
        window.addEventListener('resize', this.close, false );
1318
      }
1319
    },
1320

    
1321
    actions : function() {
1322
      var self = this;
1323

    
1324
      this.toggle = function(e) {
1325
        if (self.popover === null) {
1326
          self.open()
1327
        } else {
1328
          self.close()
1329
        }
1330
      },
1331
      this.open = function(e) {
1332
        clearTimeout(self.link.getAttribute('data-timer'));
1333
        self.timer = setTimeout( function() {
1334
          if (self.popover === null) {
1335
            self.createPopover();
1336
            self.stylePopover();
1337
            self.updatePopover()
1338
          }
1339
        }, self.options.duration );
1340
        self.link.setAttribute('data-timer',self.timer);
1341
      },
1342
      this.dismiss = function(e) {
1343
        if (self.popover && e.target === self.popover.querySelector('.close')) {
1344
          self.close();
1345
        }
1346
      },
1347
      this.close = function(e) {
1348
        clearTimeout(self.link.getAttribute('data-timer'));
1349
        self.timer = setTimeout( function() {
1350
          if (self.popover && self.popover !== null && /in/.test(self.popover.className)) {
1351
            self.popover.className = self.popover.className.replace(' in','');
1352
            setTimeout(function() {
1353
              self.removePopover(); // for performance/testing reasons we can keep the popovers if we want
1354
            }, self.options.duration);
1355
          }
1356

    
1357
        }, self.options.delay + self.options.duration);
1358
        self.link.setAttribute('data-timer',self.timer);
1359
      },
1360

    
1361
      //remove the popover
1362
      this.removePopover = function() {
1363
        this.popover && this.options.container.removeChild(this.popover);
1364
        this.popover = null;
1365
        this.timer = null
1366
      },
1367

    
1368
      this.createPopover = function() {
1369
        this.popover = document.createElement('div');
1370

    
1371
        if ( this.content !== null && this.options.template === null ) { //create the popover from data attributes
1372

    
1373
          this.popover.setAttribute('role','tooltip');
1374

    
1375
          var popoverArrow = document.createElement('div');
1376
          popoverArrow.setAttribute('class','arrow');
1377

    
1378
          if (this.title !== null) {
1379
            var popoverTitle = document.createElement('h3');
1380
            popoverTitle.setAttribute('class','popover-title');
1381

    
1382
            if (this.options.dismiss) {
1383
              popoverTitle.innerHTML = this.title + '<button type="button" class="close">×</button>';
1384
            } else {
1385
              popoverTitle.innerHTML = this.title;
1386
            }
1387
            this.popover.appendChild(popoverTitle);
1388
          }
1389

    
1390
          var popoverContent = document.createElement('div');
1391
          popoverContent.setAttribute('class','popover-content');
1392

    
1393
          this.popover.appendChild(popoverArrow);
1394
          this.popover.appendChild(popoverContent);
1395

    
1396
          //set popover content
1397
          if (this.options.dismiss && this.title === null) {
1398
            popoverContent.innerHTML = this.content + '<button type="button" class="close">×</button>';
1399
          } else {
1400
            popoverContent.innerHTML = this.content;
1401
          }
1402

    
1403
        } else {  // or create the popover from template
1404
          var template = document.createElement('div');
1405
          template.innerHTML = this.options.template;
1406
          this.popover.innerHTML = template.firstChild.innerHTML;
1407
        }
1408

    
1409
        //append to the container
1410
        this.options.container.appendChild(this.popover);
1411
        this.popover.style.display = 'block';
1412
      },
1413

    
1414
      this.stylePopover = function(pos) {
1415
        this.rect = this.getRect();
1416
        var placement = pos || this.options.placement;
1417
        var animation = this.options.animation === 'true' ? 'fade' : '';
1418
        this.popover.setAttribute('class','popover '+placement+' '+animation);
1419

    
1420
        var linkDim = { w: this.link.offsetWidth, h: this.link.offsetHeight }; //link real dimensions
1421

    
1422
        // all popover dimensions
1423
        var pd = this.popoverDimensions(this.popover);
1424
        var toolDim = { w : pd.w, h: pd.h }; //popover real dimensions
1425

    
1426

    
1427
        //window vertical and horizontal scroll
1428

    
1429
        var scrollYOffset = this.getScroll().y;
1430
        var scrollXOffset =  this.getScroll().x;
1431

    
1432
        //apply styling
1433
        if ( /top/.test(placement) ) { //TOP
1434
          this.popover.style.top = this.rect.top + scrollYOffset - toolDim.h + 'px';
1435
          this.popover.style.left = this.rect.left + scrollXOffset - toolDim.w/2 + linkDim.w/2 + 'px'
1436

    
1437
        } else if ( /bottom/.test(placement) ) { //BOTTOM
1438
          this.popover.style.top = this.rect.top + scrollYOffset + linkDim.h + 'px';
1439
          this.popover.style.left = this.rect.left + scrollXOffset - toolDim.w/2 + linkDim.w/2 + 'px';
1440

    
1441
        } else if ( /left/.test(placement) ) { //LEFT
1442
          this.popover.style.top = this.rect.top + scrollYOffset - toolDim.h/2 + linkDim.h/2 + 'px';
1443
          this.popover.style.left = this.rect.left + scrollXOffset - toolDim.w + 'px';
1444

    
1445
        } else if ( /right/.test(placement) ) { //RIGHT
1446
          this.popover.style.top = this.rect.top + scrollYOffset - toolDim.h/2 + linkDim.h/2 + 'px';
1447
          this.popover.style.left = this.rect.left + scrollXOffset + linkDim.w + 'px';
1448
        }
1449
      },
1450

    
1451
      this.updatePopover = function() {
1452
        var placement = null;
1453
        if ( !self.isElementInViewport(self.popover) ) {
1454
          placement = self.updatePlacement();
1455
        } else {
1456
          placement = self.options.placement;
1457
        }
1458

    
1459
        self.stylePopover(placement);
1460

    
1461
        self.popover.className += ' in';
1462
      },
1463
      this.updatePlacement = function() {
1464
        var pos = this.options.placement;
1465
        if ( /top/.test(pos) ) { //TOP
1466
          return 'bottom';
1467
        } else if ( /bottom/.test(pos) ) { //BOTTOM
1468
          return 'top';
1469
        } else if ( /left/.test(pos) ) { //LEFT
1470
          return 'right';
1471
        } else if ( /right/.test(pos) ) { //RIGHT
1472
          return 'left';
1473
        }
1474
      },
1475
      this.getRect = function() {
1476
        return this.link.getBoundingClientRect()
1477
      },
1478
      this.getScroll = function() {
1479
        return {
1480
          y : window.pageYOffset || document.documentElement.scrollTop,
1481
          x : window.pageXOffset || document.documentElement.scrollLeft
1482
        }
1483
      },
1484
      this.popoverDimensions  = function(p) {//check popover width and height
1485
        return {
1486
          w : p.offsetWidth,
1487
          h : p.offsetHeight
1488
        }
1489
      },
1490
      this.isElementInViewport = function(t) { // check if this.popover is in viewport
1491
        var r = t.getBoundingClientRect();
1492
        return (
1493
          r.top >= 0 &&
1494
          r.left >= 0 &&
1495
          r.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
1496
          r.right <= (window.innerWidth || document.documentElement.clientWidth)
1497
        )
1498
      }
1499
    }
1500
    }
1501

    
1502
  // POPOVER DATA API
1503
  // =================
1504
    var Popovers = document.querySelectorAll('[data-toggle=popover]'), i = 0, ppl = Popovers.length;
1505
  for (i;i<ppl;i++){
1506
    var item = Popovers[i], options = {};
1507
    options.trigger = item.getAttribute('data-trigger'); // click / hover / focus
1508
    options.animation = item.getAttribute('data-animation'); // true / false
1509
    options.duration = item.getAttribute('data-duration');
1510
    options.placement = item.getAttribute('data-placement');
1511
    options.dismiss = item.getAttribute('data-dismiss');
1512
    options.delay = item.getAttribute('data-delay');
1513
    new Popover(item,options);
1514
  }
1515

    
1516
  return Popover;
1517

    
1518
});
1519

    
1520

    
1521
(function(factory){
1522

    
1523
  // CommonJS/RequireJS and "native" compatibility
1524
  if(typeof module !== "undefined" && typeof exports == "object") {
1525
    // A commonJS/RequireJS environment
1526
    if(typeof window != "undefined") {
1527
      // Window and document exist, so return the factory's return value.
1528
      module.exports = factory();
1529
    } else {
1530
      // Let the user give the factory a Window and Document.
1531
      module.exports = factory;
1532
    }
1533
  } else {
1534
    // Assume a traditional browser.
1535
    window.ScrollSpy = factory();
1536
  }
1537

    
1538
})(function(){
1539

    
1540
  //SCROLLSPY DEFINITION
1541
  var ScrollSpy = function(element,item,options) {
1542
    options = options || {};
1543

    
1544
    //this is the container element we spy it's elements on
1545
    this.element = typeof element === 'object' ? element : document.querySelector(element);
1546

    
1547
    this.options = {};
1548
    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false;
1549
    // this is the UL menu component our scrollSpy object will target, configure and required by the container element
1550
    this.options.target = options.target ? (typeof options.target === 'object' ? options.target : document.querySelector(options.target)) : null;
1551

    
1552
    //we need to determine the index of each menu item
1553
    this.items = this.options.target && this.options.target.getElementsByTagName('A');
1554

    
1555
    this.item = item;
1556
    // the parent LI element
1557
    this.parent = this.item.parentNode;
1558

    
1559
    // the upper level LI ^ UL ^ LI, this is required for dropdown menus
1560
    this.parentParent = this.parent.parentNode.parentNode;
1561

    
1562
    this.tg = this.item.href && document.getElementById(this.item.getAttribute('href').replace('#',''));
1563
    this.active = false;
1564
    this.topEdge = 0;
1565
    this.bottomEdge = 0;
1566

    
1567
    //determine which is the real scrollTarget
1568
    if ( this.element.offsetHeight < this.element.scrollHeight ) { // or this.scrollHeight()
1569
      this.scrollTarget = this.element;
1570
    } else {
1571
      this.scrollTarget = window;
1572
    }
1573

    
1574
    if ( this.options.target ) {
1575
      this.init();
1576
    }
1577
  };
1578

    
1579
  //SCROLLSPY METHODS
1580
  ScrollSpy.prototype = {
1581
    init: function () {
1582
      if ( this.item.getAttribute('href') && this.item.getAttribute('href').indexOf('#') > -1 ) {
1583
        //actions
1584
        this.checkEdges();
1585
        this.refresh()
1586
        this.scrollEvent();
1587
        if (!(this.isIE && this.isIE < 9)) { this.resizeEvent(); }
1588
      }
1589
    },
1590
    topLimit: function () { // the target offset
1591
      if ( this.scrollTarget === window ) {
1592
        return this.tg.getBoundingClientRect().top + this.scrollOffset() - 5
1593
      } else {
1594
        return this.tg.offsetTop;
1595
      }
1596

    
1597
    },
1598
    bottomLimit: function () {
1599
      return this.topLimit() + this.tg.clientHeight
1600
    },
1601
    checkEdges: function () {
1602
      this.topEdge = this.topLimit();
1603
      this.bottomEdge = this.bottomLimit()
1604
    },
1605
    scrollOffset: function () {
1606
      if ( this.scrollTarget === window ) {
1607
        return window.pageYOffset || document.documentElement.scrollTop
1608
      } else {
1609
        return this.element.scrollTop
1610
      }
1611
    },
1612
    activate: function () {
1613
      if ( this.parent && this.parent.tagName === 'LI' && !/active/.test(this.parent.className) ) {
1614
        this.addClass(this.parent,'active');
1615
        if ( this.parentParent && this.parentParent.tagName === 'LI' // activate the dropdown as well
1616
          && /dropdown/.test(this.parentParent.className)
1617
          && !/active/.test(this.parentParent.className) ) { this.addClass(this.parentParent,'active'); }
1618
        this.active = true
1619
      }
1620
    },
1621
    deactivate: function () {
1622
      if ( this.parent && this.parent.tagName === 'LI' && /active/.test(this.parent.className) ) {
1623
        this.removeClass(this.parent,'active');
1624
        if ( this.parentParent && this.parentParent.tagName === 'LI' // deactivate the dropdown as well
1625
          && /dropdown/.test(this.parentParent.className)
1626
          && /active/.test(this.parentParent.className) ) { this.removeClass(this.parentParent,'active'); }
1627
        this.active = false
1628
      }
1629
    },
1630
    toggle: function () {
1631
      if ( this.active === false
1632
        && ( this.bottomEdge > this.scrollOffset() && this.scrollOffset() >= this.topEdge )) { //regular use, scroll just entered the element's topLimit or bottomLimit
1633
          this.activate();
1634
      } else if (this.active === true && (this.bottomEdge <= this.scrollOffset() && this.scrollOffset() < this.topEdge )) {
1635
        this.deactivate()
1636
      }
1637
    },
1638
    refresh : function () { // check edges again
1639
      this.deactivate();
1640
      this.checkEdges();
1641

    
1642
      this.toggle() // If any case update values again
1643
    },
1644
    scrollEvent : function(){
1645
      var self = this;
1646
      this.scrollTarget.addEventListener('scroll', onSpyScroll, false);
1647
      function onSpyScroll() {
1648
        self.refresh();
1649
      }
1650
    },
1651
    resizeEvent : function(){
1652
      var self = this;
1653
      window.addEventListener('resize', onSpyResize, false);
1654
      function onSpyResize() {
1655
        self.refresh()
1656
      }
1657
    },
1658
    scrollHeight : function() {
1659
      if ( this.scrollTarget === window ) {
1660
        return Math.max( document.body.scrollHeight, document.body.offsetHeight,
1661
          document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight );
1662
      } else {
1663
        return this.element.scrollHeight
1664
      }
1665
    },
1666
    addClass : function(el,c) {
1667
      if (el.classList) { el.classList.add(c); } else { el.className += ' '+c; }
1668
    },
1669
    removeClass : function(el,c) {
1670
      if (el.classList) { el.classList.remove(c); } else { el.className = el.className.replace(c,'').replace(/^\s+|\s+$/g,''); }
1671
    }
1672
  };
1673

    
1674

    
1675
  //SCROLLSPY API
1676
  //=============
1677
  var scrollSpyes = document.querySelectorAll('[data-spy="scroll"]'), i = 0, ssl = scrollSpyes.length; // mostly is the document.body or a large container with many elements having id="not-null-id"
1678
  for (i;i<ssl;i++) {
1679
    var spy = scrollSpyes[i], options = {};
1680
    options.target = spy.getAttribute('data-target') || null;  // this must be a .nav component with id="not-null"
1681
    if ( options.target !== null ) {
1682
      var menu = options.target === 'object' ?  options.target : document.querySelector(options.target),
1683
        items = menu.querySelectorAll('a'), j = 0, il = items.length;
1684
      for (j;j<il;j++) {
1685
        var item = items[j];
1686
        if ( item.href && item.getAttribute('href') !== '#' )
1687
        new ScrollSpy(spy, item, options);
1688
      }
1689
    }
1690
  }
1691

    
1692
  return ScrollSpy;
1693

    
1694
});
1695

    
1696

    
1697
(function(factory){
1698

    
1699
  // CommonJS/RequireJS and "native" compatibility
1700
  if(typeof module !== "undefined" && typeof exports == "object") {
1701
    // A commonJS/RequireJS environment
1702
    if(typeof window != "undefined") {
1703
      // Window and document exist, so return the factory's return value.
1704
      module.exports = factory();
1705
    } else {
1706
      // Let the user give the factory a Window and Document.
1707
      module.exports = factory;
1708
    }
1709
  } else {
1710
    // Assume a traditional browser.
1711
    window.Tab = factory();
1712
  }
1713

    
1714
})(function(){
1715

    
1716
  // TAB DEFINITION
1717
  // ===================
1718
  var Tab = function( element,options ) {
1719
    options = options || {};
1720
    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false;
1721
    this.tab = typeof element === 'object' ? element : document.querySelector(element);
1722
    this.tabs = this.tab.parentNode.parentNode;
1723
    this.dropdown = this.tabs.querySelector('.dropdown');
1724
    if ( /dropdown-menu/.test(this.tabs.className) ) {
1725
      this.dropdown = this.tabs.parentNode;
1726
      this.tabs = this.tabs.parentNode.parentNode;
1727
    }
1728
    this.options = options;
1729

    
1730
    // default tab transition duration
1731
    this.duration = 150;
1732
    this.options.duration = (this.isIE && this.isIE < 10)  ? 0 : (options.duration || this.duration);
1733
    this.init();
1734
  }
1735

    
1736
  // TAB METHODS
1737
  // ================
1738
  Tab.prototype = {
1739

    
1740
    init : function() {
1741
      this.actions();
1742
      this.tab.addEventListener('click', this.action, false);
1743
    },
1744

    
1745
    actions : function() {
1746
      var self = this;
1747

    
1748
      this.action = function(e) {
1749
        e = e || window.e; e.preventDefault();
1750
        var next = e.target; //the tab we clicked is now the next tab
1751
        var nextContent = document.getElementById(next.getAttribute('href').replace('#','')); //this is the actual object, the next tab content to activate
1752
        var isDropDown = new RegExp('(?:^|\\s)'+ 'dropdown-menu' +'(?!\\S)');
1753

    
1754
        // get current active tab and content
1755
        var activeTab = self.getActiveTab();
1756
        var activeContent = self.getActiveContent();
1757

    
1758
        if ( !/active/.test(next.parentNode.className) ) {
1759
          // toggle "active" class name
1760
          self.removeClass(activeTab,'active');
1761
          self.addClass(next.parentNode,'active');
1762

    
1763
          // handle dropdown menu "active" class name
1764
          if ( self.dropdown ) {
1765
            if ( !(isDropDown.test(self.tab.parentNode.parentNode.className)) ) {
1766
              if (/active/.test(self.dropdown.className)) self.removeClass(self.dropdown,'active');
1767
            } else {
1768
              if (!/active/.test(self.dropdown.className)) self.addClass(self.dropdown,'active');
1769
            }
1770
          }
1771

    
1772
          //1. hide current active content first
1773
          self.removeClass(activeContent,'in');
1774

    
1775
          setTimeout(function() { // console.log(self)
1776
            //2. toggle current active content from view
1777
            self.removeClass(activeContent,'active');
1778
            self.addClass(nextContent,'active');
1779
          }, self.options.duration);
1780
          setTimeout(function() {
1781
            //3. show next active content
1782
            self.addClass(nextContent,'in');
1783
          }, self.options.duration*2);
1784
        }
1785
      },
1786
      this.addClass = function(el,c) {
1787
        if (el.classList) { el.classList.add(c); } else { el.className += ' '+c; }
1788
      },
1789
      this.removeClass = function(el,c) {
1790
        if (el.classList) { el.classList.remove(c); } else { el.className = el.className.replace(c,'').replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,''); }
1791
      },
1792
      this.getActiveTab = function() {
1793
        var activeTabs = this.tabs.querySelectorAll('.active');
1794
        if ( activeTabs.length === 1 && !/dropdown/.test(activeTabs[0].className) ) {
1795
          return activeTabs[0]
1796
        } else if ( activeTabs.length > 1 ) {
1797
          return activeTabs[activeTabs.length-1]
1798
        }
1799
      },
1800
      this.getActiveContent = function() {
1801
        var a = this.getActiveTab().getElementsByTagName('A')[0].getAttribute('href').replace('#','');
1802
        return a && document.getElementById(a)
1803
      }
1804
    }
1805
  }
1806

    
1807

    
1808
  // TAB DATA API
1809
  // =================
1810
    var Tabs = document.querySelectorAll("[data-toggle='tab'], [data-toggle='pill']"), tbl = Tabs.length, i=0;
1811
  for ( i;i<tbl;i++ ) {
1812
    var tab = Tabs[i], options = {};
1813
    options.duration = tab.getAttribute('data-duration') && tab.getAttribute('data-duration') || false;
1814
    new Tab(tab,options);
1815
  }
1816

    
1817
  return Tab;
1818

    
1819
});
1820

    
1821

    
1822
(function(factory){
1823

    
1824
  // CommonJS/RequireJS and "native" compatibility
1825
  if(typeof module !== "undefined" && typeof exports == "object") {
1826
    // A commonJS/RequireJS environment
1827
    if(typeof window != "undefined") {
1828
      // Window and document exist, so return the factory's return value.
1829
      module.exports = factory();
1830
    } else {
1831
      // Let the user give the factory a Window and Document.
1832
      module.exports = factory;
1833
    }
1834
  } else {
1835
    // Assume a traditional browser.
1836
    window.Tooltip = factory();
1837
  }
1838

    
1839
})(function(root){
1840

    
1841
  // TOOLTIP DEFINITION
1842
  // ===================
1843
  var Tooltip = function( element,options ) {
1844
    options = options || {};
1845

    
1846
    this.link = typeof element === 'object' ? element : document.querySelector(element);
1847
    this.title = this.link.getAttribute('title') || this.link.getAttribute('data-original-title');
1848
    this.tooltip = null;
1849
    this.options = {};
1850
    this.options.animation = options.animation && options.animation !== 'fade' ? options.animation : 'fade';
1851
    this.options.placement = options.placement ? options.placement : 'top';
1852
    this.options.delay = parseInt(options.delay) || 100;
1853
    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false;
1854
    this.duration = 150;
1855
    this.options.duration = this.isIE && this.isIE < 10 ? 0 : (options.duration || this.duration);
1856
    this.options.container = options.container || document.body;
1857
    if ( this.title ) this.init();
1858
    this.timer = 0 // the link own event timer
1859
  }
1860

    
1861
  // TOOLTIP METHODS
1862
  // ================
1863
  Tooltip.prototype = {
1864

    
1865
    init : function() {
1866
      this.actions();
1867
      this.rect = null;
1868
      var events = ('onmouseleave' in this.link) ? [ 'mouseenter', 'mouseleave'] : [ 'mouseover', 'mouseout' ];
1869
      this.link.addEventListener(events[0], this.open, false);
1870
      this.link.addEventListener(events[1], this.close, false);
1871

    
1872
      //remove title from link
1873
      this.link.setAttribute('data-original-title',this.title);
1874
      this.link.removeAttribute('title');
1875

    
1876
    },
1877

    
1878
    actions : function() {
1879
      var self = this;
1880

    
1881
      this.open = function(e) {
1882
        clearTimeout(self.link.getAttribute('data-timer'));
1883
        self.timer = setTimeout( function() {
1884
          if (self.tooltip === null) {
1885
            self.createToolTip();
1886
            self.styleTooltip();
1887
            self.updateTooltip()
1888
          }
1889
        }, self.options.duration );
1890
        self.link.setAttribute('data-timer',self.timer);
1891
      },
1892

    
1893
      this.close = function(e) {
1894
        clearTimeout(self.link.getAttribute('data-timer'));
1895
        self.timer = setTimeout( function() {
1896
          if (self.tooltip && self.tooltip !== null) {
1897
            self.tooltip.className = self.tooltip.className.replace(' in','');
1898
            setTimeout(function() {
1899
              self.removeToolTip(); // for performance/testing reasons we can keep the tooltips if we want
1900
            }, self.options.duration);
1901
          }
1902

    
1903
        }, self.options.delay + self.options.duration);
1904
        self.link.setAttribute('data-timer',self.timer);
1905
      },
1906

    
1907
      //remove the tooltip
1908
      this.removeToolTip = function() {
1909
        this.tooltip && this.options.container.removeChild(this.tooltip);
1910
        this.tooltip = null;
1911
      },
1912

    
1913
      //create the tooltip structure
1914
      this.createToolTip = function() {
1915
        this.tooltip = document.createElement('div');
1916
        this.tooltip.setAttribute('role','tooltip');
1917

    
1918
        var tooltipArrow = document.createElement('div');
1919
        tooltipArrow.setAttribute('class','tooltip-arrow');
1920
        var tooltipInner = document.createElement('div');
1921
        tooltipInner.setAttribute('class','tooltip-inner');
1922

    
1923
        this.tooltip.appendChild(tooltipArrow);
1924
        this.tooltip.appendChild(tooltipInner);
1925

    
1926
        //set tooltip content
1927
        tooltipInner.innerHTML = this.title;
1928

    
1929
        //append to the container
1930
        this.options.container.appendChild(this.tooltip);
1931
      },
1932

    
1933
      this.styleTooltip = function(pos) {
1934
        this.rect = this.getRect();
1935
        var placement = pos || this.options.placement;
1936
        this.tooltip.setAttribute('class','tooltip '+placement+' '+this.options.animation);
1937

    
1938
        var linkDim = { w: this.link.offsetWidth, h: this.link.offsetHeight }; //link real dimensions
1939

    
1940
        // all tooltip dimensions
1941
        var td = this.tooltipDimensions(this.tooltip);
1942
        var toolDim = { w : td.w, h: td.h }; //tooltip real dimensions
1943

    
1944
        //window vertical and horizontal scroll
1945
        var scrollYOffset = this.getScroll().y;
1946
        var scrollXOffset =  this.getScroll().x;
1947

    
1948
        //apply styling
1949
        if ( /top/.test(placement) ) { //TOP
1950
          this.tooltip.style.top = this.rect.top + scrollYOffset - toolDim.h + 'px';
1951
          this.tooltip.style.left = this.rect.left + scrollXOffset - toolDim.w/2 + linkDim.w/2 + 'px'
1952

    
1953
        } else if ( /bottom/.test(placement) ) { //BOTTOM
1954
          this.tooltip.style.top = this.rect.top + scrollYOffset + linkDim.h + 'px';
1955
          this.tooltip.style.left = this.rect.left + scrollXOffset - toolDim.w/2 + linkDim.w/2 + 'px';
1956

    
1957
        } else if ( /left/.test(placement) ) { //LEFT
1958
          this.tooltip.style.top = this.rect.top + scrollYOffset - toolDim.h/2 + linkDim.h/2 + 'px';
1959
          this.tooltip.style.left = this.rect.left + scrollXOffset - toolDim.w + 'px';
1960

    
1961
        } else if ( /right/.test(placement) ) { //RIGHT
1962
          this.tooltip.style.top = this.rect.top + scrollYOffset - toolDim.h/2 + linkDim.h/2 + 'px';
1963
          this.tooltip.style.left = this.rect.left + scrollXOffset + linkDim.w + 'px';
1964
        }
1965
      },
1966

    
1967
      this.updateTooltip = function() {
1968
        var placement = null;
1969
        if ( !this.isElementInViewport(this.tooltip) ) {
1970
          placement = this.updatePlacement();
1971
        } else {
1972
          placement = this.options.placement;
1973
        }
1974

    
1975
        this.styleTooltip(placement);
1976
        this.tooltip.className += ' in';
1977
      },
1978
      this.updatePlacement = function() {
1979
        var pos = this.options.placement;
1980
        if ( /top/.test(pos) ) { //TOP
1981
          return 'bottom';
1982
        } else if ( /bottom/.test(pos) ) { //BOTTOM
1983
          return 'top';
1984
        } else if ( /left/.test(pos) ) { //LEFT
1985
          return 'right';
1986
        } else if ( /right/.test(pos) ) { //RIGHT
1987
          return 'left';
1988
        }
1989
      },
1990
      this.getRect = function() {
1991
        return this.link.getBoundingClientRect()
1992
      },
1993
      this.getScroll = function() {
1994
        return {
1995
          y : window.pageYOffset || document.documentElement.scrollTop,
1996
          x : window.pageXOffset || document.documentElement.scrollLeft
1997
        }
1998
      },
1999
      this.tooltipDimensions  = function(t) {//check tooltip width and height
2000
        return {
2001
          w : t.offsetWidth,
2002
          h : t.offsetHeight
2003
        }
2004
      },
2005
      this.isElementInViewport = function(t) { // check if this.tooltip is in viewport
2006
        var r = t.getBoundingClientRect();
2007
        return (
2008
          r.top >= 0 &&
2009
          r.left >= 0 &&
2010
          r.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
2011
          r.right <= (window.innerWidth || document.documentElement.clientWidth)
2012
        )
2013
      }
2014
    }
2015
  }
2016

    
2017
  // TOOLTIP DATA API
2018
  // =================
2019
  var Tooltips = document.querySelectorAll('[data-toggle=tooltip]'), i = 0, tpl = Tooltips.length;
2020
  for (i;i<tpl;i++){
2021
    var item = Tooltips[i], options = {};
2022
    options.animation = item.getAttribute('data-animation');
2023
    options.placement = item.getAttribute('data-placement');
2024
    options.duration = item.getAttribute('data-duration');
2025
    options.delay = item.getAttribute('data-delay');
2026
    new Tooltip(item,options);
2027
  }
2028

    
2029
  return Tooltip;
2030

    
2031
});
(10-10/17)