text: /**
   * MBP - Mobile boilerplate helper functions
   */
  
  (function(document) {
  
      window.MBP = window.MBP || {};
  
      /**
       * Fix for iPhone viewport scale bug
       * http://www.blog.highub.com/mobile-2/a-fix-for-iphone-viewport-scale-bug/
       */
  
      MBP.viewportmeta = document.querySelector && document.querySelector('meta[name="viewport"]');
      MBP.ua = navigator.userAgent;
  
      MBP.scaleFix = function() {
          if (MBP.viewportmeta && /iPhone|iPad|iPod/.test(MBP.ua) && !/Opera Mini/.test(MBP.ua)) {
              MBP.viewportmeta.content = 'width=device-width, minimum-scale=1.0, maximum-scale=1.0';
              document.addEventListener('gesturestart', MBP.gestureStart, false);
          }
      };
  
      MBP.gestureStart = function() {
          MBP.viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1.6';
      };
  
      /**
       * Normalized hide address bar for iOS & Android
       * (c) Scott Jehl, scottjehl.com
       * MIT License
       */
  
      // If we split this up into two functions we can reuse
      // this function if we aren't doing full page reloads.
  
      // If we cache this we don't need to re-calibrate everytime we call
      // the hide url bar
      MBP.BODY_SCROLL_TOP = false;
  
      // So we don't redefine this function everytime we
      // we call hideUrlBar
      MBP.getScrollTop = function() {
          var win = window;
          var doc = document;
  
          return win.pageYOffset || doc.compatMode === 'CSS1Compat' && doc.documentElement.scrollTop || doc.body.scrollTop || 0;
      };
  
      // It should be up to the mobile
      MBP.hideUrlBar = function() {
          var win = window;
  
          // if there is a hash, or MBP.BODY_SCROLL_TOP hasn't been set yet, wait till that happens
          if (!location.hash && MBP.BODY_SCROLL_TOP !== false) {
              win.scrollTo( 0, MBP.BODY_SCROLL_TOP === 1 ? 0 : 1 );
          }
      };
  
      MBP.hideUrlBarOnLoad = function() {
          var win = window;
          var doc = win.document;
          var bodycheck;
  
          // If there's a hash, or addEventListener is undefined, stop here
          if ( !location.hash && win.addEventListener ) {
  
              // scroll to 1
              window.scrollTo( 0, 1 );
              MBP.BODY_SCROLL_TOP = 1;
  
              // reset to 0 on bodyready, if needed
              bodycheck = setInterval(function() {
                  if ( doc.body ) {
                      clearInterval( bodycheck );
                      MBP.BODY_SCROLL_TOP = MBP.getScrollTop();
                      MBP.hideUrlBar();
                  }
              }, 15 );
  
              win.addEventListener('load', function() {
                  setTimeout(function() {
                      // at load, if user hasn't scrolled more than 20 or so...
                      if (MBP.getScrollTop() < 20) {
                          // reset to hide addr bar at onload
                          MBP.hideUrlBar();
                      }
                  }, 0);
              });
          }
      };
  
      /**
       * Fast Buttons - read wiki below before using
       * https://github.com/h5bp/mobile-boilerplate/wiki/JavaScript-Helper
       */
  
      MBP.fastButton = function(element, handler, pressedClass) {
          this.handler = handler;
          // styling of .pressed is defined in the project's CSS files
          this.pressedClass = typeof pressedClass === 'undefined' ? 'pressed' : pressedClass;
  
          if (element.length && element.length > 1) {
              for (var singleElIdx in element) {
                  this.addClickEvent(element[singleElIdx]);
              }
          } else {
              this.addClickEvent(element);
          }
      };
  
      MBP.fastButton.prototype.handleEvent = function(event) {
          event = event || window.event;
  
          switch (event.type) {
              case 'touchstart': this.onTouchStart(event); break;
              case 'touchmove': this.onTouchMove(event); break;
              case 'touchend': this.onClick(event); break;
              case 'click': this.onClick(event); break;
          }
      };
  
      MBP.fastButton.prototype.onTouchStart = function(event) {
          var element = event.target || event.srcElement;
          event.stopPropagation();
          element.addEventListener('touchend', this, false);
          document.body.addEventListener('touchmove', this, false);
          this.startX = event.touches[0].clientX;
          this.startY = event.touches[0].clientY;
  
          element.className+= ' ' + this.pressedClass;
      };
  
      MBP.fastButton.prototype.onTouchMove = function(event) {
          if (Math.abs(event.touches[0].clientX - this.startX) > 10 ||
              Math.abs(event.touches[0].clientY - this.startY) > 10) {
              this.reset(event);
          }
      };
  
      MBP.fastButton.prototype.onClick = function(event) {
          event = event || window.event;
          var element = event.target || event.srcElement;
          if (event.stopPropagation) {
              event.stopPropagation();
          }
          this.reset(event);
          this.handler.apply(event.currentTarget, [event]);
          if (event.type == 'touchend') {
              MBP.preventGhostClick(this.startX, this.startY);
          }
          var pattern = new RegExp(' ?' + this.pressedClass, 'gi');
          element.className = element.className.replace(pattern, '');
      };
  
      MBP.fastButton.prototype.reset = function(event) {
          var element = event.target || event.srcElement;
          rmEvt(element, 'touchend', this, false);
          rmEvt(document.body, 'touchmove', this, false);
  
          var pattern = new RegExp(' ?' + this.pressedClass, 'gi');
          element.className = element.className.replace(pattern, '');
      };
  
      MBP.fastButton.prototype.addClickEvent = function(element) {
          addEvt(element, 'touchstart', this, false);
          addEvt(element, 'click', this, false);
      };
  
      MBP.preventGhostClick = function(x, y) {
          MBP.coords.push(x, y);
          window.setTimeout(function() {
              MBP.coords.splice(0, 2);
          }, 2500);
      };
  
      MBP.ghostClickHandler = function(event) {
          if (!MBP.hadTouchEvent && MBP.dodgyAndroid) {
              // This is a bit of fun for Android 2.3...
              // If you change window.location via fastButton, a click event will fire
              // on the new page, as if the events are continuing from the previous page.
              // We pick that event up here, but MBP.coords is empty, because it's a new page,
              // so we don't prevent it. Here's we're assuming that click events on touch devices
              // that occur without a preceding touchStart are to be ignored.
              event.stopPropagation();
              event.preventDefault();
              return;
          }
          for (var i = 0, len = MBP.coords.length; i < len; i += 2) {
              var x = MBP.coords[i];
              var y = MBP.coords[i + 1];
              if (Math.abs(event.clientX - x) < 25 && Math.abs(event.clientY - y) < 25) {
                  event.stopPropagation();
                  event.preventDefault();
              }
          }
      };
  
      // This bug only affects touch Android 2.3 devices, but a simple ontouchstart test creates a false positive on
      // some Blackberry devices. https://github.com/Modernizr/Modernizr/issues/372
      // The browser sniffing is to avoid the Blackberry case. Bah
      MBP.dodgyAndroid = ('ontouchstart' in window) && (navigator.userAgent.indexOf('Android 2.3') != -1);
  
      if (document.addEventListener) {
          document.addEventListener('click', MBP.ghostClickHandler, true);
      }
  
      addEvt(document.documentElement, 'touchstart', function() {
          MBP.hadTouchEvent = true;
      }, false);
  
      MBP.coords = [];
  
      // fn arg can be an object or a function, thanks to handleEvent
      // read more about the explanation at: http://www.thecssninja.com/javascript/handleevent
      function addEvt(el, evt, fn, bubble) {
          if ('addEventListener' in el) {
              // BBOS6 doesn't support handleEvent, catch and polyfill
              try {
                  el.addEventListener(evt, fn, bubble);
              } catch(e) {
                  if (typeof fn == 'object' && fn.handleEvent) {
                      el.addEventListener(evt, function(e){
                          // Bind fn as this and set first arg as event object
                          fn.handleEvent.call(fn,e);
                      }, bubble);
                  } else {
                      throw e;
                  }
              }
          } else if ('attachEvent' in el) {
              // check if the callback is an object and contains handleEvent
              if (typeof fn == 'object' && fn.handleEvent) {
                  el.attachEvent('on' + evt, function(){
                      // Bind fn as this
                      fn.handleEvent.call(fn);
                  });
              } else {
                  el.attachEvent('on' + evt, fn);
              }
          }
      }
  
      function rmEvt(el, evt, fn, bubble) {
          if ('removeEventListener' in el) {
              // BBOS6 doesn't support handleEvent, catch and polyfill
              try {
                  el.removeEventListener(evt, fn, bubble);
              } catch(e) {
                  if (typeof fn == 'object' && fn.handleEvent) {
                      el.removeEventListener(evt, function(e){
                          // Bind fn as this and set first arg as event object
                          fn.handleEvent.call(fn,e);
                      }, bubble);
                  } else {
                      throw e;
                  }
              }
          } else if ('detachEvent' in el) {
              // check if the callback is an object and contains handleEvent
              if (typeof fn == 'object' && fn.handleEvent) {
                  el.detachEvent("on" + evt, function() {
                      // Bind fn as this
                      fn.handleEvent.call(fn);
                  });
              } else {
                  el.detachEvent('on' + evt, fn);
              }
          }
      }
  
      /**
       * Autogrow
       * http://googlecode.blogspot.com/2009/07/gmail-for-mobile-html5-series.html
       */
  
      MBP.autogrow = function(element, lh) {
          function handler(e) {
              var newHeight = this.scrollHeight;
              var currentHeight = this.clientHeight;
              if (newHeight > currentHeight) {
                  this.style.height = newHeight + 3 * textLineHeight + 'px';
              }
          }
  
          var setLineHeight = (lh) ? lh : 12;
          var textLineHeight = element.currentStyle ? element.currentStyle.lineHeight : getComputedStyle(element, null).lineHeight;
  
          textLineHeight = (textLineHeight.indexOf('px') == -1) ? setLineHeight : parseInt(textLineHeight, 10);
  
          element.style.overflow = 'hidden';
          element.addEventListener ? element.addEventListener('keyup', handler, false) : element.attachEvent('onkeyup', handler);
      };
  
      /**
       * Enable CSS active pseudo styles in Mobile Safari
       * http://alxgbsn.co.uk/2011/10/17/enable-css-active-pseudo-styles-in-mobile-safari/
       */
  
      MBP.enableActive = function() {
          document.addEventListener('touchstart', function() {}, false);
      };
  
      /**
       * Prevent default scrolling on document window
       */
  
      MBP.preventScrolling = function() {
          document.addEventListener('touchmove', function(e) {
              e.preventDefault();
          }, false);
      };
  
      /**
       * Prevent iOS from zooming onfocus
       * https://github.com/h5bp/mobile-boilerplate/pull/108
       * Adapted from original jQuery code here: http://nerd.vasilis.nl/prevent-ios-from-zooming-onfocus/
       */
  
      MBP.preventZoom = function() {
          var formFields = document.querySelectorAll('input, select, textarea');
          var contentString = 'width=device-width,initial-scale=1,maximum-scale=';
          var i = 0;
  
          for (i = 0; i < formFields.length; i++) {
              formFields[i].onfocus = function() {
                  MBP.viewportmeta.content = contentString + '1';
              };
              formFields[i].onblur = function() {
                  MBP.viewportmeta.content = contentString + '10';
              };
          }
      };
  
      /**
       * iOS Startup Image helper
       */
  
      MBP.startupImage = function() {
          var portrait;
          var landscape;
          var pixelRatio;
          var head;
          var link1;
          var link2;
  
          pixelRatio = window.devicePixelRatio;
          head = document.getElementsByTagName('head')[0];
  
          if (navigator.platform === 'iPad') {
              portrait = pixelRatio === 2 ? 'images/mobile/splash-1536x2008-retina.png' : 'images/mobile/splash-768x1004.png';
              landscape = pixelRatio === 2 ? 'images/mobile/splash-2048x1496-retina.png' : 'images/mobile/splash-1024x748.png';
  
              link1 = document.createElement('link');
              link1.setAttribute('rel', 'apple-touch-startup-image');
              link1.setAttribute('media', 'screen and (orientation: portrait)');
              link1.setAttribute('href', portrait);
              head.appendChild(link1);
  
              link2 = document.createElement('link');
              link2.setAttribute('rel', 'apple-touch-startup-image');
              link2.setAttribute('media', 'screen and (orientation: landscape)');
              link2.setAttribute('href', landscape);
              head.appendChild(link2);
          } else {
              portrait = pixelRatio === 2 ? "images/mobile/splash-320x460-retina.png" : "images/mobile/splash-320x460.png";
  
              link1 = document.createElement('link');
              link1.setAttribute('rel', 'apple-touch-startup-image');
              link1.setAttribute('href', portrait);
              head.appendChild(link1);
          }
      };
  
  })(document);
  
  // prevent links from opening in safari mobile
  // https://gist.github.com/1042167
  (function(document,navigator,standalone) {
  	// prevents links from apps from oppening in mobile safari
  	// this javascript must be the first script in your <head>
  	if ((standalone in navigator) && navigator[standalone]) {
  		var curnode, location=document.location, stop=/^(a|html)$/i;
  		document.addEventListener('click', function(e) {
  			curnode=e.target;
  			while (!(stop).test(curnode.nodeName)) {
  				curnode=curnode.parentNode;
  			}
  		// Condidions to do this only on links to your own app
  		// if you want all links, use if('href' in curnode) instead.
  		if(
  		'href' in curnode && // is a link
  		(chref=curnode.href).replace(location.href,'').indexOf('#') && // is not an anchor
  		(	!(/^[a-z\+\.\-]+:/i).test(chref) || // either does not have a proper scheme (relative links)
  		chref.indexOf(location.protocol+'//'+location.host)===0 ) // or is in the same protocol and domain
  		) {
  			e.preventDefault();
  			location.href = curnode.href;
  			}
  		},false);
  	}
  })(document,window.navigator,'standalone');