function array_filter (arr, func) { // http://kevin.vanzonneveld.net // + original by: Brett Zamir (http://brett-zamir.me) // + input by: max4ever // + improved by: Brett Zamir (http://brett-zamir.me) // % note 1: Takes a function as an argument, not a function's name // * example 1: var odd = function (num) {return (num & 1);}; // * example 1: array_filter({"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}, odd); // * returns 1: {"a": 1, "c": 3, "e": 5} // * example 2: var even = function (num) {return (!(num & 1));} // * example 2: array_filter([6, 7, 8, 9, 10, 11, 12], even); // * returns 2: {0: 6, 2: 8, 4: 10, 6: 12} // * example 3: var arr = array_filter({"a": 1, "b": false, "c": -1, "d": 0, "e": null, "f":'', "g":undefined}); // * returns 3: {"a":1, "c":-1}; var retObj = {}, k; func = func || function (v) {return v;}; for (k in arr) { if (func(arr[k])) { retObj[k] = arr[k]; } } return retObj; } function array_intersect (arr1) { // http://kevin.vanzonneveld.net // + original by: Brett Zamir (http://brett-zamir.me) // % note 1: These only output associative arrays (would need to be // % note 1: all numeric and counting from zero to be numeric) // * example 1: $array1 = {'a' : 'green', 0:'red', 1: 'blue'}; // * example 1: $array2 = {'b' : 'green', 0:'yellow', 1:'red'}; // * example 1: $array3 = ['green', 'red']; // * example 1: $result = array_intersect($array1, $array2, $array3); // * returns 1: {0: 'red', a: 'green'} var retArr = {}, argl = arguments.length, arglm1 = argl - 1, k1 = '', arr = {}, i = 0, k = ''; arr1keys: for (k1 in arr1) { arrs: for (i = 1; i < argl; i++) { arr = arguments[i]; for (k in arr) { if (arr[k] === arr1[k1]) { if (i === arglm1) { retArr[k1] = arr1[k1]; } // If the innermost loop always leads at least once to an equal value, continue the loop until done continue arrs; } } // If it reaches here, it wasn't found in at least one array, so try next value continue arr1keys; } } return retArr; } function array_key_exists (key, search) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Felix Geisendoerfer (http://www.debuggable.com/felix) // * example 1: array_key_exists('kevin', {'kevin': 'van Zonneveld'}); // * returns 1: true // input sanitation if (!search || (search.constructor !== Array && search.constructor !== Object)) { return false; } return key in search; } function array_map (callback) { // http://kevin.vanzonneveld.net // + original by: Andrea Giammarchi (http://webreflection.blogspot.com) // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Brett Zamir (http://brett-zamir.me) // % note 1: Takes a function as an argument, not a function's name // % note 2: If the callback is a string, it can only work if the function name is in the global context // * example 1: array_map( function (a){return (a * a * a)}, [1, 2, 3, 4, 5] ); // * returns 1: [ 1, 8, 27, 64, 125 ] var argc = arguments.length, argv = arguments; var j = argv[1].length, i = 0, k = 1, m = 0; var tmp = [], tmp_ar = []; while (i < j) { while (k < argc) { tmp[m++] = argv[k++][i]; } m = 0; k = 1; if (callback) { if (typeof callback === 'string') { callback = this.window[callback]; } tmp_ar[i++] = callback.apply(null, tmp); } else { tmp_ar[i++] = tmp; } tmp = []; } return tmp_ar; } function array_merge () { // http://kevin.vanzonneveld.net // + original by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Nate // + input by: josh // + bugfixed by: Brett Zamir (http://brett-zamir.me) // * example 1: arr1 = {"color": "red", 0: 2, 1: 4} // * example 1: arr2 = {0: "a", 1: "b", "color": "green", "shape": "trapezoid", 2: 4} // * example 1: array_merge(arr1, arr2) // * returns 1: {"color": "green", 0: 2, 1: 4, 2: "a", 3: "b", "shape": "trapezoid", 4: 4} // * example 2: arr1 = [] // * example 2: arr2 = {1: "data"} // * example 2: array_merge(arr1, arr2) // * returns 2: {0: "data"} var args = Array.prototype.slice.call(arguments), argl = args.length, arg, retObj = {}, k = '', argil = 0, j = 0, i = 0, ct = 0, toStr = Object.prototype.toString, retArr = true; for (i = 0; i < argl; i++) { if (toStr.call(args[i]) !== '[object Array]') { retArr = false; break; } } if (retArr) { retArr = []; for (i = 0; i < argl; i++) { retArr = retArr.concat(args[i]); } return retArr; } for (i = 0, ct = 0; i < argl; i++) { arg = args[i]; if (toStr.call(arg) === '[object Array]') { for (j = 0, argil = arg.length; j < argil; j++) { retObj[ct++] = arg[j]; } } else { for (k in arg) { if (arg.hasOwnProperty(k)) { if (parseInt(k, 10) + '' === k) { retObj[ct++] = arg[k]; } else { retObj[k] = arg[k]; } } } } } return retObj; } function array_pop (inputArr) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + bugfixed by: Brett Zamir (http://brett-zamir.me) // + input by: Theriault // % note 1: While IE (and other browsers) support iterating an object's // % note 1: own properties in order, if one attempts to add back properties // % note 1: in IE, they may end up in their former position due to their position // % note 1: being retained. So use of this function with "associative arrays" // % note 1: (objects) may lead to unexpected behavior in an IE environment if // % note 1: you add back properties with the same keys that you removed // * example 1: array_pop([0,1,2]); // * returns 1: 2 // * example 2: data = {firstName: 'Kevin', surName: 'van Zonneveld'}; // * example 2: lastElem = array_pop(data); // * returns 2: 'van Zonneveld' // * results 2: data == {firstName: 'Kevin'} var key = '', lastKey = ''; if (inputArr.hasOwnProperty('length')) { // Indexed if (!inputArr.length) { // Done popping, are we? return null; } return inputArr.pop(); } else { // Associative for (key in inputArr) { if (inputArr.hasOwnProperty(key)) { lastKey = key; } } if (lastKey) { var tmp = inputArr[lastKey]; delete(inputArr[lastKey]); return tmp; } else { return null; } } } function array_shift (inputArr) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Martijn Wieringa // % note 1: Currently does not handle objects // * example 1: array_shift(['Kevin', 'van', 'Zonneveld']); // * returns 1: 'Kevin' var props = false, shift = undefined, pr = '', allDigits = /^\d$/, int_ct = -1, _checkToUpIndices = function (arr, ct, key) { // Deal with situation, e.g., if encounter index 4 and try to set it to 0, but 0 exists later in loop (need to // increment all subsequent (skipping current key, since we need its value below) until find unused) if (arr[ct] !== undefined) { var tmp = ct; ct += 1; if (ct === key) { ct += 1; } ct = _checkToUpIndices(arr, ct, key); arr[ct] = arr[tmp]; delete arr[tmp]; } return ct; }; if (inputArr.length === 0) { return null; } if (inputArr.length > 0) { return inputArr.shift(); } /* UNFINISHED FOR HANDLING OBJECTS for (pr in inputArr) { if (inputArr.hasOwnProperty(pr)) { props = true; shift = inputArr[pr]; delete inputArr[pr]; break; } } for (pr in inputArr) { if (inputArr.hasOwnProperty(pr)) { if (pr.search(allDigits) !== -1) { int_ct += 1; if (parseInt(pr, 10) === int_ct) { // Key is already numbered ok, so don't need to change key for value continue; } _checkToUpIndices(inputArr, int_ct, pr); arr[int_ct] = arr[pr]; delete arr[pr]; } } } if (!props) { return null; } return shift; */ } function current (arr) { // http://kevin.vanzonneveld.net // + original by: Brett Zamir (http://brett-zamir.me) // % note 1: Uses global: php_js to store the array pointer // * example 1: transport = ['foot', 'bike', 'car', 'plane']; // * example 1: current(transport); // * returns 1: 'foot' // BEGIN REDUNDANT this.php_js = this.php_js || {}; this.php_js.pointers = this.php_js.pointers || []; var indexOf = function (value) { for (var i = 0, length = this.length; i < length; i++) { if (this[i] === value) { return i; } } return -1; }; // END REDUNDANT var pointers = this.php_js.pointers; if (!pointers.indexOf) { pointers.indexOf = indexOf; } if (pointers.indexOf(arr) === -1) { pointers.push(arr, 0); } var arrpos = pointers.indexOf(arr); var cursor = pointers[arrpos + 1]; if (Object.prototype.toString.call(arr) === '[object Array]') { return arr[cursor] || false; } var ct = 0; for (var k in arr) { if (ct === cursor) { return arr[k]; } ct++; } return false; // Empty } function end (arr) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + bugfixed by: Legaev Andrey // + revised by: J A R // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + restored by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + revised by: Brett Zamir (http://brett-zamir.me) // % note 1: Uses global: php_js to store the array pointer // * example 1: end({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}); // * returns 1: 'Zonneveld' // * example 2: end(['Kevin', 'van', 'Zonneveld']); // * returns 2: 'Zonneveld' // BEGIN REDUNDANT this.php_js = this.php_js || {}; this.php_js.pointers = this.php_js.pointers || []; var indexOf = function (value) { for (var i = 0, length = this.length; i < length; i++) { if (this[i] === value) { return i; } } return -1; }; // END REDUNDANT var pointers = this.php_js.pointers; if (!pointers.indexOf) { pointers.indexOf = indexOf; } if (pointers.indexOf(arr) === -1) { pointers.push(arr, 0); } var arrpos = pointers.indexOf(arr); if (Object.prototype.toString.call(arr) !== '[object Array]') { var ct = 0; for (var k in arr) { ct++; var val = arr[k]; } if (ct === 0) { return false; // Empty } pointers[arrpos + 1] = ct - 1; return val; } if (arr.length === 0) { return false; } pointers[arrpos + 1] = arr.length - 1; return arr[pointers[arrpos + 1]]; } function in_array (needle, haystack, argStrict) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: vlado houba // + input by: Billy // + bugfixed by: Brett Zamir (http://brett-zamir.me) // * example 1: in_array('van', ['Kevin', 'van', 'Zonneveld']); // * returns 1: true // * example 2: in_array('vlado', {0: 'Kevin', vlado: 'van', 1: 'Zonneveld'}); // * returns 2: false // * example 3: in_array(1, ['1', '2', '3']); // * returns 3: true // * example 3: in_array(1, ['1', '2', '3'], false); // * returns 3: true // * example 4: in_array(1, ['1', '2', '3'], true); // * returns 4: false var key = '', strict = !! argStrict; if (strict) { for (key in haystack) { if (haystack[key] === needle) { return true; } } } else { for (key in haystack) { if (haystack[key] == needle) { return true; } } } return false; } function key (arr) { // http://kevin.vanzonneveld.net // + original by: Brett Zamir (http://brett-zamir.me) // + input by: Riddler (http://www.frontierwebdev.com/) // + bugfixed by: Brett Zamir (http://brett-zamir.me) // % note 1: Uses global: php_js to store the array pointer // * example 1: array = {fruit1: 'apple', 'fruit2': 'orange'} // * example 1: key(array); // * returns 1: 'fruit1' // BEGIN REDUNDANT this.php_js = this.php_js || {}; this.php_js.pointers = this.php_js.pointers || []; var indexOf = function (value) { for (var i = 0, length = this.length; i < length; i++) { if (this[i] === value) { return i; } } return -1; }; // END REDUNDANT var pointers = this.php_js.pointers; if (!pointers.indexOf) { pointers.indexOf = indexOf; } if (pointers.indexOf(arr) === -1) { pointers.push(arr, 0); } var cursor = pointers[pointers.indexOf(arr) + 1]; if (Object.prototype.toString.call(arr) !== '[object Array]') { var ct = 0; for (var k in arr) { if (ct === cursor) { return k; } ct++; } return false; // Empty } if (arr.length === 0) { return false; } return cursor; } function date (format, timestamp) { // http://kevin.vanzonneveld.net // + original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com) // + parts by: Peter-Paul Koch (http://www.quirksmode.org/js/beat.html) // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: MeEtc (http://yass.meetcweb.com) // + improved by: Brad Touesnard // + improved by: Tim Wiel // + improved by: Bryan Elliott // // + improved by: Brett Zamir (http://brett-zamir.me) // + improved by: David Randall // + input by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Brett Zamir (http://brett-zamir.me) // + improved by: Brett Zamir (http://brett-zamir.me) // + improved by: Theriault // + derived from: gettimeofday // + input by: majak // + bugfixed by: majak // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: Alex // + bugfixed by: Brett Zamir (http://brett-zamir.me) // + improved by: Theriault // + improved by: Brett Zamir (http://brett-zamir.me) // + improved by: Theriault // + improved by: Thomas Beaucourt (http://www.webapp.fr) // + improved by: JT // + improved by: Theriault // + improved by: Rafał Kukawski (http://blog.kukawski.pl) // + bugfixed by: omid (http://phpjs.org/functions/380:380#comment_137122) // + input by: Martin // + input by: Alex Wilson // % note 1: Uses global: php_js to store the default timezone // % note 2: Although the function potentially allows timezone info (see notes), it currently does not set // % note 2: per a timezone specified by date_default_timezone_set(). Implementers might use // % note 2: this.php_js.currentTimezoneOffset and this.php_js.currentTimezoneDST set by that function // % note 2: in order to adjust the dates in this function (or our other date functions!) accordingly // * example 1: date('H:m:s \\m \\i\\s \\m\\o\\n\\t\\h', 1062402400); // * returns 1: '09:09:40 m is month' // * example 2: date('F j, Y, g:i a', 1062462400); // * returns 2: 'September 2, 2003, 2:26 am' // * example 3: date('Y W o', 1062462400); // * returns 3: '2003 36 2003' // * example 4: x = date('Y m d', (new Date()).getTime()/1000); // * example 4: (x+'').length == 10 // 2009 01 09 // * returns 4: true // * example 5: date('W', 1104534000); // * returns 5: '53' // * example 6: date('B t', 1104534000); // * returns 6: '999 31' // * example 7: date('W U', 1293750000.82); // 2010-12-31 // * returns 7: '52 1293750000' // * example 8: date('W', 1293836400); // 2011-01-01 // * returns 8: '52' // * example 9: date('W Y-m-d', 1293974054); // 2011-01-02 // * returns 9: '52 2011-01-02' var that = this, jsdate, f, formatChr = /\\?([a-z])/gi, formatChrCb, // Keep this here (works, but for code commented-out // below for file size reasons) //, tal= [], _pad = function (n, c) { if ((n = n + '').length < c) { return new Array((++c) - n.length).join('0') + n; } return n; }, txt_words = ["Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; formatChrCb = function (t, s) { return f[t] ? f[t]() : s; }; f = { // Day d: function () { // Day of month w/leading 0; 01..31 return _pad(f.j(), 2); }, D: function () { // Shorthand day name; Mon...Sun return f.l().slice(0, 3); }, j: function () { // Day of month; 1..31 return jsdate.getDate(); }, l: function () { // Full day name; Monday...Sunday return txt_words[f.w()] + 'day'; }, N: function () { // ISO-8601 day of week; 1[Mon]..7[Sun] return f.w() || 7; }, S: function () { // Ordinal suffix for day of month; st, nd, rd, th var j = f.j(); return j > 4 && j < 21 ? 'th' : {1: 'st', 2: 'nd', 3: 'rd'}[j % 10] || 'th'; }, w: function () { // Day of week; 0[Sun]..6[Sat] return jsdate.getDay(); }, z: function () { // Day of year; 0..365 var a = new Date(f.Y(), f.n() - 1, f.j()), b = new Date(f.Y(), 0, 1); return Math.round((a - b) / 864e5) + 1; }, // Week W: function () { // ISO-8601 week number var a = new Date(f.Y(), f.n() - 1, f.j() - f.N() + 3), b = new Date(a.getFullYear(), 0, 4); return _pad(1 + Math.round((a - b) / 864e5 / 7), 2); }, // Month F: function () { // Full month name; January...December return txt_words[6 + f.n()]; }, m: function () { // Month w/leading 0; 01...12 return _pad(f.n(), 2); }, M: function () { // Shorthand month name; Jan...Dec return f.F().slice(0, 3); }, n: function () { // Month; 1...12 return jsdate.getMonth() + 1; }, t: function () { // Days in month; 28...31 return (new Date(f.Y(), f.n(), 0)).getDate(); }, // Year L: function () { // Is leap year?; 0 or 1 return new Date(f.Y(), 1, 29).getMonth() === 1 | 0; }, o: function () { // ISO-8601 year var n = f.n(), W = f.W(), Y = f.Y(); return Y + (n === 12 && W < 9 ? -1 : n === 1 && W > 9); }, Y: function () { // Full year; e.g. 1980...2010 return jsdate.getFullYear(); }, y: function () { // Last two digits of year; 00...99 return (f.Y() + "").slice(-2); }, // Time a: function () { // am or pm return jsdate.getHours() > 11 ? "pm" : "am"; }, A: function () { // AM or PM return f.a().toUpperCase(); }, B: function () { // Swatch Internet time; 000..999 var H = jsdate.getUTCHours() * 36e2, // Hours i = jsdate.getUTCMinutes() * 60, // Minutes s = jsdate.getUTCSeconds(); // Seconds return _pad(Math.floor((H + i + s + 36e2) / 86.4) % 1e3, 3); }, g: function () { // 12-Hours; 1..12 return f.G() % 12 || 12; }, G: function () { // 24-Hours; 0..23 return jsdate.getHours(); }, h: function () { // 12-Hours w/leading 0; 01..12 return _pad(f.g(), 2); }, H: function () { // 24-Hours w/leading 0; 00..23 return _pad(f.G(), 2); }, i: function () { // Minutes w/leading 0; 00..59 return _pad(jsdate.getMinutes(), 2); }, s: function () { // Seconds w/leading 0; 00..59 return _pad(jsdate.getSeconds(), 2); }, u: function () { // Microseconds; 000000-999000 return _pad(jsdate.getMilliseconds() * 1000, 6); }, // Timezone e: function () { // Timezone identifier; e.g. Atlantic/Azores, ... // The following works, but requires inclusion of the very large // timezone_abbreviations_list() function. /* return this.date_default_timezone_get(); */ throw 'Not supported (see source code of date() for timezone on how to add support)'; }, I: function () { // DST observed?; 0 or 1 // Compares Jan 1 minus Jan 1 UTC to Jul 1 minus Jul 1 UTC. // If they are not equal, then DST is observed. var a = new Date(f.Y(), 0), // Jan 1 c = Date.UTC(f.Y(), 0), // Jan 1 UTC b = new Date(f.Y(), 6), // Jul 1 d = Date.UTC(f.Y(), 6); // Jul 1 UTC return 0 + ((a - c) !== (b - d)); }, O: function () { // Difference to GMT in hour format; e.g. +0200 var tzo = jsdate.getTimezoneOffset(), a = Math.abs(tzo); return (tzo > 0 ? "-" : "+") + _pad(Math.floor(a / 60) * 100 + a % 60, 4); }, P: function () { // Difference to GMT w/colon; e.g. +02:00 var O = f.O(); return (O.substr(0, 3) + ":" + O.substr(3, 2)); }, T: function () { // Timezone abbreviation; e.g. EST, MDT, ... // The following works, but requires inclusion of the very // large timezone_abbreviations_list() function. /* var abbr = '', i = 0, os = 0, default = 0; if (!tal.length) { tal = that.timezone_abbreviations_list(); } if (that.php_js && that.php_js.default_timezone) { default = that.php_js.default_timezone; for (abbr in tal) { for (i=0; i < tal[abbr].length; i++) { if (tal[abbr][i].timezone_id === default) { return abbr.toUpperCase(); } } } } for (abbr in tal) { for (i = 0; i < tal[abbr].length; i++) { os = -jsdate.getTimezoneOffset() * 60; if (tal[abbr][i].offset === os) { return abbr.toUpperCase(); } } } */ return 'UTC'; }, Z: function () { // Timezone offset in seconds (-43200...50400) return -jsdate.getTimezoneOffset() * 60; }, // Full Date/Time c: function () { // ISO-8601 date. return 'Y-m-d\\Th:i:sP'.replace(formatChr, formatChrCb); }, r: function () { // RFC 2822 return 'D, d M Y H:i:s O'.replace(formatChr, formatChrCb); }, U: function () { // Seconds since UNIX epoch return jsdate.getTime() / 1000 | 0; } }; this.date = function (format, timestamp) { that = this; jsdate = ((typeof timestamp === 'undefined') ? new Date() : // Not provided (timestamp instanceof Date) ? new Date(timestamp) : // JS Date() new Date(timestamp * 1000) // UNIX timestamp (auto-convert to int) ); return format.replace(formatChr, formatChrCb); }; return this.date(format, timestamp); } function basename (path, suffix) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Ash Searle (http://hexmen.com/blog/) // + improved by: Lincoln Ramsay // + improved by: djmix // * example 1: basename('/www/site/home.htm', '.htm'); // * returns 1: 'home' // * example 2: basename('ecra.php?p=1'); // * returns 2: 'ecra.php?p=1' var b = path.replace(/^.*[\/\\]/g, ''); if (typeof(suffix) == 'string' && b.substr(b.length - suffix.length) == suffix) { b = b.substr(0, b.length - suffix.length); } return b; } function dirname (path) { // http://kevin.vanzonneveld.net // + original by: Ozh // + improved by: XoraX (http://www.xorax.info) // * example 1: dirname('/etc/passwd'); // * returns 1: '/etc' // * example 2: dirname('c:/Temp/x'); // * returns 2: 'c:/Temp' // * example 3: dirname('/dir/test/'); // * returns 3: '/dir' return path.replace(/\\/g, '/').replace(/\/[^\/]*\/?$/, ''); } function json_decode (str_json) { // http://kevin.vanzonneveld.net // + original by: Public Domain (http://www.json.org/json2.js) // + reimplemented by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: T.J. Leahy // + improved by: Michael White // * example 1: json_decode('[\n "e",\n {\n "pluribus": "unum"\n}\n]'); // * returns 1: ['e', {pluribus: 'unum'}] /* http://www.JSON.org/json2.js 2008-11-19 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. See http://www.JSON.org/js.html */ var json = this.window.JSON; if (typeof json === 'object' && typeof json.parse === 'function') { try { return json.parse(str_json); } catch (err) { if (!(err instanceof SyntaxError)) { throw new Error('Unexpected error type in json_decode()'); } this.php_js = this.php_js || {}; this.php_js.last_error_json = 4; // usable by json_last_error() return null; } } var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; var j; var text = str_json; // Parsing happens in four stages. In the first stage, we replace certain // Unicode characters with escape sequences. JavaScript handles many characters // incorrectly, either silently deleting them, or treating them as line endings. cx.lastIndex = 0; if (cx.test(text)) { text = text.replace(cx, function (a) { return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }); } // In the second stage, we run the text against regular expressions that look // for non-JSON patterns. We are especially concerned with '()' and 'new' // because they can cause invocation, and '=' because it can cause mutation. // But just to be safe, we want to reject all unexpected forms. // We split the second stage into 4 regexp operations in order to work around // crippling inefficiencies in IE's and Safari's regexp engines. First we // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we // replace all simple value tokens with ']' characters. Third, we delete all // open brackets that follow a colon or comma or that begin the text. Finally, // we look to see that the remaining characters are only whitespace or ']' or // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. if ((/^[\],:{}\s]*$/). test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { // In the third stage we use the eval function to compile the text into a // JavaScript structure. The '{' operator is subject to a syntactic ambiguity // in JavaScript: it can begin a block or an object literal. We wrap the text // in parens to eliminate the ambiguity. j = eval('(' + text + ')'); return j; } this.php_js = this.php_js || {}; this.php_js.last_error_json = 4; // usable by json_last_error() return null; } function json_encode (mixed_val) { // http://kevin.vanzonneveld.net // + original by: Public Domain (http://www.json.org/json2.js) // + reimplemented by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Michael White // + input by: felix // + bugfixed by: Brett Zamir (http://brett-zamir.me) // * example 1: json_encode(['e', {pluribus: 'unum'}]); // * returns 1: '[\n "e",\n {\n "pluribus": "unum"\n}\n]' /* http://www.JSON.org/json2.js 2008-11-19 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. See http://www.JSON.org/js.html */ var retVal, json = this.window.JSON; try { if (typeof json === 'object' && typeof json.stringify === 'function') { retVal = json.stringify(mixed_val); // Errors will not be caught here if our own equivalent to resource // (an instance of PHPJS_Resource) is used if (retVal === undefined) { throw new SyntaxError('json_encode'); } return retVal; } var value = mixed_val; var quote = function (string) { var escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g; var meta = { // table of character substitutions '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"': '\\"', '\\': '\\\\' }; escapable.lastIndex = 0; return escapable.test(string) ? '"' + string.replace(escapable, function (a) { var c = meta[a]; return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; }; var str = function (key, holder) { var gap = ''; var indent = ' '; var i = 0; // The loop counter. var k = ''; // The member key. var v = ''; // The member value. var length = 0; var mind = gap; var partial = []; var value = holder[key]; // If the value has a toJSON method, call it to obtain a replacement value. if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } // What happens next depends on the value's type. switch (typeof value) { case 'string': return quote(value); case 'number': // JSON numbers must be finite. Encode non-finite numbers as null. return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': // If the value is a boolean or null, convert it to a string. Note: // typeof null does not produce 'null'. The case is included here in // the remote chance that this gets fixed someday. return String(value); case 'object': // If the type is 'object', we might be dealing with an object or an array or // null. // Due to a specification blunder in ECMAScript, typeof null is 'object', // so watch out for that case. if (!value) { return 'null'; } if ((this.PHPJS_Resource && value instanceof this.PHPJS_Resource) || (window.PHPJS_Resource && value instanceof window.PHPJS_Resource)) { throw new SyntaxError('json_encode'); } // Make an array to hold the partial results of stringifying this object value. gap += indent; partial = []; // Is the value an array? if (Object.prototype.toString.apply(value) === '[object Array]') { // The value is an array. Stringify every element. Use null as a placeholder // for non-JSON values. length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } // Join all of the elements together, separated with commas, and wrap them in // brackets. v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } // Iterate through all of the keys in the object. for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } // Join all of the member texts together, separated with commas, // and wrap them in braces. v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; case 'undefined': // Fall-through case 'function': // Fall-through default: throw new SyntaxError('json_encode'); } }; // Make a fake root object containing our value under the key of ''. // Return the result of stringifying the value. return str('', { '': value }); } catch (err) { // Todo: ensure error handling above throws a SyntaxError in all cases where it could // (i.e., when the JSON global is not available and there is an error) if (!(err instanceof SyntaxError)) { throw new Error('Unexpected error type in json_encode()'); } this.php_js = this.php_js || {}; this.php_js.last_error_json = 4; // usable by json_last_error() return null; } } function uniqid (prefix, more_entropy) { // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + revised by: Kankrelune (http://www.webfaktory.info/) // % note 1: Uses an internal counter (in php_js global) to avoid collision // * example 1: uniqid(); // * returns 1: 'a30285b160c14' // * example 2: uniqid('foo'); // * returns 2: 'fooa30285b1cd361' // * example 3: uniqid('bar', true); // * returns 3: 'bara20285b23dfd1.31879087' if (typeof prefix == 'undefined') { prefix = ""; } var retId; var formatSeed = function (seed, reqWidth) { seed = parseInt(seed, 10).toString(16); // to hex str if (reqWidth < seed.length) { // so long we split return seed.slice(seed.length - reqWidth); } if (reqWidth > seed.length) { // so short we pad return Array(1 + (reqWidth - seed.length)).join('0') + seed; } return seed; }; // BEGIN REDUNDANT if (!this.php_js) { this.php_js = {}; } // END REDUNDANT if (!this.php_js.uniqidSeed) { // init seed with big random int this.php_js.uniqidSeed = Math.floor(Math.random() * 0x75bcd15); } this.php_js.uniqidSeed++; retId = prefix; // start with prefix, add current milliseconds hex string retId += formatSeed(parseInt(new Date().getTime() / 1000, 10), 8); retId += formatSeed(this.php_js.uniqidSeed, 5); // add seed hex string if (more_entropy) { // for more entropy we add a float lower to 10 retId += (Math.random() * 10).toFixed(8).toString(); } return retId; } function echo () { // http://kevin.vanzonneveld.net // + original by: Philip Peterson // + improved by: echo is bad // + improved by: Nate // + revised by: Der Simon (http://innerdom.sourceforge.net/) // + improved by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Eugene Bulkin (http://doubleaw.com/) // + input by: JB // + improved by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: EdorFaus // + improved by: Brett Zamir (http://brett-zamir.me) // % note 1: If browsers start to support DOM Level 3 Load and Save (parsing/serializing), // % note 1: we wouldn't need any such long code (even most of the code below). See // % note 1: link below for a cross-browser implementation in JavaScript. HTML5 might // % note 1: possibly support DOMParser, but that is not presently a standard. // % note 2: Although innerHTML is widely used and may become standard as of HTML5, it is also not ideal for // % note 2: use with a temporary holder before appending to the DOM (as is our last resort below), // % note 2: since it may not work in an XML context // % note 3: Using innerHTML to directly add to the BODY is very dangerous because it will // % note 3: break all pre-existing references to HTMLElements. // * example 1: echo('

abc

abc

'); // * returns 1: undefined // Fix: This function really needs to allow non-XHTML input (unless in true XHTML mode) as in jQuery var arg = '', argc = arguments.length, argv = arguments, i = 0, holder, win = this.window, d = win.document, ns_xhtml = 'http://www.w3.org/1999/xhtml', ns_xul = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'; // If we're in a XUL context var stringToDOM = function (str, parent, ns, container) { var extraNSs = ''; if (ns === ns_xul) { extraNSs = ' xmlns:html="' + ns_xhtml + '"'; } var stringContainer = '<' + container + ' xmlns="' + ns + '"' + extraNSs + '>' + str + ''; var dils = win.DOMImplementationLS, dp = win.DOMParser, ax = win.ActiveXObject; if (dils && dils.createLSInput && dils.createLSParser) { // Follows the DOM 3 Load and Save standard, but not // implemented in browsers at present; HTML5 is to standardize on innerHTML, but not for XML (though // possibly will also standardize with DOMParser); in the meantime, to ensure fullest browser support, could // attach http://svn2.assembla.com/svn/brettz9/DOMToString/DOM3.js (see http://svn2.assembla.com/svn/brettz9/DOMToString/DOM3.xhtml for a simple test file) var lsInput = dils.createLSInput(); // If we're in XHTML, we'll try to allow the XHTML namespace to be available by default lsInput.stringData = stringContainer; var lsParser = dils.createLSParser(1, null); // synchronous, no schema type return lsParser.parse(lsInput).firstChild; } else if (dp) { // If we're in XHTML, we'll try to allow the XHTML namespace to be available by default try { var fc = new dp().parseFromString(stringContainer, 'text/xml'); if (fc && fc.documentElement && fc.documentElement.localName !== 'parsererror' && fc.documentElement.namespaceURI !== 'http://www.mozilla.org/newlayout/xml/parsererror.xml') { return fc.documentElement.firstChild; } // If there's a parsing error, we just continue on } catch (e) { // If there's a parsing error, we just continue on } } else if (ax) { // We don't bother with a holder in Explorer as it doesn't support namespaces var axo = new ax('MSXML2.DOMDocument'); axo.loadXML(str); return axo.documentElement; } /*else if (win.XMLHttpRequest) { // Supposed to work in older Safari var req = new win.XMLHttpRequest; req.open('GET', 'data:application/xml;charset=utf-8,'+encodeURIComponent(str), false); if (req.overrideMimeType) { req.overrideMimeType('application/xml'); } req.send(null); return req.responseXML; }*/ // Document fragment did not work with innerHTML, so we create a temporary element holder // If we're in XHTML, we'll try to allow the XHTML namespace to be available by default //if (d.createElementNS && (d.contentType && d.contentType !== 'text/html')) { // Don't create namespaced elements if we're being served as HTML (currently only Mozilla supports this detection in true XHTML-supporting browsers, but Safari and Opera should work with the above DOMParser anyways, and IE doesn't support createElementNS anyways) if (d.createElementNS && // Browser supports the method (d.documentElement.namespaceURI || // We can use if the document is using a namespace d.documentElement.nodeName.toLowerCase() !== 'html' || // We know it's not HTML4 or less, if the tag is not HTML (even if the root namespace is null) (d.contentType && d.contentType !== 'text/html') // We know it's not regular HTML4 or less if this is Mozilla (only browser supporting the attribute) and the content type is something other than text/html; other HTML5 roots (like svg) still have a namespace )) { // Don't create namespaced elements if we're being served as HTML (currently only Mozilla supports this detection in true XHTML-supporting browsers, but Safari and Opera should work with the above DOMParser anyways, and IE doesn't support createElementNS anyways); last test is for the sake of being in a pure XML document holder = d.createElementNS(ns, container); } else { holder = d.createElement(container); // Document fragment did not work with innerHTML } holder.innerHTML = str; while (holder.firstChild) { parent.appendChild(holder.firstChild); } return false; // throw 'Your browser does not support DOM parsing as required by echo()'; }; var ieFix = function (node) { if (node.nodeType === 1) { var newNode = d.createElement(node.nodeName); var i, len; if (node.attributes && node.attributes.length > 0) { for (i = 0, len = node.attributes.length; i < len; i++) { newNode.setAttribute(node.attributes[i].nodeName, node.getAttribute(node.attributes[i].nodeName)); } } if (node.childNodes && node.childNodes.length > 0) { for (i = 0, len = node.childNodes.length; i < len; i++) { newNode.appendChild(ieFix(node.childNodes[i])); } } return newNode; } else { return d.createTextNode(node.nodeValue); } }; var replacer = function (s, m1, m2) { // We assume for now that embedded variables do not have dollar sign; to add a dollar sign, you currently must use {$$var} (We might change this, however.) // Doesn't cover all cases yet: see http://php.net/manual/en/language.types.string.php#language.types.string.syntax.double if (m1 !== '\\') { return m1 + eval(m2); } else { return s; } }; this.php_js = this.php_js || {}; var phpjs = this.php_js, ini = phpjs.ini, obs = phpjs.obs; for (i = 0; i < argc; i++) { arg = argv[i]; if (ini && ini['phpjs.echo_embedded_vars']) { arg = arg.replace(/(.?)\{?\$(\w*?\}|\w*)/g, replacer); } if (!phpjs.flushing && obs && obs.length) { // If flushing we output, but otherwise presence of a buffer means caching output obs[obs.length - 1].buffer += arg; continue; } if (d.appendChild) { if (d.body) { if (win.navigator.appName === 'Microsoft Internet Explorer') { // We unfortunately cannot use feature detection, since this is an IE bug with cloneNode nodes being appended d.body.appendChild(stringToDOM(ieFix(arg))); } else { var unappendedLeft = stringToDOM(arg, d.body, ns_xhtml, 'div').cloneNode(true); // We will not actually append the div tag (just using for providing XHTML namespace by default) if (unappendedLeft) { d.body.appendChild(unappendedLeft); } } } else { d.documentElement.appendChild(stringToDOM(arg, d.documentElement, ns_xul, 'description')); // We will not actually append the description tag (just using for providing XUL namespace by default) } } else if (d.write) { d.write(arg); } /* else { // This could recurse if we ever add print! print(arg); }*/ } } function number_format (number, decimals, dec_point, thousands_sep) { // http://kevin.vanzonneveld.net // + original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + bugfix by: Michael White (http://getsprink.com) // + bugfix by: Benjamin Lupton // + bugfix by: Allan Jensen (http://www.winternet.no) // + revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) // + bugfix by: Howard Yeend // + revised by: Luke Smith (http://lucassmith.name) // + bugfix by: Diogo Resende // + bugfix by: Rival // + input by: Kheang Hok Chin (http://www.distantia.ca/) // + improved by: davook // + improved by: Brett Zamir (http://brett-zamir.me) // + input by: Jay Klehr // + improved by: Brett Zamir (http://brett-zamir.me) // + input by: Amir Habibi (http://www.residence-mixte.com/) // + bugfix by: Brett Zamir (http://brett-zamir.me) // + improved by: Theriault // + input by: Amirouche // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // * example 1: number_format(1234.56); // * returns 1: '1,235' // * example 2: number_format(1234.56, 2, ',', ' '); // * returns 2: '1 234,56' // * example 3: number_format(1234.5678, 2, '.', ''); // * returns 3: '1234.57' // * example 4: number_format(67, 2, ',', '.'); // * returns 4: '67,00' // * example 5: number_format(1000); // * returns 5: '1,000' // * example 6: number_format(67.311, 2); // * returns 6: '67.31' // * example 7: number_format(1000.55, 1); // * returns 7: '1,000.6' // * example 8: number_format(67000, 5, ',', '.'); // * returns 8: '67.000,00000' // * example 9: number_format(0.9, 0); // * returns 9: '1' // * example 10: number_format('1.20', 2); // * returns 10: '1.20' // * example 11: number_format('1.20', 4); // * returns 11: '1.2000' // * example 12: number_format('1.2000', 3); // * returns 12: '1.200' // * example 13: number_format('1 000,50', 2, '.', ' '); // * returns 13: '100 050.00' // Strip all characters but numerical ones. number = (number + '').replace(/[^0-9+\-Ee.]/g, ''); var n = !isFinite(+number) ? 0 : +number, prec = !isFinite(+decimals) ? 0 : Math.abs(decimals), sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, dec = (typeof dec_point === 'undefined') ? '.' : dec_point, s = '', toFixedFix = function (n, prec) { var k = Math.pow(10, prec); return '' + Math.round(n * k) / k; }; // Fix for IE parseFloat(0.55).toFixed(0) = 0; s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.'); if (s[0].length > 3) { s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep); } if ((s[1] || '').length < prec) { s[1] = s[1] || ''; s[1] += new Array(prec - s[1].length + 1).join('0'); } return s.join(dec); } function sprintf () { // http://kevin.vanzonneveld.net // + original by: Ash Searle (http://hexmen.com/blog/) // + namespaced by: Michael White (http://getsprink.com) // + tweaked by: Jack // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: Paulo Freitas // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: Brett Zamir (http://brett-zamir.me) // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // * example 1: sprintf("%01.2f", 123.1); // * returns 1: 123.10 // * example 2: sprintf("[%10s]", 'monkey'); // * returns 2: '[ monkey]' // * example 3: sprintf("[%'#10s]", 'monkey'); // * returns 3: '[####monkey]' var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g; var a = arguments, i = 0, format = a[i++]; // pad() var pad = function (str, len, chr, leftJustify) { if (!chr) { chr = ' '; } var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr); return leftJustify ? str + padding : padding + str; }; // justify() var justify = function (value, prefix, leftJustify, minWidth, zeroPad, customPadChar) { var diff = minWidth - value.length; if (diff > 0) { if (leftJustify || !zeroPad) { value = pad(value, minWidth, customPadChar, leftJustify); } else { value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length); } } return value; }; // formatBaseX() var formatBaseX = function (value, base, prefix, leftJustify, minWidth, precision, zeroPad) { // Note: casts negative numbers to positive ones var number = value >>> 0; prefix = prefix && number && { '2': '0b', '8': '0', '16': '0x' }[base] || ''; value = prefix + pad(number.toString(base), precision || 0, '0', false); return justify(value, prefix, leftJustify, minWidth, zeroPad); }; // formatString() var formatString = function (value, leftJustify, minWidth, precision, zeroPad, customPadChar) { if (precision != null) { value = value.slice(0, precision); } return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar); }; // doFormat() var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) { var number; var prefix; var method; var textTransform; var value; if (substring == '%%') { return '%'; } // parse flags var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false, customPadChar = ' '; var flagsl = flags.length; for (var j = 0; flags && j < flagsl; j++) { switch (flags.charAt(j)) { case ' ': positivePrefix = ' '; break; case '+': positivePrefix = '+'; break; case '-': leftJustify = true; break; case "'": customPadChar = flags.charAt(j + 1); break; case '0': zeroPad = true; break; case '#': prefixBaseX = true; break; } } // parameters may be null, undefined, empty-string or real valued // we want to ignore null, undefined and empty-string values if (!minWidth) { minWidth = 0; } else if (minWidth == '*') { minWidth = +a[i++]; } else if (minWidth.charAt(0) == '*') { minWidth = +a[minWidth.slice(1, -1)]; } else { minWidth = +minWidth; } // Note: undocumented perl feature: if (minWidth < 0) { minWidth = -minWidth; leftJustify = true; } if (!isFinite(minWidth)) { throw new Error('sprintf: (minimum-)width must be finite'); } if (!precision) { precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : undefined; } else if (precision == '*') { precision = +a[i++]; } else if (precision.charAt(0) == '*') { precision = +a[precision.slice(1, -1)]; } else { precision = +precision; } // grab value using valueIndex if required? value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++]; switch (type) { case 's': return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar); case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad); case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad); case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad); case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad); case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase(); case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad); case 'i': case 'd': number = (+value) | 0; prefix = number < 0 ? '-' : positivePrefix; value = prefix + pad(String(Math.abs(number)), precision, '0', false); return justify(value, prefix, leftJustify, minWidth, zeroPad); case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': number = +value; prefix = number < 0 ? '-' : positivePrefix; method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())]; textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2]; value = prefix + Math.abs(number)[method](precision); return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform](); default: return substring; } }; return format.replace(regex, doFormat); } function substr (str, start, len) { // Returns part of a string // // version: 909.322 // discuss at: http://phpjs.org/functions/substr // + original by: Martijn Wieringa // + bugfixed by: T.Wild // + tweaked by: Onno Marsman // + revised by: Theriault // + improved by: Brett Zamir (http://brett-zamir.me) // % note 1: Handles rare Unicode characters if 'unicode.semantics' ini (PHP6) is set to 'on' // * example 1: substr('abcdef', 0, -1); // * returns 1: 'abcde' // * example 2: substr(2, 0, -6); // * returns 2: false // * example 3: ini_set('unicode.semantics', 'on'); // * example 3: substr('a\uD801\uDC00', 0, -1); // * returns 3: 'a' // * example 4: ini_set('unicode.semantics', 'on'); // * example 4: substr('a\uD801\uDC00', 0, 2); // * returns 4: 'a\uD801\uDC00' // * example 5: ini_set('unicode.semantics', 'on'); // * example 5: substr('a\uD801\uDC00', -1, 1); // * returns 5: '\uD801\uDC00' // * example 6: ini_set('unicode.semantics', 'on'); // * example 6: substr('a\uD801\uDC00z\uD801\uDC00', -3, 2); // * returns 6: '\uD801\uDC00z' // * example 7: ini_set('unicode.semantics', 'on'); // * example 7: substr('a\uD801\uDC00z\uD801\uDC00', -3, -1) // * returns 7: '\uD801\uDC00z' // Add: (?) Use unicode.runtime_encoding (e.g., with string wrapped in "binary" or "Binary" class) to // allow access of binary (see file_get_contents()) by: charCodeAt(x) & 0xFF (see https://developer.mozilla.org/En/Using_XMLHttpRequest ) or require conversion first? var i = 0, allBMP = true, es = 0, el = 0, se = 0, ret = ''; str += ''; var end = str.length; // BEGIN REDUNDANT this.php_js = this.php_js || {}; this.php_js.ini = this.php_js.ini || {}; // END REDUNDANT switch ((this.php_js.ini['unicode.semantics'] && this.php_js.ini['unicode.semantics'].local_value.toLowerCase())) { case 'on': // Full-blown Unicode including non-Basic-Multilingual-Plane characters // strlen() for (i = 0; i < str.length; i++) { if (/[\uD800-\uDBFF]/.test(str.charAt(i)) && /[\uDC00-\uDFFF]/.test(str.charAt(i + 1))) { allBMP = false; break; } } if (!allBMP) { if (start < 0) { for (i = end - 1, es = (start += end); i >= es; i--) { if (/[\uDC00-\uDFFF]/.test(str.charAt(i)) && /[\uD800-\uDBFF]/.test(str.charAt(i - 1))) { start--; es--; } } } else { var surrogatePairs = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; while ((surrogatePairs.exec(str)) != null) { var li = surrogatePairs.lastIndex; if (li - 2 < start) { start++; } else { break; } } } if (start >= end || start < 0) { return false; } if (len < 0) { for (i = end - 1, el = (end += len); i >= el; i--) { if (/[\uDC00-\uDFFF]/.test(str.charAt(i)) && /[\uD800-\uDBFF]/.test(str.charAt(i - 1))) { end--; el--; } } if (start > end) { return false; } return str.slice(start, end); } else { se = start + len; for (i = start; i < se; i++) { ret += str.charAt(i); if (/[\uD800-\uDBFF]/.test(str.charAt(i)) && /[\uDC00-\uDFFF]/.test(str.charAt(i + 1))) { se++; // Go one further, since one of the "characters" is part of a surrogate pair } } return ret; } break; } // Fall-through case 'off': // assumes there are no non-BMP characters; // if there may be such characters, then it is best to turn it on (critical in true XHTML/XML) default: if (start < 0) { start += end; } end = typeof len === 'undefined' ? end : (len < 0 ? len + end : len + start); // PHP returns false if start does not fall within the string. // PHP returns false if the calculated end comes before the calculated start. // PHP returns an empty string if start and end are the same. // Otherwise, PHP returns the portion of the string from start to end. return start >= str.length || start < 0 || start > end ? !1 : str.slice(start, end); } return undefined; // Please Netbeans } function trim (str, charlist) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: mdsjack (http://www.mdsjack.bo.it) // + improved by: Alexander Ermolaev (http://snippets.dzone.com/user/AlexanderErmolaev) // + input by: Erkekjetter // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: DxGx // + improved by: Steven Levithan (http://blog.stevenlevithan.com) // + tweaked by: Jack // + bugfixed by: Onno Marsman // * example 1: trim(' Kevin van Zonneveld '); // * returns 1: 'Kevin van Zonneveld' // * example 2: trim('Hello World', 'Hdle'); // * returns 2: 'o Wor' // * example 3: trim(16, 1); // * returns 3: 6 var whitespace, l = 0, i = 0; str += ''; if (!charlist) { // default list whitespace = " \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000"; } else { // preg_quote custom list charlist += ''; whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '$1'); } l = str.length; for (i = 0; i < l; i++) { if (whitespace.indexOf(str.charAt(i)) === -1) { str = str.substring(i); break; } } l = str.length; for (i = l - 1; i >= 0; i--) { if (whitespace.indexOf(str.charAt(i)) === -1) { str = str.substring(0, i + 1); break; } } return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''; } function ucfirst (str) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + bugfixed by: Onno Marsman // + improved by: Brett Zamir (http://brett-zamir.me) // * example 1: ucfirst('kevin van zonneveld'); // * returns 1: 'Kevin van zonneveld' str += ''; var f = str.charAt(0).toUpperCase(); return f + str.substr(1); } function rawurldecode (str) { // http://kevin.vanzonneveld.net // + original by: Brett Zamir (http://brett-zamir.me) // + input by: travc // + input by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: Ratheous // + reimplemented by: Brett Zamir (http://brett-zamir.me) // % note 1: Please be aware that this function expects to decode from UTF-8 encoded strings, as found on // % note 1: pages served as UTF-8 // * example 1: rawurldecode('Kevin+van+Zonneveld%21'); // * returns 1: 'Kevin+van+Zonneveld!' // * example 2: rawurldecode('http%3A%2F%2Fkevin.vanzonneveld.net%2F'); // * returns 2: 'http://kevin.vanzonneveld.net/' // * example 3: rawurldecode('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'); // * returns 3: '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' // * example 4: rawurldecode('-22%97bc%2Fbc'); // * returns 4: '-22—bc/bc' return decodeURIComponent(str + ''); } function rawurlencode (str) { // http://kevin.vanzonneveld.net // + original by: Brett Zamir (http://brett-zamir.me) // + input by: travc // + input by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: Michael Grier // + bugfixed by: Brett Zamir (http://brett-zamir.me) // + input by: Ratheous // + reimplemented by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Joris // + reimplemented by: Brett Zamir (http://brett-zamir.me) // % note 1: This reflects PHP 5.3/6.0+ behavior // % note 2: Please be aware that this function expects to encode into UTF-8 encoded strings, as found on // % note 2: pages served as UTF-8 // * example 1: rawurlencode('Kevin van Zonneveld!'); // * returns 1: 'Kevin%20van%20Zonneveld%21' // * example 2: rawurlencode('http://kevin.vanzonneveld.net/'); // * returns 2: 'http%3A%2F%2Fkevin.vanzonneveld.net%2F' // * example 3: rawurlencode('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'); // * 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' str = (str + '').toString(); // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following. return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28'). replace(/\)/g, '%29').replace(/\*/g, '%2A'); } function urldecode (str) { // http://kevin.vanzonneveld.net // + original by: Philip Peterson // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: AJ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Brett Zamir (http://brett-zamir.me) // + input by: travc // + input by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Lars Fischer // + input by: Ratheous // + improved by: Orlando // + reimplemented by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Rob // + input by: e-mike // + improved by: Brett Zamir (http://brett-zamir.me) // % note 1: info on what encoding functions to use from: http://xkr.us/articles/javascript/encode-compare/ // % note 2: Please be aware that this function expects to decode from UTF-8 encoded strings, as found on // % note 2: pages served as UTF-8 // * example 1: urldecode('Kevin+van+Zonneveld%21'); // * returns 1: 'Kevin van Zonneveld!' // * example 2: urldecode('http%3A%2F%2Fkevin.vanzonneveld.net%2F'); // * returns 2: 'http://kevin.vanzonneveld.net/' // * example 3: urldecode('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'); // * returns 3: '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' return decodeURIComponent((str + '').replace(/\+/g, '%20')); } function urlencode (str) { // http://kevin.vanzonneveld.net // + original by: Philip Peterson // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: AJ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: travc // + input by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Lars Fischer // + input by: Ratheous // + reimplemented by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Joris // + reimplemented by: Brett Zamir (http://brett-zamir.me) // % note 1: This reflects PHP 5.3/6.0+ behavior // % note 2: Please be aware that this function expects to encode into UTF-8 encoded strings, as found on // % note 2: pages served as UTF-8 // * example 1: urlencode('Kevin van Zonneveld!'); // * returns 1: 'Kevin+van+Zonneveld%21' // * example 2: urlencode('http://kevin.vanzonneveld.net/'); // * returns 2: 'http%3A%2F%2Fkevin.vanzonneveld.net%2F' // * 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'); // * 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' str = (str + '').toString(); // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following. return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28'). replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+'); } function empty (mixed_var) { // http://kevin.vanzonneveld.net // + original by: Philippe Baumann // + input by: Onno Marsman // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: LH // + improved by: Onno Marsman // + improved by: Francesco // + improved by: Marc Jansen // + input by: Stoyan Kyosev (http://www.svest.org/) // * example 1: empty(null); // * returns 1: true // * example 2: empty(undefined); // * returns 2: true // * example 3: empty([]); // * returns 3: true // * example 4: empty({}); // * returns 4: true // * example 5: empty({'aFunc' : function () { alert('humpty'); } }); // * returns 5: false var key; if (mixed_var === "" || mixed_var === 0 || mixed_var === "0" || mixed_var === null || mixed_var === false || typeof mixed_var === 'undefined') { return true; } if (typeof mixed_var == 'object') { for (key in mixed_var) { return false; } return true; } return false; } function intval (mixed_var, base) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: stensi // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: Matteo // + bugfixed by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Rafał Kukawski (http://kukawski.pl) // * example 1: intval('Kevin van Zonneveld'); // * returns 1: 0 // * example 2: intval(4.2); // * returns 2: 4 // * example 3: intval(42, 8); // * returns 3: 42 // * example 4: intval('09'); // * returns 4: 9 // * example 5: intval('1e', 16); // * returns 5: 30 var tmp; var type = typeof(mixed_var); if (type === 'boolean') { return +mixed_var; } else if (type === 'string') { tmp = parseInt(mixed_var, base || 10); return (isNaN(tmp) || !isFinite(tmp)) ? 0 : tmp; } else if (type === 'number' && isFinite(mixed_var)) { return mixed_var | 0; } else { return 0; } } function is_array (mixed_var) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Legaev Andrey // + bugfixed by: Cord // + bugfixed by: Manish // + improved by: Onno Marsman // + improved by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Brett Zamir (http://brett-zamir.me) // + improved by: Nathan Sepulveda // + improved by: Brett Zamir (http://brett-zamir.me) // % note 1: In php.js, javascript objects are like php associative arrays, thus JavaScript objects will also // % note 1: return true in this function (except for objects which inherit properties, being thus used as objects), // % note 1: unless you do ini_set('phpjs.objectsAsArrays', 0), in which case only genuine JavaScript arrays // % note 1: will return true // * example 1: is_array(['Kevin', 'van', 'Zonneveld']); // * returns 1: true // * example 2: is_array('Kevin van Zonneveld'); // * returns 2: false // * example 3: is_array({0: 'Kevin', 1: 'van', 2: 'Zonneveld'}); // * returns 3: true // * example 4: is_array(function tmp_a(){this.name = 'Kevin'}); // * returns 4: false var ini, _getFuncName = function (fn) { var name = (/\W*function\s+([\w\$]+)\s*\(/).exec(fn); if (!name) { return '(Anonymous)'; } return name[1]; }, _isArray = function (mixed_var) { // return Object.prototype.toString.call(mixed_var) === '[object Array]'; // The above works, but let's do the even more stringent approach: (since Object.prototype.toString could be overridden) // Null, Not an object, no length property so couldn't be an Array (or String) if (!mixed_var || typeof mixed_var !== 'object' || typeof mixed_var.length !== 'number') { return false; } var len = mixed_var.length; mixed_var[mixed_var.length] = 'bogus'; // The only way I can think of to get around this (or where there would be trouble) would be to have an object defined // with a custom "length" getter which changed behavior on each call (or a setter to mess up the following below) or a custom // setter for numeric properties, but even that would need to listen for specific indexes; but there should be no false negatives // and such a false positive would need to rely on later JavaScript innovations like __defineSetter__ if (len !== mixed_var.length) { // We know it's an array since length auto-changed with the addition of a // numeric property at its length end, so safely get rid of our bogus element mixed_var.length -= 1; return true; } // Get rid of the property we added onto a non-array object; only possible // side-effect is if the user adds back the property later, it will iterate // this property in the older order placement in IE (an order which should not // be depended on anyways) delete mixed_var[mixed_var.length]; return false; }; if (!mixed_var || typeof mixed_var !== 'object') { return false; } // BEGIN REDUNDANT this.php_js = this.php_js || {}; this.php_js.ini = this.php_js.ini || {}; // END REDUNDANT ini = this.php_js.ini['phpjs.objectsAsArrays']; return _isArray(mixed_var) || // Allow returning true unless user has called // ini_set('phpjs.objectsAsArrays', 0) to disallow objects as arrays ((!ini || ( // if it's not set to 0 and it's not 'off', check for objects as arrays (parseInt(ini.local_value, 10) !== 0 && (!ini.local_value.toLowerCase || ini.local_value.toLowerCase() !== 'off'))) ) && ( Object.prototype.toString.call(mixed_var) === '[object Object]' && _getFuncName(mixed_var.constructor) === 'Object' // Most likely a literal and intended as assoc. array )); } function is_numeric (mixed_var) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: David // + improved by: taith // + bugfixed by: Tim de Koning // + bugfixed by: WebDevHobo (http://webdevhobo.blogspot.com/) // + bugfixed by: Brett Zamir (http://brett-zamir.me) // * example 1: is_numeric(186.31); // * returns 1: true // * example 2: is_numeric('Kevin van Zonneveld'); // * returns 2: false // * example 3: is_numeric('+186.31e2'); // * returns 3: true // * example 4: is_numeric(''); // * returns 4: false // * example 4: is_numeric([]); // * returns 4: false return (typeof(mixed_var) === 'number' || typeof(mixed_var) === 'string') && mixed_var !== '' && !isNaN(mixed_var); } function is_string (mixed_var) { // http://kevin.vanzonneveld.net // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // * example 1: is_string('23'); // * returns 1: true // * example 2: is_string(23.5); // * returns 2: false return (typeof(mixed_var) == 'string'); } function print_r (array, return_val) { // http://kevin.vanzonneveld.net // + original by: Michael White (http://getsprink.com) // + improved by: Ben Bryan // + input by: Brett Zamir (http://brett-zamir.me) // + improved by: Brett Zamir (http://brett-zamir.me) // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // - depends on: echo // * example 1: print_r(1, true); // * returns 1: 1 var output = '', pad_char = ' ', pad_val = 4, d = this.window.document, getFuncName = function (fn) { var name = (/\W*function\s+([\w\$]+)\s*\(/).exec(fn); if (!name) { return '(Anonymous)'; } return name[1]; }, repeat_char = function (len, pad_char) { var str = ''; for (var i = 0; i < len; i++) { str += pad_char; } return str; }, formatArray = function (obj, cur_depth, pad_val, pad_char) { if (cur_depth > 0) { cur_depth++; } var base_pad = repeat_char(pad_val * cur_depth, pad_char); var thick_pad = repeat_char(pad_val * (cur_depth + 1), pad_char); var str = ''; if (typeof obj === 'object' && obj !== null && obj.constructor && getFuncName(obj.constructor) !== 'PHPJS_Resource') { str += 'Array\n' + base_pad + '(\n'; for (var key in obj) { if (Object.prototype.toString.call(obj[key]) === '[object Array]') { str += thick_pad + '[' + key + '] => ' + formatArray(obj[key], cur_depth + 1, pad_val, pad_char); } else { str += thick_pad + '[' + key + '] => ' + obj[key] + '\n'; } } str += base_pad + ')\n'; } else if (obj === null || obj === undefined) { str = ''; } else { // for our "resource" class str = obj.toString(); } return str; }; output = formatArray(array, 0, pad_val, pad_char); if (return_val !== true) { if (d.body) { this.echo(output); } else { try { d = XULDocument; // We're in XUL, so appending as plain text won't work; trigger an error out of XUL this.echo('
' + output + '
'); } catch (e) { this.echo(output); // Outputting as plain text may work in some plain XML } } return true; } return output; }