Implemented URL query parsing for initial token /opa/?token=abcde
[src/app-framework-demo.git] / afb-client / bower_components / viewport-units-buggyfill / viewport-units-buggyfill.js
1 /*!
2  * viewport-units-buggyfill v0.4.1
3  * @web: https://github.com/rodneyrehm/viewport-units-buggyfill/
4  * @author: Rodney Rehm - http://rodneyrehm.de/en/
5  */
6
7 (function (root, factory) {
8   'use strict';
9   if (typeof define === 'function' && define.amd) {
10     // AMD. Register as an anonymous module.
11     define([], factory);
12   } else if (typeof exports === 'object') {
13     // Node. Does not work with strict CommonJS, but
14     // only CommonJS-like enviroments that support module.exports,
15     // like Node.
16     module.exports = factory();
17   } else {
18     // Browser globals (root is window)
19     root.viewportUnitsBuggyfill = factory();
20   }
21 }(this, function () {
22   'use strict';
23   /*global document, window, location, XMLHttpRequest, XDomainRequest*/
24
25   var initialized = false;
26   var options;
27   var isMobileSafari = /(iPhone|iPod|iPad).+AppleWebKit/i.test(window.navigator.userAgent);
28   var viewportUnitExpression = /([+-]?[0-9.]+)(vh|vw|vmin|vmax)/g;
29   var forEach = [].forEach;
30   var dimensions;
31   var declarations;
32   var styleNode;
33   var isOldInternetExplorer = false;
34
35   // Do not remove the following comment!
36   // It is a conditional comment used to
37   // identify old Internet Explorer versions
38
39   /*@cc_on
40
41   @if (@_jscript_version <= 10)
42     isOldInternetExplorer = true;
43   @end
44
45   @*/
46
47   function debounce(func, wait) {
48     var timeout;
49     return function() {
50       var context = this;
51       var args = arguments;
52       var callback = function() {
53         func.apply(context, args);
54       };
55
56       clearTimeout(timeout);
57       timeout = setTimeout(callback, wait);
58     };
59   }
60
61   // from http://stackoverflow.com/questions/326069/how-to-identify-if-a-webpage-is-being-loaded-inside-an-iframe-or-directly-into-t
62   function inIframe() {
63     try {
64       return window.self !== window.top;
65     } catch (e) {
66       return true;
67     }
68   }
69
70   function initialize(initOptions) {
71     if (initialized) {
72       return;
73     }
74
75     if (initOptions === true) {
76       initOptions = {
77         force: true
78       };
79     }
80
81     options = initOptions || {};
82     options.isMobileSafari = isMobileSafari;
83
84     if (!options.force && !isMobileSafari && !isOldInternetExplorer && (!options.hacks || !options.hacks.required(options))) {
85       // this buggyfill only applies to mobile safari
86       return;
87     }
88
89     options.hacks && options.hacks.initialize(options);
90
91     initialized = true;
92     styleNode = document.createElement('style');
93     styleNode.id = 'patched-viewport';
94     document.head.appendChild(styleNode);
95
96     // Issue #6: Cross Origin Stylesheets are not accessible through CSSOM,
97     // therefore download and inject them as <style> to circumvent SOP.
98     importCrossOriginLinks(function() {
99       var _refresh = debounce(refresh, options.refreshDebounceWait || 100);
100       // doing a full refresh rather than updateStyles because an orientationchange
101       // could activate different stylesheets
102       window.addEventListener('orientationchange', _refresh, true);
103       // orientationchange might have happened while in a different window
104       window.addEventListener('pageshow', _refresh, true);
105
106       if (options.force || isOldInternetExplorer || inIframe()) {
107         window.addEventListener('resize', _refresh, true);
108         options._listeningToResize = true;
109       }
110
111       options.hacks && options.hacks.initializeEvents(options, refresh, _refresh);
112
113       refresh();
114     });
115   }
116
117   function updateStyles() {
118     styleNode.textContent = getReplacedViewportUnits();
119   }
120
121   function refresh() {
122     if (!initialized) {
123       return;
124     }
125
126     findProperties();
127
128     // iOS Safari will report window.innerWidth and .innerHeight as 0
129     // unless a timeout is used here.
130     // TODO: figure out WHY innerWidth === 0
131     setTimeout(function() {
132       updateStyles();
133     }, 1);
134   }
135
136   function findProperties() {
137     declarations = [];
138     forEach.call(document.styleSheets, function(sheet) {
139       if (sheet.ownerNode.id === 'patched-viewport' || !sheet.cssRules) {
140         // skip entire sheet because no rules ara present or it's the target-element of the buggyfill
141         return;
142       }
143
144       if (sheet.media && sheet.media.mediaText && window.matchMedia && !window.matchMedia(sheet.media.mediaText).matches) {
145         // skip entire sheet because media attribute doesn't match
146         return;
147       }
148
149       forEach.call(sheet.cssRules, findDeclarations);
150     });
151
152     return declarations;
153   }
154
155   function findDeclarations(rule) {
156     if (rule.type === 7) {
157       var value = rule.cssText;
158       viewportUnitExpression.lastIndex = 0;
159       if (viewportUnitExpression.test(value)) {
160         // KeyframesRule does not have a CSS-PropertyName
161         declarations.push([rule, null, value]);
162         options.hacks && options.hacks.findDeclarations(declarations, rule, null, value);
163       }
164
165       return;
166     }
167
168     if (!rule.style) {
169       if (!rule.cssRules) {
170         return;
171       }
172
173       forEach.call(rule.cssRules, function(_rule) {
174         findDeclarations(_rule);
175       });
176
177       return;
178     }
179
180     forEach.call(rule.style, function(name) {
181       var value = rule.style.getPropertyValue(name);
182       viewportUnitExpression.lastIndex = 0;
183       if (viewportUnitExpression.test(value)) {
184         declarations.push([rule, name, value]);
185         options.hacks && options.hacks.findDeclarations(declarations, rule, name, value);
186       }
187     });
188   }
189
190   function getReplacedViewportUnits() {
191     dimensions = getViewport();
192
193     var css = [];
194     var buffer = [];
195     var open;
196     var close;
197
198     declarations.forEach(function(item) {
199       var _item = overwriteDeclaration.apply(null, item);
200       var _open = _item.selector.length ? (_item.selector.join(' {\n') + ' {\n') : '';
201       var _close = new Array(_item.selector.length + 1).join('\n}');
202
203       if (!_open || _open !== open) {
204         if (buffer.length) {
205           css.push(open + buffer.join('\n') + close);
206           buffer.length = 0;
207         }
208
209         if (_open) {
210           open = _open;
211           close = _close;
212           buffer.push(_item.content);
213         } else {
214           css.push(_item.content);
215           open = null;
216           close = null;
217         }
218
219         return;
220       }
221
222       if (_open && !open) {
223         open = _open;
224         close = _close;
225       }
226
227       buffer.push(_item.content);
228     });
229
230     if (buffer.length) {
231       css.push(open + buffer.join('\n') + close);
232     }
233
234     return css.join('\n\n');
235   }
236
237   function overwriteDeclaration(rule, name, value) {
238     var _value = value.replace(viewportUnitExpression, replaceValues);
239     var  _selectors = [];
240
241     if (options.hacks) {
242       _value = options.hacks.overwriteDeclaration(rule, name, _value);
243     }
244
245     if (name) {
246       // skipping KeyframesRule
247       _selectors.push(rule.selectorText);
248       _value = name + ': ' + _value + ';';
249     }
250
251     var _rule = rule.parentRule;
252     while (_rule) {
253       _selectors.unshift('@media ' + _rule.media.mediaText);
254       _rule = _rule.parentRule;
255     }
256
257     return {
258       selector: _selectors,
259       content: _value
260     };
261   }
262
263   function replaceValues(match, number, unit) {
264     var _base = dimensions[unit];
265     var _number = parseFloat(number) / 100;
266     return (_number * _base) + 'px';
267   }
268
269   function getViewport() {
270     var vh = window.innerHeight;
271     var vw = window.innerWidth;
272
273     return {
274       vh: vh,
275       vw: vw,
276       vmax: Math.max(vw, vh),
277       vmin: Math.min(vw, vh)
278     };
279   }
280
281   function importCrossOriginLinks(next) {
282     var _waiting = 0;
283     var decrease = function() {
284       _waiting--;
285       if (!_waiting) {
286         next();
287       }
288     };
289
290     forEach.call(document.styleSheets, function(sheet) {
291       if (!sheet.href || origin(sheet.href) === origin(location.href)) {
292         // skip <style> and <link> from same origin
293         return;
294       }
295
296       _waiting++;
297       convertLinkToStyle(sheet.ownerNode, decrease);
298     });
299
300     if (!_waiting) {
301       next();
302     }
303   }
304
305   function origin(url) {
306     return url.slice(0, url.indexOf('/', url.indexOf('://') + 3));
307   }
308
309   function convertLinkToStyle(link, next) {
310     getCors(link.href, function() {
311       var style = document.createElement('style');
312       style.media = link.media;
313       style.setAttribute('data-href', link.href);
314       style.textContent = this.responseText;
315       link.parentNode.replaceChild(style, link);
316       next();
317     }, next);
318   }
319
320   function getCors(url, success, error) {
321     var xhr = new XMLHttpRequest();
322     if ('withCredentials' in xhr) {
323       // XHR for Chrome/Firefox/Opera/Safari.
324       xhr.open('GET', url, true);
325     } else if (typeof XDomainRequest !== 'undefined') {
326       // XDomainRequest for IE.
327       xhr = new XDomainRequest();
328       xhr.open('GET', url);
329     } else {
330       throw new Error('cross-domain XHR not supported');
331     }
332
333     xhr.onload = success;
334     xhr.onerror = error;
335     xhr.send();
336     return xhr;
337   }
338
339   return {
340     version: '0.4.1',
341     findProperties: findProperties,
342     getCss: getReplacedViewportUnits,
343     init: initialize,
344     refresh: refresh
345   };
346
347 }));