PageSourceSearch

https://www.hotelwawel.pl/js/restive.js?1572259631

js hotelwawel.pl collected 2026-10-05 22:10:07 UTC 252,782 bytes, 6,243 lines download raw bytes

1/*! PHP-JS | @link https://github.com/kvz/phpjs | @copyright Kevin van Zonneveld | @license MIT and GPL */
2function count (mixed_var, mode) {
3    // http://kevin.vanzonneveld.net
4    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
5    // +      input by: Waldo Malqui Silva
6    // +   bugfixed by: Soren Hansen
7    // +      input by: merabi
8    // +   improved by: Brett Zamir (http://brett-zamir.me)
9    // +   bugfixed by: Olivier Louvignes (http://mg-crea.com/)
10    // +   improved by: Obinwanne Hill on 22-03-2013 (https://about.me/obinwanne.hill)
11    // +   dependencies: isArray() and isObject()
12    // *     example 1: count([[0,0],[0,-4]], 'COUNT_RECURSIVE');
13    // *     returns 1: 6
14    // *     example 2: count({'one' : [1,2,3,4,5]}, 'COUNT_RECURSIVE');
15    // *     returns 2: 6
16    var key, nvld = false, cnt = 0;
17
18    switch(true)
19    {
20        case (mixed_var === null || typeof mixed_var === 'undefined'):
21            return 0;
22            break;
23
24        case (!isArray(mixed_var) && !isObject(mixed_var)):
25            nvld = true;
26            break;
27    }
28
29    switch(true)
30    {
31        case (mixed_var.hasOwnProperty('length')):
32            return mixed_var.length;
33            break;
34    }
35
36    //Return 1 if !isArray && !Object && does not have .length
37    switch(true)
38    {
39        case (nvld):
40            return 1;
41            break;
42    }
43
44    switch(true)
45    {
46        case (mode === 'COUNT_RECURSIVE'):
47            mode = 1;
48            break;
49    }
50
51    switch(true)
52    {
53        case (mode != 1):
54            mode = 0;
55            break;
56    }
57
58    for (key in mixed_var) {
59        switch(true)
60        {
61            case (mixed_var.hasOwnProperty(key)):
62                cnt++;
63                switch(true)
64                {
65                    case (mode == 1 && mixed_var[key] && (isArray(mixed_var[key]) || isObject(mixed_var[key]))):
66                        cnt += this.count(mixed_var[key], 1);
67                        break;
68                }
69                break;
70        }
71    }
72
73    return cnt;
74}
75
76function in_array (needle, haystack, argStrict) {
77    // http://kevin.vanzonneveld.net
78    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
79    // +   improved by: vlado houba
80    // +   input by: Billy
81    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
82    // *     example 1: in_array('van', ['Kevin', 'van', 'Zonneveld']);
83    // *     returns 1: true
84    // *     example 2: in_array('vlado', {0: 'Kevin', vlado: 'van', 1: 'Zonneveld'});
85    // *     returns 2: false
86    // *     example 3: in_array(1, ['1', '2', '3']);
87    // *     returns 3: true
88    // *     example 3: in_array(1, ['1', '2', '3'], false);
89    // *     returns 3: true
90    // *     example 4: in_array(1, ['1', '2', '3'], true);
91    // *     returns 4: false
92    var key = '',
93        strict = !! argStrict;
94
95    if (strict) {
96        for (key in haystack) {
97            if (haystack[key] === needle) {
98                return true;
99            }
100        }
101    } else {
102        for (key in haystack) {
103            if (haystack[key] == needle) {
104                return true;
105            }
106        }
107    }
108
109    return false;
110}
111
112function array_search (needle, haystack, argStrict) {
113    // http://kevin.vanzonneveld.net
114    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
115    // +      input by: Brett Zamir (http://brett-zamir.me)
116    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
117    // *     example 1: array_search('zonneveld', {firstname: 'kevin', middle: 'van', surname: 'zonneveld'});
118    // *     returns 1: 'surname'
119    // *     example 2: ini_set('phpjs.return_phpjs_arrays', 'on');
120    // *     example 2: var ordered_arr = array({3:'value'}, {2:'value'}, {'a':'value'}, {'b':'value'});
121    // *     example 2: var key = array_search(/val/g, ordered_arr); // or var key = ordered_arr.search(/val/g);
122    // *     returns 2: '3'
123
124    var strict = !!argStrict,
125        key = '';
126
127    if (haystack && typeof haystack === 'object' && haystack.change_key_case) { // Duck-type check for our own array()-created PHPJS_Array
128        return haystack.search(needle, argStrict);
129    }
130    if (typeof needle === 'object' && needle.exec) { // Duck-type for RegExp
131        if (!strict) { // Let's consider case sensitive searches as 
vendor: 4,380 bytes, lines 131-263
131strict
132            var flags = 'i' + (needle.global ? 'g' : '') +
133                (needle.multiline ? 'm' : '') +
134                (needle.sticky ? 'y' : ''); // sticky is FF only
135            needle = new RegExp(needle.source, flags);
136        }
137        for (key in haystack) {
138            if (needle.test(haystack[key])) {
139                return key;
140            }
141        }
142        return false;
143    }
144
145    for (key in haystack) {
146        if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
147            return key;
148        }
149    }
150
151    return false;
152}
153
154function array_keys (input, search_value, argStrict) {
155    // http://kevin.vanzonneveld.net
156    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
157    // +      input by: Brett Zamir (http://brett-zamir.me)
158    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
159    // +   improved by: jd
160    // +   improved by: Brett Zamir (http://brett-zamir.me)
161    // +   input by: P
162    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
163    // *     example 1: array_keys( {firstname: 'Kevin', surname: 'van Zonneveld'} );
164    // *     returns 1: {0: 'firstname', 1: 'surname'}
165
166    var search = typeof search_value !== 'undefined',
167        tmp_arr = [],
168        strict = !!argStrict,
169        include = true,
170        key = '';
171
172    if (input && typeof input === 'object' && input.change_key_case) { // Duck-type check for our own array()-created PHPJS_Array
173        return input.keys(search_value, argStrict);
174    }
175
176    for (key in input) {
177        if (input.hasOwnProperty(key)) {
178            include = true;
179            if (search) {
180                if (strict && input[key] !== search_value) {
181                    include = false;
182                }
183                else if (input[key] != search_value) {
184                    include = false;
185                }
186            }
187
188            if (include) {
189                tmp_arr[tmp_arr.length] = key;
190            }
191        }
192    }
193
194    return tmp_arr;
195}
196
197function array_values (input) {
198    // http://kevin.vanzonneveld.net
199    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
200    // +      improved by: Brett Zamir (http://brett-zamir.me)
201    // *     example 1: array_values( {firstname: 'Kevin', surname: 'van Zonneveld'} );
202    // *     returns 1: {0: 'Kevin', 1: 'van Zonneveld'}
203    var tmp_arr = [],
204        key = '';
205
206    if (input && typeof input === 'object' && input.change_key_case) { // Duck-type check for our own array()-created PHPJS_Array
207        return input.values();
208    }
209
210    for (key in input) {
211        tmp_arr[tmp_arr.length] = input[key];
212    }
213
214    return tmp_arr;
215}
216
217function array_combine (keys, values) {
218    // http://kevin.vanzonneveld.net
219    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
220    // +   improved by: Brett Zamir (http://brett-zamir.me)
221    // *     example 1: array_combine([0,1,2], ['kevin','van','zonneveld']);
222    // *     returns 1: {0: 'kevin', 1: 'van', 2: 'zonneveld'}
223    var new_array = {},
224        keycount = keys && keys.length,
225        i = 0;
226
227    // input sanitation
228    if (typeof keys !== 'object' || typeof values !== 'object' || // Only accept arrays or array-like objects
229        typeof keycount !== 'number' || typeof values.length !== 'number' || !keycount) { // Require arrays to have a count
230        return false;
231    }
232
233    // number of elements does not match
234    if (keycount != values.length) {
235        return false;
236    }
237
238    for (i = 0; i < keycount; i++) {
239        new_array[keys[i]] = values[i];
240    }
241
242    return new_array;
243}
244
245function implode (glue, pieces) {
246    // http://kevin.vanzonneveld.net
247    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
248    // +   improved by: Waldo Malqui Silva
249    // +   improved by: Itsacon (http://www.itsacon.net/)
250    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
251    // *     example 1: implode(' ', ['Kevin', 'van', 'Zonneveld']);
252    // *     returns 1: 'Kevin van Zonneveld'
253    // *     example 2: implode(' ', {first:'Kevin', last: 'van Zonneveld'});
254    // *     returns 2: 'Kevin van Zonneveld'
255    var i = '',
256        retVal = '',
257        tGlue = '';
258    if (arguments.length === 1) {
259        pieces = glue;
260        glue = '';
261    }
262    if (typeof(pieces) === 'object') {
263        for (i in pieces) {
264            retVal += tGlue + pieces[i];
265            tGlue = glue;
266        }
267        return retVal;
268    }
269    return pieces;
270}
271
272function explode (delimiter, string, limit) {
273
274    if ( arguments.length < 2 || typeof delimiter == 'undefined' || typeof string == 'undefined' ) return null;
275    if ( delimiter === '' || delimiter === false || delimiter === null) return false;
276    if ( typeof delimiter == 'function' || typeof delimiter == 'object' || typeof string == 'function' || typeof string == 'object'){
277        return { 0: '' };
278    }
279    if ( delimiter === true ) delimiter = '1';
280
281    // Here we go...
282    delimiter += '';
283    string += '';
284
285    var s = string.split( delimiter );
286
287
288    if ( typeof limit === 'undefined' ) return s;
289
290    // Support for limit
291    if ( limit === 0 ) limit = 1;
292
293    // Positive limit
294    if ( limit > 0 ){
295        if ( limit >= s.length ) return s;
296        return s.slice( 0, limit - 1 ).concat( [ s.slice( limit - 1 ).join( delimiter ) ] );
297    }
298
299    // Negative limit
300    if ( -limit >= s.length ) return [];
301
302    s.splice( s.length + limit );
303    return s;
304}
305
306function urlencode (str) {
307    // http://kevin.vanzonneveld.net
308    // + original by: Philip Peterson
309    // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
310    // + input by: AJ
311    // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
312    // + improved by: Brett Zamir (http://brett-zamir.me)
313    // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
314    // + input by: travc
315    // + input by: Brett Zamir (http://brett-zamir.me)
316    // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
317    // + improved by: Lars Fischer
318    // + input by: Ratheous
319    // + reimplemented by: Brett Zamir (http://brett-zamir.me)
320    // + bugfixed by: Joris
321    // + reimplemented by: Brett Zamir (http://brett-zamir.me)
322    // % note 1: This reflects PHP 5.3/6.0+ behavior
323    // % note 2: Please be aware that this function expects to encode into UTF-8 encoded strings, as found on
324    // % note 2: pages served as UTF-8
325    // * example 1: urlencode('Kevin van Zonneveld!');
326    // * returns 1: 'Kevin+van+Zonneveld%21'
327    // * example 2: urlencode('http://kevin.vanzonneveld.net/');
328    // * returns 2: 'http%3A%2F%2Fkevin.vanzonneveld.net%2F'
329    // * example 3: urlencode('http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a');
330    // * returns 3: 'http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a'
331    str = (str + '').toString();
332
333    // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current
334    // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following.
335    return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').
336        replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+');
337}
338
339function strrpos (haystack, needle, offset) {
340    // http://kevin.vanzonneveld.net
341    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
342    // +   bugfixed by: Onno Marsman
343    // +   input by: saulius
344    // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
345    // *     example 1: strrpos('Kevin van Zonneveld', 'e');
346    // *     returns 1: 16
347    // *     example 2: strrpos('somepage.com', '.', false);
348    // *     returns 2: 8
349    // *     example 3: strrpos('baa', 'a', 3);
350    // *     returns 3: false
351    // *     example 4: strrpos('baa', 'a', 2);
352    // *     returns 4: 2
353    var i = -1;
354    if (offset) {
355        i = (haystack + '').slice(offset).lastIndexOf(needle); // strrpos' offset indicates starting point of range till end,
356        // while lastIndexOf's optional 2nd argument indicates ending point of range from the beginning
357        if (i !== -1) {
358            i += offset;
359        }
360    } else {
361        i = (haystack + '').lastIndexOf(needle);
362    }
363    return i >= 0 ? i : false;
364}
365
366function uasort (inputArr, sorter) {
367    // http://kevin.vanzonneveld.net
368    // +   original by: Brett Zamir (http://brett-zamir.me)
369    // +   improved by: Brett Zamir (http://brett-zamir.me)
370    // +   improved by: Theriault
371    // %        note 1: This function deviates from PHP in returning a copy of the array instead
372    // %        note 1: of acting by reference and returning true; this was necessary because
373    // %        note 1: IE does not allow deleting and re-adding of properties without caching
374    // %        note 1: of property position; you can set the ini of "phpjs.strictForIn" to true to
375    // %        note 1: get the PHP behavior, but use this only if you are in an environment
376    // %        note 1: such as Firefox extensions where for-in iteration order is fixed and true
377    // %        note 1: property deletion is supported. Note that we intend to implement the PHP
378    // %        note 1: behavior by default if IE ever does allow it; only gives shallow copy since
379    // %        note 1: is by reference in PHP anyways
380    // *     example 1: fruits = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'};
381    // *     example 1: fruits = uasort(fruits, function (a, b) { if (a > b) {return 1;}if (a < b) {return -1;} return 0;});
382    // *     results 1: fruits == {c: 'apple', b: 'banana', d: 'lemon', a: 'orange'}
383    var valArr = [],
384        tempKeyVal, tempValue, ret, k = '',
385        i = 0,
386        strictForIn = false,
387        populateArr = {};
388
389    if (typeof sorter === 'string') {
390        sorter = this[sorter];
391    } else if (Object.prototype.toString.call(sorter) === '[object Array]') {
392        sorter = this[sorter[0]][sorter[1]];
393    }
394
395    // BEGIN REDUNDANT
396    this.php_js = this.php_js || {};
397    this.php_js.ini = this.php_js.ini || {};
398    // END REDUNDANT
399    strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js.ini['phpjs.strictForIn'].local_value !== 'off';
400    populateArr = strictForIn ? inputArr : populateArr;
401
402
403    for (k in inputArr) { // Get key and value arrays
404        if (inputArr.hasOwnProperty(k)) {
405            valArr.push([k, inputArr[k]]);
406            if (strictForIn) {
407                delete inputArr[k];
408            }
409        }
410    }
411    valArr.sort(function (a, b) {
412        return sorter(a[1], b[1]);
413    });
414
415    for (i = 0; i < valArr.length; i++) { // Repopulate the old array
416        populateArr[valArr[i][0]] = valArr[i][1];
417    }
418
419    return strictForIn || populateArr;
420}
421
422function microtime (get_as_float) {
423    // http://kevin.vanzonneveld.net
424    // +   original by: Paulo Freitas
425    // *     example 1: timeStamp = microtime(true);
426    // *     results 1: timeStamp > 1000000000 && timeStamp < 2000000000
427    var now = new Date().getTime() / 1000;
428    var s = parseInt(now, 10);
429
430    return (get_as_float) ? now : (Math.round((now - s) * 1000) / 1000) + ' ' + s;
431}
432
433/*! md5.js - MD5 Message-Digest - v2.0.0 | @copyright 1999,2002 Masanao Izumo <[email protected]>  */
434/* md5.js - MD5 Message-Digest
435 * Copyright (C) 1999,2002 Masanao Izumo <[email protected]>
436 * Version: 2.0.0
437 * LastModified: May 13 2002
438 *
439 * This program is free software.  You can redistribute it and/or modify
440 * it without any warranty.  This library calculates the MD5 based on RFC1321.
441 * See RFC1321 for more information and algorithm.
442 */
443
444/* Interface:
445 * md5_hexstr = md5(data);
446 */
447
448/* ChangeLog
449 * 2013/07/20: Updated by Obinwanne Ugwuh
450 * 2002/05/13: Version 2.0.0 released
451 * NOTICE: API is changed.
452 * 2002/04/15: Bug fix about MD5 length.
453 */
454(function() {
455    var MD5_T = new Array(0x00000000, 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391);
456
457    var MD5_round1 = new Array(new Array(0, 7, 1), new Array(1, 12, 2), new Array(2, 17, 3), new Array(3, 22, 4), new Array(4, 7, 5), new Array(5, 12, 6), new Array(6, 17, 7), new Array(7, 22, 8), new Array(8, 7, 9), new Array(9, 12, 10), new Array(10, 17, 11), new Array(11, 22, 12), new Array(12, 7, 13), new Array(13, 12, 14), new Array(14, 17, 15), new Array(15, 22, 16));
458
459    var MD5_round2 = new Array(new Array(1, 5, 17), new Array(6, 9, 18), new Array(11, 14, 19), new Array(0, 20, 20), new Array(5, 5, 21), new Array(10, 9, 22), new Array(15, 14, 23), new Array(4, 20, 24), new Array(9, 5, 25), new Array(14, 9, 26), new Array(3, 14, 27), new Array(8, 20, 28), new Array(13, 5, 29), new Array(2, 9, 30), new Array(7, 14, 31), new Array(12, 20, 32));
460
461    var MD5_round3 = new Array(new Array(5, 4, 33), new Array(8, 11, 34), new Array(11, 16, 35), new Array(14, 23, 36), new Array(1, 4, 37), new Array(4, 11, 38), new Array(7, 16, 39), new Array(10, 23, 40), new Array(13, 4, 41), new Array(0, 11, 42), new Array(3, 16, 43), new Array(6, 23, 44), new Array(9, 4, 45), new Array(12, 11, 46), new Array(15, 16, 47), new Array(2, 23, 48));
462
463    var MD5_round4 = new Array(new Array(0, 6, 49), new Array(7, 10, 50), new Array(14, 15, 51), new Array(5, 21, 52), new Array(12, 6, 53), new Array(3, 10, 54), new Array(10, 15, 55), new Array(1, 21, 56), new Array(8, 6, 57), new Array(15, 10, 58), new Array(6, 15, 59), new Array(13, 21, 60), new Array(4, 6, 61), new Array(11, 10, 62), new Array(2, 15, 63), new Array(9, 21, 64));
464
465    function MD5_F(x, y, z) {
466        return (x & y) | (~x & z);
467    }
468
469    function MD5_G(x, y, z) {
470        return (x & z) | (y & ~z);
471    }
472
473    function MD5_H(x, y, z) {
474        return x ^ y ^ z;
475    }
476
477    function MD5_I(x, y, z) {
478        return y ^ (x | ~z);
479    }
480
481    var MD5_round = new Array(new Array(MD5_F, MD5_round1), new Array(MD5_G, MD5_round2), new Array(MD5_H, MD5_round3), new Array(MD5_I, MD5_round4));
482
483    function MD5_pack(n32) {
484        return String.fromCharCode(n32 & 0xff) + String.fromCharCode((n32 >>> 8) & 0xff) + String.fromCharCode((n32 >>> 16) & 0xff) + String.fromCharCode((n32 >>> 24) & 0xff);
485    }
486
487    function MD5_unpack(s4) {
488        return s4.charCodeAt(0) | (s4.charCodeAt(1) << 8) | (s4.charCodeAt(2) << 16) | (s4.charCodeAt(3) << 24);
489    }
490
491    function MD5_number(n) {
492        while (n < 0)
493            n += 4294967296;
494        while (n > 4294967295)
495            n -= 4294967296;
496        return n;
497    }
498
499    function MD5_apply_round(x, s, f, abcd, r) {
500        var a, b, c, d;
501        var kk, ss, ii;
502        var t, u;
503
504        a = abcd[0];
505        b = abcd[1];
506        c = abcd[2];
507        d = abcd[3];
508        kk = r[0];
509        ss = r[1];
510        ii = r[2];
511
512        u = f(s[b], s[c], s[d]);
513        t = s[a] + u + x[kk] + MD5_T[ii];
514        t = MD5_number(t);
515        t = ((t << ss) | (t >>> (32 - ss)));
516        t += s[b];
517        s[a] = MD5_number(t);
518    }
519
520    function utf8_encode(s)
521    {
522        for(var c, i = -1, l = (s = s.split("")).length, o = String.fromCharCode; ++i < l;
523            s[i] = (c = s[i].charCodeAt(0)) >= 127 ? o(0xc0 | (c >>> 6)) + o(0x80 | (c & 0x3f)) : s[i]
524            );
525        return s.join("");
526    }
527
528    function MD5_hash(data) {
529        var abcd, x, state, s;
530        var len, index, padLen, f, r;
531        var i, j, k;
532        var tmp;
533
534        if (/[\x80-\xFF]/.test(data)) {
535            data = utf8_encode(data);
536
537        }
538
539        state = new Array(0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476);
540        len = data.length;
541        index = len & 0x3f;
542        padLen = (index < 56) ? (56 - index) : (120 - index);
543        if (padLen > 0) {
544            data += "\x80";
545            for (i = 0; i < padLen - 1; i++)
546                data += "\x00";
547        }
548        data += MD5_pack(len * 8);
549        data += MD5_pack(0);
550        len += padLen + 8;
551        abcd = new Array(0, 1, 2, 3);
552        x = new Array(16);
553        s = new Array(4);
554
555        for (k = 0; k < len; k += 64) {
556            for (i = 0, j = k; i < 16; i++, j += 4) {
557                x[i] = data.charCodeAt(j) | (data.charCodeAt(j + 1) << 8) | (data.charCodeAt(j + 2) << 16) | (data.charCodeAt(j + 3) << 24);
558            }
559            for (i = 0; i < 4; i++)
560                s[i] = state[i];
561            for (i = 0; i < 4; i++) {
562                f = MD5_round[i][0];
563                r = MD5_round[i][1];
564                for (j = 0; j < 16; j++) {
565                    MD5_apply_round(x, s, f, abcd, r[j]);
566                    tmp = abcd[0];
567                    abcd[0] = abcd[3];
568                    abcd[3] = abcd[2];
569                    abcd[2] = abcd[1];
570                    abcd[1] = tmp;
571                }
572            }
573
574            for (i = 0; i < 4; i++) {
575                state[i] += s[i];
576                state[i] = MD5_number(state[i]);
577            }
578        }
579
580        return MD5_pack(state[0]) + MD5_pack(state[1]) + MD5_pack(state[2]) + MD5_pack(state[3]);
581    }
582
583    function MD5_hexhash(data) {
584        var i, out, c;
585        var bit128;
586
587        bit128 = MD5_hash(data);
588        out = "";
589        for (i = 0; i < 16; i++) {
590            c = bit128.charCodeAt(i);
591            out += "0123456789abcdef".charAt((c >> 4) & 0xf);
592            out += "0123456789abcdef".charAt(c & 0xf);
593        }
594        return out;
595    }
596
597    md5 = function (s) {
598        return MD5_hexhash(s);
599    }
600})();
601
602/*! json2.js | @link https://github.com/douglascrockford/JSON-js | @copyright Douglas Crockford <[email protected]> */
603
604// Create a JSON object only if one does not already exist. We create the
605// methods in a closure to avoid creating global variables.
606
607if (typeof JSON !== 'object') {
608    JSON = {};
609}
610
611(function () {
612    'use strict';
613
614    function f(n) {
615        // Format integers to have at least two digits.
616        return n < 10 ? '0' + n : n;
617    }
618
619    if (typeof Date.prototype.toJSON !== 'function') {
620
621        Date.prototype.toJSON = function () {
622
623            return isFinite(this.valueOf())
624                ? this.getUTCFullYear()     + '-' +
625                f(this.getUTCMonth() + 1) + '-' +
626                f(this.getUTCDate())      + 'T' +
627                f(this.getUTCHours())     + ':' +
628                f(this.getUTCMinutes())   + ':' +
629                f(this.getUTCSeconds())   + 'Z'
630                : null;
631        };
632
633        String.prototype.toJSON      =
634            Number.prototype.toJSON  =
635                Boolean.prototype.toJSON = function () {
636                    return this.valueOf();
637                };
638    }
639
640    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
641        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
642        gap,
643        indent,
644        meta = {    // table of character substitutions
645            '\b': '\\b',
646            '\t': '\\t',
647            '\n': '\\n',
648            '\f': '\\f',
649            '\r': '\\r',
650            '"' : '\\"',
651            '\\': '\\\\'
652        },
653        rep;
654
655
656    function quote(string) {
657
658// If the string contains no control characters, no quote characters, and no
659// backslash characters, then we can safely slap some quotes around it.
660// Otherwise we must also replace the offending characters with safe escape
661// sequences.
662
663        escapable.lastIndex = 0;
664        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
665            var c = meta[a];
666            return typeof c === 'string'
667                ? c
vendor: 8,717 bytes, lines 668-915
668                : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
669        }) + '"' : '"' + string + '"';
670    }
671
672
673    function str(key, holder) {
674
675// Produce a string from holder[key].
676
677        var i,          // The loop counter.
678            k,          // The member key.
679            v,          // The member value.
680            length,
681            mind = gap,
682            partial,
683            value = holder[key];
684
685// If the value has a toJSON method, call it to obtain a replacement value.
686
687        if (value && typeof value === 'object' &&
688            typeof value.toJSON === 'function') {
689            value = value.toJSON(key);
690        }
691
692// If we were called with a replacer function, then call the replacer to
693// obtain a replacement value.
694
695        if (typeof rep === 'function') {
696            value = rep.call(holder, key, value);
697        }
698
699// What happens next depends on the value's type.
700
701        switch (typeof value) {
702            case 'string':
703                return quote(value);
704
705            case 'number':
706
707// JSON numbers must be finite. Encode non-finite numbers as null.
708
709                return isFinite(value) ? String(value) : 'null';
710
711            case 'boolean':
712            case 'null':
713
714// If the value is a boolean or null, convert it to a string. Note:
715// typeof null does not produce 'null'. The case is included here in
716// the remote chance that this gets fixed someday.
717
718                return String(value);
719
720// If the type is 'object', we might be dealing with an object or an array or
721// null.
722
723            case 'object':
724
725// Due to a specification blunder in ECMAScript, typeof null is 'object',
726// so watch out for that case.
727
728                if (!value) {
729                    return 'null';
730                }
731
732// Make an array to hold the partial results of stringifying this object value.
733
734                gap += indent;
735                partial = [];
736
737// Is the value an array?
738
739                if (Object.prototype.toString.apply(value) === '[object Array]') {
740
741// The value is an array. Stringify every element. Use null as a placeholder
742// for non-JSON values.
743
744                    length = value.length;
745                    for (i = 0; i < length; i += 1) {
746                        partial[i] = str(i, value) || 'null';
747                    }
748
749// Join all of the elements together, separated with commas, and wrap them in
750// brackets.
751
752                    v = partial.length === 0
753                        ? '[]'
754                        : gap
755                        ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
756                        : '[' + partial.join(',') + ']';
757                    gap = mind;
758                    return v;
759                }
760
761// If the replacer is an array, use it to select the members to be stringified.
762
763                if (rep && typeof rep === 'object') {
764                    length = rep.length;
765                    for (i = 0; i < length; i += 1) {
766                        if (typeof rep[i] === 'string') {
767                            k = rep[i];
768                            v = str(k, value);
769                            if (v) {
770                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
771                            }
772                        }
773                    }
774                } else {
775
776// Otherwise, iterate through all of the keys in the object.
777
778                    for (k in value) {
779                        if (Object.prototype.hasOwnProperty.call(value, k)) {
780                            v = str(k, value);
781                            if (v) {
782                                partial.push(quote(k) + (gap ? ': ' : ':') + v);
783                            }
784                        }
785                    }
786                }
787
788// Join all of the member texts together, separated with commas,
789// and wrap them in braces.
790
791                v = partial.length === 0
792                    ? '{}'
793                    : gap
794                    ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
795                    : '{' + partial.join(',') + '}';
796                gap = mind;
797                return v;
798        }
799    }
800
801// If the JSON object does not yet have a stringify method, give it one.
802
803    if (typeof JSON.stringify !== 'function') {
804        JSON.stringify = function (value, replacer, space) {
805
806// The stringify method takes a value and an optional replacer, and an optional
807// space parameter, and returns a JSON text. The replacer can be a function
808// that can replace values, or an array of strings that will select the keys.
809// A default replacer method can be provided. Use of the space parameter can
810// produce text that is more easily readable.
811
812            var i;
813            gap = '';
814            indent = '';
815
816// If the space parameter is a number, make an indent string containing that
817// many spaces.
818
819            if (typeof space === 'number') {
820                for (i = 0; i < space; i += 1) {
821                    indent += ' ';
822                }
823
824// If the space parameter is a string, it will be used as the indent string.
825
826            } else if (typeof space === 'string') {
827                indent = space;
828            }
829
830// If there is a replacer, it must be a function or an array.
831// Otherwise, throw an error.
832
833            rep = replacer;
834            if (replacer && typeof replacer !== 'function' &&
835                (typeof replacer !== 'object' ||
836                    typeof replacer.length !== 'number')) {
837                throw new Error('JSON.stringify');
838            }
839
840// Make a fake root object containing our value under the key of ''.
841// Return the result of stringifying the value.
842
843            return str('', {'': value});
844        };
845    }
846
847
848// If the JSON object does not yet have a parse method, give it one.
849
850    if (typeof JSON.parse !== 'function') {
851        JSON.parse = function (text, reviver) {
852
853// The parse method takes a text and an optional reviver function, and returns
854// a JavaScript value if the text is a valid JSON text.
855
856            var j;
857
858            function walk(holder, key) {
859
860// The walk method is used to recursively walk the resulting structure so
861// that modifications can be made.
862
863                var k, v, value = holder[key];
864                if (value && typeof value === 'object') {
865                    for (k in value) {
866                        if (Object.prototype.hasOwnProperty.call(value, k)) {
867                            v = walk(value, k);
868                            if (v !== undefined) {
869                                value[k] = v;
870                            } else {
871                                delete value[k];
872                            }
873                        }
874                    }
875                }
876                return reviver.call(holder, key, value);
877            }
878
879
880// Parsing happens in four stages. In the first stage, we replace certain
881// Unicode characters with escape sequences. JavaScript handles many characters
882// incorrectly, either silently deleting them, or treating them as line endings.
883
884            text = String(text);
885            cx.lastIndex = 0;
886            if (cx.test(text)) {
887                text = text.replace(cx, function (a) {
888                    return '\\u' +
889                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
890                });
891            }
892
893// In the second stage, we run the text against regular expressions that look
894// for non-JSON patterns. We are especially concerned with '()' and 'new'
895// because they can cause invocation, and '=' because it can cause mutation.
896// But just to be safe, we want to reject all unexpected forms.
897
898// We split the second stage into 4 regexp operations in order to work around
899// crippling inefficiencies in IE's and Safari's regexp engines. First we
900// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
901// replace all simple value tokens with ']' characters. Third, we delete all
902// open brackets that follow a colon or comma or that begin the text. Finally,
903// we look to see that the remaining characters are only whitespace or ']' or
904// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
905
906            if (/^[\],:{}\s]*$/
907                .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
908                .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
909                .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
910
911// In the third stage we use the eval function to compile the text into a
912// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
913// in JavaScript: it can begin a block or an object literal. We wrap the text
914// in parens to eliminate the ambiguity.
915
916                j = eval('(' + text + ')');
917
918// In the optional fourth stage, we recursively walk the new structure, passing
919// each name/value pair to a reviver function for possible transformation.
920
921                return typeof reviver === 'function'
922                    ? walk({'': j}, '')
923                    : j;
924            }
925
926// If the text is not JSON parseable, then a SyntaxError is thrown.
927
928            throw new SyntaxError('JSON.parse');
929        };
930    }
931}());
932
933/*! AmplifyJS-Store - v1.1.0 | @link http://amplifyjs.com/api/store/ | @copyright 2012 AppendTo <http://appendto.com/contact> | @license MIT and GPL V2 */
934(function( amplify, undefined ) {
935
936    var store = amplify.store = function( key, value, options ) {
937        var type = store.type;
938        if ( options && options.type && options.type in store.types ) {
939            type = options.type;
940        }
941        return store.types[ type ]( key, value, options || {} );
942    };
943
944    store.types = {};
945    store.type = null;
946    store.addType = function( type, storage ) {
947        if ( !store.type ) {
948            store.type = type;
949        }
950
951        store.types[ type ] = storage;
952        store[ type ] = function( key, value, options ) {
953            options = options || {};
954            options.type = type;
955            return store( key, value, options );
956        };
957    };
958    store.error = function() {
959        return "amplify.store quota exceeded";
960    };
961
962    var rprefix = /^__amplify__/;
963    function createFromStorageInterface( storageType, storage ) {
964        store.addType( storageType, function( key, value, options ) {
965            var storedValue, parsed, i, remove,
966                ret = value,
967                now = (new Date()).getTime();
968
969            if ( !key ) {
970                ret = {};
971                remove = [];
972                i = 0;
973                try {
974                    // accessing the length property works around a localStorage bug
975                    // in Firefox 4.0 where the keys don't update cross-page
976                    // we assign to key just to avoid Closure Compiler from removing
977                    // the access as "useless code"
978                    // https://bugzilla.mozilla.org/show_bug.cgi?id=662511
979                    key = storage.length;
980
981                    while ( key = storage.key( i++ ) ) {
982                        if ( rprefix.test( key ) ) {
983                            parsed = JSON.parse( storage.getItem( key ) );
984                            if ( parsed.expires && parsed.expires <= now ) {
985                                remove.push( key );
986                            } else {
987                                ret[ key.replace( rprefix, "" ) ] = parsed.data;
988                            }
989                        }
990                    }
991                    while ( key = remove.pop() ) {
992                        storage.removeItem( key );
993                    }
994                } catch ( error ) {}
995                return ret;
996            }
997
998            // protect against name collisions with direct storage
999            key = "__amplify__" + key;
1000
1001            if ( value === undefined ) {
1002                storedValue = storage.getItem( key );
1003                parsed = storedValue ? JSON.parse( storedValue ) : { expires: -1 };
1004                if ( parsed.expires && parsed.expires <= now ) {
1005                    storage.removeItem( key );
1006                } else {
1007                    return parsed.data;
1008                }
1009            } else {
1010                if ( value === null ) {
1011                    storage.removeItem( key );
1012                } else {
1013                    parsed = JSON.stringify({
1014                        data: value,
1015                        expires: options.expires ? now + options.expires : null
1016                    });
1017                    try {
1018                        storage.setItem( key, parsed );
1019                        // quota exceeded
1020                    } catch( error ) {
1021                        // expire old data and try again
1022                        store[ storageType ]();
1023                        try {
1024                            storage.setItem( key, parsed );
1025                        } catch( error ) {
1026                            throw store.error();
1027                        }
1028                    }
1029                }
1030            }
1031
1032            return ret;
1033        });
1034    }
1035
1036// localStorage + sessionStorage
1037// IE 8+, Firefox 3.5+, Safari 4+, Chrome 4+, Opera 10.5+, iPhone 2+, Android 2+
1038    for ( var webStorageType in { localStorage: 1, sessionStorage: 1 } ) {
1039        // try/catch for file protocol in Firefox and Private Browsing in Safari 5
1040        try {
1041            // Safari 5 in Private Browsing mode exposes localStorage
1042            // but doesn't allow storing data, so we attempt to store and remove an item.
1043            // This will unfortunately give us a false negative if we're at the limit.
1044            window[ webStorageType ].setItem( "__amplify__", "x" );
1045            window[ webStorageType ].removeItem( "__amplify__" );
1046            createFromStorageInterface( webStorageType, window[ webStorageType ] );
1047        } catch( e ) {}
1048    }
1049
1050// globalStorage
1051// non-standard: Firefox 2+
1052// https://developer.mozilla.org/en/dom/storage#globalStorage
1053    if ( !store.types.localStorage && window.globalStorage ) {
1054        // try/catch for file protocol in Firefox
1055        try {
1056            createFromStorageInterface( "globalStorage",
1057                window.globalStorage[ window.location.hostname ] );
1058            // Firefox 2.0 and 3.0 have sessionStorage and globalStorage
1059            // make sure we default to globalStorage
1060            // but don't default to globalStorage in 3.5+ which also has localStorage
1061            if ( store.type === "sessionStorage" ) {
1062                store.type = "globalStorage";
1063            }
1064        } catch( e ) {}
1065    }
1066
1067// userData
1068// non-standard: IE 5+
1069// http://msdn.microsoft.com/en-us/library/ms531424(v=vs.85).aspx
1070    (function() {
1071        // IE 9 has quirks in userData that are a huge pain
1072        // rather than finding a way to detect these quirks
1073        // we just don't register userData if we have localStorage
1074        if ( store.types.localStorage ) {
1075            return;
1076        }
1077
1078        // append to html instead of body so we can do this from the head
1079        var div = document.createElement( "div" ),
1080            attrKey = "amplify";
1081        div.style.display = "none";
1082        document.getElementsByTagName( "head" )[ 0 ].appendChild( div );
1083
1084        // we can't feature detect userData support
1085        // so just try and see if it fails
1086        // surprisingly, even just adding the behavior isn't enough for a failure
1087        // so we need to load the data as well
1088        try {
1089            div.addBehavior( "#default#userdata" );
1090            div.load( attrKey );
1091        } catch( e ) {
1092            div.parentNode.removeChild( div );
1093            return;
1094        }
1095
1096        store.addType( "userData", function( key, value, options ) {
1097            div.load( attrKey );
1098            var attr, parsed, prevValue, i, remove,
1099                ret = value,
1100                now = (new Date()).getTime();
1101
1102            if ( !key ) {
1103                ret = {};
1104                remove = [];
1105                i = 0;
1106                while ( attr = div.XMLDocument.documentElement.attributes[ i++ ] ) {
1107                    parsed = JSON.parse( attr.value );
1108                    if ( parsed.expires && parsed.expires <= now ) {
1109                        remove.push( attr.name );
1110                    } else {
1111                        ret[ attr.name ] = parsed.data;
1112                    }
1113                }
1114                while ( key = remove.pop() ) {
1115                    div.removeAttribute( key );
1116                }
1117                div.save( attrKey );
1118                return ret;
1119            }
1120
1121            // convert invalid characters to dashes
1122            // http://www.w3.org/TR/REC-xml/#NT-Name
1123            // simplified to assume the starting character is valid
1124            // also removed colon as it is invalid in HTML attribute names
1125            key = key.replace( /[^\-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/g, "-" );
1126            // adjust invalid starting character to deal with our simplified sanitization
1127            key = key.replace( /^-/, "_-" );
1128
1129            if ( value === undefined ) {
1130                attr = div.getAttribute( key );
1131                parsed = attr ? JSON.parse( attr ) : { expires: -1 };
1132                if ( parsed.expires && parsed.expires <= now ) {
1133                    div.removeAttribute( key );
1134                } else {
1135                    return parsed.data;
1136                }
1137            } else {
1138                if ( value === null ) {
1139                    div.removeAttribute( key );
1140                } else {
1141                    // we need to get the previous value in case we need to rollback
1142                    prevValue = div.getAttribute( key );
1143                    parsed = JSON.stringify({
1144                        data: value,
1145                        expires: (options.expires ? (now + options.expires) : null)
1146                    });
1147                    div.setAttribute( key, parsed );
1148                }
1149            }
1150
1151            try {
1152                div.save( attrKey );
1153                // quota exceeded
1154            } catch ( error ) {
1155                // roll the value back to the previous value
1156                if ( prevValue === null ) {
1157                    div.removeAttribute( key );
1158                } else {
1159                    div.setAttribute( key, prevValue );
1160                }
1161
1162                // expire old data and try again
1163                store.userData();
1164                try {
1165                    div.setAttribute( key, parsed );
1166                    div.save( attrKey );
1167                } catch ( error ) {
1168                    // roll the value back to the previous value
1169                    if ( prevValue === null ) {
1170                        div.removeAttribute( key );
1171                    } else {
1172                        div.setAttribute( key, prevValue );
1173                    }
1174                    throw store.error();
1175                }
1176            }
1177            return ret;
1178        });
1179    }() );
1180
1181// in-memory storage
1182// fallback for all browsers to enable the API even if we can't persist data
1183    (function() {
1184        var memory = {},
1185            timeout = {};
1186
1187        function copy( obj ) {
1188            return obj === undefined ? undefined : JSON.parse( JSON.stringify( obj ) );
1189        }
1190
1191        store.addType( "memory", function( key, value, options ) {
1192            if ( !key ) {
1193                return copy( memory );
1194            }
1195
1196            if ( value === undefined ) {
1197                return copy( memory[ key ] );
1198            }
1199
1200            if ( timeout[ key ] ) {
1201                clearTimeout( timeout[ key ] );
1202                delete timeout[ key ];
1203            }
1204
1205            if ( value === null ) {
1206                delete memory[ key ];
1207                return null;
1208            }
1209
1210            memory[ key ] = value;
1211            if ( options.expires ) {
1212                timeout[ key ] = setTimeout(function() {
1213                    delete memory[ key ];
1214                    delete timeout[ key ];
1215                }, options.expires );
1216            }
1217
1218            return value;
1219        });
1220    }() );
1221
1222}( this.amplify = this.amplify || {} ) );
1223
1224/*! ios-orientationchange-fix.js | Script by @scottjehl rebound by @wilto, modified by Peter Wooster | @link https://github.com/scottjehl/iOS-Orientationchange-Fix | @copyright Scott Jehl <@scottjehl> | @license MIT / GPLV2 */
1225(function(w){
1226
1227    // This fix addresses an Mobile Safari iOS bug, so return early if the UA claims it's something else.
1228    var ua = navigator.userAgent.toLowerCase();
1229    if( !( /iphone|ipad|ipod/.test( navigator.platform.toLowerCase() )
1230        && /os [1-5]_[0-9_]* like mac os x/i.test(ua)
1231        && ua.indexOf( "applewebkit" ) > -1
1232        && ua.indexOf( "crios") == -1  // chrome for iOS doesn't have the bug
1233        )){
1234        return;
1235    }
1236
1237    var doc = w.document;
1238
1239    if( !doc.querySelector ){ return; }
1240    var meta = doc.querySelector( "meta[name=viewport]" );
1241    if( !meta ){ return; }
1242    var initialContent = meta && meta.getAttribute( "content" );
1243    var disabledZoom = initialContent + ",maximum-scale=1";
1244    var enabledZoom = initialContent + ",maximum-scale=10";
1245    var enabled = true;
1246    var	x, y, z, aig;
1247    function restoreZoom(){
1248        meta.setAttribute( "content", enabledZoom );
1249        enabled = true;
1250    }
1251
1252    function disableZoom(){
1253        meta.setAttribute( "content", disabledZoom );
1254        enabled = false;
1255    }
1256
1257    function checkTilt( e ){
1258        var ori = w.orientation;
1259        // if it's landscape we're out of here
1260        if(90 == Math.abs(w.orientation)) {
1261            if(enabled)restoreZoom();
1262            return;
1263        }
1264
1265        aig = e.accelerationIncludingGravity;
1266        x = Math.abs( aig.x );
1267        y = Math.abs( aig.y );
1268
1269        // If in the danger zone where x is much greater than y turn off zoom
1270        if(y == 0 || (x/y) > 1.2){
1271            if(enabled)disableZoom();
1272        }else if( !enabled )restoreZoom();
1273    }
1274
1275    w.addEventListener( "orientationchange", restoreZoom, false );
1276    w.addEventListener( "devicemotion", checkTilt, false );
1277
1278})( this );
1279
1280
1281/*! jQuery resize event - v1.1 | @link http://benalman.com/projects/jquery-resize-plugin/ | Copyright (c) 2010 "Cowboy" Ben Alman | @license MIT/GPL */
1282// Script: jQuery resize event
1283//
1284// *Version: 1.1, Last updated: 3/14/2010*
1285//
1286// Project Home - http://benalman.com/projects/jquery-resize-plugin/
1287// GitHub       - http://github.com/cowboy/jquery-resize/
1288// Source       - http://github.com/cowboy/jquery-resize/raw/master/jquery.ba-resize.js
1289// (Minified)   - http://github.com/cowboy/jquery-resize/raw/master/jquery.ba-resize.min.js (1.0kb)
1290//
1291// About: License
1292//
1293// Copyright (c) 2010 "Cowboy" Ben Alman,
1294// Dual licensed under the MIT and GPL licenses.
1295// http://benalman.com/about/license/
1296//
1297// About: Examples
1298//
1299// This working example, complete with fully commented code, illustrates a few
1300// ways in which this plugin can be used.
1301//
1302// resize event - http://benalman.com/code/projects/jquery-resize/examples/resize/
1303//
1304// About: Support and Testing
1305//
1306// Information about what version or versions of jQuery this plugin has been
1307// tested with, what browsers it has been tested in, and where the unit tests
1308// reside (so you can test it yourself).
1309//
1310// jQuery Versions - 1.3.2, 1.4.1, 1.4.2
1311// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome, Opera 9.6-10.1.
1312// Unit Tests      - http://benalman.com/code/projects/jquery-resize/unit/
1313//
1314// About: Release History
1315//
1316// 1.1 - (3/14/2010) Fixed a minor bug that was causing the event to trigger
1317//       immediately after bind in some circumstances. Also changed $.fn.data
1318//       to $.data to improve performance.
1319// 1.0 - (2/10/2010) Initial release
1320
1321(function($,window,undefined){
1322    '$:nomunge'; // Used by YUI compressor.
1323
1324    // A jQuery object containing all non-window elements to which the resize
1325    // event is bound.
1326    var elems = $([]),
1327
1328    // Extend $.resize if it already exists, otherwise create it.
1329        jq_resize = $.resizecontainer = $.extend( $.resize, {} ),
1330
1331        timeout_id,
1332
1333    // Reused strings.
1334        str_setTimeout = 'setTimeout',
1335        str_resize = 'resizecontainer',
1336        str_data = str_resize + '-special-event',
1337        str_delay = 'delay',
1338        str_throttle = 'throttleWindow';
1339
1340    // Property: jQuery.resize.delay
1341    //
1342    // The numeric interval (in milliseconds) at which the resize event polling
1343    // loop executes. Defaults to 250.
1344
1345    jq_resize[ str_delay ] = 250;
1346
1347    // Property: jQuery.resize.throttleWindow
1348    //
1349    // Throttle the native window object resize event to fire no more than once
1350    // every <jQuery.resize.delay> milliseconds. Defaults to true.
1351    //
1352    // Because the window object has its own resize event, it doesn't need to be
1353    // provided by this plugin, and its execution can be left entirely up to the
1354    // browser. However, since certain browsers fire the resize event continuously
1355    // while others do not, enabling this will throttle the window resize event,
1356    // making event behavior consistent across all elements in all browsers.
1357    //
1358    // While setting this property to false will disable window object resize
1359    // event throttling, please note that this property must be changed before any
1360    // window object resize event callbacks are bound.
1361
1362    jq_resize[ str_throttle ] = true;
1363
1364    // Event: resize event
1365    //
1366    // Fired when an element's width or height changes. Because browsers only
1367    // provide this event for the window element, for other elements a polling
1368    // loop is initialized, running every <jQuery.resize.delay> milliseconds
1369    // to see if elements' dimensions have changed. You may bind with either
1370    // .resize( fn ) or .bind( "resize", fn ), and unbind with .unbind( "resize" ).
1371    //
1372    // Usage:
1373    //
1374    // > jQuery('selector').bind( 'resize', function(e) {
1375    // >   // element's width or height has changed!
1376    // >   ...
1377    // > });
1378    //
1379    // Additional Notes:
1380    //
1381    // * The polling loop is not created until at least one callback is actually
1382    //   bound to the 'resize' event, and this single polling loop is shared
1383    //   across all elements.
1384    //
1385    // Double firing issue in jQuery 1.3.2:
1386    //
1387    // While this plugin works in jQuery 1.3.2, if an element's event callbacks
1388    // are manually triggered via .trigger( 'resize' ) or .resize() those
1389    // callbacks may double-fire, due to limitations in the jQuery 1.3.2 special
1390    // events system. This is not an issue when using jQuery 1.4+.
1391    //
1392    // > // While this works in jQuery 1.4+
1393    // > $(elem).css({ width: new_w, height: new_h }).resize();
1394    // >
1395    // > // In jQuery 1.3.2, you need to do this:
1396    // > var elem = $(elem);
1397    // > elem.css({ width: new_w, height: new_h });
1398    // > elem.data( 'resize-special-event', { width: elem.width(), height: elem.height() } );
1399    // > elem.resize();
1400
1401    $.event.special[ str_resize ] = {
1402
1403        // Called only when the first 'resize' event callback is bound per element.
1404        setup: function() {
1405            // Since window has its own native 'resize' event, return false so that
1406            // jQuery will bind the event using DOM methods. Since only 'window'
1407            // objects have a .setTimeout method, this should be a sufficient test.
1408            // Unless, of course, we're throttling the 'resize' event for window.
1409            if ( !jq_resize[ str_throttle ] && this[ str_setTimeout ] ) { return false; }
1410
1411            var elem = $(this);
1412
1413            // Add this element to the list of internal elements to monitor.
1414            elems = elems.add( elem );
1415
1416            // Initialize data store on the element.
1417            $.data( this, str_data, { w: elem.width(), h: elem.height() } );
1418
1419            // If this is the first element added, start the polling loop.
1420            if ( elems.length === 1 ) {
1421                loopy();
1422            }
1423        },
1424
1425        // Called only when the last 'resize' event callback is unbound per element.
1426        teardown: function() {
1427            // Since window has its own native 'resize' event, return false so that
1428            // jQuery will unbind the event using DOM methods. Since only 'window'
1429            // objects have a .setTimeout method, this should be a sufficient test.
1430            // Unless, of course, we're throttling the 'resize' event for window.
1431            if ( !jq_resize[ str_throttle ] && this[ str_setTimeout ] ) { return false; }
1432
1433            var elem = $(this);
1434
1435            // Remove this element from the list of internal elements to monitor.
1436            elems = elems.not( elem );
1437
1438            // Remove any data stored on the element.
1439            elem.removeData( str_data );
1440
1441            // If this is the last element removed, stop the polling loop.
1442            if ( !elems.length ) {
1443                clearTimeout( timeout_id );
1444            }
1445        },
1446
1447        // Called every time a 'resize' event callback is bound per element (new in
1448        // jQuery 1.4).
1449        add: function( handleObj ) {
1450            // Since window has its own native 'resize' event, return false so that
1451            // jQuery doesn't modify the event object. Unless, of course, we're
1452            // throttling the 'resize' event for window.
1453            if ( !jq_resize[ str_throttle ] && this[ str_setTimeout ] ) { return false; }
1454
1455            var old_handler;
1456
1457            // The new_handler function is executed every time the event is triggered.
1458            // This is used to update the internal element data store with the width
1459            // and height when the event is triggered manually, to avoid double-firing
1460            // of the event callback. See the "Double firing issue in jQuery 1.3.2"
1461            // comments above for more information.
1462
1463            function new_handler( e, w, h ) {
1464                var elem = $(this),
1465                    data = $.data( this, str_data );
1466
1467                // If called from the polling loop, w and h will be passed in as
1468                // arguments. If called manually, via .trigger( 'resize' ) or .resize(),
1469                // those values will need to be computed.
1470                data.w = w !== undefined ? w : elem.width();
1471                data.h = h !== undefined ? h : elem.height();
1472
1473                old_handler.apply( this, arguments );
1474            }
1475
1476            // This may seem a little complicated, but it normalizes the special event
1477            // .add method between jQuery 1.4/1.4.1 and 1.4.2+
1478            if ( $.isFunction( handleObj ) ) {
1479                // 1.4, 1.4.1
1480                old_handler = handleObj;
1481                return new_handler;
1482            } else {
1483                // 1.4.2+
1484                old_handler = handleObj.handler;
1485                handleObj.handler = new_handler;
1486            }
1487        }
1488
1489    };
1490
1491    function loopy() {
1492
1493        // Start the polling loop, asynchronously.
1494        timeout_id = window[ str_setTimeout ](function(){
1495
1496            // Iterate over all elements to which the 'resize' event is bound.
1497            elems.each(function(){
1498                var elem = $(this),
1499                    width = elem.width(),
1500                    height = elem.height(),
1501                    data = $.data( this, str_data );
1502
1503                // If element size has changed since the last time, update the element
1504                // data store and trigger the 'resize' event.
1505                if ( width !== data.w || height !== data.h ) {
1506                    elem.trigger( str_resize, [ data.w = width, data.h = height ] );
1507                }
1508
1509            });
1510
1511            // Loop.
1512            loopy();
1513
1514        }, jq_resize[ str_delay ] );
1515
1516    }
1517
1518})(jQuery, window);
1519
1520/**
1521 * Count the number of substring occurrences
1522 * @param haystack {String} the string to search in
1523 * @param needle {String} the substring to search for
1524 * @return {Number}
1525 */
1526function substr_count(haystack, needle)
1527{
1528    var needle_esc = needle.replace(/(?=[\\^$*+?.\(\)|{\}[\]])/g, "\\");
1529    var pattern = new RegExp(""+needle_esc+"", "g");
1530    var count = haystack.match(pattern);
1531    return count ? count.length : 0;
1532}
1533
1534/**
1535 * Checks if a variable is a String
1536 * @param str {*} The variable to test
1537 * @return {Boolean}
1538 */
1539function isString(str)
1540{
1541    return typeof str == "string";
1542}
1543
1544/**
1545 * Checks if a variable is a Number
1546 * @param num {*} The variable to test
1547 * @return {Boolean}
1548 */
1549function isNumber(num)
1550{
1551    return (!isNaN(parseFloat(num)) && isFinite(num));
1552}
1553
1554/**
1555 * Checks if a variable is a Boolean
1556 * @param bool {*} The variable to test
1557 * @return {Boolean}
1558 */
1559function isBool(bool)
1560{
1561    return (bool === true || bool === false);
1562}
1563
1564/**
1565 * Checks if the variable is an array
1566 * @param arr {*} The variable to test
1567 * @return {Boolean}
1568 */
1569function isArray(arr) {
1570    return Object.prototype.toString.call(arr) === "[object Array]";
1571}
1572
1573/**
1574 * Checks if a variable is an Object
1575 * @param obj {*} The variable to test
1576 * @return {Boolean}
1577 */
1578function isObject(obj)
1579{
1580    switch(true)
1581    {
1582        case (isArray(obj)):
1583            return false;
1584            break;
1585    }
1586
1587    var is_empty_obj_bool;
1588    for ( var p in obj )
1589    {
1590        if (obj.hasOwnProperty(p))
1591        {
1592            is_empty_obj_bool = false;
1593            break;
1594        }
1595    }
1596    is_empty_obj_bool = (isBool(is_empty_obj_bool)) ? is_empty_obj_bool: true;
1597
1598    switch(true)
1599    {
1600        case (typeof obj === "object" && is_empty_obj_bool === false):
1601            return true;
1602            break;
1603    }
1604
1605    return false;
1606}
1607
1608/**
1609 * Checks if a variable is a Function
1610 * @param obj {*} The variable to test
1611 * @return {Boolean}
1612 */
1613function isFunction(obj) {
1614    return !!(obj && obj.constructor && obj.call && obj.apply);
1615}
1616
1617/**
1618 * Converts a string array to an integer array
1619 * It converts all the string values of an array into their integer equivalents
1620 * @param str_arr {Array} The array to convert
1621 * @return {Array}
1622 */
1623function arrayToInteger(str_arr)
1624{
1625    var int_arr_item_int,
1626        array_count_int,
1627        keys_arr = [],
1628        values_arr = [],
1629        values_int_arr = [],
1630        final_int_arr = [];
1631
1632    keys_arr = array_keys(str_arr);
1633    values_arr = array_values(str_arr);
1634
1635    array_count_int = count(str_arr);
1636    for(var i = 0; i < array_count_int; i++)
1637    {
1638        int_arr_item_int = parseInt(values_arr[i]);
1639        values_int_arr.push(int_arr_item_int);
1640    }
1641
1642    final_int_arr = array_combine(keys_arr, values_int_arr);
1643    return final_int_arr;
1644}
1645
1646/**
1647 * Checks to see if array has duplicate values
1648 * @param arr {Array} the array to check
1649 * @return {Boolean}
1650 */
1651function arrayHasDuplicates(arr) {
1652    var valuesSoFar = {},
1653        array_count_int = count(arr);
1654
1655    for (var i = 0; i < array_count_int; ++i) {
1656        var value = arr[i];
1657        if (Object.prototype.hasOwnProperty.call(valuesSoFar, value)) {
1658            return true;
1659        }
1660        valuesSoFar[value] = true;
1661    }
1662    return false;
1663}
1664
1665/**
1666 * Gets a value from an array derived after a tokenized string is exploded
1667 * @param str {String} the tokenized string that will be exploded to an array
1668 * @param delim {String} the delimiter
1669 * @param key {Integer} the position of the array to return
1670 * @return {String}
1671 */
1672function getValueAfterExplode(str, delim, key)
1673{
1674    var arr = explode(delim, str);
1675    return arr[key];
1676}
1677
1678/**
1679 * Sorts an array in numerical order and returns an array containing the keys of the array in the new sorted order
1680 * @param values_arr {Array} The array to sort
1681 * @return {Array}
1682 */
1683function getSortedKeys(values_arr)
1684{
1685    var array_with_keys = [];
1686    for (var i = 0; i < values_arr.length; i++) {
1687        array_with_keys.push({ key: i, value: values_arr[i] });
1688    }
1689
1690    array_with_keys.sort(function(a, b) {
1691        if (a.value < b.value) { return -1; }
1692        if (a.value > b.value) { return  1; }
1693        return 0;
1694    });
1695
1696    var keys = [];
1697    for (var i = 0; i < array_with_keys.length; i++) {
1698        keys.push(array_with_keys[i].key);
1699    }
1700
1701    return keys;
1702}
1703
1704/**
1705 * Finds the nearest matching number in an array containing integers
1706 * It is recommended that you sort the array in order before using it with this function
1707 * @param haystack_arr {Array} The array containing the integer values
1708 * @param needle_int {Number} The reference integer which is used to find the match
1709 * @param return_key_only_bool {Boolean} If true, will return the key position of the nearest match. Default is false.
1710 * @param is_ceil_bool {Boolean} If true, will return the nearest highest number even if a lower number is technically 'closer'. Default value is true.
1711 * @param disable_ceil_offset_int {Number} Please see explanation below.
1712 * For example, let's say needle_int is 120 and the nearest matching numbers are 115 on the lower end and 140 on the higher end
1713 * Being the is_ceil_bool is true by default, 140 would ordinarily be the nearest number selected. However, if disable_ceil_offset is set to 5, this will set is_ceil_bool to false, and 115 will be returned as the nearest number selected because the difference between it (the true nearest matching number) and 120 (needle_int) is 5 or less, even though needle_int is higher and under normal circumstances 120 would have been returned instead
1714 * @return {Number}
1715 */
1716function getClosestNumberMatchArray(haystack_arr, needle_int)
1717{
1718    var myArgs = Array.prototype.slice.call(arguments),
1719        return_key_only_bool = (isBool(myArgs[2])) ? myArgs[2]: false,
1720        is_ceil_bool = (isBool(myArgs[3])) ? myArgs[3]: true,
1721        disable_ceil_offset_int = (isNumber(myArgs[4])) ? myArgs[4] : 0,
1722        value_diff_int,
1723        value_diff_keys_sort_arr = [],
1724        value_diff_values_arr = [],
1725        key_final_int,
1726        value_final_int,
1727        value_final_needle_diff_int
1728        ;
1729
1730    haystack_arr = arrayToInteger(haystack_arr);
1731    needle_int = parseInt(needle_int);
1732
1733    for(var i = 0; i < count(haystack_arr); i++)
1734    {
1735        value_diff_int = needle_int - haystack_arr[i];
1736        value_diff_int = Math.abs(value_diff_int);
1737        value_diff_values_arr.push(value_diff_int);
1738    }
1739
1740    value_diff_keys_sort_arr = getSortedKeys(value_diff_values_arr);
1741    key_final_int = value_diff_keys_sort_arr[0];
1742    value_final_int = haystack_arr[key_final_int];
1743
1744    value_final_needle_diff_int = value_final_int - needle_int;
1745    value_final_needle_diff_int = Math.abs(value_final_needle_diff_int);
1746
1747    //Manage for when needle_int is higher than nearest matching number, and highest matching number is required
1748    switch(true)
1749    {
1750        case (value_final_int < needle_int):
1751            is_ceil_bool = (value_final_needle_diff_int <= disable_ceil_offset_int) ? false : is_ceil_bool;
1752            key_final_int = (is_ceil_bool) ? key_final_int + 1 : key_final_int;
1753            break;
1754    }
1755
1756    //return value or key
1757    value_final_int = haystack_arr[key_final_int];
1758    return (return_key_only_bool) ? key_final_int: value_final_int;
1759}
1760
1761/**
1762 * This function checks if a number is an integer decimal and if the integral part of the decimal is even
1763 * For example, 640.123 will be true, 641.123 will be false
1764 * @param number_int {Number} The Integer Decimal
1765 * @param allow_negative_bool {Boolean} This will allow negative numbers to be considered
1766 * @return {Boolean}
1767 */
1768function isEvenDecimal(number_int)
1769{
1770    var myArgs = Array.prototype.slice.call(arguments),
1771        allow_negative_bool = (isBool(myArgs[1])) ? myArgs[1]: false,
1772        number_temp_int,
1773        number_temp_mod_int;
1774
1775    number_temp_int = (number_int < 0 && allow_negative_bool) ? number_int * -1 : number_int;
1776    number_temp_mod_int = number_temp_int % 1;
1777
1778    //return false if Number is less than one or is not a decimal integer
1779    switch(true)
1780    {
1781        case (!isNumber(number_temp_int) || number_temp_int < 1 || number_temp_mod_int == 0):
1782            return false;
1783            break;
1784    }
1785
1786    //Check if integral part is even number
1787    number_temp_int = Math.floor(number_temp_int);
1788    number_temp_mod_int = number_temp_int % 2;
1789
1790    return !!((number_temp_mod_int == 0));
1791}
1792
1793/**
1794 * Retrieves the current and full URL of the document
1795 * @param option_flag_str {String} If present, specifies a specific part of the URL to return
1796 * The two options flags available are:
1797 * 1. bp [basepath] - Will return 'http://restive.io/index.html' if current URL is 'http://restive.io/index.html?id=1234'
1798 * 2. bd [basedir] - Will return 'http://restive.io/test' if current URL is 'http://restive.io/test/index.html?id=4'
1799 * 3. q [query] - Will return 'id=1234' if current URL is 'http://restive.io/index.html?id=1234'
1800 * @param url_str {String} By default, this function uses document.URL to capture the URL. You may provide your own url using this parameter
1801 * @return {String}
1802 */
1803function getUrl()
1804{
1805    var myArgs = Array.prototype.slice.call(arguments),
1806        option_flag_str = (isString(myArgs[0]) && myArgs[0] != '') ? myArgs[0]: '',
1807        url_str = (isString(myArgs[1]) && myArgs[1] != '') ? myArgs[1] : document.URL,
1808        url_temp_str,
1809        url_temp_arr = [],
1810        is_url_has_q_bool = /\?+/.test(url_str),
1811        url_match_arr = url_str.match(/^([h|f]{1}[t]{0,1}tp[s]{0,1}\:\/\/)([^ ]+?)\?([^ ]*)/i);
1812
1813    switch(true)
1814    {
1815        case (option_flag_str == 'basepath' || option_flag_str == 'bp'):
1816            return (is_url_has_q_bool) ? url_match_arr[1]+url_match_arr[2] : url_str;
1817            break;
1818
1819        case (option_flag_str == 'basedir' || option_flag_str == 'bd'):
1820            url_temp_str = (is_url_has_q_bool) ? url_match_arr[1]+url_match_arr[2] : url_str;
1821            url_temp_arr = explode('/', url_temp_str);
1822            url_temp_arr.pop();
1823
1824            return implode('/', url_temp_arr);
1825            break;
1826
1827        case (option_flag_str == 'query' || option_flag_str == 'q'):
1828            return (is_url_has_q_bool) ? url_match_arr[3]: "";
1829            break;
1830
1831        default:
1832            return url_str;
1833    }
1834}
1835
1836(function($){
1837
1838    /**
1839     * Determines if a given element is a child or descendant of another
1840     * @param {String} $elem_sel_parent_str The selector of the parent object
1841     * @param {String} $elem_sel_child_str The selector of the suspected child object
1842     * @return {Boolean}
1843     */
1844    window.elementIsChildOf = function($elem_sel_parent_str, $elem_sel_child_str){
1845        var result_bool = false,
1846            elem_parent = $(''+$elem_sel_parent_str+''),
1847            elem_child = $(''+$elem_sel_child_str+'');
1848
1849        switch(true)
1850        {
1851            case ($(elem_child).parents().index(elem_parent) != -1):
1852                result_bool = true;
1853                break;
1854        }
1855
1856        return result_bool;
1857    };
1858
1859    /**
1860     * Retrieves the text value of a JQuery Selector
1861     * @param {Object} el the JQuery Object/Element
1862     * @return {String}
1863     */
1864    window.getSelector = function(el){
1865        var $el = $(el);
1866
1867        var id = $el.attr("id");
1868        if (id) { //"should" only be one of these if theres an ID
1869            return "#"+ id;
1870        }
1871
1872        var node = $el[0].nodeName.toLowerCase();
1873        if(node == 'html' || node == 'body'){
1874            return node;
1875        }
1876
1877        var selector = $el.parents()
1878            .map(function() { return this.tagName; })
1879            .get().reverse().join(" ");
1880
1881        if (selector) {
1882            selector += " "+ $el[0].nodeName;
1883        }
1884
1885        var classNames = $el.attr("class");
1886        if (classNames) {
1887            selector += "." + $.trim(classNames).replace(/\s/gi, ".");
1888        }
1889
1890        var name = $el.attr('name');
1891        if (name) {
1892            selector += "[name='" + name + "']";
1893        }
1894        if (!name){
1895            var index = $el.index();
1896            if (index) {
1897                index = index + 1;
1898                selector += ":nth-child(" + index + ")";
1899            }
1900        }
1901        return selector;
1902    };
1903
1904})(jQuery);
1905
1906
1907/*! Restive.JS | @copyright 2013 Obinwanne Hill */
1908var Restive = (function(window, document, $) {
1909
1910    //Check for Dependency
1911    switch(true)
1912    {
1913        case (typeof $ != 'function'):
1914            //exit gracefully if missing
1915            throw 'Restive.JS requires JQuery to run!';
1916            break;
1917    }
1918
1919    //Define local vars
1920    var root = this,
1921        Restive,
1922        win = window,
1923        docElem = document.documentElement,
1924        $win = $(win),
1925        screen = win.screen,
1926        vSpan, vPitch, cSpan, cPitch, dSpan, dPitch, eSpan, ePitch,
1927        media  = win.matchMedia || win.msMatchMedia || Object
1928        ;
1929
1930    //Create window storage
1931    window.rstv_store = {'main': {}};
1932    window.parent.rstv_store = {'main': {}};
1933
1934    //Create window storage function
1935    window.rstv_store.storage = function(){
1936        var myArgs = Array.prototype.slice.call(arguments),
1937            key_str = myArgs[0],
1938            value_res = myArgs[1],
1939            is_value_valid_bool = !!((typeof value_res !== "undefined" && value_res !== null) && ((isString(value_res) && value_res != "") || isNumber(value_res) || (isArray(value_res) && count(value_res) > 0) || isBool(value_res) || isObject(value_res))),
1940            is_value_null_bool = !!((value_res === null))
1941            ;
1942
1943        switch(true)
1944        {
1945            case (is_value_valid_bool):
1946                window.rstv_store.main[""+key_str+""] = value_res;
1947                return;
1948                break;
1949
1950            case (is_value_null_bool):
1951                window.rstv_store.main[""+key_str+""] = null;
1952                return;
1953                break;
1954
1955            default:
1956                return window.rstv_store.main[""+key_str+""];
1957        }
1958    };
1959
1960    /**
1961     * Initialize and store some important default values.
1962     * Return false if initialization has already been performed in same session.
1963     * @return {Boolean}
1964     */
1965    var init = function () {
1966        //detect private browsing
1967        window.rstv_store.main["rstv_is_priv_browsing"] = !!((_detectPrivateBrowsing()));
1968
1969        var is_init_bool = store("rstv_is_init"),
1970            retr;
1971
1972        switch (true) {
1973            case (is_init_bool):
1974                store("rstv_timestamp_curr", microtime(true));
1975
1976                store("rstv_url", getUrl('bp'));
1977
1978                //load counter
1979                _loadCounter();
1980
1981                /** FIX FOR LOCAL BROWSER-BASED EMULATORS **/
1982                _fixForLocalDev();
1983
1984                //update the dimension and orientation info storage-wide
1985                _initDimensionVars();
1986                _updateDimensionStore();
1987                _updateOrientationStore();
1988
1989                retr = false;
1990                break;
1991
1992            default:
1993                //flag that defaults are set
1994                store("rstv_timestamp_curr", microtime(true));
1995                store("rstv_timestamp_init", store("rstv_timestamp_curr"));
1996                store("rstv_loaded_count", 0, '', {expires: 1500});
1997
1998                store("rstv_is_init", true);
1999
2000                store("rstv_url", getUrl('bp'));
2001                store("rstv_url_hash", md5(getUrl('bp')));
2002
2003                _initDimensionVars();
2004                _updateDimensionStore();
2005                store("rstv_ort_init", getOrientation());
2006                store("rstv_ort_curr", getOrientation());
2007
2008                //load counter
2009                _loadCounter();
2010
2011                retr = true;
2012        }
2013
2014        return retr;
2015    };
2016
2017    /**
2018     * Reinitializes the Restive Class on Demand
2019     * It resets Dimension, Orientation, and Timestamp Info
2020     * The Restive Class is initialized as soon as Restive.JS is called via <script\> tag. In certain circumstances
2021     * this might bring out a slight change in Dimension and Orientation Data especially for PCs.
2022     * Re-initialization will usually correct any discrepancies
2023     * NOTE: It is advised that you use this function only once, within document.ready, and before any other Restive-related methods
2024     */
2025    function reInit()
2026    {
2027        //reset timestamps
2028        store("rstv_timestamp_curr", microtime(true));
2029        store("rstv_timestamp_init", store("rstv_timestamp_curr"));
2030
2031        //update the dimension and orientation info storage-wide
2032        _initDimensionVars();
2033        _updateDimensionStore();
2034        store("rstv_ort_init", getOrientation());
2035        store("rstv_ort_curr", getOrientation());
2036    }
2037
2038    /**
2039     * Initializes important dimension variables to Local storage
2040     * @private
2041     */
2042    function _initDimensionVars()
2043    {
2044        store("rstv_var_doc_client_w", docElem.clientWidth);
2045        store("rstv_var_doc_client_h", docElem.clientHeight);
2046        store("rstv_var_win_outer_w", window.outerWidth);
2047        store("rstv_var_win_outer_h", window.outerHeight);
2048        store("rstv_var_win_screen_w", screen.width);
2049        store("rstv_var_win_screen_h", screen.height);
2050    }
2051
2052    /**
2053     * Keeps track of how many times Restive.JS is loaded in rapid succession in a single browser session
2054     * @private
2055     */
2056    function _loadCounter()
2057    {
2058        var load_count_int = parseInt(store("rstv_loaded_count"));
2059        switch(true)
2060        {
2061            case (!isNumber(load_count_int)):
2062                load_count_int = 0;
2063                break;
2064        }
2065        load_count_int++;
2066        store("rstv_loaded_count", load_count_int, '', {expires: 1500});
2067    }
2068
2069    /**
2070     * This is a special function to deal with certain issues experienced when using Restive.JS in Chrome Ripple
2071     * and other Browser Based Mobile Device emulators that load scripts more than once in rapid succession
2072     * when they are being initialized
2073     * @private
2074     */
2075    function _fixForLocalDev()
2076    {
2077        var load_count_int = parseInt(store("rstv_loaded_count")),
2078            ffld_is_init_bool = store("rstv_ffld_is_init");
2079
2080        switch(true)
2081        {
2082            case (load_count_int > 1):
2083                store("rstv_viewportW rstv_viewportW_dip rstv_viewportH rstv_viewportH_dip rstv_screenW rstv_screenH", null);
2084                store("rstv_is_ios rstv_is_android rstv_is_blackberry rstv_is_symbian rstv_is_windows rstv_is_windows_phone", null);
2085                store("rstv_is_android_1_ rstv_is_android_2_ rstv_is_android_3_", null);
2086                store("rstv_is_phone rstv_is_tablet rstv_is_tv rstv_is_pc", null);
2087                store("rstv_ort_curr rstv_timestamp_curr rstv_is_portrait rstv_is_landscape", null);
2088                store("rstv_multi_count rstv_multi_bpm_idx rstv_cache_bpm rstv_cache_bpm_lock rstv_cache_req rstv_cache_bpm_viewport_diff", null);
2089                store("rstv_user_agent", null);
2090
2091                store("rstv_timestamp_curr", microtime(true));
2092                store("rstv_ort_curr", getOrientation());
2093
2094                switch(true)
2095                {
2096                    case (!ffld_is_init_bool):
2097
2098                        store("rstv_timestamp_init", store("rstv_timestamp_curr"));
2099                        store("rstv_ort_init", getOrientation());
2100
2101                        //Mark that this function has been executed
2102                        store("rstv_ffld_is_init", true);
2103                        break;
2104                }
2105
2106                break;
2107        }
2108    }
2109
2110    /**
2111     * Detects whether private browsing is active or not
2112     * @return {Boolean}
2113     */
2114    function _detectPrivateBrowsing()
2115    {
2116        try {
2117            localStorage.setItem("__test", "data");
2118        }
2119        catch (e)
2120        {
2121            if (/QUOTA_?EXCEEDED/i.test(e.name)) {
2122                return true;
2123            }
2124        }
2125        return false;
2126    }
2127
2128    /**
2129     * Stores a value in LocalStorage [or other storage type], or retrieves previously stored value
2130     * Leverages AmplifyJS Store
2131     * @param key_str The identifier for the value being stored
2132     * @param value_res The value to store [optional]
2133     * @param type_str The type of storage format to be used
2134     * @param options_res A set of key/value pairs that relate to settings for storing the value
2135     * @return {*}
2136     */
2137    function store()
2138    {
2139        var myArgs = Array.prototype.slice.call(arguments);
2140        var is_priv_browsing_bool = window.rstv_store.main["rstv_is_priv_browsing"],
2141            key_str = myArgs[0],
2142            value_res = myArgs[1],
2143            type_str = ((typeof myArgs[2] !== "undefined" && myArgs[2] !== null) && (isString(myArgs[2]) && myArgs[2] != "")) ? myArgs[2] : 'ss',
2144            options_res = myArgs[3],
2145            store_func_name,
2146            store_func,
2147            list_del_key_arr = [],
2148            is_getall_bool = (isString(key_str) && key_str != "") ? false: true,
2149            is_value_valid_bool = !!((typeof value_res !== "undefined" && value_res !== null) && ((isString(value_res) && value_res != "") || isNumber(value_res) || (isArray(value_res) && count(value_res) > 0) || isBool(value_res) || isObject(value_res))),
2150            is_value_null_bool = !!((value_res === null));
2151
2152        try
2153        {
2154            switch(true)
2155            {
2156                case (is_priv_browsing_bool):
2157                    //Private Browsing Detected, Use Windows Store
2158                    store_func_name = 'storage';
2159                    store_func = window.rstv_store[store_func_name];
2160                    break;
2161
2162                default:
2163                    //Use AmplifyJS Store
2164                    switch(true)
2165                    {
2166                        case (type_str == 'ls'):
2167                            store_func_name = 'localStorage';
2168                            break;
2169
2170                        default:
2171                            store_func_name = 'sessionStorage';
2172                    }
2173                    store_func = amplify.store[store_func_name];
2174
2175                    //if sessionStorage is not supported, default to amplifyJS
2176                    switch(true)
2177                    {
2178                        case (!window.sessionStorage || !window.localStorage):
2179                            store_func = amplify.store;
2180                            break;
2181                    }
2182
2183                    //return all values if no key is provided
2184                    switch(true)
2185                    {
2186                        case (is_getall_bool):
2187                            return store_func();
2188                            break;
2189                    }
2190            }
2191
2192            //return stored value if empty value argument and value is not null
2193            switch(true)
2194            {
2195                case (!is_value_valid_bool && !is_value_null_bool):
2196                    return store_func(key_str);
2197                    break;
2198            }
2199
2200            //delete object if value is null
2201            switch(true)
2202            {
2203                case (is_value_null_bool):
2204                    //delete stored object(s)
2205                    list_del_key_arr = explode(" ", key_str);
2206                    for (var i = 0; i < count(list_del_key_arr); i++)
2207                    {
2208                        store_func(list_del_key_arr[i], null);
2209                    }
2210                    return null;
2211                    break;
2212            }
2213
2214            //store value
2215            store_func(key_str, null);
2216            store_func(key_str, value_res, options_res);
2217        }
2218        catch(e){
2219            alert(e);
2220            
2221        }
2222    }
2223
2224    /**
2225     * This function is used to track specific String values in a storage system
2226     * The two possible storage options are (1) Cookies, and (2) Local Storage
2227     * It will store individual values as a tokenized string.
2228     * For example, if you call this function on two strings 'trial' and 'error', the stored value will be 'trial|error'
2229     *
2230     * @param key_str {String} The identifier of the value being stored
2231     * @param value_str {String} The individual value to store and track
2232     * @param store_type_str {String} The storage type of the container that will hold the stored value. 'ck' represents 'Cookie', and 'ls' represents 'LocalStorage'
2233     * @param unique_bool {Boolean} The setting that determines if the individual values should be unique. If this is true, no two string values will be identical
2234     * @param expires_ck_int|expires_ls_int {Number} Expiry setting
2235     * @param reverse_order_bool {Boolean} This affects the order with which data is stored. If true, data will be stored in a LIFO (Last In - First Out) format. If false, data will be store in a FIFO (First In - First Out) format
2236     * @param delim_str {String} The character that will be used to delimit the stored string
2237     * @param data_count_int {Number} The number of individual
2238     * @return {Boolean}
2239     */
2240    function storeVarTracker(key_str, value_str)
2241    {
2242        /**
2243         * This function saves the current Restive.JS settings tracking code to history
2244         */
2245        var myArgs = Array.prototype.slice.call(arguments),
2246            store_type_str = (isString(myArgs[2]) && myArgs[2] != "") ? myArgs[2] : 'ck',
2247            unique_bool = (isBool(myArgs[3])) ? myArgs[3]: false,
2248            expires_ls_int = (isNumber(myArgs[4]) || isString(myArgs[4])) ? parseInt(myArgs[4]): '',
2249            expires_ck_int = (isNumber(myArgs[4]) || isString(myArgs[4])) ? parseInt(myArgs[4]): 30,
2250            reverse_order_bool = (isBool(myArgs[5])) ? myArgs[5]: true,
2251            delim_str = (isString(myArgs[6]) && myArgs[6] != "") ? myArgs[6]: '-!',
2252            data_count_int = (isNumber(myArgs[7]) || isString(myArgs[7])) ? parseInt(myArgs[7]): 60,
2253            history_tok_str,
2254            history_upd_tok_str,
2255            history_arr = [],
2256            history_upd_arr = []
2257            ;
2258
2259        //check if this tracking code exists
2260        history_tok_str = (store_type_str == 'ls') ? store(key_str) : $.cookie(key_str);
2261        switch(true)
2262        {
2263            case (history_tok_str === null || typeof history_tok_str === "undefined"):
2264                (store_type_str == 'ls') ? store(key_str, value_str,
2265                    '', {expires: expires_ls_int}) : $.cookie(key_str, value_str, { expires: expires_ck_int, path: '/' });
2266
2267                return true;
2268                break;
2269
2270            case (typeof history_tok_str !== "undefined" && history_tok_str !== null && history_tok_str != ""):
2271                //get cookie info and check if tracking cookie exists
2272                history_arr = explode(delim_str, history_tok_str);
2273                switch(true)
2274                {
2275                    case (in_array(value_str, history_arr) && unique_bool):
2276                        return false;
2277                        break;
2278
2279                    default:
2280                        //generate the current tracking code
2281                        switch(true)
2282                        {
2283                            case (reverse_order_bool):
2284                                history_arr.unshift(value_str);
2285                                history_upd_arr = history_arr.slice(0, data_count_int);
2286
2287                                history_upd_tok_str = implode(delim_str, history_upd_arr);
2288                                break;
2289
2290                            default:
2291                                history_arr.push(value_str);
2292                                history_upd_tok_str = implode(delim_str, history_arr);
2293                        }
2294
2295                        //store the tracking code
2296                        (store_type_str == 'ls') ? store(key_str, history_upd_tok_str, '', {expires: expires_ls_int}) : $.cookie(key_str, history_upd_tok_str, { expires: expires_ck_int, path: '/' });
2297
2298                        return true;
2299                }
2300                break;
2301        }
2302    }
2303
2304    /**
2305     * This function is used to validate a string value against the tokenized string stored via storeVarTracker()
2306     * It checks to see if the string value is one of the tokenized item. If yes, it returns true; if no, it returns false
2307     * For example if needle = 'trial', and the var_key_str identifies a stored string with value = 'trial|error', then validation will be successful
2308     * @param value_needle_str {String} The string value that will be validated against the stored value
2309     * @param key_str {String} The identifier of the value that was stored via storeVarTracker()
2310     * @param store_type_str {String} The storage type of the container holding the stored value. 'ck' represents 'Cookie', and 'ls' represents 'LocalStorage'
2311     * @param delim_str {String} The character that will be used to delimit the stored string
2312     * @return {Boolean}
2313     */
2314    function storeVarValidator(value_needle_str, key_str)
2315    {
2316        var myArgs = Array.prototype.slice.call(arguments),
2317            store_type_str = (isString(myArgs[2]) && myArgs[2] != "") ? myArgs[2] : 'ck',
2318            delim_str = (isString(myArgs[3]) && myArgs[3] != "") ? myArgs[3] : '-!',
2319            value_str = (store_type_str == 'ls') ? store(key_str) : $.cookie(key_str);
2320
2321        switch(true)
2322        {
2323            case (typeof value_str !== "undefined" && value_str !== null && value_str != ""):
2324                var value_arr = [];
2325                value_arr = explode(delim_str, value_str);
2326
2327                switch(true)
2328                {
2329                    case (in_array(value_needle_str, value_arr)):
2330                        //tracking code is in history
2331                        return true;
2332                        break;
2333
2334                    default:
2335                        return false;
2336                }
2337                break;
2338
2339            default:
2340                return false;
2341        }
2342    }
2343
2344    /**
2345     * Checks if a value stored in LocalStorage exists and contains a value
2346     * Also stores a value if provided if the value did not previously exist or was invali
2346d
2347     * @param key_str {String} The identifier for the value that was stored
2348     * @param value_store_res {*} The value to store [optional]
2349     * @return {Boolean}
2350     */
2351    function isStorageValueSet(key_str)
2352    {
2353        var myArgs = Array.prototype.slice.call(arguments),
2354            value_store_res = myArgs[1],
2355            value_retr_res = store(''+key_str+''),
2356            is_value_valid_bool = !!((typeof value_store_res !== "undefined" && value_store_res !== null)),
2357            is_store_value_set_bool = false
2358            ;
2359
2360        //Determine if store value exists and is valid
2361        switch(true)
2362        {
2363            case (isBool(value_retr_res) || (value_retr_res !== null && typeof value_retr_res !== "undefined" && value_retr_res != "")):
2364                is_store_value_set_bool = true;
2365                break;
2366        }
2367
2368        //Return result of check immediately if no value is provided
2369        switch(true)
2370        {
2371            case (!is_value_valid_bool):
2372                return is_store_value_set_bool;
2373                break;
2374        }
2375
2376        //Store value if it does not exist and/or is invalid.
2377        switch(true)
2378        {
2379            case (!is_store_value_set_bool):
2380                store(key_str, value_store_res);
2381                break;
2382        }
2383    }
2384
2385    /**
2386     * Increment (or Decrement) a stored variable
2387     * @param key_str {String} The identifier of the value that was stored
2388     * @param increment_value_int {Number} The size of the increment operation. Default is 1
2389     * @param is_decrement_bool {Boolean} If set to true, will decrement instead of increment
2390     * @return {Number|Boolean}
2391     */
2392    function incrementStorageValue(key_str)
2393    {
2394        var myArgs = Array.prototype.slice.call(arguments),
2395            increment_value_int = (isNumber(myArgs[1])) ? myArgs[1]: 1,
2396            is_decrement_bool = (isBool(myArgs[2])) ? myArgs[2]: false,
2397            value_int;
2398
2399        value_int = parseInt(store(key_str));
2400        switch(true)
2401        {
2402            case (!isNumber(value_int)):
2403                return false;
2404                break;
2405        }
2406
2407        value_int = (is_decrement_bool) ? value_int - increment_value_int: value_int + increment_value_int;
2408        store(key_str, value_int);
2409
2410        return value_int;
2411    }
2412
2413    /**
2414     * Returns a list of standard resolution dimensions
2415     * @param class_str {String} the class of dimensions to return. It could be 'w' = widths, or 'h' = heights
2416     * @return {Array}
2417     * @private
2418     */
2419    function _getResolutionDimensionList(class_str)
2420    {
2421        var std_w_arr = [120, 128, 160, 200, 240, 272, 300, 320, 352, 360, 480, 540, 576, 600, 640, 720, 768, 800, 864, 900, 1024, 1050, 1080, 1152, 1200, 1440, 1536, 1600, 1800, 2048, 2160, 2400, 3072, 3200, 4096, 4320, 4800],
2422            std_h_arr = [160, 240, 260, 320, 400, 432, 480, 640, 720, 800, 854, 960, 1024, 1136, 1152, 1280, 1360, 1366, 1400, 1440, 1600, 1680, 1920, 2048, 2560, 2880, 3200, 3840, 4096, 5120, 6400, 7680]
2423            ;
2424
2425        switch(true)
2426        {
2427            case (class_str == 'w'):
2428                return std_w_arr;
2429                break;
2430
2431            case (class_str == 'h'):
2432                return std_h_arr;
2433                break;
2434        }
2435    }
2436
2437    /**
2438     * Get the Viewport or Screen Dimensions of the Device
2439     * @param type_str {String} The type of operation to execute
2440     * vW = viewport width, vH = viewport height, sW = screen width, sH = screen height
2441     * @param adj_screen_size_bool {Boolean} This determines if the screen size result should be adjusted to return the nearest standard resolution. For example if actual screen height is 1184, 1280 will be returned as it is the nearest standard resolution height. Default is true
2442     * @return {*}
2443     * @private
2444     */
2445    function _getDimension(type_str)
2446    {
2447        var myArgs = Array.prototype.slice.call(arguments),
2448            adj_screen_size_bool = (isBool(myArgs[1])) ? myArgs[1]: true,
2449            dim_res,
2450            dim_res_adj,
2451            adj_dim_res_bool = false,
2452            is_pc_or_tv_bool = !!((isPC() || isTV())),
2453            pixel_ratio_device_int = getPixelRatio(),
2454            pixel_ratio_virtual_int,
2455            win_outer_w_int = store("rstv_var_win_outer_w"),
2456            win_outer_h_int = store("rstv_var_win_outer_h"),
2457            doc_client_w_int = store("rstv_var_doc_client_w"),
2458            doc_client_h_int = store("rstv_var_doc_client_h"),
2459            win_screen_w_int = store("rstv_var_win_screen_w"),
2460            win_screen_h_int = store("rstv_var_win_screen_h")
2461            ;
2462
2463        /**
2464         * Return dimensions quickly if device is PC
2465         */
2466        switch(true)
2467        {
2468            case (is_pc_or_tv_bool):
2469                switch(true)
2470                {
2471                    case (type_str == 'vW'):
2472                        dim_res = doc_client_w_int;
2473                        break;
2474
2475                    case (type_str == 'vH'):
2476                        dim_res = doc_client_h_int;
2477                        break;
2478
2479                    case (type_str == 'sW'):
2480                        dim_res = win_screen_w_int;
2481                        break;
2482
2483                    case (type_str == 'sH'):
2484                        dim_res = win_screen_h_int;
2485                        break;
2486                }
2487
2488                switch(true)
2489                {
2490                    case (type_str == 'vW' || type_str == 'vH'):
2491                        dim_res = (pixel_ratio_device_int >= 1.5) ? dim_res * pixel_ratio_device_int : dim_res;
2492                        break;
2493                }
2494
2495                dim_res = Math.floor(dim_res);
2496                return dim_res;
2497
2498                break;
2499        }
2500
2501        /**
2502         * If not PC, continue processing
2503         */
2504
2505        var device_user_agent_str = getUserAgent(),
2506            is_opera_browser_bool = /opera.+(mini|mobi)/i.test(device_user_agent_str),
2507            is_ios_bool = !!((isIOS())),
2508            is_symbian_bool = !!((isSymbian())),
2509            is_windows_bool = !!((isWindows())),
2510            is_android_bool = !!((isAndroid())),
2511            is_android_1_bool = !!((isAndroid('1.'))),
2512            is_android_2_bool = !!((isAndroid('2.'))),
2513            is_special_needs_bool = !!(((is_android_1_bool || is_android_2_bool) || is_symbian_bool || is_windows_bool)),
2514            viewport_w_int,
2515            viewport_h_int,
2516            screen_w_int = win_screen_w_int,
2517            screen_h_int = win_screen_h_int,
2518            screen_w_fix_int = screen_w_int,
2519            ort_w_int,
2520            ort_h_int,
2521            viewport_w_to_screen_w_ratio_int,
2522            screen_w_to_viewport_w_diff_int,
2523            screen_w_to_h_ratio_int,
2524            fixed_screen_dim_bool,
2525            std_w_arr = _getResolutionDimensionList('w'),
2526            std_h_arr = _getResolutionDimensionList('h'),
2527            std_w_temp_arr = std_w_arr,
2528            std_h_temp_arr = std_h_arr,
2529            is_landscape_v_bool,                    //viewport
2530            is_landscape_s_bool,                    //screen
2531            is_landscape_v_extended_verify_bool
2532            ;
2533
2534        /**
2535         * Get the viewport dimensions
2536         */
2537        switch(true)
2538        {
2539            case (is_special_needs_bool):
2540                viewport_w_int = (win_outer_w_int <= 0) ? doc_client_w_int : win_outer_w_int;
2541                viewport_h_int = (win_outer_h_int <= 0) ? doc_client_h_int : win_outer_h_int;
2542                ort_w_int = viewport_w_int;
2543                ort_h_int = viewport_h_int;
2544                break;
2545
2546            default:
2547                viewport_w_int = doc_client_w_int;
2548                viewport_h_int = doc_client_h_int;
2549                ort_w_int = doc_client_w_int;
2550                ort_h_int = doc_client_h_int;
2551        }
2552
2553        /**
2554         * Modify Screen Dimensions if Android 2 or Symbian Platform
2555         */
2556        switch(true)
2557        {
2558            case ((is_android_2_bool || is_symbian_bool) && !is_opera_browser_bool):
2559                screen_w_int = (win_outer_w_int <= 0) ? screen_w_int : win_outer_w_int;
2560                screen_h_int = (win_outer_h_int <= 0) ? screen_h_int : win_outer_h_int;
2561                break;
2562        }
2563
2564        //Determine orientation
2565        screen_w_to_h_ratio_int = screen_w_int/screen_h_int;
2566        screen_w_to_viewport_w_diff_int = screen_w_int - viewport_w_int;
2567        screen_w_to_viewport_w_diff_int = Math.abs(screen_w_to_viewport_w_diff_int);
2568
2569        is_landscape_v_extended_verify_bool = (is_opera_browser_bool && viewport_w_int < 260) ? ((screen_w_to_viewport_w_diff_int <= 4) && (screen_w_to_h_ratio_int >= 1) ? true : false) : true;
2570        is_landscape_v_bool = !!((ort_h_int <= ort_w_int) && is_landscape_v_extended_verify_bool);
2571        is_landscape_s_bool = !!((screen_h_int <= screen_w_int));
2572
2573        /**
2574         * Reduce resolution dimension list size if iOS
2575         * This improves the accuracy for first-generation iOS devices
2576         */
2577        switch(true)
2578        {
2579            case (is_ios_bool):
2580                std_w_temp_arr = std_w_temp_arr.slice(7);
2581                std_h_temp_arr = std_h_temp_arr.slice(6);
2582                break;
2583
2584            case (is_android_bool):
2585                std_w_temp_arr = std_w_temp_arr.slice(4);
2586                std_h_temp_arr = std_h_temp_arr.slice(3);
2587                break;
2588
2589            case (is_symbian_bool):
2590                std_w_temp_arr = std_w_temp_arr.slice(4);
2591                break;
2592        }
2593
2594        /**
2595         * Reverse resolution dimension list when orientation changes
2596         */
2597        switch(true)
2598        {
2599            case (is_landscape_v_bool):
2600                std_w_arr = std_h_temp_arr;
2601                std_h_arr = std_w_temp_arr;
2602                break;
2603
2604            default:
2605                std_w_arr = std_w_temp_arr;
2606                std_h_arr = std_h_temp_arr;
2607        }
2608
2609        /**
2610         * Get Dimensions
2611         */
2612        switch(true)
2613        {
2614            case (type_str == 'vW'):
2615                dim_res = viewport_w_int;
2616                break;
2617
2618            case (type_str == 'vH'):
2619                dim_res = viewport_h_int;
2620                break;
2621
2622            case (type_str == 'sW'):
2623                /**
2624                 * This aims to correct any screen dimension discrepancies that usually occur when the
2625                 * raw viewport dimensions say the orientation is in one mode, but the raw screen dimensions
2626                 * say it is in another mode. Certain devices e.g. iPad will not change screen dimensions as the
2627                 * orientation changes. When this happens, we reverse values for screen_w and screen_h to compensate
2628                 */
2629                fixed_screen_dim_bool = !!((is_landscape_v_bool === true && is_landscape_s_bool === false) || (is_landscape_v_bool === false && is_landscape_s_bool === true));
2630
2631                dim_res = (fixed_screen_dim_bool) ? screen_h_int : screen_w_int ;
2632
2633                //get the fixed screen width
2634                screen_w_fix_int = (fixed_screen_dim_bool) ? screen_h_int : screen_w_int ;
2635
2636                dim_res_adj = dim_res * pixel_ratio_device_int;
2637                adj_dim_res_bool = adj_screen_size_bool ? ((in_array(dim_res, std_w_arr) || in_array(dim_res_adj, std_w_arr)) ? false: true) : false;
2638                break;
2639
2640            case (type_str == 'sH'):
2641                /**
2642                 * This aims to correct any screen dimension discrepancies that usually occur when the
2643                 * raw viewport dimensions say the orientation is in one mode, but the raw screen dimensions
2644                 * say it is in another mode. Certain devices e.g. iPad will not change screen dimensions as the
2645                 * orientation changes. When this happens, we reverse values for screen_w and screen_h to compensate
2646                 */
2647                fixed_screen_dim_bool = !!((is_landscape_v_bool === true && is_landscape_s_bool === false) || (is_landscape_v_bool === false && is_landscape_s_bool === true));
2648
2649                dim_res = (fixed_screen_dim_bool) ? screen_w_int : screen_h_int ;
2650
2651                //get the fixed screen width
2652                screen_w_fix_int = (fixed_screen_dim_bool) ? screen_h_int : screen_w_int ;
2653
2654                dim_res_adj = dim_res * pixel_ratio_device_int;
2655                adj_dim_res_bool = adj_screen_size_bool ? ((in_array(dim_res, std_h_arr) || in_array(dim_res_adj, std_h_arr)) ? false: true) : false;
2656                break;
2657        }
2658
2659        /**
2660         * Get the virtual pixel ratio i.e. screen vs viewport dimensions
2661         */
2662        pixel_ratio_virtual_int = screen_w_fix_int/viewport_w_int;
2663
2664        /**
2665         * Return if Device Pixel Ratio is 1 or less and Virtual Pixel Ratio is less than 1.1
2666         */
2667        switch(true)
2668        {
2669            case (pixel_ratio_device_int <= 1 && pixel_ratio_virtual_int <= 1.1):
2670                switch(true)
2671                {
2672                    case (type_str == 'sW' && adj_dim_res_bool):
2673                        dim_res = getClosestNumberMatchArray(std_w_arr, dim_res, '', '', 8);
2674                        break;
2675
2676                    case (type_str == 'sH' && adj_dim_res_bool):
2677                        dim_res = getClosestNumberMatchArray(std_h_arr, dim_res, '', '', 8);
2678                        break;
2679                }
2680                return dim_res;
2681                break;
2682        }
2683
2684        /**
2685         * Continue if Pixel Ratio is greater than 1
2686         */
2687        switch(true)
2688        {
2689            case (is_ios_bool):
2690                dim_res = dim_res * pixel_ratio_device_int;
2691                break;
2692
2693            default:
2694                switch(true)
2695                {
2696                    case (!is_android_2_bool):
2697                        /**
2698                         * Case 1: Device Pixel Ratio is 1 or less, and Virtual Pixel Ratio is greater than 1.1
2699                         * Update Viewport Dimensions only. Do not update Screen Dimensions
2700                         * Case 2. Device Pixel Ratio is more than 1, and Virtual Pixel Ratio is less than or equal to 1.1
2701                         * Update both Viewport and Screen Dimensions
2702                         * Case 3. Device Pixel Ratio is more than 1, and Virtual Pixel Ratio is greater than 1.1
2703                         * Update Viewport Dimensions only. Do not update Screen Dimensions
2704                         */
2705                        switch(true)
2706                        {
2707                            //1
2708                            case (pixel_ratio_device_int <= 1 && pixel_ratio_virtual_int > 1.1):
2709                                dim_res = (in_array(type_str, ['vW', 'vH'])) ? dim_res * pixel_ratio_virtual_int : dim_res;
2710                                break;
2711                            //2
2712                            case (pixel_ratio_device_int > 1 && pixel_ratio_virtual_int <= 1.1):
2713                                switch(true)
2714                                {
2715                                    case (pixel_ratio_device_int <= 1.1):
2716                                        //Special Operation for some devices that report device pixel ratio slightly above one
2717                                        switch(true)
2718                                        {
2719                                            case (in_array(type_str, ['vW', 'vH'])):
2720                                                dim_res = dim_res * pixel_ratio_device_int;
2721                                                dim_res = (isEvenDecimal(dim_res)) ? Math.floor(dim_res) : dim_res;
2722                                                break;
2723                                        }
2724                                        break;
2725
2726                                    default:
2727                                        dim_res = dim_res * pixel_ratio_device_int;
2728                                }
2729                                break;
2730                            //3
2731                            case (pixel_ratio_device_int > 1 && pixel_ratio_virtual_int > 1.1):
2732                                switch(true)
2733                                {
2734                                    case (in_array(type_str, ['vW', 'vH'])):
2735                                        dim_res = dim_res * pixel_ratio_device_int;
2736                                        dim_res = (isEvenDecimal(dim_res)) ? Math.floor(dim_res) : Math.ceil(dim_res);
2737                                        break;
2738                                }
2739                                break;
2740                        }
2741                        break;
2742                }
2743
2744                /**
2745                 * Get the nearest standard screen widths or heights
2746                 */
2747                switch(true)
2748                {
2749                    case (type_str == 'sW' && adj_dim_res_bool):
2750                        dim_res = getClosestNumberMatchArray(std_w_arr, dim_res, '', '', 8);
2751                        break;
2752
2753                    case (type_str == 'sH' && adj_dim_res_bool):
2754                        dim_res = getClosestNumberMatchArray(std_h_arr, dim_res, '', '', 8);
2755                        break;
2756                }
2757        }
2758
2759        dim_res = Math.floor(dim_res);
2760        return dim_res;
2761    }
2762
2763    /**
2764     * Get the Viewport dimensions in Device-Independent Pixels
2765     * @param type_str {String} The type of operation. Either 'w' for width, or 'h' for height
2766     * @return {Number}
2767     * @private
2768     */
2769    function _getViewportDimensionDIP(type_str)
2770    {
2771        var dim_res,
2772            is_width_bool = !!((type_str == 'w')),
2773            is_pc_or_tv_bool = !!((isPC() || isTV())),
2774            pixel_ratio_int = getPixelRatio()
2775            ;
2776
2777        switch(true)
2778        {
2779            case (is_pc_or_tv_bool):
2780                //If pc or tv, moderate use of pixel ratio
2781                pixel_ratio_int = (pixel_ratio_int <= 1.5) ? 1 : pixel_ratio_int;
2782                break;
2783        }
2784        dim_res = (is_width_bool) ? viewportW()/pixel_ratio_int : viewportH()/pixel_ratio_int;
2785        return Math.round(dim_res);
2786    }
2787
2788    /**
2789     * Get the dimension of a DOM Element.
2790     * It uses the JQuery dimension functions e.g. width(), innerHeight(), etc.
2791     * @param el_obj {String} The JQuery element object
2792     * @param type_str {String} The type of operation. w = width, h = height
2793     * @param format_str {String} The dimension retrieval method to use. There are three as follows
2794     * 1: d = default = el_obj.width() or el_obj.height()
2795     * 2: i = inner = el_obj.innerWidth() or el_obj.innerHeight()
2796     * 3: o = outer = el_obj.outerWidth() or el_obj.outerHeight()
2797     * @param force_dip_bool {Boolean} Determines whether to consider the element dimensions in device-independent pixel format or not. true = do not use DIP, false [default] = use DIP
2798     * @return {Number|Boolean}
2799     * @private
2800     */
2801    function _getElementDimension(el_obj, type_str)
2802    {
2803        var myArgs = Array.prototype.slice.call(arguments),
2804            format_str = (isString(myArgs[2]) && myArgs[2] != "") ? myArgs[2]: 'd',
2805            force_dip_bool = (isBool(myArgs[3])) ? myArgs[3]: fal
2805se,
2806            dim_final_int
2807            ;
2808        type_str = type_str.toLowerCase();
2809
2810        switch(true)
2811        {
2812            case (type_str == 'w'):
2813                switch(true)
2814                {
2815                    case (format_str == 'i'):
2816                        dim_final_int = el_obj.innerWidth();
2817                        break;
2818
2819                    case (format_str == 'o'):
2820                        dim_final_int = el_obj.outerWidth();
2821                        break;
2822
2823                    default:
2824                        dim_final_int = el_obj.width();
2825                }
2826                break;
2827
2828            case (type_str == 'h'):
2829                switch(true)
2830                {
2831                    case (format_str == 'i'):
2832                        dim_final_int = el_obj.innerHeight();
2833                        break;
2834
2835                    case (format_str == 'o'):
2836                        dim_final_int = el_obj.outerHeight();
2837                        break;
2838
2839                    default:
2840                        dim_final_int = el_obj.height();
2841                }
2842                break;
2843
2844            default:
2845                dim_final_int = false;
2846        }
2847
2848        switch(true)
2849        {
2850            case (force_dip_bool === false):
2851                //Convert to Device Pixels
2852                dim_final_int = dim_final_int * getPixelRatio();
2853                break;
2854        }
2855
2856        return dim_final_int;
2857    }
2858
2859    /**
2860     * Get the width of a DOM element
2861     * @param el_obj {Object} The JQuery Element Object
2862     * @param dim_format_str {String} The dimension retrieval method to use.
2863     * @param force_dip_bool {Boolean} Flag for forced Device-Independent Pixel consideration
2864     * @return {Number|Boolean}
2865     * @private
2866     */
2867    function _elementW(el_obj){
2868        var myArgs = Array.prototype.slice.call(arguments),
2869            dim_format_str = myArgs[1],
2870            force_dip_bool = myArgs[2]
2871            ;
2872        return _getElementDimension(el_obj, 'w', dim_format_str, force_dip_bool);
2873    }
2874
2875    /**
2876     * Get the height of a DOM element
2877     * @param el_obj {Object} The JQuery Element Object
2878     * @param dim_format_str {String} The dimension retrieval method to use.
2879     * @param force_dip_bool {Boolean} Flag for forced Device-Independent Pixel consideration
2880     * @return {Number|Boolean}
2881     * @private
2882     */
2883    function _elementH(el_obj){
2884        var myArgs = Array.prototype.slice.call(arguments),
2885            dim_format_str = myArgs[1],
2886            force_dip_bool = myArgs[2]
2887            ;
2888        return _getElementDimension(el_obj, 'h', dim_format_str, force_dip_bool);
2889    }
2890
2891    /**
2892     * Get the width of the viewport
2893     * @return {*|Number}
2894     */
2895    function viewportW(){
2896        return (isStorageValueSet("rstv_viewportW")) ? store("rstv_viewportW"): _getDimension('vW', store("rstv_is_getdim_screen_adj"));
2897    }
2898
2899    /**
2900     * Get the height of the viewport
2901     * @return {*|Number}
2902     */
2903    function viewportH(){
2904        return (isStorageValueSet("rstv_viewportH")) ? store("rstv_viewportH"): _getDimension('vH', store("rstv_is_getdim_screen_adj"));
2905    }
2906
2907    /**
2908     * Get the width of the screen i.e. device width
2909     * @return {*|Number}
2910     */
2911    function screenW(){
2912        return (isStorageValueSet("rstv_screenW")) ? store("rstv_screenW"): _getDimension('sW', store("rstv_is_getdim_screen_adj"));
2913    }
2914
2915    /**
2916     * Get the height of the screen i.e. device height
2917     * @return {*|Number}
2918     */
2919    function screenH(){
2920        return (isStorageValueSet("rstv_screenH")) ? store("rstv_screenH"): _getDimension('sH', store("rstv_is_getdim_screen_adj"));
2921    }
2922
2923    /**
2924     * Get the Device-Independent Pixel width of the viewport
2925     */
2926    function pixelW()
2927    {
2928        return (isStorageValueSet("rstv_viewportW_dip")) ? store("rstv_viewportW_dip"): _getViewportDimensionDIP('w');
2929    }
2930
2931    /**
2932     * Get the Device-Independent Pixel height of the viewport
2933     */
2934    function pixelH()
2935    {
2936        return (isStorageValueSet("rstv_viewportH_dip")) ? store("rstv_viewportH_dip"): _getViewportDimensionDIP('h');
2937    }
2938
2939    /**
2940     * Resets/Updates the cached values (localStorage) of Viewport and Screen Dimension Info
2941     * @private
2942     */
2943    function _updateDimensionStore()
2944    {
2945        //reset
2946        store("rstv_viewportW rstv_viewportW_dip rstv_viewportH rstv_viewportH_dip rstv_screenW rstv_screenH", null);
2947
2948        //reload
2949        store("rstv_viewportW", viewportW());
2950        store("rstv_viewportH", viewportH());
2951        store("rstv_screenW", screenW());
2952        store("rstv_screenH", screenH());
2953        store("rstv_viewportW_dip", pixelW());
2954        store("rstv_viewportH_dip", pixelH());
2955    }
2956
2957    /**
2958     * Get the Device Pixel Ratio
2959     * @param decimal {Number} An optional number (integer or float) to check against actual pixel ratio
2960     * @return {Number|Boolean}
2961     */
2962    function getPixelRatio(decimal)
2963    {
2964        //check if pixel ratio check has already been done. If so, return stored value
2965        switch(true)
2966        {
2967            case (isStorageValueSet("rstv_pixel_ratio")):
2968                return store("rstv_pixel_ratio");
2969                break;
2970        }
2971
2972        var device_user_agent_str = getUserAgent(),
2973            is_opera_browser_bool = /opera.+(mini|mobi)/i.test(device_user_agent_str),
2974            doc_client_w = store("rstv_var_doc_client_w"),
2975            win_outer_w = store("rstv_var_win_outer_w"),
2976            win_screen_w = store("rstv_var_win_screen_w"),
2977            is_symbian_bool = !!(isSymbian()),
2978            is_windows_bool = !!(isWindows()),
2979            is_android_1_bool = !!((isAndroid('1.'))),
2980            is_android_2_bool = !!((isAndroid('2.'))),
2981            is_special_needs_bool = !!(((is_android_1_bool || is_android_2_bool) || is_symbian_bool || is_windows_bool)),
2982            is_windows_or_symbian_bool = !!(is_windows_bool || is_symbian_bool),
2983            viewport_w = (is_special_needs_bool) ? ((win_outer_w <= 0) ? doc_client_w : win_outer_w) : doc_client_w,
2984            screen_w = ((is_android_2_bool || is_symbian_bool) && !is_opera_browser_bool) ? ((win_outer_w <= 0) ? win_screen_w : win_outer_w) : win_screen_w,
2985            dPR,
2986            dPR_temp,
2987            dPR_virtual,
2988            dPR_retr
2989            ;
2990
2991        /**
2992         * Get the Pixel Ratio
2993         * Make Adjustments for when window.devicePixelRatio is 0
2994         */
2995        dPR_temp = win.devicePixelRatio;
2996        switch(true)
2997        {
2998            case (dPR_temp <= 0 || typeof dPR_temp === 'undefined' || dPR_temp === null):
2999                dPR_virtual = screen_w/viewport_w;
3000                dPR = dPR_virtual;
3001                switch(true)
3002                {
3003                    case (is_windows_or_symbian_bool):
3004                        switch(true)
3005                        {
3006                            case (dPR > 0.5 && dPR < 1.2):
3007                                dPR = 1;
3008                                break;
3009
3010                            case (dPR >= 1.2 && dPR < 2):
3011                                dPR = 1.5;
3012                                break;
3013
3014                            case (dPR >= 2 && dPR < 3):
3015                                dPR = 2;
3016                                break;
3017
3018                            case (dPR >= 3):
3019                                dPR = 3;
3020                                break;
3021
3022                            default:
3023                                dPR = 1;
3024                        }
3025                        break;
3026                }
3027                store("rstv_pixel_ratio_virtual", dPR_virtual);
3028                break;
3029
3030            default:
3031                dPR = dPR_temp;
3032        }
3033
3034        //Return Pixel Ratio variations
3035        switch(true)
3036        {
3037            case (!isNumber(decimal)):
3038                dPR_retr = dPR || (getPixelRatio(3) ? 3 : getPixelRatio(2) ? 2 : getPixelRatio(1.5) ? 1.5 : getPixelRatio(1) ? 1 : 0);
3039                store("rstv_pixel_ratio", dPR_retr);
3040                return dPR_retr;
3041                break;
3042        }
3043
3044        //Return false if not finite
3045        switch(true)
3046        {
3047            case (!isFinite(decimal)):
3048                return false;
3049                break;
3050        }
3051
3052        switch(true)
3053        {
3054            case (dPR && dPR > 0):
3055                return dPR >= decimal;
3056                break;
3057        }
3058
3059        //Revert to .matchMedia/.msMatchMedia for Gecko (FF6+) support
3060        decimal = 'only all and (min--moz-device-pixel-ratio:' + decimal + ')';
3061        switch(true)
3062        {
3063            case (media(decimal).matches):
3064                return true;
3065                break;
3066        }
3067
3068        return !!media(decimal.replace('-moz-', '')).matches;
3069    }
3070
3071    /**
3072     * Checks if the device is a Retina-device i.e. it has a Pixel Ratio of 2 or greater
3073     * @return {Boolean}
3074     */
3075    function isRetina()
3076    {
3077        var pixel_ratio_int = getPixelRatio();
3078        switch(true)
3079        {
3080            case (pixel_ratio_int >= 2):
3081                return true;
3082                break;
3083        }
3084
3085        return false;
3086    }
3087
3088    /**
3089     * A comparison function for checking if a number is within a range of two other numbers
3090     * @param {Function} fn
3091     * @return {Function}
3092     */
3093    function rangeCompare(fn) {
3094        return function(min, max) {
3095            var myArgs = Array.prototype.slice.call(arguments),
3096                bool,
3097                el = myArgs[2],
3098                el_valid_bool = !!((isObject(el) && (typeof el !== "undefined" && el !== null))),
3099                wf = myArgs[3],
3100                f_dip = myArgs[4],
3101                curr = (el_valid_bool) ? fn(el, wf, f_dip) : fn()
3102                ;
3103
3104            bool = curr >= (min || 0);
3105            return !max ? bool : bool && curr <= max;
3106        };
3107    }
3108
3109    //Range Comparison Booleans for Viewport and Screen
3110    vSpan = rangeCompare(viewportW);
3111    vPitch = rangeCompare(viewportH);
3112    dSpan = rangeCompare(screenW);
3113    dPitch = rangeCompare(screenH);
3114    cSpan = rangeCompare(pixelW);
3115    cPitch = rangeCompare(pixelH);
3116
3117    //Range Comparison Booleans for DOM Element Containers
3118    eSpan = rangeCompare(_elementW);
3119    ePitch = rangeCompare(_elementH);
3120
3121    /**
3122     * Gets the user agent of the Device
3123     * This function makes provision for proxy-based browsers that employ X11 forwarding
3124     * @return {String}
3125     */
3126    function getUserAgent()
3127    {
3128        //check if user agent check has been done and is in storage. If so, return stored value
3129        switch(true)
3130        {
3131            case (isStorageValueSet("rstv_user_agent")):
3132                return store("rstv_user_agent");
3133                break;
3134        }
3135
3136        var ua = navigator.userAgent.toLowerCase(),
3137            is_proxy_bool;
3138
3139        //Check if device user agent is being updated by proxy-based browser
3140        is_proxy_bool = /mozilla.+x11/i.test(ua);
3141
3142        switch(true)
3143        {
3144            case (is_proxy_bool):
3145                $.ajax({
3146                    type: "GET",
3147                    async: false,
3148                    crossDomain: true,
3149                    url: "http://www.restive.io/ping/ua.php",
3150                    headers: {
3151                        "Cache-Control":"no-cache",
3152                        "Pragma":"no-cache"
3153                    },
3154                    success: function(response) {
3155                        ua = response;
3156                    },
3157                    error: function(xhr, status, error_msg){
3158                        console.log('error');/*RemoveLogging:skip*/
3159                    }
3160                });
3161                break;
3162        }
3163
3164        store("rstv_user_agent", ua);
3165        return ua;
3166    }
3167
3168    /**
3169     * Gets the Operating System Platform of the Device
3170     * There are six possible platforms available
3171     * (1) ios, (2) android, (3) Symbian, (4) Blackberry, (5) Windows, (6) Other
3172     * @return {String}
3173     */
3174    function getPlatform()
3175    {
3176        switch(true)
3177        {
3178            case (_checkOS("ios")):
3179                return "ios";
3180                break;
3181
3182            case (_checkOS("android")):
3183                return "android";
3184                break;
3185
3186            case (_checkOS("symbian")):
3187                return "symbian";
3188                break;
3189
3190            case (_checkOS("blackberry")):
3191                return "blackberry";
3192                break;
3193
3194            case (_checkOS("windows")):
3195                return "windows";
3196                break;
3197
3198            default:
3199                return "other";
3200        }
3201    }
3202
3203    /**
3204     * Detects the Operating System [Platform] of the Device
3205     * @param os_str {String} The name of the OS
3206     * @param version_str An optional version number [Only valid for Android]
3207     * @return {Boolean}
3208     * @private
3209     */
3210    function _checkOS(os_str)
3211    {
3212        var myArgs = Array.prototype.slice.call(arguments),
3213            is_version_valid_bool = !!((isString(myArgs[1]) && myArgs[1] != "")),
3214            version_str = '',
3215            version_regex_suffix_str = '',
3216            version_store_suffix_str = ''
3217            ;
3218
3219        //manage version string if provided
3220        switch(true)
3221        {
3222            case (is_version_valid_bool):
3223                version_str = myArgs[1];
3224                version_str = version_str.replace(/^\s+|\s+$/g, "");
3225                version_regex_suffix_str = ' '+version_str;
3226                version_store_suffix_str = '_'+version_str.replace(".", "_");
3227                break;
3228        }
3229
3230        //Check if value is stored. Return if true
3231        switch(true)
3232        {
3233            case (isStorageValueSet("rstv_is_"+os_str+version_store_suffix_str)):
3234                return store("rstv_is_"+os_str+version_store_suffix_str);
3235                break;
3236        }
3237
3238        var nav = getUserAgent(),
3239            is_os_bool = false;
3240
3241        switch(true)
3242        {
3243            case (os_str == "ios"):
3244                is_os_bool = /\bipad|\biphone|\bipod/i.test(nav);
3245                break;
3246
3247            case (os_str == "android"):
3248                var pattern = new RegExp("\\bandroid"+version_regex_suffix_str, "i");
3249                is_os_bool = pattern.test(nav);
3250                break;
3251
3252            case (os_str == "symbian"):
3253                is_os_bool = /series(4|6)0|symbian|symbos|syb-[0-9]+|\bs60\b/i.test(nav);
3254                break;
3255
3256            case (os_str == "blackberry"):
3257                is_os_bool = /bb[0-9]+|blackberry|playbook|rim +tablet/i.test(nav);
3258                break;
3259
3260            case (os_str == "windows"):
3261                is_os_bool = /window mobile|windows +(ce|phone)|windows +nt.+arm|windows +nt.+touch|xblwp7|zunewp7/i.test(nav);
3262                break;
3263
3264            case (os_str == "windows_phone"):
3265                is_os_bool = /windows +phone|xblwp7|zunewp7/i.test(nav);
3266                break;
3267
3268            default:
3269                return false;
3270        }
3271
3272        //persist to local storage and return
3273        store("rstv_is_"+os_str+version_store_suffix_str, is_os_bool);
3274        return !!((is_os_bool));
3275    }
3276
3277    /**
3278     * Checks if the Device is based on Apple's iOS Platform
3279     * @return {Boolean}
3280     */
3281    function isIOS()
3282    {
3283        return _checkOS("ios");
3284    }
3285
3286    /**
3287     * Checks if the Device is based on Apple's iOS Platform
3288     * @return {Boolean}
3289     */
3290    function isApple()
3291    {
3292        return _checkOS("ios");
3293    }
3294
3295    /**
3296     * Checks if the Device is based on Android Platform
3297     * @return {Boolean}
3298     */
3299    function isAndroid()
3300    {
3301        var myArgs = Array.prototype.slice.call(arguments),
3302            version_str = myArgs[0];
3303        return _checkOS("android", version_str);
3304    }
3305
3306    /**
3307     * Checks if the Device is based on Symbian Platform
3308     * @return {Boolean}
3309     */
3310    function isSymbian()
3311    {
3312        return _checkOS("symbian");
3313    }
3314
3315    /**
3316     * Checks if the Device is based on Blackberry Platform
3317     * @return {Boolean}
3318     */
3319    function isBlackberry()
3320    {
3321        return _checkOS("blackberry");
3322    }
3323
3324    /**
3325     * Checks if the Device is based on a Windows Platform
3326     * @return {Boolean}
3327     */
3328    function isWindows()
3329    {
3330        return _checkOS("windows");
3331    }
3332
3333    /**
3334     * Checks if the Device is based on Windows Phone Platform
3335     * @return {Boolean}
3336     */
3337    function isWindowsPhone()
3338    {
3339        return _checkOS("windows_phone");
3340    }
3341
3342    /**
3343     * Mobile Browser Detection Regex
3344     * @param ua {String} User Agent String
3345     * @return {Boolean}
3346     * @private
3347     */
3348    function _mobileDetect(ua)
3349    {
3350        return /android|android.+mobile|avantgo|bada\/|\bbb[0-9]+|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|\bip(hone|od|ad)|iris|kindle|lge |maemo|meego.+mobile|midp|mmp|motorola|mobile.+firefox|netfront|nokia|nintendo +3ds|opera m(ob|in)i|palm|palm( os)?|phone|p(ixi|re)\/|playbook|rim +tablet|playstation.+vita|plucker|pocket|psp|samsung|(gt\-|bgt\-|sgh\-|sph\-|sch\-)[a-z][0-9]+|series(4|6)0|symbian|symbos|\bs60\b|treo|up\.(browser|link)|vertu|vodafone|wap|windows (ce|phone)|windows +nt.+arm|windows +nt.+touch|xda|xiino|xblwp7|zunewp7/i.test(ua) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|
3350sy(01|mb|b\-[0-9]+)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(ua.substr(0, 4));
3351    }
3352
3353    /**
3354     * Gets the Form Factor of the device
3355     * There are only three form factors available
3356     * (1) Phone, (2) Tablet, (3) TV, (4) PC
3357     * @return {String}
3358     */
3359    function getFormFactor()
3360    {
3361        var form_factor_str = "";
3362
3363        switch(true)
3364        {
3365            case (isTablet()):
3366                form_factor_str = "tablet";
3367                break;
3368
3369            case (isTV()):
3370                form_factor_str = "tv";
3371                break;
3372
3373            default:
3374                switch(true)
3375                {
3376                    case (isPhone()):
3377                        form_factor_str = "phone";
3378                        break;
3379
3380                    default:
3381                        form_factor_str = "pc";
3382                }
3383        }
3384
3385        return form_factor_str;
3386    }
3387
3388    /**
3389     * Check if the Device is a Phone
3390     * @return {Boolean}
3391     */
3392    function isPhone()
3393    {
3394        //check if phone check has already been done. If so, return stored value
3395        switch(true)
3396        {
3397            case (isStorageValueSet("rstv_is_phone")):
3398                return store("rstv_is_phone");
3399                break;
3400        }
3401
3402        //Check if Device is a Tablet
3403        switch(true)
3404        {
3405            case (isTablet(true) || isTV()):
3406                //is not phone
3407                store("rstv_is_phone", false);
3408                return false;
3409                break;
3410        }
3411
3412        //Check if it is a phone
3413        switch(true)
3414        {
3415            case (_mobileDetect(getUserAgent() || navigator.vendor.toLowerCase() || window.opera)):
3416                store("rstv_is_phone", true);
3417                return true;
3418                break;
3419        }
3420
3421        store("rstv_is_phone", false);
3422        return false;
3423    }
3424
3425    /**
3426     * Check if the Device is a Tablet
3427     * @param bypass_storage_bool {Boolean} Prevent this method from caching its result in local storage
3428     * @return {Boolean}
3429     */
3430    function isTablet()
3431    {
3432        var myArgs = Array.prototype.slice.call(arguments),
3433            bypass_storage_bool = isBool(myArgs[0]) ? myArgs[0] : false
3434            ;
3435
3436        //check if tablet check has already been done. If so, return stored value
3437        switch(true)
3438        {
3439            case (isStorageValueSet("rstv_is_tablet")):
3440                return store("rstv_is_tablet");
3441                break;
3442        }
3443
3444        var regex_raw_str,
3445            regex,
3446            is_tablet_bool,
3447            nav = getUserAgent();
3448
3449        //if iPad or Blackberry Playbook, return true
3450        regex = new RegExp("ipad|playbook|rim +tablet", "i");
3451        is_tablet_bool = regex.test(nav);
3452        switch(true)
3453        {
3454            case (is_tablet_bool):
3455                if(!bypass_storage_bool){ store("rstv_is_tablet", true); }
3456                return true;
3457                break;
3458        }
3459
3460        //if Windows Surface, return true
3461        regex = new RegExp("windows +nt.+arm|windows +nt.+touch", "i");
3462        is_tablet_bool = regex.test(nav);
3463        switch(true)
3464        {
3465            case (is_tablet_bool):
3466                if(!bypass_storage_bool){ store("rstv_is_tablet", true); }
3467                return true;
3468                break;
3469        }
3470
3471        /**
3472         * Check Other Known Tablets
3473         *
3474         * 1. Amazon Kindle: android.+kindle|kindle +fire|android.+silk|silk.*accelerated
3475         * 2. Google Nexus Tablet: android.+nexus +(7|10)
3476         * 3. Samsung Tablet: samsung.*tablet|galaxy.*tab|sc-01c|gt-p1000|gt-p1003|gt-p1010|gt-p3105|gt-p6210|gt-p6800|gt-p6810|gt-p7100|gt-p7300|gt-p7310|gt-p7500|gt-p7510|sch-i800|sch-i815|sch-i905|sgh-i957|sgh-i987|sgh-t849|sgh-t859|sgh-t869|sph-p100|gt-p3100|gt-p3108|gt-p3110|gt-p5100|gt-p5110|gt-p6200|gt-p7320|gt-p7511|gt-n8000|gt-p8510|sgh-i497|sph-p500|sgh-t779|sch-i705|sch-i915|gt-n8013|gt-p3113|gt-p5113|gt-p8110|gt-n8010|gt-n8005|gt-n8020|gt-p1013|gt-p6201|gt-p7501|gt-n5100|gt-n5110|shv-e140k|shv-e140l|shv-e140s|shv-e150s|shv-e230k|shv-e230l|shv-e230s|shw-m180k|shw-m180l|shw-m180s|shw-m180w|shw-m300w|shw-m305w|shw-m380k|shw-m380s|shw-m380w|shw-m430w|shw-m480k|shw-m480s|shw-m480w|shw-m485w|shw-m486w|shw-m500w|gt-i9228|sch-p739|sch-i925|gt-i9200|gt-i9205|gt-p5200|gt-p5210|sm-t311|sm-t310|sm-t210|sm-t210r|sm-t211|sm-p600|sm-p601|sm-p605|sm-p900|sm-t217|sm-t217a|sm-t217s|sm-p6000|sm-t3100|sgh-i467|xe500
3477         * 4. HTC Tablet: htc flyer|htc jetstream|htc-p715a|htc evo view 4g|pg41200
3478         * 5. Motorola Tablet: xoom|sholest|mz615|mz605|mz505|mz601|mz602|mz603|mz604|mz606|mz607|mz608|mz609|mz615|mz616|mz617
3479         * 6. Asus Tablet: transformer|^.*padfone((?!mobile).)*$|tf101|tf201|tf300|tf700|tf701|tf810|me171|me301t|me302c|me371mg|me370t|me372mg|me172v|me173x|me400c|slider *sl101
3480         * 7. Nook Tablet: android.+nook|nookcolor|nook browser|bnrv200|bnrv200a|bntv250|bntv250a|bntv400|bntv600|logicpd zoom2
3481         * 8. Acer Tablet: android.*\b(a100|a101|a110|a200|a210|a211|a500|a501|a510|a511|a700|a701|w500|w500p|w501|w501p|w510|w511|w700|g100|g100w|b1-a71|b1-710|b1-711|a1-810)\b|w3-810
3482         * 9. Toshiba Tablet: android.*(at100|at105|at200|at205|at270|at275|at300|at305|at1s5|at500|at570|at700|at830)|toshiba.*folio
3483         * 10. LG Tablet: \bl-06c|lg-v900|lg-v905|lg-v909
3484         * 11. Yarvik Tablet: android.+(xenta.+tab|tab210|tab211|tab224|tab250|tab260|tab264|tab310|tab360|tab364|tab410|tab411|tab420|tab424|tab450|tab460|tab461|tab464|tab465|tab467|tab468|tab469)
3485         * 12. Medion Tablet: android.+\boyo\b|life.*(p9212|p9514|p9516|s9512)|lifetab
3486         * 13. Arnova Tablet: an10g2|an7bg3|an7fg3|an8g3|an8cg3|an7g3|an9g3|an7dg3|an7dg3st|an7dg3childpad|an10bg3|an10bg3dt
3487         * 14. Archos Tablet: android.+archos|\b(101g9|80g9|a101it)\b|qilive 97r|
3488         * 15. Ainol Tablet: novo7|novo7aurora|novo7basic|novo7paladin|novo8|novo9|novo10
3489         * 16. Sony Tablet: sony tablet|sony tablet s|sgpt12|sgpt121|sgpt122|sgpt123|sgpt111|sgpt112|sgpt113|sgpt211|sgpt213|ebrd1101|ebrd1102|ebrd1201|sgpt311|sgpt312|sonyso-03e
3490         * 17. Cube Tablet: android.*(k8gt|u9gt|u10gt|u16gt|u17gt|u18gt|u19gt|u20gt|u23gt|u30gt)|cube u8gt
3491         * 18. Coby Tablet: mid1042|mid1045|mid1125|mid1126|mid7012|mid7014|mid7034|mid7035|mid7036|mid7042|mid7048|mid7127|mid8042|mid8048|mid8127|mid9042|mid9740|mid9742|mid7022|mid7010
3492         * 19. SMiTTablet: android.*(\bmid\b|mid-560|mtv-t1200|mtv-pnd531|mtv-p1101|mtv-pnd530)
3493         * 20. RockchipTablet: android.*(rk2818|rk2808a|rk2918|rk3066)|rk2738|rk2808a
3494         * 21. TelstraTablet: t-hub2
3495         * 22. FlyTablet: iq310|fly vision
3496         * 23. bqTablet: bq.*(elcano|curie|edison|maxwell|kepler|pascal|tesla|hypatia|platon|newton|livingstone|cervantes|avant)
3497         * 24. HuaweiTablet: mediapad|ideos s7|s7-201c|s7-202u|s7-101|s7-103|s7-104|s7-105|s7-106|s7-201|s7-slim
3498         * 25. NecTablet: \bn-06d|\bn-08d
3499         * 26. Pantech: pantech.*p4100
3500         * 27. BronchoTablet: broncho.*(n701|n708|n802|a710)
3501         * 28. VersusTablet: touchpad.*[78910]|\btouchtab\b
3502         * 29. Zynctablet: z1000|z99 2g|z99|z930|z999|z990|z909|z919|z900
3503         * 30. Positivo: tb07sta|tb10sta|tb07fta|tb10fta
3504         * 31. NabiTablet: android.*\bnabi
3505         * 32. Playstation: playstation.*(portable|vita)
3506         * 33. Dell: dell.*streak
3507         * 34. Milagrow: milagrow +tab.*top
3508         * 35. Lenovo: android.+(ideapad|ideatab|lenovo +a1|s2110|s6000|k3011|a3000|a1000|a2107|a2109|a1107)
3509         * 37. UPad: android.+f8-sup
3510         * 38. Kobo: android.+(k080|arc|vox)
3511         * 39. MSI: android.*(msi.+enjoy|enjoy +7|enjoy +10)
3512         * 40. Agasio: dropad.+a8
3513         * 41. Acho: android.+c906
3514         * 42. Iberry: android.+iberry.+auxus
3515         * 43. Aigo: android.+aigopad
3516         * 44. Airpad: android.*(airpad|liquid metal)
3517         * 45. HCL: android.+hcl.+tablet|connect-3g-2.0|connect-2g-2.0|me tablet u1|me tablet u2|me tablet g1|me tablet x1|me tablet y2|me tablet sync
3518         * 46. Karbonn: android.*(a39|a37|a34|st8|st10|st7|smarttab|smart +tab)
3519         * 47. Micromax: android.*(micromax.+funbook|funbook|p250|p275|p300|p350|p362|p500|p600)|micromax.*(p250|p275|p350|p362|p500|p600)|funbook
3520         * 48. Penta: android.+penta
3521         * 49. Celkon: android.*(celkon.+ct|ct-[0-9])
3522         * 50. Intex: android.+i-buddy
3523         * 51. Viewsonic: android.*(viewbook|viewpad)
3524         * 52: ZTE: android.*(v9|zte.+v8110|light tab|light pro|beeline|base.*tab)
3525         * 53. Pegatron: chagall
3526         * 54. Advan: android.*(vandroid|t3i)
3527         * 55. Creative: android.*(ziio7|ziio10)
3528         * 56. OlivePad: android.*(v-t100|v-tw100|v-tr200|v-t300)
3529         * 57. Vizio: android.+vtab1008
3530         * 58. Bookeen: bookeen|cybook
3531         * 59. Medion: android.*lifetab_(s9512|p9514|p9516)
3532         * 60. IRU Tablet: m702pro
3533         * 61. IRULU: irulu-al101
3534         * 62. Prestigio: pmp3170b|pmp3270b|pmp3470b|pmp7170b|pmp3370b|pmp3570c|pmp5870c|pmp3670b|pmp5570c|pmp5770d|pmp3970b|pmp3870c|pmp5580c|pmp5880d|pmp5780d|pmp5588c|pmp7280c|pmp7280|pmp7880d|pmp5597d|pmp5597|pmp7100d|per3464|per3274|per3574|per3884|per5274|per5474|pmp5097cpro|pmp5097|pmp7380d|pmp5297c|pmp5297c_quad
3535         * 63. AllView: allview.*(viva|alldro|city|speed|all tv|frenzy|quasar|shine|tx1|ax1|ax2)
3536         * 64: Megafon: megafon v9
3537         * 65: Lava: android.+(z7c|z7h|z7s)
3538         * 66: iBall: android.+iball.+slide.+(3g *7271|3g *7334|3g *7307|3g *7316|i7119|i7011)|android.+iball.+i6012
3539         * 67. Tabulet: android.+(tabulet|troy +duos)
3540         * 68. Texet Tablet: navipad|tb-772a|tm-7045|tm-7055|tm-9750|tm-7016|tm-7024|tm-7026|tm-7041|tm-7043|tm-7047|tm-8041|tm-9741|tm-9747|tm-9748|tm-9751|tm-7022|tm-7021|tm-7020|tm-7011|tm-7010|tm-7023|tm-7025|tm-7037w|tm-7038w|tm-7027w|tm-9720|tm-9725|tm-9737w|tm-1020|tm-9738w|tm-9740|tm-9743w|tb-807a|tb-771a|tb-727a|tb-725a|tb-719a|tb-823a|tb-805a|tb-723a|tb-715a|tb-707a|tb-705a|tb-709a|tb-711a|tb-890hd|tb-880hd|tb-790hd|tb-780hd|tb-770hd|tb-721hd|tb-710hd|tb-434hd|tb-860hd|tb-840hd|tb-760hd|tb-750hd|tb-740hd|tb-730hd|tb-722hd|tb-720hd|tb-700hd|tb-500hd|tb-470hd|tb-431hd|tb-430hd|tb-506|tb-504|tb-446|tb-436|tb-416|tb-146se|tb-126se
3541         * 69. GalapadTablet: android.*\bg1\b
3542         * 70. GUTablet: tx-a1301|tx-m9002|q702
3543         * 71. GT-Pad: ly-f528
3544         * 72. Danew: android.+dslide.*\b(700|701r|702|703r|704|802|970|971|972|973|974|1010|1012)\b
3545         * 73. MIDTablet: m9701|m9000|m9100|m806|m1052|m806|t703|mid701|mid713|mid710|mid727|mid760|mid830|mid728|mid933|mid125|mid810|mid732|mid120|mid930|mid800|mid731|mid900|mid100|mid820|mid735|mid980|mid130|mid833|mid737|mid960|mid135|mid860|mid736|mid140|mid930|mid835|mid733
3546         * 74. Fujitsu: android.*\b(f-01d|f-05e|f-10d|m532|q572)\b
3547         * 75. GPad: android.+casiatab8
3548         * 76. Tesco Hudl: android.+hudl
3549         * 77. Polaroid: android.*(polaroid.*tablet|pmid1000|pmid10c|pmid800|pmid700|pmid4311|pmid701c|pmid701i|pmid705|pmid706|pmi
3549d70dc|pmid70c|pmid720|pmid80c|pmid901|ptab7200|ptab4300|ptab750|midc010|midc407|midc409|midc410|midc497|midc700|midc800|midc801|midc802|midc901)
3550         * 78. Eboda: e-boda.+(supreme|impresspeed|izzycomm|essential)
3551         * 79. HP Tablet: hp slate 7|hp elitepad 900|hp-tablet|elitebook.*touch
3552         * 80. AllFineTablet: fine7 genius|fine7 shine|fine7 air|fine8 style|fine9 more|fine10 joy|fine11 wide
3553         * 81. Sanei: android.*\b(n10|n10-4core|n78|n79|n83|n90 ii)\b
3554         * 82: ProScan Tablet: \b(pem63|plt1023g|plt1041|plt1044|plt1044g|plt1091|plt4311|plt4311pl|plt4315|plt7030|plt7033|plt7033d|plt7035|plt7035d|plt7044k|plt7045k|plt7045kb|plt7071kg|plt7072|plt7223g|plt7225g|plt7777g|plt7810k|plt7849g|plt7851g|plt7852g|plt8015|plt8031|plt8034|plt8036|plt8080k|plt8082|plt8088|plt8223g|plt8234g|plt8235g|plt8816k|plt9011|plt9045k|plt9233g|plt9735|plt9760g|plt9770g)\b
3555         * 83: YonesTablet : bq1078|bc1003|bc1077|rk9702|bc9730|bc9001|it9001|bc7008|bc7010|bc708|bc728|bc7012|bc7030|bc7027|bc7026
3556         * 84: ChangJiaTablet: tpc7102|tpc7103|tpc7105|tpc7106|tpc7107|tpc7201|tpc7203|tpc7205|tpc7210|tpc7708|tpc7709|tpc7712|tpc7110|tpc8101|tpc8103|tpc8105|tpc8106|tpc8203|tpc8205|tpc8503|tpc9106|tpc9701|tpc97101|tpc97103|tpc97105|tpc97106|tpc97111|tpc97113|tpc97203|tpc97603|tpc97809|tpc97205|tpc10101|tpc10103|tpc10106|tpc10111|tpc10203|tpc10205|tpc10503
3557         * 85: RoverPad: android.*(roverpad|rp3wg70)
3558         * 86. PointofView Tablet: tab-p506|tab-navi-7-3g-m|tab-p517|tab-p-527|tab-p701|tab-p703|tab-p721|tab-p731n|tab-p741|tab-p825|tab-p905|tab-p925|tab-pr945|tab-pl1015|tab-p1025|tab-pi1045|tab-p1325|tab-protab[0-9]+|tab-protab25|tab-protab26|tab-protab27|tab-protab26xl|tab-protab2-ips9|tab-protab30-ips9|tab-protab25xxl|tab-protab26-ips10|tab-protab30-ips10
3559         * 87: Overmax: android.*ov-(steelcore|newbase|basecore|baseone|exellen|quattor|edutab|solution|action|basictab|teddytab|magictab|stream|tb-08|tb-09)
3560         * 88: DPS Tablet: dps dream 9|dps dual 7
3561         * 89: Visture Tablet: v97 hd|i75 3g|visture v4( hd)?|visture v5( hd)?|visture v10
3562         * 90: Cresta Tablet: ctp(-)?810|ctp(-)?818|ctp(-)?828|ctp(-)?838|ctp(-)?888|ctp(-)?978|ctp(-)?980|ctp(-)?987|ctp(-)?988|ctp(-)?989
3563         * 200. Generic Tablet: android.*\b97d\b|tablet(?!.*pc)|viewpad7|lg-v909|mid7015|bntv250a|logicpd zoom2|\ba7eb\b|catnova8|a1_07|ct704|ct1002|\bm721\b|rk30sdk|\bevotab\b|smarttabii10|smarttab10
3564         */
3565        regex_raw_str = ""+
3566            "android.+kindle|kindle +fire|android.+silk|silk.*accelerated|"+
3567            "android.+nexus +(7|10)|"+
3568            "samsung.*tablet|galaxy.*tab|sc-01c|gt-p1000|gt-p1003|gt-p1010|gt-p3105|gt-p6210|gt-p6800|gt-p6810|gt-p7100|gt-p7300|gt-p7310|gt-p7500|gt-p7510|sch-i800|sch-i815|sch-i905|sgh-i957|sgh-i987|sgh-t849|sgh-t859|sgh-t869|sph-p100|gt-p3100|gt-p3108|gt-p3110|gt-p5100|gt-p5110|gt-p6200|gt-p7320|gt-p7511|gt-n8000|gt-p8510|sgh-i497|sph-p500|sgh-t779|sch-i705|sch-i915|gt-n8013|gt-p3113|gt-p5113|gt-p8110|gt-n8010|gt-n8005|gt-n8020|gt-p1013|gt-p6201|gt-p7501|gt-n5100|gt-n5110|shv-e140k|shv-e140l|shv-e140s|shv-e150s|shv-e230k|shv-e230l|shv-e230s|shw-m180k|shw-m180l|shw-m180s|shw-m180w|shw-m300w|shw-m305w|shw-m380k|shw-m380s|shw-m380w|shw-m430w|shw-m480k|shw-m480s|shw-m480w|shw-m485w|shw-m486w|shw-m500w|gt-i9228|sch-p739|sch-i925|gt-i9200|gt-i9205|gt-p5200|gt-p5210|sm-t311|sm-t310|sm-t210|sm-t210r|sm-t211|sm-p600|sm-p601|sm-p605|sm-p900|sm-t217|sm-t217a|sm-t217s|sm-p6000|sm-t3100|sgh-i467|xe500|"+
3569            "htc flyer|htc jetstream|htc-p715a|htc evo view 4g|pg41200|"+
3570            "xoom|sholest|mz615|mz605|mz505|mz601|mz602|mz603|mz604|mz606|mz607|mz608|mz609|mz615|mz616|mz617|"+
3571            "transformer|^.*padfone((?!mobile).)*$|tf101|tf201|tf300|tf700|tf701|tf810|me171|me301t|me302c|me371mg|me370t|me372mg|me172v|me173x|me400c|slider *sl101|"+
3572            "android.+nook|nookcolor|nook browser|bnrv200|bnrv200a|bntv250|bntv250a|bntv400|bntv600|logicpd zoom2|"+
3573            "android.*\\b(a100|a101|a110|a200|a210|a211|a500|a501|a510|a511|a700|a701|w500|w500p|w501|w501p|w510|w511|w700|g100|g100w|b1-a71|b1-710|b1-711|a1-810)\\b|w3-810|"+
3574            "android.*(at100|at105|at200|at205|at270|at275|at300|at305|at1s5|at500|at570|at700|at830)|toshiba.*folio|"+
3575            "\\bl-06c|lg-v900|lg-v905|lg-v909|"+
3576            "android.+(xenta.+tab|tab210|tab211|tab224|tab250|tab260|tab264|tab310|tab360|tab364|tab410|tab411|tab420|tab424|tab450|tab460|tab461|tab464|tab465|tab467|tab468|tab469)|"+
3577            "android.+\\boyo\\b|life.*(p9212|p9514|p9516|s9512)|lifetab|"+
3578            "an10g2|an7bg3|an7fg3|an8g3|an8cg3|an7g3|an9g3|an7dg3|an7dg3st|an7dg3childpad|an10bg3|an10bg3dt|"+
3579            "android.+archos|\\b(101g9|80g9|a101it)\\b|qilive 97r|"+
3580            "novo7|novo7aurora|novo7basic|novo7paladin|novo8|novo9|novo10|"+
3581            "sony tablet|sony tablet s|sgpt12|sgpt121|sgpt122|sgpt123|sgpt111|sgpt112|sgpt113|sgpt211|sgpt213|ebrd1101|ebrd1102|ebrd1201|sgpt311|sgpt312|sonyso-03e|"+
3582            "android.*(k8gt|u9gt|u10gt|u16gt|u17gt|u18gt|u19gt|u20gt|u23gt|u30gt)|cube u8gt|"+
3583            "mid1042|mid1045|mid1125|mid1126|mid7012|mid7014|mid7034|mid7035|mid7036|mid7042|mid7048|mid7127|mid8042|mid8048|mid8127|mid9042|mid9740|mid9742|mid7022|mid7010|"+
3584            "android.*(\\bmid\\b|mid-560|mtv-t1200|mtv-pnd531|mtv-p1101|mtv-pnd530)|"+
3585            "android.*(rk2818|rk2808a|rk2918|rk3066)|rk2738|rk2808a|"+
3586            "t-hub2|"+
3587            "iq310|fly vision|"+
3588            "bq.*(elcano|curie|edison|maxwell|kepler|pascal|tesla|hypatia|platon|newton|livingstone|cervantes|avant)|"+
3589            "mediapad|ideos s7|s7-201c|s7-202u|s7-101|s7-103|s7-104|s7-105|s7-106|s7-201|s7-slim|"+
3590            "\\bn-06d|\\bn-08d|"+
3591            "pantech.*p4100|"+
3592            "broncho.*(n701|n708|n802|a710)|"+
3593            "touchpad.*[78910]|\\btouchtab\\b|"+
3594            "z1000|z99 2g|z99|z930|z999|z990|z909|z919|z900|"+
3595            "tb07sta|tb10sta|tb07fta|tb10fta|"+
3596            "android.*\\bnabi|"+
3597            "playstation.*(portable|vita)|"+
3598            "dell.*streak|"+
3599            "milagrow +tab.*top|"+
3600            "android.+(ideapad|ideatab|lenovo +a1|s2110|s6000|k3011|a3000|a1000|a2107|a2109|a1107)|"+
3601            "android.+f8-sup|"+
3602            "android.*(k080|arc|vox)|"+
3603            "android.*(msi.+enjoy|enjoy +7|enjoy +10)|"+
3604            "dropad.+a8|"+
3605            "android.+c906|"+
3606            "android.+iberry.+auxus|"+
3607            "android.+aigopad|"+
3608            "android.*(airpad|liquid metal)|"+
3609            "android.+hcl.+tablet|connect-3g-2.0|connect-2g-2.0|me tablet u1|me tablet u2|me tablet g1|me tablet x1|me tablet y2|me tablet sync|"+
3610            "android.*(a39|a37|a34|st8|st10|st7|smarttab|smart +tab)|"+
3611            "android.*(micromax.+funbook|funbook|p250|p275|p300|p350|p362|p500|p600)|micromax.*(p250|p275|p350|p362|p500|p600)|funbook|"+
3612            "android.+penta|"+
3613            "android.*(celkon.+ct|ct-[0-9])|"+
3614            "android.+i-buddy|"+
3615            "android.*(viewbook|viewpad)|"+
3616            "android.*(v9|zte.+v8110|light tab|light pro|beeline|base.*tab)|"+
3617            "chagall|"+
3618            "android.*(vandroid|t3i)|"+
3619            "android.*(ziio7|ziio10)|"+
3620            "android.*(v-t100|v-tw100|v-tr200|v-t300)|"+
3621            "android.+vtab1008|"+
3622            "bookeen|cybook|"+
3623            "android.*lifetab_(s9512|p9514|p9516)|"+
3624            "m702pro|"+
3625            "irulu-al101|"+
3626            "pmp3170b|pmp3270b|pmp3470b|pmp7170b|pmp3370b|pmp3570c|pmp5870c|pmp3670b|pmp5570c|pmp5770d|pmp3970b|pmp3870c|pmp5580c|pmp5880d|pmp5780d|pmp5588c|pmp7280c|pmp7280|pmp7880d|pmp5597d|pmp5597|pmp7100d|per3464|per3274|per3574|per3884|per5274|per5474|pmp5097cpro|pmp5097|pmp7380d|pmp5297c|pmp5297c_quad|"+
3627            "allview.*(viva|alldro|city|speed|all tv|frenzy|quasar|shine|tx1|ax1|ax2)|"+
3628            "megafon +v9|"+
3629            "android.+(z7c|z7h|z7s)|"+
3630            "android.+iball.+slide.+(3g *7271|3g *7334|3g *7307|3g *7316|i7119|i7011)|android.+iball.+i6012|"+
3631            "navipad|tb-772a|tm-7045|tm-7055|tm-9750|tm-7016|tm-7024|tm-7026|tm-7041|tm-7043|tm-7047|tm-8041|tm-9741|tm-9747|tm-9748|tm-9751|tm-7022|tm-7021|tm-7020|tm-7011|tm-7010|tm-7023|tm-7025|tm-7037w|tm-7038w|tm-7027w|tm-9720|tm-9725|tm-9737w|tm-1020|tm-9738w|tm-9740|tm-9743w|tb-807a|tb-771a|tb-727a|tb-725a|tb-719a|tb-823a|tb-805a|tb-723a|tb-715a|tb-707a|tb-705a|tb-709a|tb-711a|tb-890hd|tb-880hd|tb-790hd|tb-780hd|tb-770hd|tb-721hd|tb-710hd|tb-434hd|tb-860hd|tb-840hd|tb-760hd|tb-750hd|tb-740hd|tb-730hd|tb-722hd|tb-720hd|tb-700hd|tb-500hd|tb-470hd|tb-431hd|tb-430hd|tb-506|tb-504|tb-446|tb-436|tb-416|tb-146se|tb-126se|"+
3632            "android.*\\bg1\\b|"+
3633            "tx-a1301|tx-m9002|q702|"+
3634            "ly-f528|"+
3635            "android.+dslide.*\\b(700|701r|702|703r|704|802|970|971|972|973|974|1010|1012)\\b|"+
3636            "m9701|m9000|m9100|m806|m1052|m806|t703|mid701|mid713|mid710|mid727|mid760|mid830|mid728|mid933|mid125|mid810|mid732|mid120|mid930|mid800|mid731|mid900|mid100|mid820|mid735|mid980|mid130|mid833|mid737|mid960|mid135|mid860|mid736|mid140|mid930|mid835|mid733|"+
3637            "android.*\\b(f-01d|f-05e|f-10d|m532|q572)\\b|"+
3638            "android.+casiatab8|"+
3639            "android.+hudl|"+
3640            "android.*(polaroid.*tablet|pmid1000|pmid10c|pmid800|pmid700|pmid4311|pmid701c|pmid701i|pmid705|pmid706|pmid70dc|pmid70c|pmid720|pmid80c|pmid901|ptab7200|ptab4300|ptab750|midc010|midc407|midc409|midc410|midc497|midc700|midc800|midc801|midc802|midc901)|"+
3641            "e-boda.+(supreme|impresspeed|izzycomm|essential)|"+
3642            "hp slate 7|hp elitepad 900|hp-tablet|elitebook.*touch|"+
3643            "fine7 genius|fine7 shine|fine7 air|fine8 style|fine9 more|fine10 joy|fine11 wide|"+
3644            "android.*\\b(n10|n10-4core|n78|n79|n83|n90 ii)\\b|"+
3645            "\\b(pem63|plt1023g|plt1041|plt1044|plt1044g|plt1091|plt4311|plt4311pl|plt4315|plt7030|plt7033|plt7033d|plt7035|plt7035d|plt7044k|plt7045k|plt7045kb|plt7071kg|plt7072|plt7223g|plt7225g|plt7777g|plt7810k|plt7849g|plt7851g|plt7852g|plt8015|plt8031|plt8034|plt8036|plt8080k|plt8082|plt8088|plt8223g|plt8234g|plt8235g|plt8816k|plt9011|plt9045k|plt9233g|plt9735|plt9760g|plt9770g)\\b|"+
3646            "bq1078|bc1003|bc1077|rk9702|bc9730|bc9001|it9001|bc7008|bc7010|bc708|bc728|bc7012|bc7030|bc7027|bc7026|"+
3647            "tpc7102|tpc7103|tpc7105|tpc7106|tpc7107|tpc7201|tpc7203|tpc7205|tpc7210|tpc7708|tpc7709|tpc7712|tpc7110|tpc8101|tpc8103|tpc8105|tpc8106|tpc8203|tpc8205|tpc8503|tpc9106|tpc9701|tpc97101|tpc97103|tpc97105|tpc97106|tpc97111|tpc97113|tpc97203|tpc97603|tpc97809|tpc97205|tpc10101|tpc10103|tpc10106|tpc10111|tpc10203|tpc10205|tpc10503|"+
3648            "android.*(roverpad|rp3wg70)|"+
3649            "tab-p506|tab-navi-7-3g-m|tab-p517|tab-p-527|tab-p701|tab-p703|tab-p721|tab-p731n|tab-p741|tab-p825|tab-p905|tab-p925|tab-pr945|tab-pl1015|tab-p1025|tab-pi1045|tab-p1325|tab-protab[0-9]+|tab-protab25|tab-protab26|tab-protab27|tab-protab26xl|tab-protab2-ips9|tab-protab30-ips9|tab-protab25xxl|tab-protab26-ips10|tab-protab30-ips10|"+
3650            "android.*ov-(steelcore|newbase|basecore|baseone|exellen|quattor|edutab|solution|action|basictab|teddytab|magictab|stream|tb-08|tb-09)|"+
3651            "dps dream 9|dps dual 7|"+
3652            "v97 hd|i75 3g|visture v4( hd)?|visture v5( hd)?|visture v10|"+
3653            "ctp(-)?810|ctp(-)?818|ctp(-)?828|ctp(-)?838|ctp(-)?888|ctp(-)?978|ctp(-)?980|ctp(-)?987|ctp(-)?988|ctp(-)?989|"+
3654            "android.*\\b97d\\b|tablet(?!.*pc)|viewpad7|lg-v909|mid7015|bntv250a|logicpd zoom2|\\ba7eb\\b|catnova8|a1_07|ct704|ct1002|\\bm721\\b|rk30sdk|\\bevotab\\b|smarttabii10|smarttab10"+
3655            "";
3656
3657        //Check Main Tablet
3658        regex = new RegExp(regex_raw_str, "i");
3659        is_tablet_bool = regex.test(nav);
3660        switch(true)
3661        {
3662            case (is_tablet_bool):
3663                if(!bypass_storage_bool){ store("rstv_is_tablet", true); }
3664                return true;
3665                break;
3666        }
3667
3668        //Check Android Tablet
3669        var regex_1_bool = /android/i.test(nav),
3670            regex_2_bool = !/mobile/i.test(nav),
3671            pixel_w_int = parseInt(store("rstv_viewportW_dip")),
3672            pixel_h_int = parseInt(store("rstv_viewportH_dip")),
3673            pixel_dim_int = (store("rstv_is_portrait")) ? pixel_w_int : pixel_h_int
3674            ;
3675
3676        switch(true)
3677        {
3678            case (regex_1_bool):
3679                /**
3680                 * if tablet has either:
3681                 * 1. Device independent viewport width between 520px and 800px when in portrait
3682                 * 2. Device independent viewport height between 520px and 800px when in landscape
3683                 */
3684                switch(true)
3685                {
3686                    case (isNumber(pixel_dim_int) && (pixel_dim_int >= 520 && pixel_dim_int <= 800)):
3687                        if(!bypass_storage_bool){ store("rstv_is_tablet", true); }
3688                        return true;
3689                        break;
3690                }
3691
3692                //if user agent is Android but 'mobile' keyword is absent
3693                switch(true)
3694                {
3695                    case (regex_2_bool):
3696                        if(!bypass_storage_bool){ store("rstv_is_tablet", true); }
3697                        return true;
3698                        break;
3699                }
3700
3701                break;
3702        }
3703
3704        //Return false if otherwise
3705        if(!bypass_storage_bool){ store("rstv_is_tablet", false); }
3706        return false;
3707    }
3708
3709    /**
3710     * Check if the device is a TV
3711     * @return {Boolean}
3712     */
3713    function isTV()
3714    {
3715        //check if TV check has already been done. If so, return stored value
3716        switch(true)
3717        {
3718            case (isStorageValueSet("rstv_is_tv")):
3719                return store("rstv_is_tv");
3720                break;
3721        }
3722
3723        //get the user agent
3724        var nav = getUserAgent();
3725
3726        /**
3727         * Check for known TVs
3728         */
3729        var is_tv_bool = /googletv|smart\-tv|smarttv|internet +tv|netcast|nettv|appletv|boxee|kylo|roku|vizio|dlnadoc|ce\-html|ouya|xbox|playstation *(3|4)|wii/i.test(nav);
3730
3731        switch(true)
3732        {
3733            case (is_tv_bool):
3734                store("rstv_is_tv", true);
3735                return true;
3736                break;
3737        }
3738
3739        store("rstv_is_tv", false);
3740        return false;
3741    }
3742
3743    /**
3744     * Checks if the device is a Personal Computer
3745     * @return {Boolean}
3746     */
3747    function isPC()
3748    {
3749        //check if PC check has already been done. If so, return stored value
3750        switch(true)
3751        {
3752            case (isStorageValueSet("rstv_is_pc")):
3753                return store("rstv_is_pc");
3754                break;
3755        }
3756
3757        switch(true)
3758        {
3759            case (isMobile() === false && isTV() === false):
3760                store("rstv_is_pc", true);
3761                return true;
3762                break;
3763        }
3764
3765        store("rstv_is_pc", false);
3766        return false;
3767    }
3768
3769    /**
3770     * Checks if the device is a mobile device
3771     * @return {Boolean}
3772     */
3773    function isMobile()
3774    {
3775        //check if device is phone or tablet
3776        switch(true)
3777        {
3778            case (isPhone() || isTablet(true)):
3779                return true;
3780                break;
3781
3782            default:
3783                return false;
3784        }
3785    }
3786
3787    /**
3788     * Checks if the device is a non-mobile device
3789     * @return {Boolean}
3790     */
3791    function isNonMobile()
3792    {
3793        //check if device is not phone or mobile
3794        switch(true)
3795        {
3796            case (!isMobile()):
3797                return true;
3798                break;
3799
3800            default:
3801                return false;
3802        }
3803    }
3804
3805    /**
3806     * Gets the orientation of the device
3807     * @param bypass_cache_bool {Boolean} Determines if the stored value for current orientation should be retrieved or not. True will ignore the value stored and will re-test the orientation
3808     * @return {String}
3809     */
3810    function getOrientation()
3811    {
3812        var myArgs = Array.prototype.slice.call(arguments),
3813            bypass_cache_bool = isBool(myArgs[0]) ? myArgs[0] : false,
3814            ort_final_str;
3815
3816        //check if current orientation value is stored and bypass_cache_bool is false. If so, return stored value
3817        switch(true)
3818        {
3819            case (isStorageValueSet("rstv_ort_curr") && !bypass_cache_bool):
3820                return store("rstv_ort_curr");
3821                break;
3822        }
3823
3824        //Reset Viewport Dimensions if bypass_cache_bool is true
3825        switch(true)
3826        {
3827            case (bypass_cache_bool):
3828                store("rstv_viewportW rstv_viewportW_dip rstv_viewportH rstv_viewportH_dip rstv_screenW rstv_screenH", null);
3829                break;
3830        }
3831
3832        //Get the Viewport Dimensions
3833        var device_user_agent_str = getUserAgent(),
3834            is_opera_mini_bool = /opera.+(mini|mobi)/i.test(device_user_agent_str),
3835            viewport_w_int = viewportW(),
3836            viewport_h_int = viewportH(),
3837            screen_w_int = screenW(),
3838            screen_h_int = screenH(),
3839            screen_w_to_h_ratio_int = screen_w_int/screen_h_int,
3840            screen_w_to_viewport_w_diff_int = screen_w_int - viewport_w_int,
3841            is_landscape_extended_verify_bool,
3842            is_landscape_bool;
3843
3844        screen_w_to_viewport_w_diff_int = Math.abs(screen_w_to_viewport_w_diff_int);
3845        is_landscape_extended_verify_bool = (is_opera_mini_bool && viewport_w_int < 260) ? ((screen_w_to_viewport_w_diff_int <= 4) && (screen_w_to_h_ratio_int >= 1) ? true : false) : true;
3846        is_landscape_bool = !!((viewport_h_int <= viewport_w_int) && is_landscape_extended_verify_bool);
3847
3848        switch(true)
3849        {
3850            case (is_landscape_bool):
3851                //landscape
3852                ort_final_str = 'landscape';
3853
3854                //do not alter cached orientation variables if bypass_cache_bool is true
3855                switch(true)
3856                {
3857                    case (!bypass_cache_bool):
3858                        store("rstv_is_portrait", false);
3859                        store("rstv_is_landscape", true);
3860                        break;
3861                }
3862
3863                break;
3864
3865            default:
3866                //portrait
3867                ort_final_str = 'portrait';
3868
3869                //do not alter cached orientation variables if bypass_cache_bool is true
3870                switch(true)
3871                {
3872                    case (!bypass_cache_bool):
3873                        store("rstv_is_portrait", true);
3874                        store("rstv_is_landscape", false);
3875                        break;
3876                }
3877        }
3878
3879        return ort_final_str;
3880    }
3881
3882    /**
3883     * Resets/Updates the cached values (localStorage) of Orientation Info
3884     * @private
3885     */
3886    function _updateOrientationStore()
3887    {
3888        //reset
3889        store("rstv_ort_curr rstv_is_portrait rstv_is_landscape", null);
3890
3891        //reload
3892        store("rstv_ort_curr", getOrientation());
3893    }
3894
3895    /**
3896     * Checks if the device is currently in Portrait mode
3897     * @return {Boolean}
3898     */
3899    function isPortrait()
3900    {
3901        //check if portrait orientation value is stored. If so, return stored value
3902        switch(true)
3903        {
3904            case (isStorageValueSet("rstv_is_portrait")):
3905                return store("rstv_is_portrait");
3906                break;
3907        }
3908        return !!((getOrientation() == 'portrait'));
3909    }
3910
3911    /**
3912     * Checks if the device is currently in Landscape mode
3913     * @return {Boolean}
3914     */
3915    function isLandscape()
3916    {
3917        //check if landscape orientation value is stored. If so, return stored value
3918        switch(true)
3919        {
3920            case (isStorageValueSet("rstv_is_landscape")):
3921                return store("rstv_is_landscape");
3922                break;
3923        }
3924        return !!((getOrientation() == 'landscape'));
3925    }
3926
3927    /**
3928     * Gets the Standard Display Resolution of the given device
3929     * @return {String}
3930     */
3931    function getResolution()
3932    {
3933        var is_landscape_bool = isLandscape(),
3934            screen_w = screenW(),
3935            screen_h = screenH(),
3936            std_w_arr = (is_landscape_bool) ? _getResolutionDimensionList('h') :_getResolutionDimensionList('w'),
3937            std_h_arr = (is_landscape_bool) ? _getResolutionDimensionList('w'): _getResolutionDimensionList('h'),
3938            screen_w_std = getClosestNumberMatchArray(std_w_arr, screen_w),
3939            screen_h_std = getClosestNumberMatchArray(std_h_arr, screen_h),
3940            screen_res_str,
3941            screen_res_matrix_arr = _getResolutionMatrix(),
3942            screen_res_name_str
3943            ;
3944
3945        switch(true)
3946        {
3947            case (screen_w_std >= screen_h_std):
3948                screen_res_str = screen_h_std+'_'+screen_w_std;
3949                break;
3950
3951            default:
3952                screen_res_str = screen_w_std+'_'+screen_h_std;
3953        }
3954
3955        screen_res_name_str = array_search(screen_res_str, screen_res_matrix_arr);
3956
3957        return screen_res_name_str;
3958    }
3959
3960    /**
3961     * Composes and Saves a List of Standard Graphic Resolutions
3962     * @return {Array}
3963     * @private
3964     */
3965    function _getResolutionList()
3966    {
3967        //Check if Resolution List is Stored
3968        switch(true)
3969        {
3970            case (isStorageValueSet("rstv_is_cache_res_list")):
3971                return store("rstv_cache_res_list");
3972                break;
3973        }
3974
3975        var $res_arr = [
3976            'qqvga', 'qqvgax1', 'hqvga', 'hqvgax1', 'hqvgax2', 'hvgax1', 'qvga', 'wqvga', 'wqvga1', 'hvga',
3977            'hvga1', 'hvga2', 'hvga3', 'hvgax1', 'hvgax2', 'vga', 'wvga', 'wvgax1', 'fwvga', 'svga',
3978            'dvga', 'dvgax1', 'wsvga', 'wsvga1', 'xga', 'wxga', 'wxga1', 'wxga2', 'wxga3', 'wxga4', 'wxga5',
3979            'xga+', 'wxga+', 'sxga', 'sxga+', 'wsxga+', 'uxga', 'wuxga', 'qwxga', 'qxga', 'wqxga',
3980            'qsxga', 'wqsxga', 'quxga', 'wquxga', 'hxga', 'whxga', 'hsxga', 'whsxga', 'huxga', 'whuxga',
3981            'nhd', 'nhdx1', 'qhd', 'hd', '720p', 'fhd', '1080p', '1080i', 'wqhd', 'mbprhd', '4kuhd', '8kuhd'
3982        ];
3983
3984        store("rstv_is_cache_res_list", true);
3985        store("rstv_cache_res_list", $res_arr);
3986        return $res_arr;
3987    }
3988
3989    /**
3990     * Composes and Saves a Resolution Matrix (Resolution to Dimensions)
3991     * @return {Array|Object}
3992     * @private
3993     */
3994    function _getResolutionMatrix()
3995    {
3996        //Check if Resolution Matrix is Stored
3997        switch(true)
3998        {
3999            case (isStorageValueSet("rstv_is_cache_res_matrix")):
4000                return store("rstv_cache_res_matrix");
4001                break;
4002        }
4003
4004        var $res_matrix_arr = {
4005            'qqvga': '120_160', 'qqvgax1': '128_160', 'hqvga': '160_240', 'hqvgax1': '240_240', 'hqvgax2': '240_260',
4006            'qvga': '240_320', 'wqvga': '240_400', 'wqvga1': '240_432', 'hvga': '320_480',
4007            'hvga1': '360_480', 'hvga2': '272_480', 'hvga3': '240_640', 'hvgax1': '200_640', 'hvgax2': '300_640',
4008            'hvgax3': '360_400',
4009            'vga': '480_640', 'wvga': '480_800', 'wvgax1': '352_800', 'fwvga': '480_854', 'svga': '600_800',
4010            'dvga': '640_960', 'dvgax1': '640_1136', 'wsvga': '576_1024', 'wsvga1': '600_1024', 'xga': '768_1024',
4011            'wxga': '768_1280', 'wxga1': '720_1280', 'wxga2': '800_1280', 'wxga3': '768_1360', 'wxga4': '768_1366',
4012            'wxga5': '720_720',
4013            'xga+': '864_1152', 'wxga+': '900_1440', 'sxga': '1024_1280', 'sxga+': '1050_1400', 'wsxga+': '1050_1680',
4014            'uxga': '1200_1600', 'wuxga': '1200_1920', 'qwxga': '1152_2048', 'qxga': '1536_2048', 'wqxga': '1600_2560',
4015            'wqxga+': '1800_3200',
4016            'qsxga': '2048_2560', 'wqsxga': '2048_3200', 'quxga': '2400_3200', 'wquxga': '2400_3840', 'hxga': '3072_4096',
4017            'whxga': '3200_5120', 'hsxga': '4096_5120', 'whsxga': '4096_6400', 'huxga': '4800_6400', 'whuxga': '4800_7680',
4018            'nhd': '360_640', 'nhdx1': '320_640', 'qhd': '540_960', 'hd': '720_1280', '720p': '720_1280', 'fhd': '1080_1920',
4019            '1080p': '1080_1920', '1080i': '1080_1920', 'wqhd': '1440_2560', 'mbprhd': '1800_2880', '4kuhd': '2160_3840',
4020            '8kuhd': '4320_7680'
4021        };
4022
4023        store("rstv_is_cache_res_matrix", true);
4024        store("rstv_cache_res_matrix", $res_matrix_arr);
4025        return $res_matrix_arr;
4026    }
4027
4028    /**
4029     * Converts various types of breakpoints into pixel breakpoints
4030     * It converts 'Device' and 'Resolution' breakpoints
4031     * @param bp_arr {Array} The breakpoints you define
4032     * @param bp_class_arr {Array} The names of CSS classes paired with breakpoints
4033     * @return {Array}
4034     * @private
4035     */
4036    function _toViewportBreakpoints(bp_arr, bp_class_arr)
4037    {
4038        try{
4039            //Create local variables
4040            var bp_attrib_arr = [],
4041                list_dev_arr,
4042                list_res_arr,
4043                matrix_dev_arr,
4044                matrix_res_arr,
4045                ort_marker_str = '',
4046                ort_marker_key_str = '',
4047                error_marker_str = '',
4048                bp_temp_w_arr = [],
4049                bp_item_w_temp_int = '',
4050                bp_temp_h_arr = [],
4051                bp_item_h_temp_int = '',
4052                bp_temp_type_arr = [],
4053                bp_ort_marker_temp_arr = [],
4054                bp_final_arr = [],
4055                bp_item_temp_str,
4056                bp_item_res_temp_str,
4057                bp_item_final_str,
4058                bp_item_v_temp_str,
4059                bp_item_v_temp_arr = [],
4060                is_class_def_bool = false,
4061                is_attrib_def_bool = false;
4062
4063            //Create variables for counter functionality
4064            var counter_int = 0,
4065                counter_alpha_str = '',
4066                counter_alpha_arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
4067                    'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'ag', 'ah', 'ai',
4068                    'aj', 'ak', 'al', 'am', 'an', 'ao', 'ap', 'aq', 'ar', 'as', 'at', 'au', 'av', 'aw', 'ax'
4069                ],
4070                counter_alpha_pre_arr = [],
4071                counter_alpha_post_arr = [],
4072                bp_arr_count_int = count(bp_arr),
4073                bp_class_arr_count_int = count(bp_class_arr),
4074                bp_attrib_arr_count_int = count(bp_attrib_arr),
4075                bp_item_w_temp_final_int,
4076                bp_item_h_temp_final_int;
4077
4078            //check that value in argument is array and is not empty
4079            switch(true)
4080            {
4081                case (!isArray(bp_arr)):
4082                    throw new Error ("The first argument must be an array!");
4083                    break;
4084
4085                case (isArray(bp_arr) && bp_arr_count_int == 0):
4086                    throw new Error ("The first argument must not be empty!");
4087                    break;
4088            }
4089
4090            //Check that only either classes or attributes are defined
4091            switch(true)
4092            {
4093                case ((bp_class_arr_count_int > 0) && (bp_attrib_arr_count_int > 0)):
4094                    throw new Error("You can only define either 'Classes' or 'Attributes' settings!");
4095                    break;
4096            }
4097
4098            //If classes are defined, ensure they correspond with the number of breakpoints defined
4099            switch(true)
4100            {
4101                case (bp_class_arr_count_int > 0):
4102                    //classes are defined
4103                    is_class_def_bool = true;
4104                    switch(true)
4105                    {
4106                        case (bp_class_arr_count_int !== bp_arr_count_int):
4107                            throw new Error ("The number items for 'Breakpoints' and 'Classes' settings must match");
4108                            break;
4109                    }
4110                    break;
4111            }
4112
4113            //If attributes are defined, ensure they correspond with the number of breakpoints defined
4114            switch(true)
4115            {
4116                case (bp_attrib_arr_count_int > 0):
4117                    //attributes are defined
4118                    is_attrib_def_bool = true;
4119                    switch(true)
4120                    {
4121                        case (bp_attrib_arr_count_int !== bp_arr_count_int):
4122                            throw new Error ("The number items for 'Breakpoints' and 'Attributes' settings must match");
4123                            break;
4124                    }
4125                    break;
4126            }
4127
4128            //Get Breakpoint Reference Data
4129            list_res_arr = _getResolutionList();
4130            matrix_res_arr = _getResolutionMatrix();
4131
4132            //iterate over the breakpoints provided
4133            for(var i = 0; i < bp_arr_count_int; i++)
4134            {
4135                bp_item_temp_str = bp_arr[i];
4136
4137                counter_alpha_str = counter_alpha_arr[i];
4138
4139                //ensure that the orientation markers are valid i.e. only -p and -l if any
4140                switch(true)
4141                {
4142                    case (/-+/i.test(bp_item_temp_str) && !/^[^-]*-[^-]*$/i.test(bp_item_temp_str)):
4143                        //error in the way orientation markers are defined
4144                        error_marker_str += '2';
4145                        break;
4146                }
4147
4148                //find out if there are any resolution markers e.g. -l or -p
4149                ort_marker_str = '';
4150                ort_marker_key_str = '';
4151                switch(true)
4152                {
4153                    case (substr_count(bp_item_temp_str, '-p') > 0):
4154                        ort_marker_str = 'p';
4155                        ort_marker_key_str = '-p';
4156
4157                        bp_ort_marker_temp_arr.push('p');
4158                        break;
4159
4160                    case (substr_count(bp_item_temp_str, '-l') > 0):
4161                        ort_marker_str = 'l';
4162                        ort_marker_key_str = '-l';
4163
4164                        bp_ort_marker_temp_arr.push('l');
4165                        break;
4166
4167                    default:
4168                        bp_ort_marker_temp_arr.push('x');
4169                }
4170
4171                //reset the breakpoint i.e. remove any resolution markers
4172                bp_item_final_str = bp_item_temp_str.replace(''+ort_marker_key_str+'', '');
4173
4174                //find out which class of breakpoint i.e. viewport, device, or resolution
4175                switch(true)
4176                {
4177                    case (in_array(bp_item_final_str, list_res_arr)):
4178                        //is resolution breakpoint. Get viewport dimensions
4179                        bp_item_v_temp_str = matrix_res_arr[''+bp_item_final_str+''];
4180
4181                        bp_item_v_temp_arr = arrayToInteger(explode('_', bp_item_v_temp_str));
4182
4183                        bp_item_w_temp_int = parseInt(bp_item_v_temp_arr[0]);
4184                        bp_item_h_temp_int = parseInt(bp_item_v_temp_arr[1]);
4185
4186                        //consider landscape orientation markers
4187                        bp_item_w_temp_final_int = bp_item_w_temp_int;
4188                        bp_item_h_temp_final_int = bp_item_h_temp_int;
4189                        switch(true)
4190                        {
4191                            case (ort_marker_str == 'l'):
4192                                bp_item_w_temp_final_int = bp_item_h_temp_int;
4193                                bp_item_h_temp_final_int = bp_item_w_temp_int;
4194                                break;
4195                        }
4196
4197                        bp_temp_w_arr[counter_alpha_str] = bp_item_w_temp_final_int;
4198                        bp_temp_h_arr[counter_alpha_str] = bp_item_h_temp_final_int;
4199
4200                        //set breakpoint type as resolution
4201                        bp_temp_type_arr.push('r');
4202
4203                        break;
4204
4205                    case (/[0-9]+/i.test(bp_item_final_str)):
4206                        //is viewport breakpoint
4207                        bp_temp_w_arr[counter_alpha_str] = parseInt(bp_item_final_str);
4208                        bp_temp_h_arr[counter_alpha_str] = parseInt(bp_item_final_str);
4209
4210                        //set breakpoint type as viewport
4211                        bp_temp_type_arr.push('v');
4212                        break;
4213
4214                    default:
4215                        //mark error
4216                        error_marker_str += '1';
4217                }
4218
4219                counter_alpha_pre_arr.push(counter_alpha_str);
4220
4221                counter_int++;
4222            }
4223
4224            //check if there are any errors. If yes, throw error
4225            switch(true)
4226            {
4227                case (/[1]+/i.test(error_marker_str)):
4228                    throw new Error("There are errors in your 'Breakp
4228oints' settings!");
4229                    break;
4230
4231                case (/[2]+/i.test(error_marker_str)):
4232                    throw new Error("There are errors in your 'Breakpoints' settings with regard to the way you have defined orientation markers e.g. -p or -l!");
4233                    break;
4234            }
4235
4236            //compose breakpoints
4237            var cmp = function ($a, $b) {
4238                if ($a == $b) {
4239                    return 0;
4240                }
4241                return ($a < $b) ? -1 : 1;
4242            };
4243
4244            var bp_temp_w_sort_arr = [],
4245                bp_temp_h_sort_arr = [],
4246                bp_temp_w_sort_int,
4247                bp_temp_w_sort_juxta_key_int,
4248                bp_type_arr = [],
4249                bp_temp_ort_sort_arr = [],
4250                bp_temp_class_arr = [],
4251                bp_temp_pre_attrib_arr = [],
4252                bp_temp_attrib_arr = [];
4253
4254            //reformat attribute array
4255            bp_temp_pre_attrib_arr = bp_attrib_arr;
4256
4257            //sort viewport width breakpoints
4258            bp_temp_w_sort_arr = uasort(bp_temp_w_arr, cmp);
4259
4260            //sort other arrays in an identical fashion to viewport width breakpoints
4261            counter_alpha_post_arr = array_keys(bp_temp_w_sort_arr);
4262
4263            var bp_temp_w_sort_arr_size_int = count(bp_temp_w_sort_arr);
4264            for(var i = 0; i < bp_temp_w_sort_arr_size_int; i++)
4265            {
4266                bp_temp_w_sort_int = counter_alpha_post_arr[i];
4267                bp_temp_w_sort_juxta_key_int = array_search(bp_temp_w_sort_int, counter_alpha_pre_arr);
4268
4269                //sort breakpoint heights array
4270                bp_temp_h_sort_arr[bp_temp_w_sort_int] = bp_temp_h_arr[bp_temp_w_sort_int];
4271
4272                //sort breakpoint type array
4273                bp_type_arr[i] = bp_temp_type_arr[bp_temp_w_sort_juxta_key_int];
4274
4275                //sort the orientation marker array
4276                bp_temp_ort_sort_arr[i] = bp_ort_marker_temp_arr[bp_temp_w_sort_juxta_key_int];
4277
4278                //sort the classes array
4279                bp_temp_class_arr[i] = bp_class_arr[bp_temp_w_sort_juxta_key_int];
4280
4281                //sort the attributes array
4282                bp_temp_attrib_arr[i] = bp_temp_pre_attrib_arr[bp_temp_w_sort_juxta_key_int];
4283            }
4284
4285            //Save Primary Results Data to Array
4286            bp_final_arr["bp_w"] = implode('|', bp_temp_w_sort_arr);                //width
4287            bp_final_arr["bp_h"] = implode('|', bp_temp_h_sort_arr);                //height
4288            bp_final_arr["bp_o"] = implode('|', bp_temp_ort_sort_arr);              //orientation
4289            bp_final_arr["bp_t"] = implode('|', bp_type_arr);                       //type
4290
4291            //add data for classes if defined
4292            switch(true)
4293            {
4294                case (is_class_def_bool):
4295                    var c_str = implode('|', bp_temp_class_arr);
4296                    bp_final_arr["bp_c"] = c_str;                   //classes
4297                    break;
4298            }
4299
4300            //add data for attributes if defined
4301            switch(true)
4302            {
4303                case (is_attrib_def_bool):
4304                    var a_str = implode('|', bp_temp_attrib_arr);
4305                    bp_final_arr["bp_a"] = a_str;                   //attributes
4306                    break;
4307            }
4308
4309            return bp_final_arr;
4310        }
4311        catch(e){
4312            var e_msg_str = "There was an error: "+ e.message;
4313            alert(e_msg_str);
4314        }
4315    }
4316
4317    /**
4318     * Wrapper class for _toViewportBreakpoints
4319     * @param bp_arr {Array} The list of breakpoints
4320     * @param bp_class_arr {Array} The corresponding list of classes
4321     * @return {Array}
4322     */
4323    function getBreakpoints(bp_arr, bp_class_arr)
4324    {
4325        var data_arr = [];
4326        data_arr = _toViewportBreakpoints(bp_arr, bp_class_arr);
4327
4328        return data_arr;
4329    }
4330
4331    /**
4332     * Monitors the viewport for size and orientation changes
4333     */
4334    function viewportMonitor()
4335    {
4336        var myArgs = Array.prototype.slice.call(arguments),
4337            trigger_suffix_str = (isNumber(myArgs[0])) ? "_"+myArgs[0]: "";
4338
4339        var viewport_monit_fn = function(){
4340
4341            //get viewport info before they are reset in storage
4342            var viewport_w_prev_int = store("rstv_viewportW"),
4343                viewport_h_prev_int = store("rstv_viewportH");
4344
4345            //re-initialize dimension variables
4346            _initDimensionVars();
4347
4348            //get current and active and define local variables
4349            var is_mobile_bool = isMobile(),
4350                ort_active_str = getOrientation(true),
4351                ort_curr_str = store("rstv_ort_curr"),
4352                viewport_w_curr_int,
4353                viewport_h_curr_int,
4354                viewport_w_diff_int,
4355                viewport_w_diff_abs_int,
4356                viewport_w_diff_pc_int,
4357                viewport_h_diff_int,
4358                viewport_h_diff_abs_int,
4359                viewport_h_diff_pc_int,
4360                is_softkey_bool = false;
4361
4362            //Update stored values for dimensions
4363            _updateDimensionStore();
4364
4365            /**
4366             * Perform soft keyboard check
4367             * This manages for mobile devices that resize the viewport when the soft keyboard is initialized
4368             * This scenario will sometimes result in a pseudo-orientation change which is unwanted
4369             */
4370            switch(true)
4371            {
4372                case (is_mobile_bool):
4373                    viewport_w_curr_int = store("rstv_viewportW");
4374                    viewport_h_curr_int = store("rstv_viewportH");
4375                    viewport_w_diff_int = viewport_w_curr_int-viewport_w_prev_int;
4376                    viewport_h_diff_int = viewport_h_curr_int-viewport_h_prev_int;
4377                    viewport_w_diff_abs_int = Math.abs(viewport_w_diff_int);
4378                    viewport_h_diff_abs_int = Math.abs(viewport_h_diff_int);
4379
4380                    //get the percentage changes in viewport width and height
4381                    viewport_w_diff_pc_int = (viewport_w_diff_abs_int/viewport_w_prev_int)*100;
4382                    viewport_h_diff_pc_int = (viewport_h_diff_abs_int/viewport_h_prev_int)*100;
4383
4384                    switch(true)
4385                    {
4386                        case (viewport_w_diff_pc_int < 1):
4387                            switch(true)
4388                            {
4389                                case (viewport_h_diff_pc_int > 35 && viewport_h_diff_int < 0):
4390                                    //soft keyboard is opening
4391                                    is_softkey_bool = true;
4392                                    break;
4393
4394                                case (viewport_h_diff_pc_int > 35 && viewport_h_diff_int > 0):
4395                                    //Soft keyboard closing - start
4396                                    is_softkey_bool = true;
4397                                    break;
4398
4399                                case (viewport_h_diff_pc_int > 12 && viewport_h_diff_pc_int <= 35 && viewport_h_diff_int > 0):
4400                                    //Soft keyboard closing - end
4401                                    is_softkey_bool = true;
4402                                    break;
4403
4404                                case (viewport_h_diff_pc_int == 0):
4405                                    //No movement - possible Soft keyboard action
4406                                    is_softkey_bool = true;
4407                                    break;
4408                            }
4409                            break;
4410                    }
4411                    break;
4412            }
4413
4414            /**
4415             * Trigger events only if soft keyboard action is not detected
4416             */
4417            switch(true)
4418            {
4419                case (!is_softkey_bool):
4420                    switch(true)
4421                    {
4422                        case ((ort_curr_str !== ort_active_str)):
4423                            //orientation has changed. Update stored values for dimensions and orientation
4424                            _updateOrientationStore();
4425
4426                            $(window).trigger("change_orientation"+trigger_suffix_str);
4427                            break;
4428
4429                        default:
4430                            /**
4431                             * Fire resize only for devices that are non-mobile
4432                             * This eliminates resize callback functionality for mobile devices
4433                             */
4434                            switch(true)
4435                            {
4436                                case (!is_mobile_bool):
4437                                    $(window).trigger("resize_viewport"+trigger_suffix_str);
4438                                    break;
4439                            }
4440                    }
4441                    break;
4442            }
4443        };
4444        resize(viewport_monit_fn);
4445    }
4446
4447    /**
4448     * Monitors a DOM element/container for size changes
4449     */
4450    function containerMonitor(elem)
4451    {
4452        var myArgs = Array.prototype.slice.call(arguments),
4453            trigger_suffix_str = (isNumber(myArgs[1])) ? "_"+myArgs[1]: ""
4454            ;
4455
4456        var container_monit_fn = function(){
4457            $(window).trigger("resize_container"+trigger_suffix_str);
4458        };
4459        resizeContainer(elem, container_monit_fn);
4460    }
4461
4462    /**
4463     * Attach an event handler for the resize event
4464     * @param {Function} fn The function to execute
4465     * @return object
4466     */
4467    function resize(fn)
4468    {
4469        $win.on('resize', fn);
4470        return Restive;
4471    }
4472
4473    /**
4474     * Attach an event handler for the resizecontainer event
4475     * @param {Function} fn The function to execute
4476     * @return object
4477     */
4478    function resizeContainer(el, fn)
4479    {
4480        el.on('resizecontainer', fn);
4481        return Restive;
4482    }
4483
4484    //Define Restive Object
4485    Restive = {
4486        init: init(),
4487        reInit: reInit,
4488        getUserAgent: getUserAgent,
4489        isStorageValueSet: isStorageValueSet,
4490        store: store,
4491        storeVarTracker: storeVarTracker,
4492        storeVarValidator: storeVarValidator,
4493        incrementStorageValue: incrementStorageValue,
4494        getBreakpoints: getBreakpoints,
4495        viewportW: viewportW,
4496        viewportH: viewportH,
4497        screenW: screenW,
4498        screenH: screenH,
4499        pixelW: pixelW,
4500        pixelH: pixelH,
4501        vSpan: vSpan,
4502        vPitch: vPitch,
4503        dSpan: dSpan,
4504        dPitch: dPitch,
4505        cSpan: cSpan,
4506        cPitch: cPitch,
4507        eSpan: eSpan,
4508        ePitch: ePitch,
4509        isRetina: isRetina,
4510        getPixelRatio: getPixelRatio,
4511        getPlatform: getPlatform,
4512        getFormFactor: getFormFactor,
4513        getOrientation: getOrientation,
4514        getResolution: getResolution,
4515        isPortrait: isPortrait,
4516        isLandscape: isLandscape,
4517        viewportMonitor: viewportMonitor,
4518        containerMonitor: containerMonitor,
4519        isMobile: isMobile,
4520        isNonMobile: isNonMobile,
4521        isPhone: isPhone,
4522        isTablet: isTablet,
4523        isPC: isPC,
4524        isTV: isTV,
4525        isIOS: isIOS,
4526        isApple: isApple,
4527        isAndroid: isAndroid,
4528        isSymbian: isSymbian,
4529        isBlackberry: isBlackberry,
4530        isWindows: isWindows,
4531        isWindowsPhone: isWindowsPhone,
4532        resize: resize,
4533        resizeContainer: resizeContainer
4534    };
4535    return Restive;
4536
4537})(window, document, jQuery);
4538
4539/*
4540 * Restive.JS Plugin v1.3.0
4541 * http://restivejs.com
4542 *
4543 * Copyright 2013 Obinwanne Hill <https://about.me/obinwanne.hill>
4544 * Released under MIT License
4545 */
4546(function (window, document, $, undefined) {
4547    //Gets the content of a function
4548    Function.prototype.getFuncBody = function()
4549    {
4550        // Get content between first { and last }
4551        var m = this.toString().match(/\{([\s\S]*)\}/m)[1];
4552        // Strip comments
4553        return m.replace(/^\s*\/\/.*$/mg,'');
4554    };
4555
4556    var methods = {
4557		init : function(options){
4558
4559			try{
4560
4561                //Multiple Constructor Manager
4562                methods._multiConstructorCounter();
4563                methods._multiConstructorManager();
4564
4565                //Create plugin variables
4566                var $options = options,
4567                    $valid_platform_arr = ['all', 'ios', 'android', 'symbian', 'blackberry', 'windows'],
4568                    $valid_formfactor_arr = ['all', 'pc', 'tv', 'tablet', 'phone'],
4569                    $platform_init_str = options.platform,
4570                    $formfactor_init_str = options.formfactor,
4571                    responsive_basis_str,
4572                    is_resp_basis_container_bool,
4573                    is_multi_start_bool = Restive.store("rstv_multi_start"),
4574                    rstv_store_multi_counter_int = Restive.store("rstv_multi_count"),
4575                    is_multi_abort_2_bool = Restive.store("rstv_multi_abort_2");
4576
4577                //Ensure Platform Values are within range
4578				switch(true)
4579				{
4580					case(in_array($platform_init_str, $valid_platform_arr) === false):
4581						methods._error('rstv_error_001', '"'+$platform_init_str+'" is not a valid Platform option!');
4582                        return false;
4583					    break;
4584				}
4585
4586                //Ensure Form Factor Values are within range
4587                switch(true)
4588                {
4589                    case(in_array($formfactor_init_str, $valid_formfactor_arr) === false):
4590                        methods._error('rstv_error_002', '"'+$formfactor_init_str+'" is not a valid Form Factor option!');
4591                        return false;
4592                        break;
4593                }
4594
4595                //Abort if endMulti() is not called after startMulti() with multiple constructors
4596                switch(true)
4597                {
4598                    case (is_multi_abort_2_bool):
4599                        methods._error('rstv_error_003', 'If you are calling the Restive.JS Constructor more than once, you must call $.restive.endMulti() at the end!');
4600                        return false;
4601                        break;
4602                }
4603
4604                //Get Initial Breakpoints
4605				var $breakpoints_arr = [],
4606                    $breakpoints_init_arr = [],
4607                    $classes_init_arr = [];
4608
4609                $breakpoints_init_arr = options.breakpoints;
4610                $classes_init_arr = options.classes;
4611
4612                $breakpoints_arr = methods.getBreakpoints($breakpoints_init_arr, $classes_init_arr);
4613
4614                /**
4615                 * Generate Restive Core Information
4616                 */
4617                var $rstv_core_info_arr = [];
4618
4619                //A1. Get the Device Platform e.g. iOS, Android, etc.
4620                $rstv_core_info_arr["platform"] = methods.getPlatform();
4621
4622                //A2. Get the Device Form Factor
4623                $rstv_core_info_arr["formfactor"] = methods.getFormFactor();
4624
4625                //A3. Check if Device is a mobile device
4626                $rstv_core_info_arr["is_mobile"] = methods.isMobile();
4627
4628                //A4. Get the Device Pixel Ratio
4629                $rstv_core_info_arr["pixelratio"] = methods.getPixelRatio();
4630
4631                //A5. Get the Orientation and Set Orientation Marker
4632                $rstv_core_info_arr["orientation"] = methods.getOrientation();
4633
4634                //A6. Get the Selector of the Element
4635                $rstv_core_info_arr["selector"] = getSelector(this);
4636
4637                //A7. Get the Tag Name of the Element
4638                $rstv_core_info_arr["tagname"] = this.prop("tagName").toLowerCase();
4639
4640                //Get the Basis for Responsiveness
4641                responsive_basis_str = methods._responsiveBasis($options, $rstv_core_info_arr);
4642                is_resp_basis_container_bool = !!((responsive_basis_str == 'c'));
4643
4644                //Add Responsive Basis Indicator to Device Core Info
4645                $rstv_core_info_arr["is_resp_basis_container"] = is_resp_basis_container_bool;
4646
4647                //Set Event Handlers and Callbacks according to Responsive Basis
4648                switch(true)
4649                {
4650                    case (is_resp_basis_container_bool):
4651                        methods._containerMonitor($breakpoints_arr, this, $options, $rstv_core_info_arr);
4652                        break;
4653
4654                    default:
4655                        switch(true)
4656                        {
4657                            case (!is_multi_start_bool):
4658                                methods._viewportMonitor($breakpoints_arr, this, $options, $rstv_core_info_arr);
4659                                methods._callbackManager($options, ['ready', 'init']);
4660                                break;
4661
4662                            default:
4663                                //Store some variables required for later use
4664                                window.parent.rstv_store.main["rstv_breakpoints_"+rstv_store_multi_counter_int] = $breakpoints_arr;
4665                                window.parent.rstv_store.main["rstv_this_"+rstv_store_multi_counter_int] = this;
4666                                window.parent.rstv_store.main["rstv_options_"+rstv_store_multi_counter_int] = $options;
4667                                window.parent.rstv_store.main["rstv_core_info_"+rstv_store_multi_counter_int] = $rstv_core_info_arr;
4668
4669                                window.rstv_store.main = window.parent.rstv_store.main;
4670                        }
4671                }
4672
4673                //reset turbo_classes_reflow sessionStorage variable
4674                Restive.store("rstv_turbo_classes_reflow_status_in", null);
4675
4676                //set initialization marker for addclass callback
4677                Restive.store("rstv_bpm_addclass_init", false);
4678
4679                /**
4680                 * Manage Breakpoints
4681                 */
4682                return this.each(function(){
4683					var $this = $(this);
4684                    methods.setBreakpoints($breakpoints_arr, $this, $options, $rstv_core_info_arr);
4685				});
4686			}
4687			catch(e){
4688				alert(e);
4689			    console.log(e)/*RemoveLogging:skip*/;
4690			}	
4691		},
4692        _error: function(code, message){
4693            var error_msg_is_init_bool = !!((String(Restive.store(code+"_init")).toLowerCase() === "true"));
4694            switch(true)
4695            {
4696                case (!error_msg_is_init_bool):
4697                    Restive.store(code+"_init", true);
4698                    throw new Error(message);
4699                    break;
4700            }
4701        },
4702        _callbackManager: function(){
4703
4704            var myArgs = Array.prototype.slice.call(arguments),
4705                options = myArgs[0],
4706                callback_type_arr = myArgs[1],
4707                $on_func,
4708                $on_func_body_count
4709                ;
4710
4711            //Execute onReady
4712            switch(true)
4713            {
4714                case (in_array('ready', callback_type_arr)):
4715                    var $on_ready = options.onReady,
4716                        $on_ready_body_count = options.onReady.getFuncBody().length;
4717                    switch(true)
4718                    {
4719                        case ($.isFunction($on_ready) && ($on_ready_body_count > 0)):
4720                            //Execute Callback
4721                            $on_ready();
4722                            break;
4723                    }
4724                break;
4725            }
4726
4727            //Resize Callbacks
4728            switch(true)
4729            {
4730                case (in_array('resize', callback_type_arr)):
4731                    var $on_resize = options.onResize,
4732                        $on_resize_body_count = options.onResize.getFuncBody().length;
4733                    switch(true)
4734                    {
4735                        case ($.isFunction($on_resize) && ($on_resize_body_count > 0)):
4736                            //Execute Callback
4737                            $on_resize();
4738                            break;
4739                    }
4740                    break;
4741            }
4742
4743            //PC Force Reflow Callbacks
4744            switch(true)
4745            {
4746                case (in_array('turboclassesreflow', callback_type_arr)):
4747                    var $reflow_direction_str = callback_type_arr[1],
4748                        $on_reflow = options.onTurboClassReflow,
4749                        $on_reflow_body_count = options.onTurboClassReflow.getFuncBody().length;
4750                    switch(true)
4751                    {
4752                        case ($.isFunction($on_reflow) && ($on_reflow_body_count > 0)):
4753                            //Execute Callback
4754                            $on_reflow();
4755                            break;
4756                    }
4757
4758                    var $on_reflow_in = options.onTurboClassReflowIn,
4759                        $on_reflow_in_body_count = options.onTurboClassReflowIn.getFuncBody().length;
4760                    switch(true)
4761                    {
4762                        case ($.isFunction($on_reflow_in) && ($on_reflow_in_body_count > 0)):
4763                            //Execute Callback
4764                            switch(true)
4765                            {
4766                                case ($reflow_direction_str == 'in'):
4767                                    $on_reflow_in();
4768                                    break;
4769                            }
4770                            break;
4771                    }
4772
4773                    var $on_reflow_out = options.onTurboClassReflowOut,
4774                        $on_reflow_out_body_count = options.onTurboClassReflowOut.getFuncBody().length;
4775                    switch(true)
4776                    {
4777                        case ($.isFunction($on_reflow_out) && ($on_reflow_out_body_count > 0)):
4778                            //Execute Callback
4779                            switch(true)
4780                            {
4781                                case ($reflow_direction_str == 'out'):
4782                                    $on_reflow_out();
4783                                    break;
4784                            }
4785                            break;
4786                    }
4787
4788                    break;
4789            }
4790
4791            //Rotate/Orientation Callbacks
4792            switch(true)
4793            {
4794                case (in_array('rotate', callback_type_arr)):
4795                    var ort_curr_str = Restive.getOrientation(),
4796                        $on_rotate = options.onRotate,
4797                        $on_rotate_body_count = options.onRotate.getFuncBody().length;
4798                    switch(true)
4799                    {
4800                        case ($.isFunction($on_rotate) && ($on_rotate_body_count > 0)):
4801                            //Execute Callback
4802                            $on_rotate();
4803                            break;
4804                    }
4805
4806                    //Execute onRotateToP
4807                    var $on_rotate_to_p = options.onRotateToP,
4808                        $on_rotate_to_p_body_count = options.onRotateToP.getFuncBody().length;
4809                    switch(true)
4810                    {
4811                        case ($.isFunction($on_rotate_to_p) && ($on_rotate_to_p_body_count > 0)):
4812                            //Execute Callback
4813                            switch(true)
4814                            {
4815                                case (ort_curr_str == 'portrait'):
4816                                    $on_rotate_to_p();
4817                                    break;
4818                            }
4819                            break;
4820                    }
4821
4822                    //Execute onRotateToL
4823                    var $on_rotate_to_l = options.onRotateToL,
4824                        $on_rotate_to_l_body_count = options.onRotateToL.getFuncBody().length;
4825                    switch(true)
4826                    {
4827                        case ($.isFunction($on_rotate_to_l) && ($on_rotate_to_l_body_count > 0)):
4828                            //Execute Callback
4829                            switch(true)
4830                            {
4831                                case (ort_curr_str == 'landscape'):
4832                                    $on_rotate_to_l();
4833                                    break;
4834                            }
4835                            break;
4836                    }
4837                    break;
4838            }
4839
4840            //Add/Remove Class Callbacks
4841            switch(true)
4842            {
4843                case (in_array('addclass', callback_type_arr) || in_array('removeclass', callback_type_arr)):
4844                    var $callback_type_str = callback_type_arr[0],
4845                        $callback_type_args = callback_type_arr[1],
4846                        $callback_data_arr = {'addclass': 'onAddClass', 'removeclass': 'onRemoveClass'}
4847                        ;
4848                    $on_func = options[$callback_data_arr[''+$callback_type_str+'']];
4849                    $on_func_body_count = $on_func.getFuncBody().length;
4850
4851                    switch(true)
4852                    {
4853                        case ($.isFunction($on_func) && ($on_func_body_count > 0)):
4854                            //Execute Callback
4855                            $on_func($callback_type_args);
4856                            break;
4857                    }
4858                    break;
4859            }
4860
4861            //Initialization Callbacks
4862            switch(true)
4863            {
4864                case (in_array('init', callback_type_arr)):
4865                    switch(true)
4866                    {
4867                        case (in_array('init', callback_type_arr)):
4868                            var callback_name_arr = [
4869                                'onPortrait', 'onLandscape', 'onRetina', 'onPhone', 'onTablet', 'onPC', 'onTV', 'onIOS', 'onAn
4869droid', 'onSymbian', 'onBlackberry', 'onWindows', 'onWindowsPhone', 'onMobile', 'onNonMobile'
4870                            ],
4871                                func_name_arr = [
4872                                'isPortrait', 'isLandscape', 'isRetina', 'isPhone', 'isTablet', 'isPC', 'isTV', 'isIOS', 'isAndroid', 'isSymbian', 'isBlackberry', 'isWindows', 'isWindowsPhone', 'isMobile', 'isNonMobile'
4873                            ];
4874
4875                            for(var i = 0; i < count(func_name_arr); i++)
4876                            {
4877                                $on_func = options[callback_name_arr[i]];
4878                                $on_func_body_count = $on_func.getFuncBody().length;
4879
4880                                switch(true)
4881                                {
4882                                    case ($.isFunction($on_func) && ($on_func_body_count > 0)):
4883                                        var $on_func_res = methods[func_name_arr[i]],
4884                                            $on_func_bool = $on_func_res();
4885                                        switch(true)
4886                                        {
4887                                            case ($on_func_bool):
4888                                                $on_func();
4889                                                break;
4890                                        }
4891                                        break;
4892                                }
4893                            }
4894                            break;
4895                    }
4896                    break;
4897            }
4898        },
4899        _URLMonitor: function(){
4900            //monitor changes from URL to URL
4901            var $rstv_url_str = Restive.store("rstv_url"),
4902                $rstv_url_hash_prev_str = Restive.store("rstv_url_hash"),
4903                $rstv_url_hash_curr_str = md5($rstv_url_str);
4904
4905            switch(true)
4906            {
4907                case ($rstv_url_hash_curr_str != $rstv_url_hash_prev_str):
4908                    //page has changed
4909                    Restive.store("rstv_multi_bpm_idx rstv_cache_bpm rstv_cache_bpm_lock rstv_cache_req rstv_cache_bpm_viewport_diff", null);
4910
4911                    Restive.store("rstv_url_hash", $rstv_url_hash_curr_str);
4912                    break;
4913            }
4914        },
4915        _responsiveBasis: function($options, $rstv_core_info){
4916            /**
4917             * This determines the basis for responsive i.e. viewport or container
4918             * 1. If anchor option is 'element' and Restive.JS selector is under the body tag, basis is 'container' or 'c'
4919             * 2. If not 1, basis is 'viewport' or 'v'
4920             */
4921            var resp_basis_str,
4922                selector_name_str = $rstv_core_info["selector"],
4923                elem_is_id_selector_bool = /^#[^\s]+$/i.test(selector_name_str),
4924                elem_is_child_of_body_bool = elementIsChildOf('body', selector_name_str),
4925                anchor_str = $options.anchor
4926                ;
4927
4928            try
4929            {
4930                switch(true)
4931                {
4932                    case (elem_is_child_of_body_bool && (anchor_str == 'element' || anchor_str == 'e')):
4933                        switch(true)
4934                        {
4935                            case (!elem_is_id_selector_bool):
4936                                throw new Error("You must use only the JQuery ID selector when the 'anchor' option is set to 'e' or 'element'!");
4937                                break;
4938                        }
4939                        resp_basis_str = 'c';
4940                        break;
4941
4942                    default:
4943                        resp_basis_str = 'v';
4944                        /**
4945                         * This indicates that at least one Restive.JS constructor has a Responsive Basis of 'viewport'
4946                         * NOTE: It is ultimately used to prevent the viewport and callback manager from being activated if all Restive.JS constructors are determined to have a 'container' responsiveness basis
4947                         */
4948                        Restive.store("rstv_resp_basis_viewport_init", true);
4949                }
4950
4951                return resp_basis_str;
4952            }
4953            catch(e){
4954                alert(e);
4955                console.log(e);/*RemoveLogging:skip*/
4956            }
4957        },
4958        _viewportMonitor: function($bp_arr, $this, $options, $rstv_core_info){
4959            //set event handler for resize
4960            var event_name_resize_str = "resize_viewport",
4961                event_name_ort_str = "change_orientation";
4962
4963            //set event handler for viewport resize
4964            $(window).on(event_name_resize_str, function(){
4965                methods._onResizeViewport($bp_arr, $this, $options, $rstv_core_info);
4966            });
4967
4968            //set event handler for orientation change
4969            $(window).on(event_name_ort_str, function(){
4970                methods._onChangeOrientation($bp_arr, $this, $options, $rstv_core_info);
4971            });
4972
4973            //activate Viewport Monitor
4974            Restive.viewportMonitor();
4975        },
4976        _containerMonitor: function($bp_arr, $this, $options, $rstv_core_info){
4977            var event_name_resize_container_str = "resizecontainer"
4978                ;
4979
4980            //set event handler for container resize
4981            $this.on(event_name_resize_container_str, function(){
4982                methods._onResizeContainer($bp_arr, $this, $options, $rstv_core_info);
4983            });
4984        },
4985        _onResizeViewport: function($bp_arr, $this, $options, $rstv_core_info){
4986            try{
4987                return $this.each(function(){
4988                    var $_this = $(this)
4989                        ;
4990                    methods.setBreakpoints($bp_arr, $_this, $options, $rstv_core_info, 'rv');
4991
4992                    //call resize callbacks
4993                    methods._callbackManager($options, ['resize']);
4994                });
4995            }
4996            catch(e){
4997                alert(e);
4998                console.log(e);/*RemoveLogging:skip*/
4999            }
5000        },
5001        _onResizeContainer: function($bp_arr, $this, $options, $rstv_core_info){
5002            try{
5003                return $this.each(function(){
5004                    var $_this = $(this)
5005                        ;
5006                    methods.setBreakpoints($bp_arr, $_this, $options, $rstv_core_info, 'rc');
5007                });
5008            }
5009            catch(e){
5010                alert(e);
5011                console.log(e);/*RemoveLogging:skip*/
5012            }
5013        },
5014        _onChangeOrientation: function($bp_arr, $this, $options, $rstv_core_info){
5015            try{
5016                return $this.each(function(){
5017                    var $_this = $(this);
5018                    methods.setBreakpoints($bp_arr, $_this, $options, $rstv_core_info, 'co');
5019
5020                    //call orientation callbacks
5021                    methods._callbackManager($options, ['rotate']);
5022                });
5023            }
5024            catch(e){
5025                alert(e);
5026                console.log(e);/*RemoveLogging:skip*/
5027            }
5028        },
5029        getBreakpoints: function(bp_arr, bp_class_arr){
5030            return Restive.getBreakpoints(bp_arr, bp_class_arr);
5031        },
5032        setBreakpoints: function(){
5033
5034            var myArgs = Array.prototype.slice.call(arguments);
5035            var bp_arr = myArgs[0],
5036                elem = myArgs[1],
5037                rstv_options = myArgs[2],
5038                rstv_core_info = myArgs[3],
5039                rstv_event_info = myArgs[4],
5040                is_ort_change_bool = false,
5041                is_resize_viewport_bool = false,
5042                is_resize_container_bool = false,
5043                is_resp_basis_container_bool = rstv_core_info["is_resp_basis_container"],
5044                is_multi_abort_1_bool = Restive.store("rstv_multi_abort_1")
5045            ;
5046
5047            //Capture orientation change
5048            switch(true)
5049            {
5050                case (rstv_event_info == 'co'):
5051                    //there has been a change in orientation. manage accordingly
5052                    is_ort_change_bool = true;
5053                    break;
5054            }
5055
5056            //Capture resize
5057            switch(true)
5058            {
5059                case (rstv_event_info == 'rv'):
5060                    //the viewport has been resized. manage accordingly
5061                    is_resize_viewport_bool = true;
5062                    break;
5063            }
5064
5065            //Capture resize container
5066            switch(true)
5067            {
5068                case (rstv_event_info == 'rc'):
5069                    //the selected container has been resized. manage accordingly
5070                    is_resize_container_bool = true;
5071                    break;
5072            }
5073
5074            //Abort Restive.JS if multiple constructor anomalies occur
5075            switch(true)
5076            {
5077                case (is_multi_abort_1_bool):
5078                    methods._error('rstv_error_004', 'If you are calling the Restive.JS Constructor more than once, you must call $.restive.startMulti() before calling these constructors!');
5079                    return false;
5080                    break;
5081            }
5082
5083            /**
5084             * When multiple Restive.JS Constructors are used, and a match is found, that match is saved
5085             * On successive attempts, the breakpoint conditions that previously failed are prevented from being executed further to improve overall performace
5086             * The following code manages this process
5087             * NOTE: If the Responsive Basis is 'container', this functionality is ignored
5088             */
5089            var rstv_store_is_multi_bool = Restive.store("rstv_multi_start"),
5090                rstv_store_multi_count_int = parseInt(Restive.store("rstv_multi_count")),
5091                rstv_store_bpm_idx_int = parseInt(Restive.store("rstv_multi_bpm_idx")),
5092                rstv_store_bpm_lock_bool = Restive.store("rstv_cache_bpm_lock")
5093                ;
5094
5095            switch(true)
5096            {
5097                case (!is_resp_basis_container_bool):
5098                    /**
5099                     * Do only if Responsive Basis is Viewport
5100                     */
5101                    switch(true)
5102                    {
5103                        case (rstv_store_is_multi_bool && !is_ort_change_bool && rstv_store_bpm_lock_bool):
5104                            switch(true)
5105                            {
5106                                case (isNumber(rstv_store_multi_count_int) && isNumber(rstv_store_bpm_idx_int) && rstv_store_multi_count_int != rstv_store_bpm_idx_int):
5107                                    return false;
5108                                    break;
5109                            }
5110                            break;
5111                    }
5112                    break;
5113            }
5114
5115            //get Device and Orientation Options and Information
5116            var restive_user_agent_str = Restive.getUserAgent(),
5117                options_platform_str = rstv_options.platform,
5118                options_formfactor_str = rstv_options.formfactor,
5119                options_force_dip_str = rstv_options.force_dip,
5120                restive_platform_str = rstv_core_info["platform"],
5121                restive_formfactor_str = rstv_core_info["formfactor"],
5122                restive_pixelratio_str = rstv_core_info["pixelratio"],
5123                restive_is_mobile_str = (rstv_core_info["is_mobile"] == true) ? "true": "false",
5124                ort_init_str = Restive.store("rstv_ort_init"),
5125                ort_curr_str = Restive.store("rstv_ort_curr"),
5126                is_portrait_bool = Restive.isPortrait(),
5127                is_landscape_bool = (is_portrait_bool === true) ? false : true;
5128
5129
5130            var dim_arr = [],
5131                viewport_w_int,
5132                viewport_h_int,
5133                screen_w_int,
5134                screen_h_int,
5135                pixel_w_int,
5136                pixel_h_int,
5137                viewport_w_active_int,
5138                bp_set_arr = [],
5139                bp_class_arr = [],
5140                is_class_def_bool = false,
5141                bp_width_tok_str = bp_arr["bp_w"],
5142                bp_height_tok_str = bp_arr["bp_h"],
5143                bp_ort_tok_str = bp_arr["bp_o"],
5144                bp_type_tok_str = bp_arr["bp_t"],
5145                bp_class_tok_str = bp_arr["bp_c"],
5146                bp_width_arr = [],
5147                bp_height_arr = [],
5148                bp_ort_arr = [],
5149                bp_type_arr = [];
5150
5151            viewport_w_int = Restive.viewportW();
5152            viewport_w_active_int = viewport_w_int;
5153            viewport_h_int = Restive.viewportH();
5154            screen_w_int = Restive.screenW();
5155            screen_h_int = Restive.screenH();
5156            pixel_w_int = Restive.pixelW();
5157            pixel_h_int = Restive.pixelH();
5158
5159            switch(true)
5160            {
5161                case (options_force_dip_str == true):
5162                    viewport_w_active_int = Restive.pixelW();
5163                    break;
5164            }
5165
5166            //Extract Data to Array
5167            bp_width_arr = arrayToInteger(explode("|", bp_width_tok_str));
5168            bp_height_arr = arrayToInteger(explode("|", bp_height_tok_str));
5169            bp_ort_arr = explode("|", bp_ort_tok_str);
5170            bp_type_arr = explode("|", bp_type_tok_str);
5171
5172            //Manage Classes Data
5173            switch(true)
5174            {
5175                case (typeof bp_class_tok_str !== "undefined" || bp_class_tok_str != null):
5176                    is_class_def_bool = true;
5177                    bp_class_arr = explode("|", bp_class_tok_str);
5178                    break;
5179            }
5180
5181            var bp_width_arr_has_dupl_bool,
5182                bp_width_tok_no_dupl_str = '',
5183                bp_break_on_match_bool,
5184                bp_width_int,
5185                bp_width_prev_int,
5186                bp_width_prev_ort_marker_int,
5187                is_curr_bp_in_ort_range_bool = true,
5188                is_prev_bp_in_ort_range_bool = true,
5189                is_ort_marker_set_init_bool = false,        //this indicates whether orientation markers have been used at least once
5190                bp_width_start_int,
5191                bp_width_min_int,
5192                bp_width_max_int,
5193                bp_height_int,
5194                bp_width_diff_r_int,                        //the difference between current viewport width and bp_width_max_int
5195                bp_width_diff_r_abs_int,                    //the absolute difference between current viewport width and bp_width_max_int
5196                bp_width_diff_l_int,                        //the difference between current viewport width and bp_width_min_int
5197                bp_width_diff_r_comp_int,
5198                bp_type_str,
5199                bp_ort_str,
5200                bp_class_str,
5201                bp_class_last_sel_str,
5202                span_range_bool,
5203                ort_range_bool,
5204                is_breakpoint_match_bool = false,
5205                is_breakpoint_match_hit_bool = false,
5206                is_breakpoint_match_os_bool = true,
5207                is_breakpoint_match_ff_bool = true,
5208                ba_usage_log_status_str = '',
5209                ba_usage_log_status_code_str = '',
5210                elem_set_data_str
5211                ;
5212
5213            var bp_width_arr_count_int = count(bp_width_arr);
5214
5215            //check if there are duplicate width values
5216            bp_width_arr_has_dupl_bool = arrayHasDuplicates(bp_width_arr);
5217            bp_break_on_match_bool = (bp_width_arr_has_dupl_bool) ? false : true;
5218
5219            /**
5220             * Iterate over individual breakpoints
5221             */
5222            for(var i = 0; i < bp_width_arr_count_int; i++)
5223            {
5224                /**
5225                 * Filter for:
5226                 * 1. platform
5227                 * 2. form factor
5228                 * If provided in the options
5229                 * Break out of for loop
5230                 */
5231                //1
5232                switch(true)
5233                {
5234                    case (rstv_options.platform != 'all' && rstv_options.platform != restive_platform_str):
5235                        is_breakpoint_match_os_bool = false;
5236                        break;
5237                }
5238
5239                //2
5240                switch(true)
5241                {
5242                    case (rstv_options.formfactor != 'all' && rstv_options.formfactor != restive_formfactor_str):
5243                        is_breakpoint_match_ff_bool = false;
5244                        break;
5245                }
5246
5247                //break out of for loop if match is not found
5248                if(!is_breakpoint_match_os_bool || !is_breakpoint_match_ff_bool) break;
5249
5250                var i_prev = i - 1;
5251                bp_width_int = bp_width_arr[i];
5252
5253                //manage previous breakpoint widths
5254                switch(true)
5255                {
5256                    case (i > 0):
5257                        bp_width_prev_int = bp_width_arr[i_prev];
5258                        break;
5259
5260                    default:
5261                        bp_width_prev_int = 0;
5262                        bp_width_prev_ort_marker_int = 0;
5263                }
5264
5265                bp_height_int = bp_height_arr[i];
5266
5267                bp_type_str = bp_type_arr[i];
5268                bp_ort_str = bp_ort_arr[i];
5269
5270                //Consider orientation markers
5271                is_prev_bp_in_ort_range_bool = is_curr_bp_in_ort_range_bool;
5272                switch(true)
5273                {
5274                    case (bp_ort_str == "p"):
5275                        ort_range_bool = (is_portrait_bool) ? true : false;
5276                        is_ort_marker_set_init_bool = true;
5277
5278                        is_curr_bp_in_ort_range_bool = ort_range_bool;
5279                        bp_width_tok_no_dupl_str = (is_prev_bp_in_ort_range_bool === false) ? bp_width_prev_ort_marker_int: bp_width_tok_no_dupl_str;
5280                        break;
5281
5282                    case (bp_ort_str == "l"):
5283                        ort_range_bool = (is_landscape_bool) ? true : false;
5284                        is_ort_marker_set_init_bool = true;
5285
5286                        is_curr_bp_in_ort_range_bool = ort_range_bool;
5287                        bp_width_tok_no_dupl_str = (is_prev_bp_in_ort_range_bool === false) ? bp_width_prev_ort_marker_int: bp_width_tok_no_dupl_str;
5288                        break;
5289
5290                    default:
5291                        /**
5292                         * If is_prev_bp_in_ort_range_bool is false, it means that the previous breakpoint
5293                         * had an orientation marker ('-p' or '-l') that did not match the current
5294                         * orientation of the viewport.
5295                         * And if is_ort_marker_set_init_bool is true, then there has been a transition from a
5296                         * breakpoint with an orientation marker to one without one.
5297                         */
5298                        bp_width_tok_no_dupl_str = (is_ort_marker_set_init_bool === true && is_prev_bp_in_ort_range_bool === false) ? bp_width_prev_ort_marker_int: bp_width_tok_no_dupl_str;
5299
5300                        bp_width_prev_ort_marker_int = (i > 0) ? bp_width_int: 0;
5301                        ort_range_bool = true;
5302                        is_curr_bp_in_ort_range_bool = ort_range_bool;
5303                }
5304
5305                //Manage duplicate entries
5306                switch(true)
5307                {
5308                    case (i == 0):
5309                        bp_width_start_int = 0;
5310                        bp_width_tok_no_dupl_str = bp_width_int;
5311                        break;
5312
5313                    case (i >= 1):
5314
5315                        switch(true)
5316                        {
5317                            case (bp_width_int !== bp_width_prev_int):
5318                                bp_width_tok_no_dupl_str = bp_width_int+'-!'+bp_width_tok_no_dupl_str;
5319                                break;
5320                        }
5321
5322                        bp_width_start_int = parseInt(getValueAfterExplode(bp_width_tok_no_dupl_str, '-!', 1));
5323
5324                        break;
5325                }
5326
5327                //Define classes
5328                bp_class_str = bp_class_arr[i];
5329
5330                //set ranges for widths
5331                switch(true)
5332                {
5333                    case (i == 0):
5334                        bp_width_min_int = bp_width_start_int;
5335                        bp_width_max_int = bp_width_int;
5336
5337                        break;
5338
5339                    default:
5340                        bp_width_min_int = (bp_width_start_int == 0) ? bp_width_start_int : bp_width_start_int 
5340+ 1;
5341                        bp_width_max_int = bp_width_int;
5342                }
5343
5344                /**
5345                 * Check for Matching Breakpoints
5346                 * 1. Do for Container Basis
5347                 * 2. Do for Viewport Basis. Make sure to consider force_dip option
5348                 */
5349                switch(true)
5350                {
5351                    case (is_resp_basis_container_bool):
5352                        //1
5353                        span_range_bool = Restive.eSpan(bp_width_min_int, bp_width_max_int, elem, rstv_options.anchor_e_df, rstv_options.force_dip);
5354                        break;
5355
5356                    default:
5357                        //2
5358                        span_range_bool = (options_force_dip_str == true) ? Restive.cSpan(bp_width_min_int, bp_width_max_int): Restive.vSpan(bp_width_min_int, bp_width_max_int);
5359                }
5360
5361                /**
5362                 * Set Breakpoints
5363                 * A. For Container Basis
5364                 *
5365                 * B. For Viewport Basis
5366                 * Status codes as follows:
5367                 * 1: Viewport matched breakpoint with clean hit on initialization i.e. viewport is virtually identical to breakpoint
5368                 * 2: Viewport matched breakpoint with clean hit after orientation change
5369                 * 3: Viewport matched breakpoint but not with a clean hit i.e. margin between viewport width and upper limit of matched breakpoint range is significant
5370                 * 4: Viewport matched breakpoint after orientation change but not with a clean hit i.e. margin between viewport width and upper limit of matched breakpoint range is significant
5371                 */
5372                switch(true)
5373                {
5374                    case (span_range_bool && ort_range_bool):
5375
5376                        switch(true)
5377                        {
5378                            case (is_resp_basis_container_bool):
5379                                //A
5380                                is_breakpoint_match_bool = true;
5381                                break;
5382
5383                            default:
5384                                //B
5385                                bp_width_diff_r_int = bp_width_max_int - viewport_w_active_int;
5386                                bp_width_diff_r_abs_int = Math.abs(bp_width_diff_r_int);
5387                                bp_width_diff_l_int = viewport_w_active_int - bp_width_min_int;
5388
5389                                bp_width_diff_r_comp_int = bp_width_max_int*0.1;
5390                                bp_width_diff_r_comp_int = Math.round(bp_width_diff_r_comp_int);
5391
5392                                switch(true)
5393                                {
5394                                    case (is_ort_change_bool):
5395                                        //capture some key metrics
5396                                        switch(true)
5397                                        {
5398                                            case (bp_width_diff_r_int > bp_width_diff_r_comp_int):
5399                                                ba_usage_log_status_code_str = "4";
5400                                                break;
5401
5402                                            default:
5403                                                ba_usage_log_status_code_str = "2";
5404                                        }
5405                                        break;
5406
5407                                    default:
5408                                        //capture some key metrics
5409                                        switch(true)
5410                                        {
5411                                            case (bp_width_diff_r_int > bp_width_diff_r_comp_int):
5412                                                ba_usage_log_status_code_str = "3";
5413                                                break;
5414
5415                                            default:
5416                                                ba_usage_log_status_code_str = "1";
5417                                        }
5418                                }
5419
5420                                is_breakpoint_match_bool = true;
5421
5422                                //Capture class values of last hit
5423                                switch(true)
5424                                {
5425                                    case (is_breakpoint_match_bool):
5426                                        is_breakpoint_match_hit_bool = true;
5427
5428                                        bp_class_last_sel_str = bp_class_
5428str;
5429
5430                                        switch(true)
5431                                        {
5432                                            case (bp_ort_str != "x"):
5433                                                bp_break_on_match_bool = true;
5434                                                break;
5435                                        }
5436                                        break;
5437                                }
5438                        }
5439
5440                        break;
5441
5442                    default:
5443                        is_breakpoint_match_bool = false;
5444                }
5445
5446                //break out of for loop if match is found
5447                if(is_breakpoint_match_bool && bp_break_on_match_bool) break;
5448            }
5449
5450            //Perform adjustment of breakpoint match value to compensate for if bp_break_on_match_bool is false
5451            switch(true)
5452            {
5453                case (is_breakpoint_match_hit_bool):
5454                    is_breakpoint_match_bool = true;
5455                    bp_class_str = bp_class_last_sel_str;
5456                    break;
5457            }
5458
5459            //Some Breakpoint Advisory Information
5460            switch(true)
5461            {
5462                case (!is_breakpoint_match_bool):
5463
5464                    //Do for Container Basis
5465                    switch(true)
5466                    {
5467                        case (is_resp_basis_container_bool):
5468                            methods.unsetElementDOM(elem, rstv_options);
5469                            return;
5470                            break;
5471                    }
5472
5473                    //Do for Viewport Basis
5474                    bp_width_min_int = 0;
5475                    bp_width_max_int = 0;
5476
5477                    switch(true)
5478                    {
5479                        case (!Restive.store("rstv_multi_start") || is_ort_change_bool):
5480                            methods.unsetElementDOM(elem, rstv_options);
5481                            break;
5482                    }
5483
5484                    switch(true)
5485                    {
5486                        case (!is_breakpoint_match_os_bool && is_breakpoint_match_ff_bool):
5487                            ba_usage_log_status_code_str = "7";
5488                            break;
5489
5490                        case (!is_breakpoint_match_ff_bool && is_breakpoint_match_os_bool):
5491                            ba_usage_log_status_code_str = "8";
5492                            break;
5493
5494                        case (!is_breakpoint_match_ff_bool && !is_breakpoint_match_os_bool):
5495                            ba_usage_log_status_code_str = "9";
5496                            break;
5497
5498                        default:
5499                            switch(true)
5500                            {
5501                                case (is_ort_change_bool):
5502                                    ba_usage_log_status_code_str = "6";
5503                                    break;
5504
5505                                default:
5506                                    ba_usage_log_status_code_str = "5";
5507                            }
5508                    }
5509
5510                    //Add Turbo Classes if any
5511                    elem_set_data_str = methods._addTurboClasses('', rstv_options.turbo_classes);
5512
5513                    //This if for turbo_classes_reflow option
5514                    elem_set_data_str = methods._addTurboClassesReflow(elem_set_data_str, rstv_options);
5515
5516                    methods.setElementDOM(elem, elem_set_data_str, rstv_options);
5517
5518                    //persist
5519                    Restive.store("rstv_breakpoint_match_curr", false);
5520
5521                    break;
5522
5523                case (is_breakpoint_match_bool):
5524                    elem_set_data_str = methods._addTurboClasses(bp_class_str, rstv_options.turbo_classes);
5525
5526                    //This if for turbo_classes_reflow option
5527                    elem_set_data_str = methods._addTurboClassesReflow(elem_set_data_str, rstv_options);
5528
5529                    /**
5530                     * Set class
5531                     */
5532                    //Do for Container Basis
5533                    switch(true)
5534                    {
5535                        case (is_resp_basis_container_bool):
5536                            methods.setElementDOM(elem, elem_set_data_str, rstv_options);
5537                            return;
5538                            break;
5539                    }
5540
5541                    //Do for Viewport Basis
5542                    switch(true)
5543                    {
5544                        case (Restive.store("rstv_multi_start")):
5545                            var bpm_h_counter_int = parseInt(Restive.store("rstv_bpm_h_counter"));
5546                            switch(true)
5547                            {
5548                                case (is_ort_change_bool):
5549                                    //change in orientation
5550                                    methods.setElementDOM(elem, elem_set_data_str, rstv_options);
5551                                    break;
5552
5553                                default:
5554                                    //initialization
5555                                    switch(true)
5556                                    {
5557                                        case (bpm_h_counter_int > 1):
5558                                            //check if the current viewport offers a better match
5559                                            var ss_bp_width_diff_r_abs_int = parseInt(Restive.store("rstv_cache_bpm_viewport_diff"));
5560
5561                                            switch(true)
5562                                            {
5563                                                case (bp_width_diff_r_abs_int < ss_bp_width_diff_r_abs_int):
5564                                                    //this is a better viewport match
5565                                                    methods.setElementDOM(elem, elem_set_data_str, rstv_options);
5566
5567                                                    switch(true)
5568                                                    {
5569                                                        case(!rstv_store_bpm_lock_bool):
5570                                                            Restive.store("rstv_multi_bpm_idx", rstv_store_multi_count_int);
5571                                                            break;
5572                                                    }
5573
5574                                                    Restive.store("rstv_cache_bpm_viewport_diff", bp_width_diff_r_abs_int);
5575                                                    break;
5576                                            }
5577
5578                                            break;
5579
5580                                        default:
5581                                            methods.setElementDOM(elem, elem_set_data_str, rstv_options);
5582                                            switch(true)
5583                                            {
5584                                                case(!rstv_store_bpm_lock_bool):
5585                                                    Restive.store("rstv_multi_bpm_idx", rstv_store_multi_count_int);
5586                                                    break;
5587                                            }
5588
5589                                            Restive.store("rstv_cache_bpm_viewport_diff", bp_width_diff_r_abs_int);
5590                                    }
5591
5592                                    bpm_h_counter_int++;
5593                                    Restive.store("rstv_bpm_h_counter", bpm_h_counter_int, '', {expires: 1000});
5594                            }
5595
5596                            break;
5597
5598                        default:
5599                            //Set the element class immediately
5600                            methods.setElementDOM(elem, elem_set_data_str, rstv_options);
5601                    }
5602
5603                    //persist
5604                    Restive.store("rstv_breakpoint_match_curr", true);
5605                    break;
5606            }
5607
5608            /**
5609             * Track Breakpoint Hits and Misses in Storage
5610             * Do this incrementally when:
5611             * 1. Multi-Constructor Mode is active
5612             * 2. There has not been a change in orientation
5613             * 3. Breakpoint Match Cache Lock is not set
5614             * NOTE: For Multi-constructor Operations only
5615             */
5616            var rstv_cache_bpm_lock_bool = Restive.store("rstv_cache_bpm_lock");
5617            switch(true)
5618            {
5619                case (rstv_store_is_multi_bool && !is_ort_change_bool && !((isString(rstv_cache_bpm_lock_bool) && rstv_cache_bpm_lock_bool != "") || isBool(rstv_cache_bpm_lock_bool))):
5620                    (Restive.store("rstv_breakpoint_match_curr")) ? methods._extVarTracker("rstv_cache_bpm", "h", "ls", false, '', false): methods._extVarTracker("rstv_cache_bpm", "m", "ls", false, '', false);
5621                    break;
5622            }
5623
5624            //Exit for Matched Breakpoint
5625            switch(true)
5626            {
5627                case (is_breakpoint_match_bool):
5628                    return true;
5629                    break;
5630            }
5631
5632            return false;
5633		},
5634        _addTurboClassesReflow: function(class_data_str, options){
5635            switch(true)
5636            {
5637                case (methods.isPC()):
5638                    //only do for Personal Computer environments
5639
5640                    switch(true)
5641                    {
5642                        case (options.turbo_classes_reflow && isString(options.turbo_classes) && options.turbo_classes != ''):
5643                            //only do if turbo_classes_reflow option is true and turbo_classes are populated
5644
5645                            var opt_isset_is_mobile_bool,
5646                                fpr_span_range_tomobile_bool,
5647                                fpr_span_range_tophone_bool,
5648                                fpr_span_range_totablet_bool,
5649                                fpr_limits_tablet_int,
5650                                fpr_limits_phone_int,
5651                                fpr_limits_bp_btw_phone_and_tablet_int,
5652                                fpr_test_key_str,
5653                                fpr_test_value_str,
5654                                fpr_limits_arr = [],
5655                                turbo_classes_arr = [],
5656                                fpr_final_data_str = class_data_str,
5657                                is_turbo_classes_reflow_match_bool = false,
5658                                is_turbo_classes_reflow_status_bool = Restive.store('rstv_turbo_classes_reflow_status_in')
5659                                ;
5660
5661                            //get the turbo_classes_reflow_limits values
5662                            fpr_limits_arr = explode(',', options.turbo_classes_reflow_limits);
5663                            fpr_limits_phone_int = parseInt(fpr_limits_arr[0]);
5664                            fpr_limits_tablet_int = parseInt(fpr_limits_arr[1]);
5665
5666                            //ensure is_mobile turbo_classes parameter
5667                            opt_isset_is_mobile_bool = /is_mobile=/i.test(options.turbo_classes);
5668                            switch(true)
5669                            {
5670                                case (opt_isset_is_mobile_bool):
5671                                    //iterate over all provided turbo_classes
5672                                    turbo_classes_arr = explode(',', options.turbo_classes);
5673                                    for(var j = 0; j < count(turbo_classes_arr); j++)
5674                                    {
5675                                        fpr_test_key_str = getValueAfterExplode(turbo_classes_arr[j], "=", 0);
5676                                        fpr_test_value_str = getValueAfterExplode(turbo_classes_arr[j], "=", 1);
5677
5678                                        switch(true)
5679                                        {
5680                                            case (fpr_test_key_str == 'is_mobile'):
5681                                                fpr_span_range_tomobile_bool = (options.force_dip == true) ? Restive.cSpan(0, fpr_limits_tablet_int): Restive.vSpan(0, fpr_limits_tablet_int);
5682
5683                                                switch(true)
5684                                                {
5685                                                    case (fpr_span_range_tomobile_bool):
5686
5687                                                        fpr_final_data_str += ' '+fpr_test_value_str;
5688                                                        is_turbo_classes_reflow_match_bool = true;
5689                                                        switch(true)
5690                                                        {
5691                                                            case (!is_turbo_classes_reflow_status_bool && is_turbo_classes_reflow_match_bool):
5692                                                                Restive.store('rstv_turbo_classes_reflow_status_in', true);
5693
5694                                                                //add callback
5695                                                                methods._callbackManager(options, ['turboclassesreflow', 'in']);
5696
5697                                                                break;
5698                                                        }
5699
5700                                                        break;
5701
5702                                                    default:
5703                                                        is_turbo_classes_reflow_match_bool = false;
5704                                                        switch(true)
5705                                                        {
5706                                                            case (is_turbo_classes_reflow_status_bool && !is_turbo_classes_reflow_match_bool):
5707                                                                Restive.store('rstv_turbo_classes_reflow_status_in', false);
5708
5709                                                                //add callback
5710                                                                methods._callbackManager(options, ['turboclassesreflow', 'out']);
5711
5712                                                                break;
5713                                                        }
5714                                                }
5715
5716                                                break;
5717                                        }
5718
5719                                        switch(true)
5720                                        {
5721                                            case (fpr_test_key_str == 'is_phone'):
5722                                                fpr_span_range_tophone_bool = (options.force_dip == true) ? Restive.cSpan(0, fpr_limits_phone_int): Restive.vSpan(0, fpr_limits_phone_int);
5723
5724                                                fpr_final_data_str = (fpr_span_range_tophone_bool) ? fpr_final_data_str + ' ' + fpr_test_value_str: fpr_final_data_str;
5725                                                break;
5726                                        }
5727
5728                                        switch(true)
5729                                        {
5730                                            case (fpr_test_key_str == 'is_tablet'):
5731                                                fpr_limits_bp_btw_phone_and_tablet_int = fpr_limits_phone_int + 1;
5732                                                fpr_span_range_totablet_bool = (options.force_dip == true) ? Restive.cSpan(fpr_limits_bp_btw_phone_and_tablet_int, fpr_limits_tablet_int): Restive.vSpan(fpr_limits_bp_btw_phone_and_tablet_int, fpr_limits_tablet_int);
5733                                                fpr_final_data_str = (fpr_span_range_totablet_bool) ? fpr_final_data_str + ' ' + fpr_test_value_str: fpr_final_data_str;
5734
5735                                                break;
5736                                        }
5737
5738                                    }
5739
5740                                    return fpr_final_data_str;
5741                                    break;
5742                            }
5743                            break;
5744                    }
5745                    break;
5746            }
5747
5748            //Restive.store('rstv_turbo_classes_reflow_status_in', false);
5749            return class_data_str;
5750        },
5751        _addTurboClasses: function(class_data_str, opt_turbo_classes){
5752            //return class name only if power classes info is invalid or empty
5753            switch(true)
5754            {
5755                case (!isString(opt_turbo_classes) || opt_turbo_classes == ''):
5756                    return class_data_str;
5757                    break;
5758            }
5759
5760            //Define variables
5761            var opt_pc_arr = [],
5762                pc_key_str,
5763                pc_value_str,
5764                pc_temp_arr = [],
5765                pc_temp_str = '',
5766                pc_final_str = '',
5767                pc_func_arr = {'is_mobile': 'isMobile', 'is_non_mobile': 'isNonMobile', 'is_retina': 'isRetina', 'is_phone': 'isPhone', 'is_tablet': 'isTablet', 'is_tv': 'isTV', 'is_pc': 'isPC', 'is_portrait': 'isPortrait', 'is_landscape': 'isLandscape'},
5768                pc_func_name_str,
5769                pc_func_res
5770                ;
5771
5772            opt_pc_arr = explode(',', opt_turbo_classes);
5773            for(var i = 0; i < count(opt_pc_arr); i++)
5774            {
5775                pc_key_str = getValueAfterExplode(opt_pc_arr[i], "=", 0);
5776                pc_value_str = getValueAfterExplode(opt_pc_arr[i], "=", 1);
5777
5778                pc_func_name_str = pc_func_arr[pc_key_str];
5779                switch(true)
5780                {
5781                    case (isString(pc_func_name_str) && pc_func_name_str != ''):
5782                        pc_func_res = methods[pc_func_name_str];
5783                        switch(true)
5784                        {
5785                            case (pc_func_res()):
5786                                pc_temp_arr.push(pc_value_str);
5787                                break;
5788                        }
5789                        break;
5790                }
5791            }
5792
5793            pc_temp_str = implode(' ', pc_temp_arr);
5794            pc_final_str = (pc_temp_str != '') ? pc_temp_str+' '+class_data_str : class_data_str;
5795            return pc_final_str;
5796        },
5797        setElementDOM: function(elem, elem_set_str, options){
5798            var data_key_str = md5(getSelector(elem)),
5799                ds_elem_set_class_name_str = "rstv_bpm_class_"+data_key_str,
5800                ds_elem_set_str,
5801                init_addclass_bool = Restive.store("rstv_bpm_addclass_init")
5802            ;
5803
5804            ds_elem_set_str = (isString(Restive.store(ds_elem_set_class_name_str)) && Restive.store(ds_elem_set_class_name_str) != '') ? Restive.store(ds_elem_set_class_name_str): '';
5805
5806            switch(true)
5807            {
5808                case (ds_elem_set_str != elem_set_str || init_addclass_bool == false):
5809                    switch(true)
5810                    {
5811                        case (ds_elem_set_str != ''):
5812                            elem.removeClass(ds_elem_set_str).addClass(elem_set_str);
5813                            methods._callbackManager(options, ['removeclass', ''+ds_elem_set_str+'']);
5814                            break;
5815
5816                        default:
5817                            elem.addClass(elem_set_str);
5818                    }
5819
5820                    Restive.store(ds_elem_set_class_name_str, elem_set_str);
5821                    methods._callbackManager(options, ['addclass', ''+elem_set_str+'']);
5822
5823                    Restive.store("rstv_bpm_addclass_init", true);
5824                    break;
5825            }
5826        },
5827        unsetElementDOM: function(elem, options){
5828            var data_key_str = md5(getSelector(elem)),
5829                ds_elem_set_class_name_str = "rstv_bpm_class_"+data_key_str,
5830                ds_elem_set_str;
5831
5832            ds_elem_set_str = (isString(Restive.store(ds_elem_set_class_name_str)) && Restive.store(ds_elem_set_class_name_str) != '') ? Restive.store(ds_elem_set_class_name_str): '';
5833
5834            elem.removeClass(ds_elem_set_str);
5835            methods._callbackManager(options, ['removeclass', ''+ds_elem_set_str+'']);
5836        },
5837        _extVarTracker: function($track_name_str, $track_value_str)
5838        {
5839            var myArgs = Array.prototype.slice.call(arguments);
5840            var store_type_str = (isString(myArgs[2]) && myArgs[2] != "") ? myArgs[2] : 'ck';
5841            var unique_bool = (isBool(myArgs[3])) ? myArgs[3]: false;
5842            var expires = (isNumber(myArgs[4]) || isString(myArgs[4])) ? parseInt(myArgs[4]): '';
5843            var reverse_order_bool = (isBool(myArgs[5])) ? myArgs[5]: true;
5844            var delim_str = (isString(myArgs[6]) && myArgs[6] != "") ? myArgs[6]: '-!';
5845            var data_count_int = (isNumber(myArgs[7]) || isString(myArgs[7])) ? parseInt(myArgs[7]): 80;
5846
5847            return Restive.storeVarTracker($track_name_str, $track_value_str, store_type_str, unique_bool, expires, reverse_order_bool, delim_str, data_count_int);
5848        },
5849        _multiConstructorSelectPos: function(){
5850            var bpm_val_str = Restive.store("rstv_cache_bpm"),
5851                bpm_val_arr = explode("-!", bpm_val_str),
5852                bpm_val_temp_str,
5853                bpm_idx_int = parseInt(Restive.store("rstv_multi_bpm_idx"))
5854                ;
5855
5856            bpm_val_temp_str = implode("", bpm_val_arr);
5857
5858            /**
5859             * 1. If only one hit is recorded, get it's position
5860             * 2. If all misses, get the last position i.e. length of string
5861             * 3. If more than one hit, get the value for the best match previously calculated
5862             */
5863            var sel_constructor_pos,
5864                sel_constructor_pos_1,
5865                pattern_1 = new RegExp("^[^h]*h[^h]*$", "gi"),
5866                pattern_2 = new RegExp("^m+$", "gi");
5867
5868            switch(true)
5869            {
5870                case (pattern_1.test(bpm_val_temp_str)):
5871                    //1
5872                    sel_constructor_pos = strrpos(bpm_val_temp_str, 'h');
5873                    break;
5874
5875                case (pattern_2.test(bpm_val_temp_str)):
5876                    //2
5877                    Restive.store("rstv_cache_bpm_all_miss", true, '', {expires: 2000});
5878                    sel_constructor_pos = strrpos(bpm_val_temp_str, 'm');
5879                    break;
5880
5881                case(substr_count(bpm_val_temp_str, "h") > 1):
5882                    //3
5883                    sel_constructor_pos = bpm_idx_int - 1;
5884                    break;
5885            }
5886            sel_constructor_pos_1 = sel_constructor_pos + 1;
5887            Restive.store("rstv_multi_bpm_idx", sel_constructor_pos_1);
5888
5889            return sel_constructor_pos;
5890        },
5891        _multiConstructorManageEvents: function(sel_constructor_pos){
5892            //Remove any events previously attached
5893            $(window).off('resize');
5894
5895            //Manage Viewport Monitoring and Callbacks
5896            var $sel_pos_final_int = parseInt(sel_constructor_pos) + 1,
5897                $breakpoints_arr = window.parent.rstv_store.main["rstv_breakpoints_"+$sel_pos_final_int],
5898                $this = window.parent.rstv_store.main["rstv_this_"+$sel_pos_final_int],
5899                $options = window.parent.rstv_store.main["rstv_options_"+$sel_pos_final_int],
5900                $rstv_core_info_arr = window.parent.rstv_store.main["rstv_core_info_"+$sel_pos_final_int]
5901                ;
5902
5903            switch(true)
5904            {
5905                case (Restive.store("rstv_resp_basis_viewport_init")):
5906                    methods._viewportMonitor($breakpoints_arr, $this, $options, $rstv_core_info_arr);
5907                    methods._callbackManager($options, ['ready', 'init']);
5908                    break;
5909            }
5910        },
5911        _multiConstructorFinalize: function(){
5912
5913            var sel_constructor_pos = methods._multiConstructorSelectPos();
5914
5915            //Redo event handlers
5916            methods._multiConstructorManageEvents(sel_constructor_pos);
5917
5918            /**
5919             * Set Breakpoint Match Cache Lock
5920             * This marks that a Breakpoint Match has been determined (i.e. hit or miss) and as such this result should be stored and reused
5921             * NOTE: Only used in Multi-Constructor Operations
5922             */
5923            Restive.store("rstv_cache_bpm_lock", true);
5924
5925            //Reset some local storage variables
5926            Restive.store("rstv_cache_req", null);
5927            Restive.store("rstv_multi_count", null);
5928        },
5929        _multiConstructorStart: function(){
5930            Restive.store("rstv_multi_count", 0);                 //counts the number of multi-constructor operations
5931            Restive.store("rstv_multi_start", true);
5932            Restive.store("rstv_multi_abort_1", false);
5933            Restive.store("rstv_multi_abort_2", false);
5934
5935            //set some expiring counters
5936            Restive.store("rstv_bpm_h_counter", 1, '', {expires: 1000});
5937            Restive.store("rstv_bpm_m_counter", 1, '', {expires: 1000});
5938
5939            //set some persistent counters
5940            switch(true)
5941            {
5942                case (!Restive.isStorageValueSet("rstv_multi_start_count")):
5943                    Restive.store("rstv_multi_start_count", 1);
5944                    Restive.store("rstv_multi_end", false);
5945                    break;
5946
5947                default:
5948                    Restive.incrementStorageValue("rstv_multi_start_count");
5949            }
5950        },
5951        _multiConstructorManager: function(){
5952            var is_multi_start_bool = Restive.store("rstv_multi_start"),
5953                is_multi_end_bool = Restive.store("rstv_multi_end"),
5954                rstv_count_int = parseInt(Restive.store("rstv_multi_count")),
5955                rstv_multi_start_count_int = parseInt(Restive.store("rstv_multi_start_count"))
5956            ;
5957
5958            /**
5959             * Check if Restive.JS Constructor has been called multiple times
5960             */
5961            switch(true)
5962            {
5963                case (rstv_count_int > 1):
5964                    //Signal abort if startMulti() method call not used
5965                    switch(true)
5966                    {
5967                        case (is_multi_start_bool === false):
5968                            Restive.store("rstv_multi_abort_1", true);
5969                            break;
5970                    }
5971                    break;
5972            }
5973
5974            /**
5975             * Check if Restive.JS Constructor has been called multiple times and has not been finalized properly with endMulti() method
5976             */
5977            switch(true)
5978            {
5979                case (rstv_multi_start_count_int > 1 && is_multi_end_bool === false):
5980                    Restive.store("rstv_multi_abort_2", true);
5981                    break;
5982            }
5983            methods._URLMonitor();
5984        },
5985        _multiConstructorCounter: function(){
5986            Restive.incrementStorageValue("rstv_multi_count");
5987        },
5988        _multiConstructorEnd: function(){
5989            //reset stored variables
5990            Restive.store("rstv_multi_start_count", 0);
5991            Restive.store("rstv_multi_end", true);
5992
5993            //finalize multi constructor operations
5994            methods._multiConstructorFinalize();
5995        },
5996        getUserAgent: function (){
5997            return Restive.getUserAgent();
5998        },
5999        getPlatform: function (){
6000            return Restive.getPlatform();
6001        },
6002        getFormFactor: function(){
6003            return Restive.getFormFactor();
6004        },
6005        getOrientation: function(){
6006            return Restive.getOrientation();
6007        },
6008        getResolution: function(){
6009            return Restive.getResolution();
6010        },
6011        getPixelRatio: function(pxl_ratio){
6012            return Restive.getPixelRatio(pxl_ratio);
6013        },
6014        getViewportW: function(){
6015            return Restive.viewportW();
6016        },
6017        getViewportH: function(){
6018            return Restive.viewportH();
6019        },
6020        getScreenW: function(){
6021            return Restive.screenW();
6022        },
6023        getScreenH: function(){
6024            return Restive.screenH();
6025        },
6026        getPixelW: function(){
6027            return Restive.pixelW();
6028        },
6029        getPixelH: function(){
6030            return Restive.pixelH();
6031        },
6032        isRetina: function(){
6033            return Restive.isRetina();
6034        },
6035        isMobile: function(){
6036            return Restive.isMobile();
6037        },
6038        isNonMobile: function(){
6039            return Restive.isNonMobile();
6040        },
6041        isPhone: function(){
6042            return Restive.isPhone();
6043        },
6044        isTablet: function(){
6045            return Restive.isTablet();
6046        },
6047        isTV: function(){
6048            return Restive.isTV();
6049        },
6050        isPC: function(){
6051            return Restive.isPC();
6052        },
6053        isIOS: function(){
6054            return Restive.isIOS();
6055        },
6056        isApple: function(){
6057            return Restive.isApple();
6058        },
6059        isAndroid: function(){
6060            return Restive.isAndroid();
6061        },
6062        isSymbian: function(){
6063            return Restive.isSymbian();
6064        },
6065        isBlackberry: function(){
6066            return Restive.isBlackberry();
6067        },
6068        isWindows: function(){
6069            return Restive.isWindows();
6070        },
6071        isWindowsPhone: function(){
6072            return Restive.isWindowsPhone();
6073        },
6074        isPortrait: function(){
6075            return Restive.isPortrait();
6076        },
6077        isLandscape: function(){
6078            return Restive.isLandscape();
6079        }
6080	};
6081
6082    /**
6083     * Plugin Initialize
6084     */
6085    $.fn.restive = function(args){
6086		
6087		if ( methods[args] )
6088		{
6089			//execute JQuery Plugin Method
6090		   	return methods[ args ].apply( this, Array.prototype.slice.call( arguments, 1 ));
6091		}
6092		else if ( typeof args === 'object' || ! args ) 
6093		{
6094			//Process JQuery Plugin Options
6095			var opts = $.extend({}, $.fn.restive.defaults, args);
6096			var new_args = new Array(opts);
6097			return methods.init.apply( this, new_args );
6098		}
6099		else 
6100		{
6101		   	$.error( 'Method ' +  args + ' does not exist on Restive.JS' );
6102		}
6103	};	
6104	
6105	/**
6106	 * Plugin Defaults
6107	 */
6108	$.fn.restive.defaults = {
6109        breakpoints: [],                                //the breakpoints
6110		classes: [],                                    //the corresponding classes
6111        anchor: 'window',                               //the basis for responsiveness
6112        anchor_e_df: 'w',                               //the dimension format for element-value anchor operations
6113        platform: 'all',						        //all, ios, android, symbian, blackberry, windows
6114        formfactor: 'all',                              //all, pc, tv, tablet, phone
6115        turbo_classes: '',                              //special class-based functionality
6116        turbo_classes_reflow: false,                    //this will apply specific turbo_classes based on limit settings
6117        turbo_classes_reflow_limits: '480,960',         //defines thresholds for turbo_classes_reflow option
6118        force_dip: false,                               //force breakpoints to use device-independent pixels
6119        onReady: 		    function(){},
6120		onResize: 		    function(){},
6121		onRotate:		    function(){},
6122		onRotateToP:	    function(){},
6123		onRotateToL:	    function(){},
6124        onPortrait:         function(){},
6125        onLandscape:        function(){},
6126        onRetina:           function(){},
6127        onPhone:            function(){},
6128        onTablet:           function(){},
6129        onPC:               function(){},
6130        onTV:               function(){},
6131        onIOS:              function(){},
6132        onAndroid:          function(){},
6133        onSymbian:          function(){},
6134        onBlackberry:       function(){},
6135        onWindows:          function(){},
6136        onWindowsPhone:     function(){},
6137        onMobile:           function(){},
6138        onNonMobile:        function(){},
6139        onTurboClassReflow:         function(){},
6140        onTurboClassReflowIn:       function(){},
6141        onTurboClassReflowOut:      function(){},
6142        onAddClass:         function(){},
6143        onRemoveClass:      function(){}
6144	};
6145
6146    /**
6147     * Plugin Methods
6148     */
6149    var D = $.restive = function(){};
6150    $.extend(D, {
6151        getUserAgent: function(){
6152            return methods.getUserAgent();
6153        },
6154        getPlatform: function(){
6155            return methods.getPlatform();
6156        },
6157        getFormFactor: function(){
6158            return methods.getFormFactor();
6159        },
6160        getOrientation: function(){
6161            return methods.getOrientation();
6162        },
6163        getResolution: function(){
6164            return methods.getResolution();
6165        },
6166        getPixelRatio: function(pxl_ratio){
6167            return methods.getPixelRatio(pxl_ratio);
6168        },
6169        getViewportW: function(){
6170            return methods.getViewportW();
6171        },
6172        getViewportH: function(){
6173            return methods.getViewportH();
6174        },
6175        getScreenW: function(){
6176            return methods.getScreenW();
6177        },
6178        getScreenH: function(){
6179            return methods.getScreenH();
6180        },
6181        getPixelW: function(){
6182            return methods.getPixelW();
6183        },
6184        getPixelH: function(){
6185            return methods.getPixelH();
6186        },
6187        isRetina: function(){
6188            return methods.isRetina();
6189        },
6190        isMobile: function(){
6191            return methods.isMobile();
6192        },
6193        isNonMobile: function(){
6194            return methods.isNonMobile();
6195        },
6196        isPhone: function(){
6197            return methods.isPhone();
6198        },
6199        isTablet: function(){
6200            return methods.isTablet();
6201        },
6202        isTV: function(){
6203            return methods.isTV();
6204        },
6205        isPC: function(){
6206            return methods.isPC();
6207        },
6208        isIOS: function(){
6209            return methods.isIOS();
6210        },
6211        isApple: function(){
6212            return methods.isIOS();
6213        },
6214        isAndroid: function(){
6215            return methods.isAndroid();
6216        },
6217        isSymbian: function(){
6218            return methods.isSymbian();
6219        },
6220        isBlackberry: function(){
6221            return methods.isBlackberry();
6222        },
6223        isWindows: function(){
6224            return methods.isWindows();
6225        },
6226        isWindowsPhone: function(){
6227            return methods.isWindowsPhone();
6228        },
6229        isPortrait: function(){
6230            return methods.isPortrait();
6231        },
6232        isLandscape: function(){
6233            return methods.isLandscape();
6234        },
6235        startMulti: function(){
6236            methods._multiConstructorStart();
6237        },
6238        endMulti: function(){
6239            methods._multiConstructorEnd();
6240        }
6241    });
6242
6243}(window, document, jQuery));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.