diff --git a/js/bootstrap-native.js b/js/bootstrap-native.js
index 8af3e83931e3e6d0cf31f5e028903e42dd714ca3..1e7d57cc2acd0822d692e946d211045637246493 100644
--- a/js/bootstrap-native.js
+++ b/js/bootstrap-native.js
@@ -1,147 +1,155 @@
 // Native Javascript for Bootstrap 3
 // by dnp_theme
 
-(function(){
-
-  // UTILITIES
-  var addClass = function(el,c) { // where modern browsers fail, use classList
-      if (el.classList) { el.classList.add(c); } else { el.className += ' '+c; el.offsetWidth; }
-    },
-    removeClass = function(el,c) {
-      if (el.classList) { el.classList.remove(c); } else { el.className = el.className.replace(c,'').replace(/^\s+|\s+$/g,''); }
-    },
-    isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false,
-    getClosest = function (el, s) { //el is the element and s the selector of the closest item to find
-    // source http://gomakethings.com/climbing-up-and-down-the-dom-tree-with-vanilla-javascript/
-      var f = s.charAt(0);
-      for ( ; el && el !== document; el = el.parentNode ) {// Get closest match
-        if ( f === '.' ) {// If selector is a class
-          if ( document.querySelector(s) !== undefined ) { return el; }
-        }
-        if ( f === '#' ) { // If selector is an ID
-          if ( el.id === s.substr(1) ) { return el; }
-        }
-      }
-      return false;
-    },
-    isElementInViewport = function(t) { // check if this.tooltip is in viewport
-      var r = t.getBoundingClientRect();
-      return (
-        r.top >= 0 &&
-        r.left >= 0 &&
-        r.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
-        r.right <= (window.innerWidth || document.documentElement.clientWidth)
-      )
-    };
+(function(factory){
+
+  // CommonJS/RequireJS and "native" compatibility
+  if(typeof module !== "undefined" && typeof exports == "object") {
+    // A commonJS/RequireJS environment
+    if(typeof window != "undefined") {
+      // Window and document exist, so return the factory's return value.
+      module.exports = factory();
+    } else {
+      // Let the user give the factory a Window and Document.
+      module.exports = factory;
+    }
+  } else {
+    // Assume a traditional browser.
+    window.Affix = factory();
+  }
 
+})(function(){
 
   //AFFIX DEFINITION
-  var Affix = window.Affix = function(element,options) {
+  var Affix = function(element,options) {
     options = options || {};
-
+    
     this.element = typeof element === 'object' ? element : document.querySelector(element);
     this.options = {};
     this.options.target = options.target ? ((typeof(options.target) === 'object') ? options.target : document.querySelector(options.target)) : null; // target is an object
     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
     this.options.offsetBottom = options.offsetBottom && options.offsetBottom ? ( options.offsetBottom === 'function' ? options.offsetBottom() : parseInt(options.offsetBottom,0) ) : null;
 
-    if (!this.element && !(this.options.target || this.options.offsetTop || this.options.offsetBottom ) ) { return; }
+    if (this.element && (this.options.target || this.options.offsetTop || this.options.offsetBottom ) ) { this.init(); }
+  }
 
-    var self = this;
+  //AFFIX METHODS
+  Affix.prototype = {
+    init: function () {
+      this.affixed = false;
+      this.affixedBottom = false;
+      this.getPinOffsetTop = 0;
+      this.getPinOffsetBottom = null;
 
-    this.processOffsetTop = function () {
+      //actions
+      this.checkPosition();
+      this.updateAffix();
+      this.scrollEvent();
+      this.resizeEvent()
+    },
+    processOffsetTop: function () {
       if ( this.options.target !== null ) {
-        return this.options.target.getBoundingClientRect().top + this.scrollOffset();
+        return this.targetRect().top + this.scrollOffset();
       } else if ( this.options.offsetTop !== null ) {
         return this.options.offsetTop
       }
-    }
-    this.processOffsetBottom = function () {
+    },
+    processOffsetBottom: function () {
       if ( this.options.offsetBottom !== null ) {
         var maxScroll = this.getMaxScroll();
-        return maxScroll - this.element.offsetHeight - this.options.offsetBottom
+        return maxScroll - this.elementHeight() - this.options.offsetBottom
       }
-    }
-    this.checkPosition = function () {
-      this.getPinOffsetTop = this.processOffsetTop
-      this.getPinOffsetBottom = this.processOffsetBottom
-    }
-    this.scrollOffset = function () {
+    },
+    offsetTop: function () {
+      return this.processOffsetTop()
+    },
+    offsetBottom: function () {
+      return this.processOffsetBottom()
+    },
+    checkPosition: function () {
+      this.getPinOffsetTop = this.offsetTop
+      this.getPinOffsetBottom = this.offsetBottom
+    },
+    scrollOffset: function () {
       return window.pageYOffset || document.documentElement.scrollTop
-    }
-    this.pinTop = function () {
+    },
+    pinTop: function () {
       if ( !/\baffix/.test(this.element.className) ) {
         this.element.className += ' affix';
         this.affixed = true
       }
-    }
-    this.unPinTop = function () {
+    },
+    unPinTop: function () {
       if ( /\baffix/.test(this.element.className) ) {
         this.element.className = this.element.className.replace(' affix','');
         this.affixed = false
       }
-    }
-    this.pinBottom = function () {
+    },
+    pinBottom: function () {
       if ( !/\baffix-bottom/.test(this.element.className) ) {
         this.element.className += ' affix-bottom';
         this.affixedBottom = true
       }
-    }
-    this.unPinBottom = function () {
-      if ( /\baffix-bottom/.test(this.element.className) ) {
+    },
+    unPinBottom: function () {
+      if ( /\baffix-bottom/.test(this.element.className) ) { 
         this.element.className = this.element.className.replace(' affix-bottom','');
         this.affixedBottom = false
       }
-    }
-    this.updatePin = function () {
-      if (this.affixed === false && (parseInt(this.processOffsetTop(),0) - parseInt(this.scrollOffset(),0) < 0)) {
+    },
+    updatePin: function () {
+      if (this.affixed === false && (parseInt(this.offsetTop(),0) - parseInt(this.scrollOffset(),0) < 0)) {
         this.pinTop();
       } else if (this.affixed === true && (parseInt(this.scrollOffset(),0) <= parseInt(this.getPinOffsetTop(),0) )) {
         this.unPinTop()
       }
 
-      if (this.affixedBottom === false && (parseInt(this.processOffsetBottom(),0) - parseInt(this.scrollOffset(),0) < 0)) {
+      if (this.affixedBottom === false && (parseInt(this.offsetBottom(),0) - parseInt(this.scrollOffset(),0) < 0)) {
         this.pinBottom();
       } else if (this.affixedBottom === true && (parseInt(this.scrollOffset(),0) <= parseInt(this.getPinOffsetBottom(),0) )) {
         this.unPinBottom()
       }
-    }
-    this.updateAffix = function () { // Unpin and check position again
+    },
+
+    updateAffix : function () { // Unpin and check position again
       this.unPinTop();
       this.unPinBottom();
       this.checkPosition()
 
       this.updatePin() // If any case update values again
-    }
-    this.getMaxScroll = function(){
-      return Math.max( document.body.scrollHeight, document.body.offsetHeight,
+    },
+
+    elementHeight : function(){
+      return this.element.offsetHeight
+    },
+
+    targetRect : function(){
+      return this.options.target.getBoundingClientRect()
+    },
+
+    getMaxScroll : function(){
+      return Math.max( document.body.scrollHeight, document.body.offsetHeight, 
         document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight )
-    }
-    this.scrollEvent = function(){
+    },
+
+    scrollEvent : function(){
+      var self = this;
       window.addEventListener('scroll', function() {
         self.updatePin()
       }, false);
 
-    }
-    this.resizeEvent = function(){
-      var dl = (isIE && isIE < 10) ? 500 : 50;
+    },
+    resizeEvent : function(){
+      var self = this, 
+        isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false, 
+        dl = (isIE && isIE < 10) ? 500 : 50;
       window.addEventListener('resize', function () {
         setTimeout(function(){
           self.updateAffix()
         },dl);
       }, false);
+
     }
-    // init
-    this.affixed = false;
-    this.affixedBottom = false;
-    this.getPinOffsetTop = 0;
-    this.getPinOffsetBottom = null;
-
-    //actions
-    this.checkPosition();
-    this.updateAffix();
-    this.scrollEvent();
-    this.resizeEvent()
   };
 
   // AFFIX DATA API
@@ -149,159 +157,263 @@
   var Affixes = document.querySelectorAll('[data-spy="affix"]'), i = 0, afl = Affixes.length;
   for (i;i<afl;i++) {
     var item = Affixes[i], options = {};
-      options.offsetTop     = item.getAttribute('data-offset-top');
+      options.offsetTop    = item.getAttribute('data-offset-top');
       options.offsetBottom  = item.getAttribute('data-offset-bottom');
-      options.target        = item.getAttribute('data-target');
+      options.target      = item.getAttribute('data-target');
 
     if ( item && (options.offsetTop !== null || options.offsetBottom !== null || options.target !== null) ) { //don't do anything unless we have something valid to pin
       new Affix(item, options);
     }
   }
 
+  return Affix;
+});
+
+
+(function(factory){
+
+  // CommonJS/RequireJS and "native" compatibility
+  if(typeof module !== "undefined" && typeof exports == "object") {
+    // A commonJS/RequireJS environment
+    if(typeof window != "undefined") {
+      // Window and document exist, so return the factory's return value.
+      module.exports = factory();
+    } else {
+      // Let the user give the factory a Window and Document.
+      module.exports = factory;
+    }
+  } else {
+    // Assume a traditional browser.
+    window.Alert = factory();
+  }
+
+})(function(root){
 
   // ALERT DEFINITION
   // ===================
-  var Alert = window.Alert = function( element ) {
+  var Alert = function( element ) {
     this.btn = typeof element === 'object' ? element : document.querySelector(element);
     this.alert = null;
     this.duration = 150; // default alert transition duration
+    this.init();
+  }
 
-    var self = this;
+  // ALERT METHODS
+  // ================
+  Alert.prototype = {
 
-    this.close = function(e) {
-      var target = e.target;
-      self.btn = target.getAttribute('data-dismiss') === 'alert' && target.className === 'close' ? target : target.parentNode;
-      self.alert = self.btn.parentNode;
+    init : function() {
+      this.actions();
+      document.addEventListener('click', this.close, false); //delegate to all alerts, including those inserted later into the DOM
+    },
+
+    actions : function() {
+      var self = this;
+
+      this.close = function(e) {
+        var target = e.target;
+        self.btn = target.getAttribute('data-dismiss') === 'alert' && target.className === 'close' ? target : target.parentNode;
+        self.alert = self.btn.parentNode;
+
+        if ( self.alert !== null && self.btn.getAttribute('data-dismiss') === 'alert' && /\bin/.test(self.alert.className) ) {
+          self.alert.className = self.alert.className.replace(' in','');
+          setTimeout(function() {
+            self.alert && self.alert.parentNode.removeChild(self.alert);
+          }, self.duration);
+        }
 
-      if ( self.alert !== null && self.btn.getAttribute('data-dismiss') === 'alert' && /\bin/.test(self.alert.className) ) {
-        self.alert.className = self.alert.className.replace(' in','');
-        setTimeout(function() {
-          self.alert && self.alert.parentNode.removeChild(self.alert);
-        }, self.duration);
       }
     }
-    document.addEventListener('click', this.close, false); //delegate to all alerts, including those inserted later into the DOM
-  };
+    }
+
   // ALERT DATA API
   // =================
-  var Alerts = document.querySelectorAll('[data-dismiss="alert"]'), i = 0, all = Alerts.length;
+    var Alerts = document.querySelectorAll('[data-dismiss="alert"]'), i = 0, all = Alerts.length;
   for (i;i<all;i++) {
     new Alert(Alerts[i]);
   }
 
+  return Alert;
+
+});
+
+
+(function(factory){
+
+  // CommonJS/RequireJS and "native" compatibility
+  if(typeof module !== "undefined" && typeof exports == "object") {
+    // A commonJS/RequireJS environment
+    if(typeof window != "undefined") {
+      // Window and document exist, so return the factory's return value.
+      module.exports = factory();
+    } else {
+      // Let the user give the factory a Window and Document.
+      module.exports = factory;
+    }
+  } else {
+    // Assume a traditional browser.
+    window.Button = factory();
+  }
+
+})(function(){
 
   // BUTTON DEFINITION
   // ===================
-  var Button = window.Button = function( element, option ) {
+  var Button = function( element, option ) {
     this.btn = typeof element === 'object' ? element : document.querySelector(element);
     this.option = typeof option === 'string' ? option : null;
 
-    var self = this,
-      changeEvent = (('CustomEvent' in window) && window.dispatchEvent)
-        ? new CustomEvent('bs.button.change') : null; // The custom event that will be triggered on demand
+    this.init();
+  };
 
-    // assign event to a trigger function
-    function triggerChange(t) { if (changeEvent) { t.dispatchEvent(changeEvent); } }
+  // BUTTON METHODS
+  // ================
+  Button.prototype = {
 
-    this.setState = function() {
-      if ( this.option === 'loading' ) {
-        addClass(this.btn,'disabled');
-        this.btn.setAttribute('disabled','disabled');
-      }
-      this.btn.innerHTML = this.state;
-    }
+    init : function() {
+      var self = this;
+      this.actions();
+
+      if ( /\bbtn/.test(this.btn.className) ) {
+        if ( this.option && this.option !== 'reset' ) {
 
-    this.reset = function() {
-      if ( /\bdisabled/.test(this.btn.className) || this.btn.getAttribute('disabled') === 'disabled' ) {
-        removeClass(this.btn,'disabled');
-        this.btn.removeAttribute('disabled');
+          this.state = this.btn.getAttribute('data-'+this.option+'-text') || null;
+
+          !this.btn.getAttribute('data-original-text') && this.btn.setAttribute('data-original-text',self.btn.innerHTML.replace(/^\s+|\s+$/g, ''));
+          this.setState();
+
+        } else if ( this.option === 'reset' ) {
+          this.reset();
+        }
       }
-      this.btn.innerHTML = this.btn.getAttribute('data-original-text');
-    }
 
-    this.toggle = function(e) {
-      var parent = e.target.parentNode,
-        label = e.target.tagName === 'LABEL' ? e.target : parent.tagName === 'LABEL' ? parent : null; // the .btn label
+      if ( /\bbtn-group/.test(this.btn.className) ) {
+        this.btn.addEventListener('click', this.toggle, false);
+      }
+    },
 
-      if ( !label ) return; //react if a label or its immediate child is clicked
+    actions : function() {
+      var self = this,
+        changeEvent = (('CustomEvent' in window) && window.dispatchEvent) 
+          ? new CustomEvent('bs.button.change') : null; // The custom event that will be triggered on demand
 
-      var target = this, //e.currentTarget || e.srcElement; // the button group, the target of the handler function
-        labels = target.querySelectorAll('.btn'), ll = labels.length, i = 0, // all the button group buttons
-        input = label.getElementsByTagName('INPUT')[0];
+      // assign event to a trigger function
+      function triggerChange(t) { if (changeEvent) { t.dispatchEvent(changeEvent); } }
 
-      if ( !input ) return; //return if no input found
+      this.setState = function() {
+        if ( this.option === 'loading' ) {
+          this.addClass(this.btn,'disabled');          
+          this.btn.setAttribute('disabled','disabled');
+        }
+        this.btn.innerHTML = this.state;
+      },
 
-      //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;
+      this.reset = function() {
+        if ( /\bdisabled/.test(self.btn.className) || self.btn.getAttribute('disabled') === 'disabled' ) {
+          this.removeClass(this.btn,'disabled');  
+          self.btn.removeAttribute('disabled');
         }
-        triggerChange(input); //trigger the change for the input
-        triggerChange(self.btn); //trigger the change for the btn-group
-      }
+        self.btn.innerHTML = self.btn.getAttribute('data-original-text');
+      },
 
-      if ( input.type === 'radio' ) { // radio buttons
-        if ( !input.checked ) { // don't trigger if already active
-          addClass(label,'active');
-          input.setAttribute('checked','checked');
-          input.checked = true;
-          triggerChange(self.btn);
-          triggerChange(input); //trigger the change
-
-          for (i;i<ll;i++) {
-            var l = labels[i];
-            if ( l !== label && /\bactive/.test(l.className) )  {
-              var inp = l.getElementsByTagName('INPUT')[0];
-              removeClass(l,'active');
-              inp.removeAttribute('checked');
-              inp.checked = false;
-              triggerChange(inp); // trigger the change
-            }
+      this.toggle = function(e) {
+        var parent = e.target.parentNode,
+          label = e.target.tagName === 'LABEL' ? e.target : parent.tagName === 'LABEL' ? parent : null; // the .btn label
+        
+        if ( !label ) return; //react if a label or its immediate child is clicked
+        
+        var target = this, //e.currentTarget || e.srcElement; // the button group, the target of the handler function
+          labels = target.querySelectorAll('.btn'), ll = labels.length, i = 0, // 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 ) {
+            self.addClass(label,'active');
+            input.getAttribute('checked');          
+            input.setAttribute('checked','checked');
+            input.checked = true;
+          } else {
+            self.removeClass(label,'active');
+            input.getAttribute('checked');            
+            input.removeAttribute('checked');
+            input.checked = false;
           }
+          triggerChange(input); //trigger the change for the input
+          triggerChange(self.btn); //trigger the change for the btn-group
         }
-      }
-    }
-    // init
-    if ( /\bbtn/.test(this.btn.className) ) {
-      if ( this.option && this.option !== 'reset' ) {
-
-        this.state = this.btn.getAttribute('data-'+this.option+'-text') || null;
 
-        !this.btn.getAttribute('data-original-text') && this.btn.setAttribute('data-original-text',self.btn.innerHTML.replace(/^\s+|\s+$/g, ''));
-        this.setState();
-
-      } else if ( this.option === 'reset' ) {
-        this.reset();
+        if ( input.type === 'radio' ) { // radio buttons
+          if ( !input.checked ) { // don't trigger if already active
+            self.addClass(label,'active');
+            input.setAttribute('checked','checked');
+            input.checked = true;          
+            triggerChange(self.btn);     
+            triggerChange(input); //trigger the change
+            
+            for (i;i<ll;i++) {
+              var l = labels[i];
+              if ( l !== label && /\bactive/.test(l.className) )  {
+                var inp = l.getElementsByTagName('INPUT')[0];
+                self.removeClass(l,'active');
+                inp.removeAttribute('checked');
+                inp.checked = false;
+                triggerChange(inp); // trigger the change                
+              }        
+            }
+          }                
+        }
+      },
+      this.addClass = function(el,c) { // where modern browsers fail, use classList  
+        if (el.classList) { el.classList.add(c); } else { el.className += ' '+c; el.offsetWidth; }
+      },
+      this.removeClass = function(el,c) {
+        if (el.classList) { el.classList.remove(c); } else { el.className = el.className.replace(c,'').replace(/^\s+|\s+$/g,''); el.offsetWidth; }
       }
     }
-    if ( /\bbtn-group/.test(this.btn.className) ) {
-      this.btn.addEventListener('click', this.toggle, false);
     }
-  };
+
   // BUTTON DATA API
   // =================
-  var Buttons = document.querySelectorAll('[data-toggle=button]'), i = 0, btl = Buttons.length;
+    var Buttons = document.querySelectorAll('[data-toggle=button]'), i = 0, btl = Buttons.length;
   for (i;i<btl;i++) {
     new Button(Buttons[i]);
   }
-
+  
   var ButtonGroups = document.querySelectorAll('[data-toggle=buttons]'), j = 0, bgl = ButtonGroups.length;
   for (j;j<bgl;j++) {
     new Button(ButtonGroups[j]);
   }
 
+  return Button;
+
+});
+
+
+(function(factory){
+
+  // CommonJS/RequireJS and "native" compatibility
+  if(typeof module !== "undefined" && typeof exports == "object") {
+    // A commonJS/RequireJS environment
+    if(typeof window != "undefined") {
+      // Window and document exist, so return the factory's return value.
+      module.exports = factory();
+    } else {
+      // Let the user give the factory a Window and Document.
+      module.exports = factory;
+    }
+  } else {
+    // Assume a traditional browser.
+    window.Carousel = factory();
+  }
+
+})(function(){
 
   // CAROUSEL DEFINITION
   // ===================
-  var Carousel = window.Carousel = function( element, options ) {
+  var Carousel = function( element, options ) {
     options = options || {};
 
     this.carousel = (typeof element === 'object') ? element : document.querySelector( element );
@@ -311,7 +423,8 @@
 
     // bootstrap carousel default transition duration / option
     this.duration = 600;
-    this.options.duration = (isIE && isIE < 10) ? 0 : (options.duration || this.duration);
+    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false; 
+    this.options.duration = (this.isIE && this.isIE < 10) ? 0 : (options.duration || this.duration);
 
     var items = this.carousel.querySelectorAll('.item'), il=items.length; //this is an object
     this.controls = this.carousel.querySelectorAll('.carousel-control');
@@ -325,27 +438,46 @@
     this.direction  = null;
     this.index    = 0;
 
-    var self = this;
-
     if (options.interval === 'false' ) {
       this.options.interval = false;
     } else {
       this.options.interval = parseInt(options.interval) || 5000;
     }
 
-    this.cycle = function(e) {
+    this.init();
+  };
+
+  // CAROUSEL METHODS
+  // ================
+  Carousel.prototype = {
+    init: function() {
+      if ( this.options.interval !== false ){
+        this.cycle();
+      }
+
+      if ( this.options && this.options.pause === 'hover' && this.options.interval !== false ) {
+        this.pause();
+      }
+      this.actions();
+      this._addEventListeners();
+      this.next && this.next.addEventListener( "click", function(e){e.preventDefault()}, false);
+      this.prev && this.prev.addEventListener( "click", function(e){e.preventDefault()}, false);
+    },
+    cycle: function(e) {
+      var self = this;
 
-      this.direction = 'left';
-      this.timer = setInterval(function() {
+      self.direction = 'left';
+      self.timer = setInterval(function() {
         self.index++;
         if( self.index == self.slides.length ) {
           self.index = 0;
         }
         self._slideTo( self.index, e );
 
-      }, this.options.interval);
-    }
-    this.pause = function() {
+      }, self.options.interval);
+    },
+    pause: function() {
+      var self = this;
       var pauseHandler = function () {
         if ( self.options.interval !==false && !/\bpaused/.test(self.carousel.className) ) {
           self.carousel.className += ' paused';
@@ -356,38 +488,39 @@
       var resumeHandler = function() {
         if ( self.options.interval !==false && /\bpaused/.test(self.carousel.className) ) {
           self.cycle();
-          self.carousel.className = self.carousel.className.replace(/\bpaused/,'');
+          self.carousel.className = self.carousel.className.replace(' paused','');
         }
       };
       self.carousel.addEventListener( "mouseenter", pauseHandler, false);
       self.carousel.addEventListener( "mouseleave", resumeHandler, false);
       self.carousel.addEventListener( "touchstart", pauseHandler, false);
       self.carousel.addEventListener( "touchend", resumeHandler, false);
-    }
-    this._slideTo = function( next, e ) {
-      var active = this._getActiveIndex(); // the current active
+    },
+    _slideTo: function( next, e ) {
+      var self = this;
+      var active = self._getActiveIndex(); // the current active
       //determine type
-      var direction = this.direction;
+      var direction = self.direction;
       var dr = direction === 'left' ? 'next' : 'prev';
-      var slid = null, slide = null;
-
+      var slid = null, slide=null;
+      
       //register events
       if (('CustomEvent' in window) && window.dispatchEvent) {
         slid =  new CustomEvent("slid.bs.carousel");
         slide = new CustomEvent("slide.bs.carousel");
       }
-      if (slide) { this.carousel.dispatchEvent(slide); } //here we go with the slide
+      if (slid) { self.carousel.dispatchEvent(slid); } //here we go with the slid
 
-      this._removeEventListeners();
-      clearInterval(this.timer);
-      this.timer = null;
-      this._curentPage( this.indicators[next] );
+      self._removeEventListeners();
+      clearInterval(self.timer);
+      self.timer = null;
+      self._curentPage( self.indicators[next] );
 
-      if ( /\bslide/.test(this.carousel.className) && !(isIE && isIE < 10) ) {
-        this.slides[next].className += (' '+dr);
-        this.slides[next].offsetWidth;
-        this.slides[next].className += (' '+direction);
-        this.slides[active].className += (' '+direction);
+      if ( /\bslide/.test(this.carousel.className) && !(this.isIE && this.isIE < 10) ) {
+        self.slides[next].className += (' '+dr);
+        self.slides[next].offsetWidth;
+        self.slides[next].className += (' '+direction);
+        self.slides[active].className += (' '+direction);
 
         setTimeout(function() { //we're gonna fake waiting for the animation to finish, cleaner and better
           self._addEventListeners();
@@ -402,131 +535,131 @@
           if ( self.options.interval !== false && !/\bpaused/.test(self.carousel.className) ){
             clearInterval(self.timer); self.cycle();
           }
-          if (slid) { self.carousel.dispatchEvent(slid); } //here we go with the slid
-        }, this.options.duration + 100 );
+          if (slide) { self.carousel.dispatchEvent(slide); } //here we go with the slide
+        }, self.options.duration + 100 );
       } else {
-        this.slides[next].className += ' active';
-        this.slides[next].offsetWidth;
-        this.slides[active].className = this.slides[active].className.replace(' active','');
+        self.slides[next].className += ' active';
+        self.slides[next].offsetWidth;
+        self.slides[active].className = self.slides[active].className.replace(' active','');
         setTimeout(function() {
           self._addEventListeners();
           if ( self.options.interval !== false && !/\bpaused/.test(self.carousel.className) ){
             clearInterval(self.timer); self.cycle();
           }
-          if (slid) { self.carousel.dispatchEvent(slid); } //here we go with the slid
-        }, this.options.duration + 100 );
+          if (slide) { self.carousel.dispatchEvent(slide); } //here we go with the slide
+        }, self.options.duration + 100 );
       }
-    }
-    this._addEventListeners = function () {
-      this.next && this.next.addEventListener( "click", this.controlsHandler, false);
-      this.prev && this.prev.addEventListener( "click", this.controlsHandler, false);
+    },
+    _addEventListeners : function () {
+      var self = this;
 
-      this.indicator && this.indicator.addEventListener( "click", this.indicatorHandler, false);
+      self.next && self.next.addEventListener( "click", self.controlsHandler, false);
+      self.prev && self.prev.addEventListener( "click", self.controlsHandler, false);
 
-      this.options.keyboard === true && window.addEventListener('keydown', this.keyHandler, false);
-    }
-    this._removeEventListeners = function () { // prevent mouse bubbles while animating
-      this.next && this.next.removeEventListener( "click", this.controlsHandler, false);
-      this.prev && this.prev.removeEventListener( "click", this.controlsHandler, false);
+      self.indicator && self.indicator.addEventListener( "click", self.indicatorHandler, false);
 
-      this.indicator && this.indicator.removeEventListener( "click", this.indicatorHandler, false);
+      self.options.keyboard === true && window.addEventListener('keydown', self.keyHandler, false);
 
-      this.options.keyboard === true && window.removeEventListener('keydown', this.keyHandler, false);
-    }
-    this._getActiveIndex = function () {
+    },
+    _removeEventListeners : function () { // prevent mouse bubbles while animating
+      var self = this;
+
+      self.next && self.next.removeEventListener( "click", self.controlsHandler, false);
+      self.prev && self.prev.removeEventListener( "click", self.controlsHandler, false);
+
+      self.indicator && self.indicator.removeEventListener( "click", self.indicatorHandler, false);
+
+      self.options.keyboard === true && window.removeEventListener('keydown', self.keyHandler, false);
+    },
+    _getActiveIndex : function () {
       return this.slides.indexOf(this.carousel.querySelector('.item.active'));
-    }
-    this._curentPage = function( p ) {
+    },
+    _curentPage: function( p ) {
       for( var i = 0; i < this.indicators.length; ++i ) {
         var a = this.indicators[i];
         a.className = "";
       }
       if (p) p.className = "active";
-    }
-    this.indicatorHandler = function(e) {
-      e.preventDefault();
-      var target = e.target;
-      var active = self._getActiveIndex(); // the current active
+    },
+    actions: function() {
+      var self = this;
+      self.indicatorHandler = function(e) {
+        e.preventDefault();
+        var target = e.target;
+        var active = self._getActiveIndex(); // the current active
+
+        if ( target && !/\bactive/.test(target.className) && target.getAttribute('data-slide-to') ) {
+          var n = parseInt( target.getAttribute('data-slide-to'), 10 );
+
+          self.index = n;
+
+          if( self.index == 0 ) {
+            self.index = 0;
+          } else if ( self.index == self.total - 1 ) {
+            self.index = self.total - 1;
+          }
 
-      if ( target && !/\bactive/.test(target.className) && target.getAttribute('data-slide-to') ) {
-        var n = parseInt( target.getAttribute('data-slide-to'), 10 );
+           //determine direction first
+          if  ( (active < self.index ) || (active === self.total - 1 && self.index === 0 ) ) {
+            self.direction = 'left'; // next
+          } else if  ( (active > self.index) || (active === 0 && self.index === self.total -1 ) ) {
+            self.direction = 'right'; // prev
+          }
+        } else { return false; }
 
-        self.index = n;
+        self._slideTo( self.index, e ); //Do the slide
 
-        if( self.index == 0 ) {
-          self.index = 0;
-        } else if ( self.index == self.total - 1 ) {
-          self.index = self.total - 1;
-        }
+      },
 
-          //determine direction first
-        if  ( (active < self.index ) || (active === self.total - 1 && self.index === 0 ) ) {
-          self.direction = 'left'; // next
-        } else if  ( (active > self.index) || (active === 0 && self.index === self.total -1 ) ) {
-          self.direction = 'right'; // prev
-        }
-      } else { return false; }
+      self.controlsHandler = function (e) {
+        var target = e.currentTarget || e.srcElement;
 
-      self._slideTo( self.index, e ); //Do the slide
-    }
-    this.controlsHandler = function (e) {
-      var target = e.currentTarget || e.srcElement;
+        if ( target === self.next ) {
+          self.index++;
+          self.direction = 'left'; //set direction first
 
-      if ( target === self.next ) {
-        self.index++;
-        self.direction = 'left'; //set direction first
+          if( self.index == self.total - 1 ) {
+            self.index = self.total - 1;
+          } else if ( self.index == self.total ){
+            self.index = 0;
+          }
+        } else if ( target === self.prev ) {
+          self.index--;
+          self.direction = 'right'; //set direction first
 
-        if( self.index == self.total - 1 ) {
-          self.index = self.total - 1;
-        } else if ( self.index == self.total ){
-          self.index = 0;
+          if( self.index == 0 ) {
+            self.index = 0;
+          } else if ( self.index < 0 ){
+            self.index = self.total - 1
+          }
         }
-      } else if ( target === self.prev ) {
-        self.index--;
-        self.direction = 'right'; //set direction first
 
-        if( self.index == 0 ) {
-          self.index = 0;
-        } else if ( self.index < 0 ){
-          self.index = self.total - 1
-        }
+        self._slideTo( self.index, e ); //Do the slide
       }
 
-      self._slideTo( self.index, e ); //Do the slide
-    }
-    this.keyHandler = function (e) {
-      switch (e.which) {
-        case 39:
-          e.preventDefault();
-          self.index++;
-          self.direction = 'left';
-          if( self.index == self.total - 1 ) { self.index = self.total - 1; } else
-          if ( self.index == self.total ){ self.index = 0 }
-          break;
-        case 37:
-          e.preventDefault();
-          self.index--;
-          self.direction = 'right';
-          if( self.index == 0 ) { self.index = 0; } else
-          if ( self.index < 0 ){ self.index = self.total - 1 }
-          break;
-        default: return;
+      self.keyHandler = function (e) {
+
+        switch (e.which) {
+          case 39:
+            e.preventDefault();
+            self.index++;
+            self.direction = 'left';
+            if( self.index == self.total - 1 ) { self.index = self.total - 1; } else
+            if ( self.index == self.total ){ self.index = 0 }
+            break;
+          case 37:
+            e.preventDefault();
+            self.index--;
+            self.direction = 'right';
+            if( self.index == 0 ) { self.index = 0; } else
+            if ( self.index < 0 ){ self.index = self.total - 1 }
+            break;
+          default: return;
+        }
+        self._slideTo( self.index, e ); //Do the slide
       }
-      self._slideTo( self.index, e ); //Do the slide
-    }
-
-    // init
-    if ( this.options.interval !== false ){
-      this.cycle();
     }
-
-    if ( this.options && this.options.pause === 'hover' && this.options.interval !== false ) {
-      this.pause();
-    }
-    this._addEventListeners();
-    this.next && this.next.addEventListener( "click", function(e){e.preventDefault()}, false);
-    this.prev && this.prev.addEventListener( "click", function(e){e.preventDefault()}, false);
-  };
+  }
 
   // CAROUSEL DATA API
   // =================
@@ -540,115 +673,172 @@
     new Carousel(c, options)
   }
 
+  return Carousel;
+
+});
+
+
+// Native Javascript for Bootstrap 3 | Collapse
+// by dnp_theme
+
+(function(factory){
+
+  // CommonJS/RequireJS and "native" compatibility
+  if(typeof module !== "undefined" && typeof exports == "object") {
+    // A commonJS/RequireJS environment
+    if(typeof window != "undefined") {
+      // Window and document exist, so return the factory's return value.
+      module.exports = factory();
+    } else {
+      // Let the user give the factory a Window and Document.
+      module.exports = factory;
+    }
+  } else {
+    // Assume a traditional browser.
+    window.Collapse = factory();
+  }
+
+})(function(){
 
   // COLLAPSE DEFINITION
   // ===================
-  var Collapse = window.Collapse = function( element, options ) {
+  var Collapse = function( element, options ) {
     options = options || {};
-
+    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false;
     this.btn = typeof element === 'object' ? element : document.querySelector(element);
     this.accordion = null;
     this.collapse = null;
     this.duration = 300; // default collapse transition duration
     this.options = {};
-    this.options.duration = (isIE && isIE < 10) ? 0 : (options.duration || this.duration);
-    var self = this;
-    var getOuterHeight = function (el) {
-      var s = el && (el.currentStyle || window.getComputedStyle(el)), // the getComputedStyle polyfill would do this for us, but we want to make sure it does
-        btp = /px/.test(s.borderTopWidth) ? Math.round(s.borderTopWidth.replace('px','')) : 0,
-        mtp = /px/.test(s.marginTop)  ? Math.round(s.marginTop.replace('px',''))    : 0,
-        mbp = /px/.test(s.marginBottom)  ? Math.round(s.marginBottom.replace('px',''))  : 0,
-        mte = /em/.test(s.marginTop)  ? Math.round(s.marginTop.replace('em','')    * parseInt(s.fontSize)) : 0,
-        mbe = /em/.test(s.marginBottom)  ? Math.round(s.marginBottom.replace('em','')  * parseInt(s.fontSize)) : 0;
-      return el.clientHeight + parseInt( btp ) + parseInt( mtp ) + parseInt( mbp ) + parseInt( mte ) + parseInt( mbe ); //we need an accurate margin value
-    };
-
-    this.toggle = function(e) {
-      e.preventDefault();
-
-      if (!/\bin/.test(self.collapse.className)) {
-        self.open();
-      } else {
-        self.close();
-      }
-    },
-    this.close = function() {
-      this._close(this.collapse);
-      addClass(this.btn,'collapsed');
+    this.options.duration = (this.isIE && this.isIE < 10) ? 0 : (options.duration || this.duration);
+    this.init();
+  };
+
+  // COLLAPSE METHODS
+  // ================
+  Collapse.prototype = {
+
+     init : function() {
+      this.actions();
+      this.addEvent();
+      this.collapse = this.getTarget();
+      this.accordion = this.btn.getAttribute('data-parent') 
+        && this.getClosest(this.btn, this.btn.getAttribute('data-parent'));
     },
-    this.open = function() {
-      this._open(this.collapse);
-      removeClass(this.btn,'collapsed');
-
-      if ( this.accordion !== null ) {
-        var active = this.accordion.querySelectorAll('.collapse.in'), al = active.length, i = 0;
-        for (i;i<al;i++) {
-          if ( active[i] !== this.collapse) this._close(active[i]);
+
+    actions : function() {
+      var self = this;
+      var getOuterHeight = function (el) {
+        var s = el && (el.currentStyle || window.getComputedStyle(el)), // the getComputedStyle polyfill would do this for us, but we want to make sure it does
+          btp = /px/.test(s.borderTopWidth) ? Math.round(s.borderTopWidth.replace('px','')) : 0,
+          mtp = /px/.test(s.marginTop)  ? Math.round(s.marginTop.replace('px',''))    : 0,
+          mbp = /px/.test(s.marginBottom)  ? Math.round(s.marginBottom.replace('px',''))  : 0,
+          mte = /em/.test(s.marginTop)  ? Math.round(s.marginTop.replace('em','')    * parseInt(s.fontSize)) : 0,
+          mbe = /em/.test(s.marginBottom)  ? Math.round(s.marginBottom.replace('em','')  * parseInt(s.fontSize)) : 0;
+        return el.clientHeight + parseInt( btp ) + parseInt( mtp ) + parseInt( mbp ) + parseInt( mte ) + parseInt( mbe ); //we need an accurate margin value
+      };
+
+      this.toggle = function(e) {
+        e.preventDefault();
+
+        if (!/\bin/.test(self.collapse.className)) {
+          self.open();
+        } else {
+          self.close();
         }
-      }
-    }
-    this._open = function(c) {
-      this.removeEvent();
-      addClass(c,'in');
-      c.setAttribute('aria-expanded','true');
-      addClass(c,'collapsing');
-      setTimeout(function() {
+      },
+      this.close = function() {
+        self._close(self.collapse);
+        self.addClass(self.btn,'collapsed');
+      },
+      this.open = function() {
+        self._open(self.collapse);
+        self.removeClass(self.btn,'collapsed');
+
+        if ( self.accordion !== null ) {
+          var active = self.accordion.querySelectorAll('.collapse.in'), al = active.length, i = 0;
+          for (i;i<al;i++) {
+            if ( active[i] !== self.collapse) self._close(active[i]);
+          }
+        }
+      },
+      this._open = function(c) {
+        self.removeEvent();
+        self.addClass(c,'in');
+        c.setAttribute('aria-expanded','true');
+        self.addClass(c,'collapsing');
+        setTimeout(function() {
+          c.style.height = self.getMaxHeight(c) + 'px'
+          c.style.overflowY = 'hidden';
+        }, 0);  
+        setTimeout(function() {
+          c.style.height = ''; 
+          c.style.overflowY = '';
+          self.removeClass(c,'collapsing');
+          self.addEvent();
+        }, self.options.duration);
+      },
+      this._close = function(c) {
+        self.removeEvent();
+        c.setAttribute('aria-expanded','false');
         c.style.height = self.getMaxHeight(c) + 'px'
-        c.style.overflowY = 'hidden';
-      }, 0);
-      setTimeout(function() {
-        c.style.height = '';
-        c.style.overflowY = '';
-        removeClass(c,'collapsing');
-        self.addEvent();
-      }, this.options.duration);
-    }
-    this._close = function(c) {
-      this.removeEvent();
-      c.setAttribute('aria-expanded','false');
-      c.style.height = this.getMaxHeight(c) + 'px'
-      setTimeout(function() {
-        c.style.height = '0px';
-        c.style.overflowY = 'hidden';
-        addClass(c,'collapsing');
-      }, 0);
-
-      setTimeout(function() {
-        removeClass(c,'collapsing');
-        removeClass(c,'in');
-        c.style.overflowY = '';
-        c.style.height = '';
-        self.addEvent();
-      }, this.options.duration);
-    }
-    this.getMaxHeight = function(l) { // get collapse trueHeight and border
-      var h = 0;
-      for (var k = 0, ll = l.children.length; k < ll; k++) {
-        h += getOuterHeight(l.children[k]);
-      }
-      return h;
-    }
-    this.removeEvent = function() {
-      this.btn.removeEventListener('click', this.toggle, false);
-    }
-    this.addEvent = function() {
-      this.btn.addEventListener('click', this.toggle, false);
-    }
-    this.getTarget = function() {
-      var t = this.btn,
-        h = t.href && t.getAttribute('href').replace('#',''),
-        d = t.getAttribute('data-target') && ( t.getAttribute('data-target') ),
-        id = h || ( d && /#/.test(d)) && d.replace('#',''),
-        cl = (d && d.charAt(0) === '.') && d, //the navbar collapse trigger targets a class
-        c = id && document.getElementById(id) || cl && document.querySelector(cl);
-      return c;
-    }
+        setTimeout(function() {
+          c.style.height = '0px';    
+          c.style.overflowY = 'hidden';
+          self.addClass(c,'collapsing');
+        }, 0);
+        
+        setTimeout(function() {
+          self.removeClass(c,'collapsing');
+          self.removeClass(c,'in'); 
+          c.style.overflowY = '';
+          c.style.height = '';          
+          self.addEvent();
+        }, self.options.duration);
+      },
+      this.getMaxHeight = function(l) { // get collapse trueHeight and border
+        var h = 0;
+        for (var k = 0, ll = l.children.length; k < ll; k++) {
+          h += getOuterHeight(l.children[k]);
+        }
+        return h;
+      },
+      this.removeEvent = function() {
+        this.btn.removeEventListener('click', this.toggle, false);
+      },
+      this.addEvent = function() {
+        this.btn.addEventListener('click', this.toggle, false);
+      },
+      this.getTarget = function() {
+        var t = this.btn,
+          h = t.href && t.getAttribute('href').replace('#',''),
+          d = t.getAttribute('data-target') && ( t.getAttribute('data-target') ),
+          id = h || ( d && /#/.test(d)) && d.replace('#',''),
+          cl = (d && d.charAt(0) === '.') && d, //the navbar collapse trigger targets a class
+          c = id && document.getElementById(id) || cl && document.querySelector(cl);
+        return c;
+      },
 
-    // init
-    this.addEvent();
-    this.collapse = this.getTarget();
-    this.accordion = this.btn.getAttribute('data-parent')
-      && getClosest(this.btn, this.btn.getAttribute('data-parent'));
+      this.getClosest = function (el, s) { //el is the element and s the selector of the closest item to find
+        // source http://gomakethings.com/climbing-up-and-down-the-dom-tree-with-vanilla-javascript/
+        var f = s.charAt(0);
+        for ( ; el && el !== document; el = el.parentNode ) {// Get closest match
+          if ( f === '.' ) {// If selector is a class
+            if ( document.querySelector(s) !== undefined ) { return el; }
+          }
+          if ( f === '#' ) { // If selector is an ID
+            if ( el.id === s.substr(1) ) { return el; }
+          }
+        }
+        return false;
+      };
+      this.addClass = function(el,c) {  
+        if (el.classList) { el.classList.add(c); } else { el.className += ' '+c; }
+      };
+      this.removeClass = function(el,c) {
+        if (el.classList) { el.classList.remove(c); } else { el.className = el.className.replace(c,'').replace(/^\s+|\s+$/g,''); }
+      };
+    }
   };
 
   // COLLAPSE DATA API
@@ -660,44 +850,83 @@
     new Collapse(item,options);
   }
 
+  return Collapse;
+
+});
+
+
+(function(factory){
+
+  // CommonJS/RequireJS and "native" compatibility
+  if(typeof module !== "undefined" && typeof exports == "object") {
+    // A commonJS/RequireJS environment
+    if(typeof window != "undefined") {
+      // Window and document exist, so return the factory's return value.
+      module.exports = factory();
+    } else {
+      // Let the user give the factory a Window and Document.
+      module.exports = factory;
+    }
+  } else {
+    // Assume a traditional browser.
+    window.Dropdown = factory();
+  }
+
+})(function(root){
 
   // DROPDOWN DEFINITION
   // ===================
-  var Dropdown = window.Modal = function( element) {
+  var Dropdown = function( element) {
     this.menu = typeof element === 'object' ? element : document.querySelector(element);
-    var self = this;
-
-    this.handle = function(e) { // fix some Safari bug with <button>
-      var target = e.target || e.currentTarget,
-          children = [], c = self.menu.parentNode.getElementsByTagName('*');
-      /\#$/g.test(target.href) && e.preventDefault();
-
-      for ( var i=0, l = c.length||0; i<l; i++) { l && children.push(c[i]); }
-      if ( target === self.menu || target.parentNode === self.menu || target.parentNode.parentNode === self.menu ) {
-        self.toggle(e);
-      }  else if ( children && children.indexOf(target) > -1  ) {
-        return;
-      } else { self.close(); }
-    }
-    this.toggle = function(e) {
-      if (/\bopen/.test(this.menu.parentNode.className)) {
-        this.close();
-        document.removeEventListener('keydown', this.key, false);
-      } else {
-        this.menu.parentNode.className += ' open';
-        this.menu.setAttribute('aria-expanded',true);
-        document.addEventListener('keydown', this.key, false);
+    this.init();
+  }
+
+  // DROPDOWN METHODS
+  // ================
+  Dropdown.prototype = {
+
+    init : function() {
+      this.actions();
+      this.menu.setAttribute('tabindex', '0'); // Fix onblur on Chrome | Safari
+      document.addEventListener('click', this.handle, false);
+    },
+
+    actions : function() {
+      var self = this;
+      
+      this.handle = function(e) { // fix some Safari bug with <button>
+        var target = e.target || e.currentTarget, 
+            children = [], c = self.menu.parentNode.getElementsByTagName('*');
+        for ( var i=0, l = c.length||0; i<l; i++) { l && children.push(c[i]); }
+
+        if ( target === self.menu || target.parentNode === self.menu || target.parentNode.parentNode === self.menu ) { 
+          self.toggle(e); 
+        }  else if ( children && children.indexOf(target) > -1  ) {
+          return;
+        } else { self.close(); }
+        /\#$/g.test(target.href) && e.preventDefault();
+      } 
+      
+      this.toggle = function(e) {
+        if (/\bopen/.test(this.menu.parentNode.className)) {
+          this.close();
+          document.removeEventListener('keydown', this.key, false);
+        } else {
+          this.menu.parentNode.className += ' open';
+          this.menu.setAttribute('aria-expanded',true);
+          document.addEventListener('keydown', this.key, false);
+        }
+      }
+      
+      this.key = function(e) {
+        if (e.which == 27) {self.close();}
+      }
+      
+      this.close = function() {
+        self.menu.parentNode.className = self.menu.parentNode.className.replace(' open','');
+        self.menu.setAttribute('aria-expanded',false);
       }
     }
-    this.key = function(e) {
-      if (e.which == 27) {self.close();}
-    }
-    this.close = function() {
-      self.menu.parentNode.className = self.menu.parentNode.className.replace(/\bopen/,'');
-      self.menu.setAttribute('aria-expanded',false);
-    }
-    this.menu.setAttribute('tabindex', '0'); // Fix onblur on Chrome | Safari
-    document.addEventListener('click', this.handle, false);
   }
 
   // DROPDOWN DATA API
@@ -707,36 +936,273 @@
     new Dropdown(Dropdowns[i]);
   }
 
+  return Dropdown;
+
+});
+
+
+(function(factory){
+
+  // CommonJS/RequireJS and "native" compatibility
+  if(typeof module !== "undefined" && typeof exports == "object") {
+    // A commonJS/RequireJS environment
+    if(typeof window != "undefined") {
+      // Window and document exist, so return the factory's return value.
+      module.exports = factory();
+    } else {
+      // Let the user give the factory a Window and Document.
+      module.exports = factory;
+    }
+  } else {
+    // Assume a traditional browser.
+    window.Modal = factory();
+  }
 
+})(function(){
+  
   //MODAL DEFINITION
-  // ===============
-  var Modal = window.Modal = function(element, options) { // element is the trigger button / options.target is the modal
+  var Modal = function(element, options) { // element is the trigger button / options.target is the modal
     options = options || {};
+    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false; 
     this.modal = typeof element === 'object' ? element : document.querySelector(element);
     this.options = {};
     this.options.backdrop = options.backdrop === 'false' ? false : true;
     this.options.keyboard = options.keyboard === 'false' ? false : true;
     this.options.content = options.content;
     this.duration = options.duration || 300; // the default modal fade duration option
-    this.options.duration = (isIE && isIE < 10) ? 0 : this.duration;
-    this.scrollbarWidth = 0;
+    this.options.duration = (this.isIE && this.isIE < 10) ? 0 : this.duration;
+
+    this.scrollbarWidth    = 0;
     this.dialog = this.modal.querySelector('.modal-dialog');
     this.timer = 0;
 
-    var self = this,
-      getWindowWidth = function() {
-        var htmlRect = document.documentElement.getBoundingClientRect(),
-          fullWindowWidth = window.innerWidth || (htmlRect.right - Math.abs(htmlRect.left));
-        return fullWindowWidth;
+    this.init();
+  };
+  
+  var getWindowWidth = function() {
+    var htmlRect = document.documentElement.getBoundingClientRect(), 
+      fullWindowWidth = window.innerWidth || (htmlRect.right - Math.abs(htmlRect.left));
+    return fullWindowWidth;
+  };
+  Modal.prototype = {
+    
+    init : function() {      
+        
+      this.actions();
+      this.trigger();  
+      if ( this.options.content && this.options.content !== undefined ) {        
+        this.content( this.options.content );
+      }
+    },
+    
+    actions : function() {
+      var self = this;
+      this.open = function() {
+        this._open();
       },
-      setScrollbar = function () {
-        var bodyStyle = window.getComputedStyle(document.body), bodyPad = parseInt((bodyStyle.paddingRight), 10);
-        if (self.bodyIsOverflowing) { document.body.style.paddingRight = (bodyPad + self.scrollbarWidth) + 'px'; }
+    
+      this.close = function() {
+        this._close();
       },
-      resetScrollbar = function () {
+    
+      this._open = function() {
+        var currentOpen = document.querySelector('.modal.in');
+        if (currentOpen){
+            clearTimeout(currentOpen.getAttribute('data-timer'));
+            this.removeClass(currentOpen,'in');
+            setTimeout( function() {
+              currentOpen.setAttribute('aria-hidden', true);
+              currentOpen.style.display = '';
+            }, self.options.duration/2);
+        }
+            
+        if ( this.options.backdrop ) {
+          this.createOverlay();
+        } else { this.overlay = null }
+        
+        if ( this.overlay ) {
+          setTimeout( function() {                                
+            self.addClass(self.overlay,'in');
+          }, 0);            
+        }
+                
+        clearTimeout(self.modal.getAttribute('data-timer'));
+        this.timer = setTimeout( function() {
+          self.modal.style.display = 'block';
+          
+          self.checkScrollbar();
+          self.adjustDialog();
+          self.setScrollbar();
+          
+          self.resize();
+          self.dismiss();
+          self.keydown();      
+          
+          self.addClass(document.body,'modal-open');
+          self.addClass(self.modal,'in');
+          self.modal.setAttribute('aria-hidden', false);
+        }, self.options.duration/2);
+        this.modal.setAttribute('data-timer',self.timer);
+      },
+    
+      this._close = function() {
+
+        if ( this.overlay ) {          
+          this.removeClass(this.overlay,'in');
+        }      
+        this.removeClass(this.modal,'in');
+        this.modal.setAttribute('aria-hidden', true);
+                
+        clearTimeout(self.modal.getAttribute('data-timer'));
+        this.timer = setTimeout( function() {
+          self.removeClass(document.body,'modal-open');
+          self.resize();
+          self.resetAdjustments();
+          self.resetScrollbar();      
+          
+          self.dismiss();
+          self.keydown();                    
+          self.modal.style.display = '';
+        }, self.options.duration/2);
+        this.modal.setAttribute('data-timer',self.timer);
+        
+        setTimeout( function() {
+          if (!document.querySelector('.modal.in')) {  self.removeOverlay(); }
+        }, self.options.duration);  
+      },
+    
+      this.content = function( content ) {
+        return this.modal.querySelector('.modal-content').innerHTML = content;
+      },
+    
+      this.createOverlay = function() {
+        var backdrop = document.createElement('div'), overlay = document.querySelector('.modal-backdrop');
+        backdrop.setAttribute('class','modal-backdrop fade');
+    
+        if ( overlay ) {
+          this.overlay = overlay;
+        } else {
+          this.overlay = backdrop;
+          document.body.appendChild(backdrop);
+        }
+      },
+    
+      this.removeOverlay = function() {
+        var overlay = document.querySelector('.modal-backdrop');
+        if ( overlay !== null && overlay !== undefined ) {
+          document.body.removeChild(overlay)
+        }
+      },
+    
+      this.keydown = function() {
+        function keyHandler(e) {
+          if (self.options.keyboard && e.which == 27) {
+            self.close();
+          }          
+        }
+        if (!/\bin/.test(this.modal.className)) {
+          document.addEventListener('keydown', keyHandler, false);
+        } else {
+          document.removeEventListener('keydown', keyHandler, false);
+        }  
+      },
+    
+      this.trigger = function() {
+        var triggers = document.querySelectorAll('[data-toggle="modal"]'), tgl = triggers.length, i = 0;
+        for ( i;i<tgl;i++ ) {
+          triggers[i].addEventListener('click', function(e) {
+            e.preventDefault();
+            var b = e.currentTarget,
+            s = b.getAttribute('data-target') && b.getAttribute('data-target').replace('#','')
+            || b.getAttribute('href') && b.getAttribute('href').replace('#','');
+            if ( document.getElementById( s ) === self.modal ) {
+              self.open()
+            }
+          })
+        }
+      },
+    
+      this._resize = function() {
+        var overlay = this.overlay||document.querySelector('.modal-backdrop'),
+          dim = { w: document.documentElement.clientWidth + 'px', h: document.documentElement.clientHeight + 'px' };
+        // setTimeout(function() {
+          if ( overlay !== null && /\bin/.test(overlay.className) ) {
+            overlay.style.height = dim.h; overlay.style.width = dim.w;
+          }
+        // }, self.options.duration/2)
+      },
+      
+      this.oneResize = function() {
+        function oneResize() {
+          self._resize();
+          self.handleUpdate();
+          window.removeEventListener('resize', oneResize, false);
+        }
+        window.addEventListener('resize', oneResize, false);      
+      },
+    
+      this.resize = function() {
+        function resizeHandler() {
+          // setTimeout(function() {
+            self._resize();
+            self.handleUpdate();
+            // console.log('offresize')
+          // }, 100)
+        }      
+
+        if (!/\bin/.test(this.modal.className)) {
+          window.addEventListener('resize', this.oneResize, false);
+        } else {
+          window.removeEventListener('resize', this.oneResize, false);
+        }
+          
+      },
+    
+      this.dismiss = function() {
+        function dismissHandler(e) {
+          if ( e.target.parentNode.getAttribute('data-dismiss') === 'modal' || e.target.getAttribute('data-dismiss') === 'modal' || e.target === self.modal ) {
+            e.preventDefault(); self.close()
+          }
+        }          
+        if (!/\bin/.test(this.modal.className)) {
+          this.modal.addEventListener('click', dismissHandler, false);
+        } else {
+          this.modal.removeEventListener('click', dismissHandler, false);
+        }  
+      },
+    
+      // these following methods are used to handle overflowing modals
+      
+      this.handleUpdate = function () {
+        this.adjustDialog(); 
+      },
+      
+      this.adjustDialog = function () {
+        this.modal.style.paddingLeft = !this.bodyIsOverflowing && this.modalIsOverflowing ? this.scrollbarWidth + 'px' : '';
+        this.modal.style.paddingRight = this.bodyIsOverflowing && !this.modalIsOverflowing ? this.scrollbarWidth + 'px' : '';
+      },
+      
+      this.resetAdjustments = function () {
+        this.modal.style.paddingLeft = '';
+        this.modal.style.paddingRight = '';
+      },
+      
+      this.checkScrollbar = function () {  
+        this.bodyIsOverflowing = document.body.clientWidth < getWindowWidth();
+        this.modalIsOverflowing = this.modal.scrollHeight > document.documentElement.clientHeight;
+        this.scrollbarWidth = this.measureScrollbar();
+      },
+      
+      this.setScrollbar = function () {
+        var bodyStyle = window.getComputedStyle(document.body), bodyPad = parseInt((bodyStyle.paddingRight), 10);
+        if (this.bodyIsOverflowing) { document.body.style.paddingRight = (bodyPad + this.scrollbarWidth) + 'px'; }
+      },
+      
+      this.resetScrollbar = function () {
         document.body.style.paddingRight = '';
       },
-      measureScrollbar = function () { // thx walsh
+      
+      this.measureScrollbar = function () { // thx walsh
         var scrollDiv = document.createElement('div');
         scrollDiv.className = 'modal-scrollbar-measure';
         document.body.appendChild(scrollDiv);
@@ -744,180 +1210,17 @@
         document.body.removeChild(scrollDiv);
         return scrollbarWidth;
       },
-      checkScrollbar = function () {
-        self.bodyIsOverflowing = document.body.clientWidth < getWindowWidth();
-        self.modalIsOverflowing = self.modal.scrollHeight > document.documentElement.clientHeight;
-        self.scrollbarWidth = measureScrollbar();
-      };
-
-    this.open = function() {
-      var currentOpen = document.querySelector('.modal.in');
-      if (currentOpen){
-        clearTimeout(currentOpen.getAttribute('data-timer'));
-        removeClass(currentOpen,'in');
-        setTimeout( function() {
-          currentOpen.setAttribute('aria-hidden', true);
-          currentOpen.style.display = '';
-        }, this.options.duration/2);
-      }
-
-      if ( this.options.backdrop ) {
-        this.createOverlay();
-      } else { this.overlay = null }
-
-      if ( this.overlay ) {
-        setTimeout( function() {
-          addClass(self.overlay,'in');
-        }, 0);
-      }
-
-      clearTimeout(self.modal.getAttribute('data-timer'));
-      this.timer = setTimeout( function() {
-        self.modal.style.display = 'block';
-
-        checkScrollbar();
-        self.adjustDialog();
-        setScrollbar();
-
-        self.resize();
-        self.dismiss();
-        self.keydown();
-
-        addClass(document.body,'modal-open');
-        addClass(self.modal,'in');
-        self.modal.setAttribute('aria-hidden', false);
-      }, this.options.duration/2);
-      this.modal.setAttribute('data-timer',this.timer);
-    }
-    this.close = function() {
-
-      if ( this.overlay ) {
-        removeClass(this.overlay,'in');
-      }
-      removeClass(this.modal,'in');
-      this.modal.setAttribute('aria-hidden', true);
-
-      clearTimeout(this.modal.getAttribute('data-timer'));
-      this.timer = setTimeout( function() {
-        removeClass(document.body,'modal-open');
-        self.resize();
-        self.resetAdjustments();
-        resetScrollbar();
-
-        self.dismiss();
-        self.keydown();
-        self.modal.style.display = '';
-      }, this.options.duration/2);
-      this.modal.setAttribute('data-timer',this.timer);
-
-      setTimeout( function() {
-        if (!document.querySelector('.modal.in')) {  self.removeOverlay(); }
-      }, this.options.duration);
-    }
-    this.content = function( content ) {
-      return this.modal.querySelector('.modal-content').innerHTML = content;
-    }
-    this.createOverlay = function() {
-      var backdrop = document.createElement('div'), overlay = document.querySelector('.modal-backdrop');
-      backdrop.setAttribute('class','modal-backdrop fade');
-
-      if ( overlay ) {
-        this.overlay = overlay;
-      } else {
-        this.overlay = backdrop;
-        document.body.appendChild(backdrop);
-      }
-    }
-    this.removeOverlay = function() {
-      var overlay = document.querySelector('.modal-backdrop');
-      if ( overlay !== null && overlay !== undefined ) {
-        document.body.removeChild(overlay)
-      }
-    }
-    this.keydown = function() {
-      function keyHandler(e) {
-        if (self.options.keyboard && e.which == 27) {
-          self.close();
-        }
-      }
-      if (!/\bin/.test(this.modal.className)) {
-        document.addEventListener('keydown', keyHandler, false);
-      } else {
-        document.removeEventListener('keydown', keyHandler, false);
-      }
-    }
-    this.trigger = function() {
-      var triggers = document.querySelectorAll('[data-toggle="modal"]'), tgl = triggers.length, i = 0;
-      for ( i;i<tgl;i++ ) {
-        triggers[i].addEventListener('click', function(e) {
-          e.preventDefault();
-          var b = this,
-          s = b.getAttribute('data-target') && b.getAttribute('data-target').replace('#','')
-          || b.getAttribute('href') && b.getAttribute('href').replace('#','');
-          if ( document.getElementById( s ) === self.modal ) {
-            self.open()
-          }
-        })
-      }
-    }
-    this._resize = function() {
-      var overlay = this.overlay||document.querySelector('.modal-backdrop'),
-        dim = { w: document.documentElement.clientWidth + 'px', h: document.documentElement.clientHeight + 'px' };
-      if ( overlay !== null && /\bin/.test(overlay.className) ) {
-        overlay.style.height = dim.h; overlay.style.width = dim.w;
-      }
-    }
-    this.oneResize = function() {
-      function oneResize() {
-        self._resize();
-        self.handleUpdate();
-        window.removeEventListener('resize', oneResize, false);
-      }
-      window.addEventListener('resize', oneResize, false);
-    }
-    this.resize = function() {
-      function resizeHandler() {
-        self._resize();
-        self.handleUpdate();
-      }
-
-      if (!/\bin/.test(this.modal.className)) {
-        window.addEventListener('resize', this.oneResize, false);
-      } else {
-        window.removeEventListener('resize', this.oneResize, false);
-      }
-    }
-    this.dismiss = function() {
-      function dismissHandler(e) {
-        if ( this.getAttribute('data-dismiss') === 'modal' || this === self.modal ) {
-            e.preventDefault(); self.close()
-        }
-      }
-      if (!/\bin/.test(this.modal.className)) {
-        this.modal.addEventListener('click', dismissHandler, false);
-      } else {
-        this.modal.removeEventListener('click', dismissHandler, false);
+      
+      this.addClass = function(el,c) {  
+        if (el.classList) { el.classList.add(c); } else { el.className += ' '+c; }
+      },
+      
+      this.removeClass = function(el,c) {
+        if (el.classList) { el.classList.remove(c); } else { el.className = el.className.replace(c,'').replace(/^\s+|\s+$/g,''); }
       }
     }
-    // these following methods are used to handle overflowing modals
-    this.handleUpdate = function () {
-      this.adjustDialog();
-    }
-    this.adjustDialog = function () {
-      this.modal.style.paddingLeft = !this.bodyIsOverflowing && this.modalIsOverflowing ? this.scrollbarWidth + 'px' : '';
-      this.modal.style.paddingRight = this.bodyIsOverflowing && !this.modalIsOverflowing ? this.scrollbarWidth + 'px' : '';
-    }
-    this.resetAdjustments = function () {
-      this.modal.style.paddingLeft = '';
-      this.modal.style.paddingRight = '';
-    }
-    //init
-    this.trigger();
-    if ( this.options.content && this.options.content !== undefined ) {
-      this.content( this.options.content );
-    }
-  };
-
+  };  
+  
   // DATA API
   var Modals = document.querySelectorAll('.modal'), mdl = Modals.length, i = 0;
   for ( i;i<mdl;i++ ) {
@@ -928,11 +1231,35 @@
     new Modal(modal,options)
   }
 
+  return Modal;
+
+});
+
+
+(function(factory){
+
+  // CommonJS/RequireJS and "native" compatibility
+  if(typeof module !== "undefined" && typeof exports == "object") {
+    // A commonJS/RequireJS environment
+    if(typeof window != "undefined") {
+      // Window and document exist, so return the factory's return value.
+      module.exports = factory();
+    } else {
+      // Let the user give the factory a Window and Document.
+      module.exports = factory;
+    }
+  } else {
+    // Assume a traditional browser.
+    window.Popover = factory();
+  }
+
+})(function(){
 
   // POPOVER DEFINITION
   // ===================
-  var Popover = window.Popover = function( element,options ) {
+  var Popover = function( element,options ) {
     options = options || {};
+    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false; 
     this.link = typeof element === 'object' ? element : document.querySelector(element);
     this.title = this.link.getAttribute('data-title') || null;
     this.content = this.link.getAttribute('data-content') || null;
@@ -943,183 +1270,225 @@
     this.options.animation = options.animation && options.animation !== 'true' ? options.animation : 'true';
     this.options.placement = options.placement ? options.placement : 'top';
     this.options.delay = parseInt(options.delay) || 100;
-    this.options.dismiss = options.dismiss && options.dismiss === 'true' ? true : false;
+    this.options.dismiss = options.dismiss && options.dismiss === 'true' ? true : false;    
     this.duration = 150;
-    this.options.duration = (isIE && isIE < 10) ? 0 : (options.duration || this.duration);
+    this.options.duration = (this.isIE && this.isIE < 10) ? 0 : (options.duration || this.duration);
     this.options.container = document.body;
-    if ( !this.content && !this.options.template ) return;
+    if ( this.content || this.options.template ) this.init();
     this.timer = 0 // the link own event timer
+    this.rect = null;
+  }
 
-    var self = this, events = ('onmouseleave' in this.link) ? [ 'mouseenter', 'mouseleave'] : [ 'mouseover', 'mouseout' ];
-
-    this.toggle = function(e) {
-      if (self.popover === null) {
-        self.open()
-      } else {
-        self.close()
+  // POPOVER METHODS
+  // ================
+  Popover.prototype = {
+
+    init : function() {
+      this.actions();
+      var events = ('onmouseleave' in this.link) ? [ 'mouseenter', 'mouseleave'] : [ 'mouseover', 'mouseout' ];
+      if (this.options.trigger === 'hover') {
+        this.link.addEventListener(events[0], this.open, false);
+        if (!this.options.dismiss) { this.link.addEventListener(events[1], this.close, false); }
+      } else if (this.options.trigger === 'click') {
+        this.link.addEventListener('click', this.toggle, false);
+        if (!this.options.dismiss) { this.link.addEventListener('blur', this.close, false); }          
+      } else if (this.options.trigger === 'focus') {
+        this.link.addEventListener('focus', this.toggle, false);
+        if (!this.options.dismiss) { this.link.addEventListener('blur', this.close, false);  }
       }
-    }
-    this.open = function(e) {
-      clearTimeout(self.link.getAttribute('data-timer'));
-      self.timer = setTimeout( function() {
+      
+      if (this.options.dismiss) {  document.addEventListener('click', this.dismiss, false); }
+        
+      if (!(this.isIE && this.isIE < 9) ) { // dismiss on window resize 
+        window.addEventListener('resize', this.close, false ); 
+      }
+    },
+
+    actions : function() {
+      var self = this;
+
+      this.toggle = function(e) {
         if (self.popover === null) {
-          self.createPopover();
-          self.stylePopover();
-          self.updatePopover()
+          self.open()
+        } else {
+          self.close()
         }
-      }, self.options.duration );
-      self.link.setAttribute('data-timer',self.timer);
-    }
-    this.dismiss = function(e) {
-      if (self.popover && e.target === self.popover.querySelector('.close')) {
-        self.close();
-      }
-    }
-    this.close = function(e) {
-      clearTimeout(self.link.getAttribute('data-timer'));
-      self.timer = setTimeout( function() {
-        if (self.popover && self.popover !== null && /\bin/.test(self.popover.className)) {
-          self.popover.className = self.popover.className.replace(' in','');
-          setTimeout(function() {
-            self.removePopover(); // for performance/testing reasons we can keep the popovers if we want
-          }, self.options.duration);
+      },
+      this.open = function(e) {
+        clearTimeout(self.link.getAttribute('data-timer'));
+        self.timer = setTimeout( function() {
+          if (self.popover === null) {
+            self.createPopover();
+            self.stylePopover();
+            self.updatePopover()
+          }
+        }, self.options.duration );
+        self.link.setAttribute('data-timer',self.timer);
+      },
+      this.dismiss = function(e) {
+        if (self.popover && e.target === self.popover.querySelector('.close')) {          
+          self.close();
         }
+      },
+      this.close = function(e) {
+        clearTimeout(self.link.getAttribute('data-timer'));
+        self.timer = setTimeout( function() {
+          if (self.popover && self.popover !== null && /\bin/.test(self.popover.className)) {
+            self.popover.className = self.popover.className.replace(' in','');
+            setTimeout(function() {
+              self.removePopover(); // for performance/testing reasons we can keep the popovers if we want
+            }, self.options.duration);
+          }
 
-      }, self.options.delay + self.options.duration);
-      self.link.setAttribute('data-timer',self.timer);
-    }
-    //remove the popover
-    this.removePopover = function() {
-      this.popover && this.options.container.removeChild(this.popover);
-      this.popover = null;
-      this.timer = null
-    }
-    this.createPopover = function() {
-      this.popover = document.createElement('div');
+        }, self.options.delay + self.options.duration);
+        self.link.setAttribute('data-timer',self.timer);
+      },
 
-      if ( this.content !== null && this.options.template === null ) { //create the popover from data attributes
+      //remove the popover
+      this.removePopover = function() {
+        this.popover && this.options.container.removeChild(this.popover);
+        this.popover = null;
+        this.timer = null
+      },
 
-        this.popover.setAttribute('role','tooltip');
+      this.createPopover = function() {
+        this.popover = document.createElement('div');
 
-        var popoverArrow = document.createElement('div');
-        popoverArrow.setAttribute('class','arrow');
+        if ( this.content !== null && this.options.template === null ) { //create the popover from data attributes
 
-        if (this.title !== null) {
-          var popoverTitle = document.createElement('h3');
-          popoverTitle.setAttribute('class','popover-title');
+          this.popover.setAttribute('role','tooltip');
 
-          if (this.options.dismiss) {
-            popoverTitle.innerHTML = this.title + '<button type="button" class="close">×</button>';
+          var popoverArrow = document.createElement('div');
+          popoverArrow.setAttribute('class','arrow');
+
+          if (this.title !== null) {
+            var popoverTitle = document.createElement('h3');
+            popoverTitle.setAttribute('class','popover-title');
+            
+            if (this.options.dismiss) {
+              popoverTitle.innerHTML = this.title + '<button type="button" class="close">×</button>';
+            } else {
+              popoverTitle.innerHTML = this.title;
+            }
+            this.popover.appendChild(popoverTitle);
+          }
+
+          var popoverContent = document.createElement('div');
+          popoverContent.setAttribute('class','popover-content');
+
+          this.popover.appendChild(popoverArrow);
+          this.popover.appendChild(popoverContent);
+
+          //set popover content
+          if (this.options.dismiss && this.title === null) {
+            popoverContent.innerHTML = this.content + '<button type="button" class="close">×</button>';
           } else {
-            popoverTitle.innerHTML = this.title;
+            popoverContent.innerHTML = this.content;
           }
-          this.popover.appendChild(popoverTitle);
+
+        } else {  // or create the popover from template
+          var template = document.createElement('div');
+          template.innerHTML = this.options.template;
+          this.popover.innerHTML = template.firstChild.innerHTML;
         }
 
-        var popoverContent = document.createElement('div');
-        popoverContent.setAttribute('class','popover-content');
+        //append to the container
+        this.options.container.appendChild(this.popover);
+        this.popover.style.display = 'block';
+      },
 
-        this.popover.appendChild(popoverArrow);
-        this.popover.appendChild(popoverContent);
+      this.stylePopover = function(pos) {
+        this.rect = this.getRect();
+        var placement = pos || this.options.placement;
+        var animation = this.options.animation === 'true' ? 'fade' : '';
+        this.popover.setAttribute('class','popover '+placement+' '+animation);
 
-        //set popover content
-        if (this.options.dismiss && this.title === null) {
-          popoverContent.innerHTML = this.content + '<button type="button" class="close">×</button>';
-        } else {
-          popoverContent.innerHTML = this.content;
-        }
+        var linkDim = { w: this.link.offsetWidth, h: this.link.offsetHeight }; //link real dimensions
 
-      } else {  // or create the popover from template
-        var template = document.createElement('div');
-        template.innerHTML = this.options.template;
-        this.popover.innerHTML = template.firstChild.innerHTML;
-      }
+        // all popover dimensions
+        var pd = this.popoverDimensions(this.popover);
+        var toolDim = { w : pd.w, h: pd.h }; //popover real dimensions
 
-      //append to the container
-      this.options.container.appendChild(this.popover);
-      this.popover.style.display = 'block';
-    }
-    this.stylePopover = function(pos) {
-      var rect = this.link.getBoundingClientRect(),
-          placement = pos || this.options.placement,
-          animation = this.options.animation === 'true' ? 'fade' : '';
 
-      this.popover.setAttribute('class','popover '+placement+' '+animation);
+        //window vertical and horizontal scroll
 
-      var ld = { w: rect.right - rect.left, h: rect.bottom - rect.top }, //link real dimensions
-          pd = { w : this.popover.offsetWidth, h: this.popover.offsetHeight }, //popover real dimensions
-          sYo = this.getScroll().y, sXo = this.getScroll().x; //window vertical and horizontal scroll
+        var scrollYOffset = this.getScroll().y;
+        var scrollXOffset =  this.getScroll().x;
 
-      //apply styling
-      if ( /top/.test(placement) ) { //TOP
-        this.popover.style.top = rect.top + sYo - pd.h + 'px';
-        this.popover.style.left = rect.left + sXo - pd.w/2 + ld.w/2 + 'px'
+        //apply styling
+        if ( /top/.test(placement) ) { //TOP
+          this.popover.style.top = this.rect.top + scrollYOffset - toolDim.h + 'px';
+          this.popover.style.left = this.rect.left + scrollXOffset - toolDim.w/2 + linkDim.w/2 + 'px'
 
-      } else if ( /bottom/.test(placement) ) { //BOTTOM
-        this.popover.style.top = rect.top + sYo + ld.h + 'px';
-        this.popover.style.left = rect.left + sXo - pd.w/2 + ld.w/2 + 'px';
+        } else if ( /bottom/.test(placement) ) { //BOTTOM
+          this.popover.style.top = this.rect.top + scrollYOffset + linkDim.h + 'px';
+          this.popover.style.left = this.rect.left + scrollXOffset - toolDim.w/2 + linkDim.w/2 + 'px';
 
-      } else if ( /left/.test(placement) ) { //LEFT
-        this.popover.style.top = rect.top + sYo - pd.h/2 + ld.h/2 + 'px';
-        this.popover.style.left = rect.left + sXo - pd.w + 'px';
+        } else if ( /left/.test(placement) ) { //LEFT
+          this.popover.style.top = this.rect.top + scrollYOffset - toolDim.h/2 + linkDim.h/2 + 'px';
+          this.popover.style.left = this.rect.left + scrollXOffset - toolDim.w + 'px';
 
-      } else if ( /right/.test(placement) ) { //RIGHT
-        this.popover.style.top = rect.top + sYo - pd.h/2 + ld.h/2 + 'px';
-        this.popover.style.left = rect.left + sXo + ld.w + 'px';
-      }
-    }
-    this.updatePopover = function() {
-      var placement = null;
-      if ( !isElementInViewport(this.popover) ) {
-        placement = this.updatePlacement();
-      } else {
-        placement = this.options.placement;
-      }
+        } else if ( /right/.test(placement) ) { //RIGHT
+          this.popover.style.top = this.rect.top + scrollYOffset - toolDim.h/2 + linkDim.h/2 + 'px';
+          this.popover.style.left = this.rect.left + scrollXOffset + linkDim.w + 'px';
+        }
+      },
 
-      this.stylePopover(placement);
-      this.popover.className += ' in';
-    }
-    this.updatePlacement = function() {
-      var pos = this.options.placement;
-      if ( /top/.test(pos) ) { //TOP
-        return 'bottom';
-      } else if ( /bottom/.test(pos) ) { //BOTTOM
-        return 'top';
-      } else if ( /left/.test(pos) ) { //LEFT
-        return 'right';
-      } else if ( /right/.test(pos) ) { //RIGHT
-        return 'left';
-      }
-    }
-    this.getScroll = function() {
-      return {
-        y : window.pageYOffset || document.documentElement.scrollTop,
-        x : window.pageXOffset || document.documentElement.scrollLeft
-      }
-    }
-    // init
-    if (this.options.trigger === 'hover') {
-      this.link.addEventListener(events[0], this.open, false);
-      if (!this.options.dismiss) { this.link.addEventListener(events[1], this.close, false); }
-    } else if (this.options.trigger === 'click') {
-      this.link.addEventListener('click', this.toggle, false);
-      if (!this.options.dismiss) { this.link.addEventListener('blur', this.close, false); }
-    } else if (this.options.trigger === 'focus') {
-      this.link.addEventListener('focus', this.toggle, false);
-      if (!this.options.dismiss) { this.link.addEventListener('blur', this.close, false);  }
-    }
+      this.updatePopover = function() {
+        var placement = null;
+        if ( !self.isElementInViewport(self.popover) ) {
+          placement = self.updatePlacement();
+        } else {
+          placement = self.options.placement;
+        }
 
-    if (this.options.dismiss) {  document.addEventListener('click', this.dismiss, false); }
+        self.stylePopover(placement);
 
-    if (!(isIE && isIE < 9) ) { // dismiss on window resize
-      window.addEventListener('resize', this.close, false );
+        self.popover.className += ' in';
+      },
+      this.updatePlacement = function() {
+        var pos = this.options.placement;
+        if ( /top/.test(pos) ) { //TOP
+          return 'bottom';
+        } else if ( /bottom/.test(pos) ) { //BOTTOM
+          return 'top';
+        } else if ( /left/.test(pos) ) { //LEFT
+          return 'right';
+        } else if ( /right/.test(pos) ) { //RIGHT
+          return 'left';
+        }
+      },
+      this.getRect = function() {
+        return this.link.getBoundingClientRect()
+      },
+      this.getScroll = function() {
+        return {
+          y : window.pageYOffset || document.documentElement.scrollTop,
+          x : window.pageXOffset || document.documentElement.scrollLeft
+        }
+      },
+      this.popoverDimensions  = function(p) {//check popover width and height
+        return {
+          w : p.offsetWidth,
+          h : p.offsetHeight
+        }
+      },
+      this.isElementInViewport = function(t) { // check if this.popover is in viewport
+        var r = t.getBoundingClientRect();
+        return (
+          r.top >= 0 &&
+          r.left >= 0 &&
+          r.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
+          r.right <= (window.innerWidth || document.documentElement.clientWidth)
+        )
+      }
+    }
     }
-  }
 
   // POPOVER DATA API
   // =================
-  var Popovers = document.querySelectorAll('[data-toggle=popover]'), i = 0, ppl = Popovers.length;
-  for (i;i<ppl;i++){
+    var Popovers = document.querySelectorAll('[data-toggle=popover]'), i = 0, ppl = Popovers.length;
+  for (i;i<ppl;i++){  
     var item = Popovers[i], options = {};
     options.trigger = item.getAttribute('data-trigger'); // click / hover / focus
     options.animation = item.getAttribute('data-animation'); // true / false
@@ -1130,15 +1499,39 @@
     new Popover(item,options);
   }
 
+  return Popover;
+
+});
+
+
+(function(factory){
+
+  // CommonJS/RequireJS and "native" compatibility
+  if(typeof module !== "undefined" && typeof exports == "object") {
+    // A commonJS/RequireJS environment
+    if(typeof window != "undefined") {
+      // Window and document exist, so return the factory's return value.
+      module.exports = factory();
+    } else {
+      // Let the user give the factory a Window and Document.
+      module.exports = factory;
+    }
+  } else {
+    // Assume a traditional browser.
+    window.ScrollSpy = factory();
+  }
+
+})(function(){
 
   //SCROLLSPY DEFINITION
-  var ScrollSpy = window.Scrollspy = function(element,item,options) {
+  var ScrollSpy = function(element,item,options) {
     options = options || {};
-
+    
     //this is the container element we spy it's elements on
     this.element = typeof element === 'object' ? element : document.querySelector(element);
 
     this.options = {};
+    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false;
     // this is the UL menu component our scrollSpy object will target, configure and required by the container element
     this.options.target = options.target ? (typeof options.target === 'object' ? options.target : document.querySelector(options.target)) : null;
 
@@ -1156,7 +1549,6 @@
     this.active = false;
     this.topEdge = 0;
     this.bottomEdge = 0;
-    var self = this;
 
     //determine which is the real scrollTarget
     if ( this.element.offsetHeight < this.element.scrollHeight ) { // or this.scrollHeight()
@@ -1165,90 +1557,104 @@
       this.scrollTarget = window;
     }
 
-    if ( !this.options.target ) { return; }
+    if ( this.options.target ) {
+      this.init();
+    }
+  };
 
-    this.topLimit = function () { // the target offset
+  //SCROLLSPY METHODS
+  ScrollSpy.prototype = {
+    init: function () {
+      if ( this.item.getAttribute('href') && this.item.getAttribute('href').indexOf('#') > -1 ) {
+        //actions
+        this.checkEdges();
+        this.refresh()
+        this.scrollEvent();
+        if (!(this.isIE && this.isIE < 9)) { this.resizeEvent(); }
+      }
+    },
+    topLimit: function () { // the target offset
       if ( this.scrollTarget === window ) {
         return this.tg.getBoundingClientRect().top + this.scrollOffset() - 5
       } else {
         return this.tg.offsetTop;
       }
-    }
-    this.bottomLimit = function () {
+
+    },
+    bottomLimit: function () {
       return this.topLimit() + this.tg.clientHeight
-    }
-    this.checkEdges = function () {
+    },
+    checkEdges: function () {
       this.topEdge = this.topLimit();
       this.bottomEdge = this.bottomLimit()
-    }
-    this.scrollOffset = function () {
+    },
+    scrollOffset: function () {
       if ( this.scrollTarget === window ) {
         return window.pageYOffset || document.documentElement.scrollTop
       } else {
         return this.element.scrollTop
       }
-    }
-    this.activate = function () {
+    },
+    activate: function () {
       if ( this.parent && this.parent.tagName === 'LI' && !/\bactive/.test(this.parent.className) ) {
-        addClass(this.parent,'active');
+        this.addClass(this.parent,'active');
         if ( this.parentParent && this.parentParent.tagName === 'LI' // activate the dropdown as well
           && /\bdropdown/.test(this.parentParent.className)
-          && !/\bactive/.test(this.parentParent.className) ) { addClass(this.parentParent,'active'); }
+          && !/\bactive/.test(this.parentParent.className) ) { this.addClass(this.parentParent,'active'); }
         this.active = true
       }
-    }
-    this.deactivate = function () {
+    },
+    deactivate: function () {
       if ( this.parent && this.parent.tagName === 'LI' && /\bactive/.test(this.parent.className) ) {
-        removeClass(this.parent,'active');
+        this.removeClass(this.parent,'active');
         if ( this.parentParent && this.parentParent.tagName === 'LI' // deactivate the dropdown as well
           && /\bdropdown/.test(this.parentParent.className)
-          && /\bactive/.test(this.parentParent.className) ) { removeClass(this.parentParent,'active'); }
+          && /\bactive/.test(this.parentParent.className) ) { this.removeClass(this.parentParent,'active'); }
         this.active = false
       }
-    }
-    this.toggle = function () {
+    },
+    toggle: function () {
       if ( this.active === false
         && ( this.bottomEdge > this.scrollOffset() && this.scrollOffset() >= this.topEdge )) { //regular use, scroll just entered the element's topLimit or bottomLimit
           this.activate();
       } else if (this.active === true && (this.bottomEdge <= this.scrollOffset() && this.scrollOffset() < this.topEdge )) {
         this.deactivate()
       }
-    }
-    this.refresh = function () { // check edges again
+    },
+    refresh : function () { // check edges again
       this.deactivate();
       this.checkEdges();
 
       this.toggle() // If any case update values again
-    }
-    this.scrollEvent = function(){
+    },
+    scrollEvent : function(){
+      var self = this;
+      this.scrollTarget.addEventListener('scroll', onSpyScroll, false);
       function onSpyScroll() {
         self.refresh();
       }
-      this.scrollTarget.addEventListener('scroll', onSpyScroll, false);
-    }
-    this.resizeEvent = function(){
+    },
+    resizeEvent : function(){
+      var self = this;
+      window.addEventListener('resize', onSpyResize, false);
       function onSpyResize() {
         self.refresh()
       }
-      window.addEventListener('resize', onSpyResize, false);
-    }
-    this.scrollHeight = function() {
+    },
+    scrollHeight : function() {
       if ( this.scrollTarget === window ) {
-        return Math.max( document.body.scrollHeight, document.body.offsetHeight,
+        return Math.max( document.body.scrollHeight, document.body.offsetHeight, 
           document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight );
       } else {
         return this.element.scrollHeight
       }
-    }
-
-    // init
-    if ( this.item.getAttribute('href') && this.item.getAttribute('href').indexOf('#') > -1 ) {
-      //actions
-      this.checkEdges();
-      this.refresh()
-      this.scrollEvent();
-      if (!(isIE && isIE < 9)) { this.resizeEvent(); }
-    }
+    },
+    addClass : function(el,c) {  
+      if (el.classList) { el.classList.add(c); } else { el.className += ' '+c; }
+    },
+    removeClass : function(el,c) {
+      if (el.classList) { el.classList.remove(c); } else { el.className = el.className.replace(c,'').replace(/^\s+|\s+$/g,''); }
+    }  
   };
 
 
@@ -1257,7 +1663,7 @@
   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"
   for (i;i<ssl;i++) {
     var spy = scrollSpyes[i], options = {};
-    options.target = spy.getAttribute('data-target') || null;  // this must be a .nav component with id="not-null"
+    options.target = spy.getAttribute('data-target') || null;  // this must be a .nav component with id="not-null"  
     if ( options.target !== null ) {
       var menu = options.target === 'object' ?  options.target : document.querySelector(options.target),
         items = menu.querySelectorAll('a'), j = 0, il = items.length;
@@ -1269,11 +1675,35 @@
     }
   }
 
+  return ScrollSpy;
+
+});
+
+
+(function(factory){
+
+  // CommonJS/RequireJS and "native" compatibility
+  if(typeof module !== "undefined" && typeof exports == "object") {
+    // A commonJS/RequireJS environment
+    if(typeof window != "undefined") {
+      // Window and document exist, so return the factory's return value.
+      module.exports = factory();
+    } else {
+      // Let the user give the factory a Window and Document.
+      module.exports = factory;
+    }
+  } else {
+    // Assume a traditional browser.
+    window.Tab = factory();
+  }
+
+})(function(){
 
   // TAB DEFINITION
   // ===================
-  var Tab = window.Tab = function( element,options ) {
+  var Tab = function( element,options ) {
     options = options || {};
+    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false;     
     this.tab = typeof element === 'object' ? element : document.querySelector(element);
     this.tabs = this.tab.parentNode.parentNode;
     this.dropdown = this.tabs.querySelector('.dropdown');
@@ -1285,78 +1715,120 @@
 
     // default tab transition duration
     this.duration = 150;
-    this.options.duration = (isIE && isIE < 10)  ? 0 : (options.duration || this.duration);
-
-    var self = this;
-
-    this.handle = function(e) {
-      e = e || window.e; e.preventDefault();
-      var next = e.target; //the tab we clicked is now the next tab
-      var nextContent = document.getElementById(next.getAttribute('href').replace('#','')); //this is the actual object, the next tab content to activate
+    this.options.duration = (this.isIE && this.isIE < 10)  ? 0 : (options.duration || this.duration);
+    this.init();
+  }
 
-      // get current active tab and content
-      var activeTab = self.getActiveTab();
-      var activeContent = self.getActiveContent();
+  // TAB METHODS
+  // ================
+  Tab.prototype = {
 
-      if ( !/\bactive/.test(next.parentNode.className) ) {
-        // toggle "active" class name
-        removeClass(activeTab,'active');
-        addClass(next.parentNode,'active');
+    init : function() {
+      this.actions();
+      this.tab.addEventListener('click', this.action, false);
+    },
 
-        // handle dropdown menu "active" class name
-        if ( self.dropdown ) {
-          if ( !(/\bdropdown-menu/.test(self.tab.parentNode.parentNode.className)) ) {
-            if (/\bactive/.test(self.dropdown.className)) removeClass(self.dropdown,'active');
-          } else {
-            if (!/\bactive/.test(self.dropdown.className)) addClass(self.dropdown,'active');
+    actions : function() {
+      var self = this;
+
+      this.action = function(e) {
+        e = e || window.e; e.preventDefault();
+        var next = e.target; //the tab we clicked is now the next tab
+        var nextContent = document.getElementById(next.getAttribute('href').replace('#','')); //this is the actual object, the next tab content to activate
+        var isDropDown = new RegExp('(?:^|\\s)'+ 'dropdown-menu' +'(?!\\S)');
+        
+        // get current active tab and content
+        var activeTab = self.getActiveTab();
+        var activeContent = self.getActiveContent();
+
+        if ( !/\bactive/.test(next.parentNode.className) ) {
+          // toggle "active" class name
+          self.removeClass(activeTab,'active');
+          self.addClass(next.parentNode,'active');    
+  
+          // handle dropdown menu "active" class name
+          if ( self.dropdown ) {
+            if ( !(isDropDown.test(self.tab.parentNode.parentNode.className)) ) {
+              if (/\bactive/.test(self.dropdown.className)) self.removeClass(self.dropdown,'active');
+            } else {
+              if (!/\bactive/.test(self.dropdown.className)) self.addClass(self.dropdown,'active');
+            }
           }
+          
+          //1. hide current active content first
+          self.removeClass(activeContent,'in');
+          
+          setTimeout(function() { // console.log(self)
+            //2. toggle current active content from view
+            self.removeClass(activeContent,'active');
+            self.addClass(nextContent,'active');
+          }, self.options.duration);
+          setTimeout(function() {
+            //3. show next active content
+            self.addClass(nextContent,'in');
+          }, self.options.duration*2);
         }
-
-        //1. hide current active content first
-        removeClass(activeContent,'in');
-
-        setTimeout(function() {
-          //2. toggle current active content from view
-          removeClass(activeContent,'active');
-          addClass(nextContent,'active');
-        }, self.options.duration);
-        setTimeout(function() {
-          //3. show next active content
-          addClass(nextContent,'in');
-        }, self.options.duration*2);
-      }
-    }
-    this.getActiveTab = function() {
-      var activeTabs = this.tabs.querySelectorAll('.active');
-      if ( activeTabs.length === 1 && !/\bdropdown/.test(activeTabs[0].className) ) {
-        return activeTabs[0]
-      } else if ( activeTabs.length > 1 ) {
-        return activeTabs[activeTabs.length-1]
+      },
+      this.addClass = function(el,c) {
+        if (el.classList) { el.classList.add(c); } else { el.className += ' '+c; }
+      },
+      this.removeClass = function(el,c) {
+        if (el.classList) { el.classList.remove(c); } else { el.className = el.className.replace(c,'').replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,''); }
+      },
+      this.getActiveTab = function() {
+        var activeTabs = this.tabs.querySelectorAll('.active');
+        if ( activeTabs.length === 1 && !/\bdropdown/.test(activeTabs[0].className) ) {
+          return activeTabs[0]
+        } else if ( activeTabs.length > 1 ) {
+          return activeTabs[activeTabs.length-1]
+        }
+      },
+      this.getActiveContent = function() {
+        var a = this.getActiveTab().getElementsByTagName('A')[0].getAttribute('href').replace('#','');
+        return a && document.getElementById(a)
       }
     }
-    this.getActiveContent = function() {
-      var a = this.getActiveTab().getElementsByTagName('A')[0].getAttribute('href').replace('#','');
-      return a && document.getElementById(a)
-    }
-
-    // init
-    this.tab.addEventListener('click', this.handle, false);
   }
 
+
   // TAB DATA API
   // =================
-  var Tabs = document.querySelectorAll("[data-toggle='tab'], [data-toggle='pill']"), tbl = Tabs.length, i=0;
+    var Tabs = document.querySelectorAll("[data-toggle='tab'], [data-toggle='pill']"), tbl = Tabs.length, i=0;
   for ( i;i<tbl;i++ ) {
     var tab = Tabs[i], options = {};
     options.duration = tab.getAttribute('data-duration') && tab.getAttribute('data-duration') || false;
     new Tab(tab,options);
   }
 
+  return Tab;
+
+});
+
+
+(function(factory){
+
+  // CommonJS/RequireJS and "native" compatibility
+  if(typeof module !== "undefined" && typeof exports == "object") {
+    // A commonJS/RequireJS environment
+    if(typeof window != "undefined") {
+      // Window and document exist, so return the factory's return value.
+      module.exports = factory();
+    } else {
+      // Let the user give the factory a Window and Document.
+      module.exports = factory;
+    }
+  } else {
+    // Assume a traditional browser.
+    window.Tooltip = factory();
+  }
+
+})(function(root){
+
   // TOOLTIP DEFINITION
   // ===================
-  var Tooltip = window.Tooltip = function( element,options ) {
+  var Tooltip = function( element,options ) {
     options = options || {};
-
+    
     this.link = typeof element === 'object' ? element : document.querySelector(element);
     this.title = this.link.getAttribute('title') || this.link.getAttribute('data-original-title');
     this.tooltip = null;
@@ -1364,129 +1836,174 @@
     this.options.animation = options.animation && options.animation !== 'fade' ? options.animation : 'fade';
     this.options.placement = options.placement ? options.placement : 'top';
     this.options.delay = parseInt(options.delay) || 100;
+    this.isIE = (new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null) ? parseFloat( RegExp.$1 ) : false;
     this.duration = 150;
-    this.options.duration = isIE && isIE < 10 ? 0 : (options.duration || this.duration);
+    this.options.duration = this.isIE && this.isIE < 10 ? 0 : (options.duration || this.duration);
     this.options.container = options.container || document.body;
-    if ( !this.title ) return;
+    if ( this.title ) this.init();
     this.timer = 0 // the link own event timer
+  }
 
-    var self = this, events = ('onmouseleave' in this.link) ? [ 'mouseenter', 'mouseleave'] : [ 'mouseover', 'mouseout' ];
+  // TOOLTIP METHODS
+  // ================
+  Tooltip.prototype = {
 
-    this.open = function(e) {
-      clearTimeout(self.link.getAttribute('data-timer'));
-      self.timer = setTimeout( function() {
-        if (self.tooltip === null) {
-          self.createToolTip();
-          self.styleTooltip();
-          self.updateTooltip()
-        }
-      }, self.options.duration );
-      self.link.setAttribute('data-timer',self.timer);
-    }
-    this.close = function(e) {
-      clearTimeout(self.link.getAttribute('data-timer'));
-      self.timer = setTimeout( function() {
-        if (self.tooltip && self.tooltip !== null) {
-          self.tooltip.className = self.tooltip.className.replace(' in','');
-          setTimeout(function() {
-            self.removeToolTip(); // for performance/testing reasons we can keep the tooltips if we want
-          }, self.options.duration);
-        }
-      }, self.options.delay + self.options.duration);
-      self.link.setAttribute('data-timer',self.timer);
-    }
-    //remove the tooltip
-    this.removeToolTip = function() {
-      this.tooltip && this.options.container.removeChild(this.tooltip);
-      this.tooltip = null;
-    }
-    //create the tooltip structure
-    this.createToolTip = function() {
-      this.tooltip = document.createElement('div');
-      this.tooltip.setAttribute('role','tooltip');
+    init : function() {
+      this.actions();
+      this.rect = null;
+      var events = ('onmouseleave' in this.link) ? [ 'mouseenter', 'mouseleave'] : [ 'mouseover', 'mouseout' ];
+      this.link.addEventListener(events[0], this.open, false);
+      this.link.addEventListener(events[1], this.close, false);
+      
+      //remove title from link
+      this.link.setAttribute('data-original-title',this.title);
+      this.link.removeAttribute('title');
 
-      var tooltipArrow = document.createElement('div');
-      tooltipArrow.setAttribute('class','tooltip-arrow');
-      var tooltipInner = document.createElement('div');
-      tooltipInner.setAttribute('class','tooltip-inner');
+    },
 
-      this.tooltip.appendChild(tooltipArrow);
-      this.tooltip.appendChild(tooltipInner);
+    actions : function() {
+      var self = this;
 
-      //set tooltip content
-      tooltipInner.innerHTML = this.title;
+      this.open = function(e) {
+        clearTimeout(self.link.getAttribute('data-timer'));
+        self.timer = setTimeout( function() {
+          if (self.tooltip === null) {
+            self.createToolTip();
+            self.styleTooltip();
+            self.updateTooltip()
+          }
+        }, self.options.duration );
+        self.link.setAttribute('data-timer',self.timer);
+      },
 
-      //append to the container
-      this.options.container.appendChild(this.tooltip);
-    }
-    this.styleTooltip = function(pos) {
-      var rect = this.link.getBoundingClientRect(),
-          placement = pos || this.options.placement;
+      this.close = function(e) {
+        clearTimeout(self.link.getAttribute('data-timer'));
+        self.timer = setTimeout( function() {
+          if (self.tooltip && self.tooltip !== null) {
+            self.tooltip.className = self.tooltip.className.replace(' in','');
+            setTimeout(function() {
+              self.removeToolTip(); // for performance/testing reasons we can keep the tooltips if we want
+            }, self.options.duration);
+          }
 
-      this.tooltip.setAttribute('class','tooltip '+placement+' '+this.options.animation);
+        }, self.options.delay + self.options.duration);
+        self.link.setAttribute('data-timer',self.timer);
+      },
 
-      var ld = { w: rect.right - rect.left, h: rect.bottom - rect.top }, //link real dimensions
-          td = { w : this.tooltip.offsetWidth, h: this.tooltip.offsetHeight }, //tooltip real dimensions
-          sYo = this.getScroll().y, sXo = this.getScroll().x; //window vertical and horizontal scroll
+      //remove the tooltip
+      this.removeToolTip = function() {
+        this.tooltip && this.options.container.removeChild(this.tooltip);
+        this.tooltip = null;
+      },
 
-      //apply styling
-      if ( /top/.test(placement) ) { //TOP
-        this.tooltip.style.top = rect.top + sYo - td.h + 'px';
-        this.tooltip.style.left = rect.left + sXo - td.w/2 + ld.w/2 + 'px'
+      //create the tooltip structure
+      this.createToolTip = function() {
+        this.tooltip = document.createElement('div');
+        this.tooltip.setAttribute('role','tooltip');
 
-      } else if ( /bottom/.test(placement) ) { //BOTTOM
-        this.tooltip.style.top = rect.top + sYo + ld.h + 'px';
-        this.tooltip.style.left = rect.left + sXo - td.w/2 + ld.w/2 + 'px';
+        var tooltipArrow = document.createElement('div');
+        tooltipArrow.setAttribute('class','tooltip-arrow');
+        var tooltipInner = document.createElement('div');
+        tooltipInner.setAttribute('class','tooltip-inner');
 
-      } else if ( /left/.test(placement) ) { //LEFT
-        this.tooltip.style.top = rect.top + sYo - td.h/2 + ld.h/2 + 'px';
-        this.tooltip.style.left = rect.left + sXo - td.w + 'px';
+        this.tooltip.appendChild(tooltipArrow);
+        this.tooltip.appendChild(tooltipInner);
 
-      } else if ( /right/.test(placement) ) { //RIGHT
-        this.tooltip.style.top = rect.top + sYo - td.h/2 + ld.h/2 + 'px';
-        this.tooltip.style.left = rect.left + sXo + ld.w + 'px';
-      }
-    }
-    this.updateTooltip = function() {
-      var placement = null;
-      if ( !isElementInViewport(this.tooltip) ) {
-        placement = this.updatePlacement();
-      } else {
-        placement = this.options.placement;
-      }
-      this.styleTooltip(placement);
-      this.tooltip.className += ' in';
-    }
-    this.updatePlacement = function() {
-      var pos = this.options.placement;
-      if ( /top/.test(pos) ) { //TOP
-        return 'bottom';
-      } else if ( /bottom/.test(pos) ) { //BOTTOM
-        return 'top';
-      } else if ( /left/.test(pos) ) { //LEFT
-        return 'right';
-      } else if ( /right/.test(pos) ) { //RIGHT
-        return 'left';
-      }
-    }
-    this.getScroll = function() {
-      return {
-        y : window.pageYOffset || document.documentElement.scrollTop,
-        x : window.pageXOffset || document.documentElement.scrollLeft
+        //set tooltip content
+        tooltipInner.innerHTML = this.title;
+
+        //append to the container
+        this.options.container.appendChild(this.tooltip);
+      },
+
+      this.styleTooltip = function(pos) {
+        this.rect = this.getRect();
+        var placement = pos || this.options.placement;
+        this.tooltip.setAttribute('class','tooltip '+placement+' '+this.options.animation);
+
+        var linkDim = { w: this.link.offsetWidth, h: this.link.offsetHeight }; //link real dimensions
+
+        // all tooltip dimensions
+        var td = this.tooltipDimensions(this.tooltip);
+        var toolDim = { w : td.w, h: td.h }; //tooltip real dimensions
+
+        //window vertical and horizontal scroll
+        var scrollYOffset = this.getScroll().y;
+        var scrollXOffset =  this.getScroll().x;
+
+        //apply styling
+        if ( /top/.test(placement) ) { //TOP
+          this.tooltip.style.top = this.rect.top + scrollYOffset - toolDim.h + 'px';
+          this.tooltip.style.left = this.rect.left + scrollXOffset - toolDim.w/2 + linkDim.w/2 + 'px'
+
+        } else if ( /bottom/.test(placement) ) { //BOTTOM
+          this.tooltip.style.top = this.rect.top + scrollYOffset + linkDim.h + 'px';
+          this.tooltip.style.left = this.rect.left + scrollXOffset - toolDim.w/2 + linkDim.w/2 + 'px';
+
+        } else if ( /left/.test(placement) ) { //LEFT
+          this.tooltip.style.top = this.rect.top + scrollYOffset - toolDim.h/2 + linkDim.h/2 + 'px';
+          this.tooltip.style.left = this.rect.left + scrollXOffset - toolDim.w + 'px';
+
+        } else if ( /right/.test(placement) ) { //RIGHT
+          this.tooltip.style.top = this.rect.top + scrollYOffset - toolDim.h/2 + linkDim.h/2 + 'px';
+          this.tooltip.style.left = this.rect.left + scrollXOffset + linkDim.w + 'px';
+        }
+      },
+
+      this.updateTooltip = function() {
+        var placement = null;
+        if ( !this.isElementInViewport(this.tooltip) ) {
+          placement = this.updatePlacement();
+        } else {
+          placement = this.options.placement;
+        }
+
+        this.styleTooltip(placement);
+        this.tooltip.className += ' in';
+      },
+      this.updatePlacement = function() {
+        var pos = this.options.placement;
+        if ( /top/.test(pos) ) { //TOP
+          return 'bottom';
+        } else if ( /bottom/.test(pos) ) { //BOTTOM
+          return 'top';
+        } else if ( /left/.test(pos) ) { //LEFT
+          return 'right';
+        } else if ( /right/.test(pos) ) { //RIGHT
+          return 'left';
+        }
+      },
+      this.getRect = function() {
+        return this.link.getBoundingClientRect()
+      },
+      this.getScroll = function() {
+        return {
+          y : window.pageYOffset || document.documentElement.scrollTop,
+          x : window.pageXOffset || document.documentElement.scrollLeft
+        }
+      },
+      this.tooltipDimensions  = function(t) {//check tooltip width and height
+        return {
+          w : t.offsetWidth,
+          h : t.offsetHeight
+        }
+      },
+      this.isElementInViewport = function(t) { // check if this.tooltip is in viewport
+        var r = t.getBoundingClientRect();
+        return (
+          r.top >= 0 &&
+          r.left >= 0 &&
+          r.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
+          r.right <= (window.innerWidth || document.documentElement.clientWidth)
+        )
       }
     }
-    // init
-    this.link.addEventListener(events[0], this.open, false);
-    this.link.addEventListener(events[1], this.close, false);
-    //remove title from link
-    this.link.setAttribute('data-original-title',this.title);
-    this.link.removeAttribute('title');
   }
-
+  
   // TOOLTIP DATA API
   // =================
   var Tooltips = document.querySelectorAll('[data-toggle=tooltip]'), i = 0, tpl = Tooltips.length;
-  for (i;i<tpl;i++){
+  for (i;i<tpl;i++){  
     var item = Tooltips[i], options = {};
     options.animation = item.getAttribute('data-animation');
     options.placement = item.getAttribute('data-placement');
@@ -1494,4 +2011,7 @@
     options.delay = item.getAttribute('data-delay');
     new Tooltip(item,options);
   }
-})();
+
+  return Tooltip;
+
+});
diff --git a/js/explorer.js b/js/explorer.js
index 1b94c9a9ab1765810ece692777a3bd5edaf2c783..3a617db750830fb287782efa0da8c6986fc942b6 100644
--- a/js/explorer.js
+++ b/js/explorer.js
@@ -137,7 +137,7 @@ var planet = {} ;
 var center_map = null ;
 
 var storage_prefix = 'Explosurf:' 
-    + document.getElementById('planet-name').innerText.toLowerCase() 
+    + document.getElementById('planet-name').innerHTML.toLowerCase() 
     + ':explorer'
   ;
 
diff --git a/js/notes.js b/js/notes.js
index 3438a7b1edb9fa237672522f031a779ec45b4bae..15f199671f76dc0a4d2f810c6eedbd1ef227f30c 100644
--- a/js/notes.js
+++ b/js/notes.js
@@ -11,7 +11,7 @@
 
 /* local storage prefix */
 var storage_prefix = 'Explosurf:' 
-    + document.getElementById('planet-name').innerText.toLowerCase() 
+    + document.getElementById('planet-name').innerHTML.toLowerCase() 
     + ':notes'
   ;
 
diff --git a/js/pgm_construction.js b/js/pgm_construction.js
index 182391b886c061eecfb6ffc139e573b308b39ce8..e0a05eb741dd17587e6e9ced318dcc1e8094fc7a 100644
--- a/js/pgm_construction.js
+++ b/js/pgm_construction.js
@@ -60,7 +60,7 @@ var has_absolute_fixed_bug = (function() {
 
 /*prefix for local storage*/
 var storage_prefix = 'Explosurf:' 
-    + document.getElementById('planet-name').innerText.toLowerCase()
+    + document.getElementById('planet-name').innerHTML.toLowerCase()
     + ':pgm'
   ;
 
@@ -145,7 +145,7 @@ function local_list_pgm() {
       //build the item from the template
       var item = pgm_entry.cloneNode(true) ;
       var label = document.createElement('span') ;
-      label.innerText = match[1] ;
+      label.innerHTML = match[1] ;
       label.className = 'pull-left' ;
       item.appendChild(label) ;
       pgm_list.appendChild(item) ;