Merge afb-client
[src/app-framework-demo.git] / afb-client / bower_components / viewport-units-buggyfill / viewport-units-buggyfill.js
diff --git a/afb-client/bower_components/viewport-units-buggyfill/viewport-units-buggyfill.js b/afb-client/bower_components/viewport-units-buggyfill/viewport-units-buggyfill.js
new file mode 100755 (executable)
index 0000000..242af2a
--- /dev/null
@@ -0,0 +1,347 @@
+/*!
+ * viewport-units-buggyfill v0.4.1
+ * @web: https://github.com/rodneyrehm/viewport-units-buggyfill/
+ * @author: Rodney Rehm - http://rodneyrehm.de/en/
+ */
+
+(function (root, factory) {
+  'use strict';
+  if (typeof define === 'function' && define.amd) {
+    // AMD. Register as an anonymous module.
+    define([], factory);
+  } else if (typeof exports === 'object') {
+    // Node. Does not work with strict CommonJS, but
+    // only CommonJS-like enviroments that support module.exports,
+    // like Node.
+    module.exports = factory();
+  } else {
+    // Browser globals (root is window)
+    root.viewportUnitsBuggyfill = factory();
+  }
+}(this, function () {
+  'use strict';
+  /*global document, window, location, XMLHttpRequest, XDomainRequest*/
+
+  var initialized = false;
+  var options;
+  var isMobileSafari = /(iPhone|iPod|iPad).+AppleWebKit/i.test(window.navigator.userAgent);
+  var viewportUnitExpression = /([+-]?[0-9.]+)(vh|vw|vmin|vmax)/g;
+  var forEach = [].forEach;
+  var dimensions;
+  var declarations;
+  var styleNode;
+  var isOldInternetExplorer = false;
+
+  // Do not remove the following comment!
+  // It is a conditional comment used to
+  // identify old Internet Explorer versions
+
+  /*@cc_on
+
+  @if (@_jscript_version <= 10)
+    isOldInternetExplorer = true;
+  @end
+
+  @*/
+
+  function debounce(func, wait) {
+    var timeout;
+    return function() {
+      var context = this;
+      var args = arguments;
+      var callback = function() {
+        func.apply(context, args);
+      };
+
+      clearTimeout(timeout);
+      timeout = setTimeout(callback, wait);
+    };
+  }
+
+  // from http://stackoverflow.com/questions/326069/how-to-identify-if-a-webpage-is-being-loaded-inside-an-iframe-or-directly-into-t
+  function inIframe() {
+    try {
+      return window.self !== window.top;
+    } catch (e) {
+      return true;
+    }
+  }
+
+  function initialize(initOptions) {
+    if (initialized) {
+      return;
+    }
+
+    if (initOptions === true) {
+      initOptions = {
+        force: true
+      };
+    }
+
+    options = initOptions || {};
+    options.isMobileSafari = isMobileSafari;
+
+    if (!options.force && !isMobileSafari && !isOldInternetExplorer && (!options.hacks || !options.hacks.required(options))) {
+      // this buggyfill only applies to mobile safari
+      return;
+    }
+
+    options.hacks && options.hacks.initialize(options);
+
+    initialized = true;
+    styleNode = document.createElement('style');
+    styleNode.id = 'patched-viewport';
+    document.head.appendChild(styleNode);
+
+    // Issue #6: Cross Origin Stylesheets are not accessible through CSSOM,
+    // therefore download and inject them as <style> to circumvent SOP.
+    importCrossOriginLinks(function() {
+      var _refresh = debounce(refresh, options.refreshDebounceWait || 100);
+      // doing a full refresh rather than updateStyles because an orientationchange
+      // could activate different stylesheets
+      window.addEventListener('orientationchange', _refresh, true);
+      // orientationchange might have happened while in a different window
+      window.addEventListener('pageshow', _refresh, true);
+
+      if (options.force || isOldInternetExplorer || inIframe()) {
+        window.addEventListener('resize', _refresh, true);
+        options._listeningToResize = true;
+      }
+
+      options.hacks && options.hacks.initializeEvents(options, refresh, _refresh);
+
+      refresh();
+    });
+  }
+
+  function updateStyles() {
+    styleNode.textContent = getReplacedViewportUnits();
+  }
+
+  function refresh() {
+    if (!initialized) {
+      return;
+    }
+
+    findProperties();
+
+    // iOS Safari will report window.innerWidth and .innerHeight as 0
+    // unless a timeout is used here.
+    // TODO: figure out WHY innerWidth === 0
+    setTimeout(function() {
+      updateStyles();
+    }, 1);
+  }
+
+  function findProperties() {
+    declarations = [];
+    forEach.call(document.styleSheets, function(sheet) {
+      if (sheet.ownerNode.id === 'patched-viewport' || !sheet.cssRules) {
+        // skip entire sheet because no rules ara present or it's the target-element of the buggyfill
+        return;
+      }
+
+      if (sheet.media && sheet.media.mediaText && window.matchMedia && !window.matchMedia(sheet.media.mediaText).matches) {
+        // skip entire sheet because media attribute doesn't match
+        return;
+      }
+
+      forEach.call(sheet.cssRules, findDeclarations);
+    });
+
+    return declarations;
+  }
+
+  function findDeclarations(rule) {
+    if (rule.type === 7) {
+      var value = rule.cssText;
+      viewportUnitExpression.lastIndex = 0;
+      if (viewportUnitExpression.test(value)) {
+        // KeyframesRule does not have a CSS-PropertyName
+        declarations.push([rule, null, value]);
+        options.hacks && options.hacks.findDeclarations(declarations, rule, null, value);
+      }
+
+      return;
+    }
+
+    if (!rule.style) {
+      if (!rule.cssRules) {
+        return;
+      }
+
+      forEach.call(rule.cssRules, function(_rule) {
+        findDeclarations(_rule);
+      });
+
+      return;
+    }
+
+    forEach.call(rule.style, function(name) {
+      var value = rule.style.getPropertyValue(name);
+      viewportUnitExpression.lastIndex = 0;
+      if (viewportUnitExpression.test(value)) {
+        declarations.push([rule, name, value]);
+        options.hacks && options.hacks.findDeclarations(declarations, rule, name, value);
+      }
+    });
+  }
+
+  function getReplacedViewportUnits() {
+    dimensions = getViewport();
+
+    var css = [];
+    var buffer = [];
+    var open;
+    var close;
+
+    declarations.forEach(function(item) {
+      var _item = overwriteDeclaration.apply(null, item);
+      var _open = _item.selector.length ? (_item.selector.join(' {\n') + ' {\n') : '';
+      var _close = new Array(_item.selector.length + 1).join('\n}');
+
+      if (!_open || _open !== open) {
+        if (buffer.length) {
+          css.push(open + buffer.join('\n') + close);
+          buffer.length = 0;
+        }
+
+        if (_open) {
+          open = _open;
+          close = _close;
+          buffer.push(_item.content);
+        } else {
+          css.push(_item.content);
+          open = null;
+          close = null;
+        }
+
+        return;
+      }
+
+      if (_open && !open) {
+        open = _open;
+        close = _close;
+      }
+
+      buffer.push(_item.content);
+    });
+
+    if (buffer.length) {
+      css.push(open + buffer.join('\n') + close);
+    }
+
+    return css.join('\n\n');
+  }
+
+  function overwriteDeclaration(rule, name, value) {
+    var _value = value.replace(viewportUnitExpression, replaceValues);
+    var  _selectors = [];
+
+    if (options.hacks) {
+      _value = options.hacks.overwriteDeclaration(rule, name, _value);
+    }
+
+    if (name) {
+      // skipping KeyframesRule
+      _selectors.push(rule.selectorText);
+      _value = name + ': ' + _value + ';';
+    }
+
+    var _rule = rule.parentRule;
+    while (_rule) {
+      _selectors.unshift('@media ' + _rule.media.mediaText);
+      _rule = _rule.parentRule;
+    }
+
+    return {
+      selector: _selectors,
+      content: _value
+    };
+  }
+
+  function replaceValues(match, number, unit) {
+    var _base = dimensions[unit];
+    var _number = parseFloat(number) / 100;
+    return (_number * _base) + 'px';
+  }
+
+  function getViewport() {
+    var vh = window.innerHeight;
+    var vw = window.innerWidth;
+
+    return {
+      vh: vh,
+      vw: vw,
+      vmax: Math.max(vw, vh),
+      vmin: Math.min(vw, vh)
+    };
+  }
+
+  function importCrossOriginLinks(next) {
+    var _waiting = 0;
+    var decrease = function() {
+      _waiting--;
+      if (!_waiting) {
+        next();
+      }
+    };
+
+    forEach.call(document.styleSheets, function(sheet) {
+      if (!sheet.href || origin(sheet.href) === origin(location.href)) {
+        // skip <style> and <link> from same origin
+        return;
+      }
+
+      _waiting++;
+      convertLinkToStyle(sheet.ownerNode, decrease);
+    });
+
+    if (!_waiting) {
+      next();
+    }
+  }
+
+  function origin(url) {
+    return url.slice(0, url.indexOf('/', url.indexOf('://') + 3));
+  }
+
+  function convertLinkToStyle(link, next) {
+    getCors(link.href, function() {
+      var style = document.createElement('style');
+      style.media = link.media;
+      style.setAttribute('data-href', link.href);
+      style.textContent = this.responseText;
+      link.parentNode.replaceChild(style, link);
+      next();
+    }, next);
+  }
+
+  function getCors(url, success, error) {
+    var xhr = new XMLHttpRequest();
+    if ('withCredentials' in xhr) {
+      // XHR for Chrome/Firefox/Opera/Safari.
+      xhr.open('GET', url, true);
+    } else if (typeof XDomainRequest !== 'undefined') {
+      // XDomainRequest for IE.
+      xhr = new XDomainRequest();
+      xhr.open('GET', url);
+    } else {
+      throw new Error('cross-domain XHR not supported');
+    }
+
+    xhr.onload = success;
+    xhr.onerror = error;
+    xhr.send();
+    return xhr;
+  }
+
+  return {
+    version: '0.4.1',
+    findProperties: findProperties,
+    getCss: getReplacedViewportUnits,
+    init: initialize,
+    refresh: refresh
+  };
+
+}));