[asterisk-commits] file: tag 1.4.26.3 r227693 - /tags/1.4.26.3/static-http/prototype.js
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Nov 4 13:14:48 CST 2009
Author: file
Date: Wed Nov 4 13:14:44 2009
New Revision: 227693
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=227693
Log:
Fix a security issue where it may be possible for someone to execute a cross-site
AJAX request exploit.
(AST-2009-009)
Modified:
tags/1.4.26.3/static-http/prototype.js
Modified: tags/1.4.26.3/static-http/prototype.js
URL: http://svnview.digium.com/svn/asterisk/tags/1.4.26.3/static-http/prototype.js?view=diff&rev=227693&r1=227692&r2=227693
==============================================================================
--- tags/1.4.26.3/static-http/prototype.js (original)
+++ tags/1.4.26.3/static-http/prototype.js Wed Nov 4 13:14:44 2009
@@ -1,17 +1,34 @@
-/* Prototype JavaScript framework, version 1.4.0
- * (c) 2005 Sam Stephenson <sam at conio.net>
+/* Prototype JavaScript framework, version 1.5.1.2
+ * (c) 2005-2008 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
- * For details, see the Prototype web site: http://prototype.conio.net/
+ * For details, see the Prototype web site: http://www.prototypejs.org/
*
/*--------------------------------------------------------------------------*/
var Prototype = {
- Version: '1.4.0',
- ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
-
- emptyFunction: function() {},
- K: function(x) {return x}
+ Version: '1.5.1.2',
+
+ Browser: {
+ IE: !!(window.attachEvent && !window.opera),
+ Opera: !!window.opera,
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1
+ },
+
+ BrowserFeatures: {
+ XPath: !!document.evaluate,
+ ElementExtensions: !!window.HTMLElement,
+ SpecificElementExtensions:
+ (document.createElement('div').__proto__ !==
+ document.createElement('form').__proto__)
+ },
+
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
+
+ emptyFunction: function() { },
+ K: function(x) { return x }
}
var Class = {
@@ -25,22 +42,62 @@
var Abstract = new Object();
Object.extend = function(destination, source) {
- for (property in source) {
+ for (var property in source) {
destination[property] = source[property];
}
return destination;
}
-Object.inspect = function(object) {
- try {
- if (object == undefined) return 'undefined';
- if (object == null) return 'null';
- return object.inspect ? object.inspect() : object.toString();
- } catch (e) {
- if (e instanceof RangeError) return '...';
- throw e;
- }
-}
+Object.extend(Object, {
+ inspect: function(object) {
+ try {
+ if (object === undefined) return 'undefined';
+ if (object === null) return 'null';
+ return object.inspect ? object.inspect() : object.toString();
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+ },
+
+ toJSON: function(object) {
+ var type = typeof object;
+ switch(type) {
+ case 'undefined':
+ case 'function':
+ case 'unknown': return;
+ case 'boolean': return object.toString();
+ }
+ if (object === null) return 'null';
+ if (object.toJSON) return object.toJSON();
+ if (object.ownerDocument === document) return;
+ var results = [];
+ for (var property in object) {
+ var value = Object.toJSON(object[property]);
+ if (value !== undefined)
+ results.push(property.toJSON() + ': ' + value);
+ }
+ return '{' + results.join(', ') + '}';
+ },
+
+ keys: function(object) {
+ var keys = [];
+ for (var property in object)
+ keys.push(property);
+ return keys;
+ },
+
+ values: function(object) {
+ var values = [];
+ for (var property in object)
+ values.push(object[property]);
+ return values;
+ },
+
+ clone: function(object) {
+ return Object.extend({}, object);
+ }
+});
Function.prototype.bind = function() {
var __method = this, args = $A(arguments), object = args.shift();
@@ -50,17 +107,15 @@
}
Function.prototype.bindAsEventListener = function(object) {
- var __method = this;
+ var __method = this, args = $A(arguments), object = args.shift();
return function(event) {
- return __method.call(object, event || window.event);
+ return __method.apply(object, [event || window.event].concat(args));
}
}
Object.extend(Number.prototype, {
toColorPart: function() {
- var digits = this.toString(16);
- if (this < 16) return '0' + digits;
- return digits;
+ return this.toPaddedString(2, 16);
},
succ: function() {
@@ -70,14 +125,32 @@
times: function(iterator) {
$R(0, this, true).each(iterator);
return this;
+ },
+
+ toPaddedString: function(length, radix) {
+ var string = this.toString(radix || 10);
+ return '0'.times(length - string.length) + string;
+ },
+
+ toJSON: function() {
+ return isFinite(this) ? this.toString() : 'null';
}
});
+
+Date.prototype.toJSON = function() {
+ return '"' + this.getFullYear() + '-' +
+ (this.getMonth() + 1).toPaddedString(2) + '-' +
+ this.getDate().toPaddedString(2) + 'T' +
+ this.getHours().toPaddedString(2) + ':' +
+ this.getMinutes().toPaddedString(2) + ':' +
+ this.getSeconds().toPaddedString(2) + '"';
+};
var Try = {
these: function() {
var returnValue;
- for (var i = 0; i < arguments.length; i++) {
+ for (var i = 0, length = arguments.length; i < length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
@@ -102,40 +175,83 @@
},
registerCallback: function() {
- setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
+ },
+
+ stop: function() {
+ if (!this.timer) return;
+ clearInterval(this.timer);
+ this.timer = null;
},
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
- this.callback();
+ this.callback(this);
} finally {
this.currentlyExecuting = false;
}
}
}
}
-
-/*--------------------------------------------------------------------------*/
-
-function $() {
- var elements = new Array();
-
- for (var i = 0; i < arguments.length; i++) {
- var element = arguments[i];
- if (typeof element == 'string')
- element = document.getElementById(element);
-
- if (arguments.length == 1)
- return element;
-
- elements.push(element);
- }
-
- return elements;
-}
+Object.extend(String, {
+ interpret: function(value) {
+ return value == null ? '' : String(value);
+ },
+ specialChar: {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '\\': '\\\\'
+ }
+});
+
Object.extend(String.prototype, {
+ gsub: function(pattern, replacement) {
+ var result = '', source = this, match;
+ replacement = arguments.callee.prepareReplacement(replacement);
+
+ while (source.length > 0) {
+ if (match = source.match(pattern)) {
+ result += source.slice(0, match.index);
+ result += String.interpret(replacement(match));
+ source = source.slice(match.index + match[0].length);
+ } else {
+ result += source, source = '';
+ }
+ }
+ return result;
+ },
+
+ sub: function(pattern, replacement, count) {
+ replacement = this.gsub.prepareReplacement(replacement);
+ count = count === undefined ? 1 : count;
+
+ return this.gsub(pattern, function(match) {
+ if (--count < 0) return match[0];
+ return replacement(match);
+ });
+ },
+
+ scan: function(pattern, iterator) {
+ this.gsub(pattern, iterator);
+ return this;
+ },
+
+ truncate: function(length, truncation) {
+ length = length || 30;
+ truncation = truncation === undefined ? '...' : truncation;
+ return this.length > length ?
+ this.slice(0, length - truncation.length) + truncation : this;
+ },
+
+ strip: function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ },
+
stripTags: function() {
return this.replace(/<\/?[^>]+>/gi, '');
},
@@ -153,28 +269,40 @@
},
evalScripts: function() {
- return this.extractScripts().map(eval);
+ return this.extractScripts().map(function(script) { return eval(script) });
},
escapeHTML: function() {
- var div = document.createElement('div');
- var text = document.createTextNode(this);
- div.appendChild(text);
- return div.innerHTML;
+ var self = arguments.callee;
+ self.text.data = this;
+ return self.div.innerHTML;
},
unescapeHTML: function() {
var div = document.createElement('div');
div.innerHTML = this.stripTags();
- return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
- },
-
- toQueryParams: function() {
- var pairs = this.match(/^\??(.*)$/)[1].split('&');
- return pairs.inject({}, function(params, pairString) {
- var pair = pairString.split('=');
- params[pair[0]] = pair[1];
- return params;
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
+ div.childNodes[0].nodeValue) : '';
+ },
+
+ toQueryParams: function(separator) {
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
+ if (!match) return {};
+
+ return match[1].split(separator || '&').inject({}, function(hash, pair) {
+ if ((pair = pair.split('='))[0]) {
+ var key = decodeURIComponent(pair.shift());
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
+ if (value != undefined) value = decodeURIComponent(value);
+
+ if (key in hash) {
+ if (hash[key].constructor != Array) hash[key] = [hash[key]];
+ hash[key].push(value);
+ }
+ else hash[key] = value;
+ }
+ return hash;
});
},
@@ -182,46 +310,156 @@
return this.split('');
},
+ succ: function() {
+ return this.slice(0, this.length - 1) +
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
+ },
+
+ times: function(count) {
+ var result = '';
+ for (var i = 0; i < count; i++) result += this;
+ return result;
+ },
+
camelize: function() {
- var oStringList = this.split('-');
- if (oStringList.length == 1) return oStringList[0];
-
- var camelizedString = this.indexOf('-') == 0
- ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
- : oStringList[0];
-
- for (var i = 1, len = oStringList.length; i < len; i++) {
- var s = oStringList[i];
- camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
- }
-
- return camelizedString;
- },
-
- inspect: function() {
- return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
+ var parts = this.split('-'), len = parts.length;
+ if (len == 1) return parts[0];
+
+ var camelized = this.charAt(0) == '-'
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
+ : parts[0];
+
+ for (var i = 1; i < len; i++)
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
+
+ return camelized;
+ },
+
+ capitalize: function() {
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
+ },
+
+ underscore: function() {
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
+ },
+
+ dasherize: function() {
+ return this.gsub(/_/,'-');
+ },
+
+ inspect: function(useDoubleQuotes) {
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
+ var character = String.specialChar[match[0]];
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
+ });
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
+ },
+
+ toJSON: function() {
+ return this.inspect(true);
+ },
+
+ unfilterJSON: function(filter) {
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
+ },
+
+ isJSON: function() {
+ var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
+ },
+
+ evalJSON: function(sanitize) {
+ var json = this.unfilterJSON();
+ try {
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
+ } catch (e) { }
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
+ },
+
+ include: function(pattern) {
+ return this.indexOf(pattern) > -1;
+ },
+
+ startsWith: function(pattern) {
+ return this.indexOf(pattern) === 0;
+ },
+
+ endsWith: function(pattern) {
+ var d = this.length - pattern.length;
+ return d >= 0 && this.lastIndexOf(pattern) === d;
+ },
+
+ empty: function() {
+ return this == '';
+ },
+
+ blank: function() {
+ return /^\s*$/.test(this);
}
});
+if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
+ escapeHTML: function() {
+ return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ },
+ unescapeHTML: function() {
+ return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
+ }
+});
+
+String.prototype.gsub.prepareReplacement = function(replacement) {
+ if (typeof replacement == 'function') return replacement;
+ var template = new Template(replacement);
+ return function(match) { return template.evaluate(match) };
+}
+
String.prototype.parseQuery = String.prototype.toQueryParams;
-var $break = new Object();
-var $continue = new Object();
+Object.extend(String.prototype.escapeHTML, {
+ div: document.createElement('div'),
+ text: document.createTextNode('')
+});
+
+with (String.prototype.escapeHTML) div.appendChild(text);
+
+var Template = Class.create();
+Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
+Template.prototype = {
+ initialize: function(template, pattern) {
+ this.template = template.toString();
+ this.pattern = pattern || Template.Pattern;
+ },
+
+ evaluate: function(object) {
+ return this.template.gsub(this.pattern, function(match) {
+ var before = match[1];
+ if (before == '\\') return match[2];
+ return before + String.interpret(object[match[3]]);
+ });
+ }
+}
+
+var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead');
var Enumerable = {
each: function(iterator) {
var index = 0;
try {
this._each(function(value) {
- try {
- iterator(value, index++);
- } catch (e) {
- if (e != $continue) throw e;
- }
+ iterator(value, index++);
});
} catch (e) {
if (e != $break) throw e;
}
+ return this;
+ },
+
+ eachSlice: function(number, iterator) {
+ var index = -number, slices = [], array = this.toArray();
+ while ((index += number) < array.length)
+ slices.push(array.slice(index, index+number));
+ return slices.map(iterator);
},
all: function(iterator) {
@@ -234,7 +472,7 @@
},
any: function(iterator) {
- var result = true;
+ var result = false;
this.each(function(value, index) {
if (result = !!(iterator || Prototype.K)(value, index))
throw $break;
@@ -245,12 +483,12 @@
collect: function(iterator) {
var results = [];
this.each(function(value, index) {
- results.push(iterator(value, index));
+ results.push((iterator || Prototype.K)(value, index));
});
return results;
},
- detect: function (iterator) {
+ detect: function(iterator) {
var result;
this.each(function(value, index) {
if (iterator(value, index)) {
@@ -291,6 +529,14 @@
return found;
},
+ inGroupsOf: function(number, fillWith) {
+ fillWith = fillWith === undefined ? null : fillWith;
+ return this.eachSlice(number, function(slice) {
+ while(slice.length < number) slice.push(fillWith);
+ return slice;
+ });
+ },
+
inject: function(memo, iterator) {
this.each(function(value, index) {
memo = iterator(memo, value, index);
@@ -300,7 +546,7 @@
invoke: function(method) {
var args = $A(arguments).slice(1);
- return this.collect(function(value) {
+ return this.map(function(value) {
return value[method].apply(value, args);
});
},
@@ -309,7 +555,7 @@
var result;
this.each(function(value, index) {
value = (iterator || Prototype.K)(value, index);
- if (value >= (result || value))
+ if (result == undefined || value >= result)
result = value;
});
return result;
@@ -319,7 +565,7 @@
var result;
this.each(function(value, index) {
value = (iterator || Prototype.K)(value, index);
- if (value <= (result || value))
+ if (result == undefined || value < result)
result = value;
});
return result;
@@ -352,7 +598,7 @@
},
sortBy: function(iterator) {
- return this.collect(function(value, index) {
+ return this.map(function(value, index) {
return {value: value, criteria: iterator(value, index)};
}).sort(function(left, right) {
var a = left.criteria, b = right.criteria;
@@ -361,7 +607,7 @@
},
toArray: function() {
- return this.collect(Prototype.K);
+ return this.map();
},
zip: function() {
@@ -371,9 +617,12 @@
var collections = [this].concat(args).map($A);
return this.map(function(value, index) {
- iterator(value = collections.pluck(index));
- return value;
- });
+ return iterator(collections.pluck(index));
+ });
+ },
+
+ size: function() {
+ return this.toArray().length;
},
inspect: function() {
@@ -394,19 +643,35 @@
return iterable.toArray();
} else {
var results = [];
- for (var i = 0; i < iterable.length; i++)
+ for (var i = 0, length = iterable.length; i < length; i++)
results.push(iterable[i]);
return results;
}
}
+if (Prototype.Browser.WebKit) {
+ $A = Array.from = function(iterable) {
+ if (!iterable) return [];
+ if (!(typeof iterable == 'function' && iterable == '[object NodeList]') &&
+ iterable.toArray) {
+ return iterable.toArray();
+ } else {
+ var results = [];
+ for (var i = 0, length = iterable.length; i < length; i++)
+ results.push(iterable[i]);
+ return results;
+ }
+ }
+}
+
Object.extend(Array.prototype, Enumerable);
-Array.prototype._reverse = Array.prototype.reverse;
+if (!Array.prototype._reverse)
+ Array.prototype._reverse = Array.prototype.reverse;
Object.extend(Array.prototype, {
_each: function(iterator) {
- for (var i = 0; i < this.length; i++)
+ for (var i = 0, length = this.length; i < length; i++)
iterator(this[i]);
},
@@ -425,13 +690,13 @@
compact: function() {
return this.select(function(value) {
- return value != undefined || value != null;
+ return value != null;
});
},
flatten: function() {
return this.inject([], function(array, value) {
- return array.concat(value.constructor == Array ?
+ return array.concat(value && value.constructor == Array ?
value.flatten() : [value]);
});
},
@@ -444,7 +709,7 @@
},
indexOf: function(object) {
- for (var i = 0; i < this.length; i++)
+ for (var i = 0, length = this.length; i < length; i++)
if (this[i] == object) return i;
return -1;
},
@@ -453,23 +718,110 @@
return (inline !== false ? this : this.toArray())._reverse();
},
- shift: function() {
- var result = this[0];
- for (var i = 0; i < this.length - 1; i++)
- this[i] = this[i + 1];
- this.length--;
- return result;
+ reduce: function() {
+ return this.length > 1 ? this : this[0];
+ },
+
+ uniq: function(sorted) {
+ return this.inject([], function(array, value, index) {
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
+ array.push(value);
+ return array;
+ });
+ },
+
+ clone: function() {
+ return [].concat(this);
+ },
+
+ size: function() {
+ return this.length;
},
inspect: function() {
return '[' + this.map(Object.inspect).join(', ') + ']';
+ },
+
+ toJSON: function() {
+ var results = [];
+ this.each(function(object) {
+ var value = Object.toJSON(object);
+ if (value !== undefined) results.push(value);
+ });
+ return '[' + results.join(', ') + ']';
}
});
-var Hash = {
+
+Array.prototype.toArray = Array.prototype.clone;
+
+function $w(string) {
+ string = string.strip();
+ return string ? string.split(/\s+/) : [];
+}
+
+if (Prototype.Browser.Opera){
+ Array.prototype.concat = function() {
+ var array = [];
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
+ for (var i = 0, length = arguments.length; i < length; i++) {
+ if (arguments[i].constructor == Array) {
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
+ array.push(arguments[i][j]);
+ } else {
+ array.push(arguments[i]);
+ }
+ }
+ return array;
+ }
+}
+var Hash = function(object) {
+ if (object instanceof Hash) this.merge(object);
+ else Object.extend(this, object || {});
+};
+
+Object.extend(Hash, {
+ toQueryString: function(obj) {
+ var parts = [];
+ parts.add = arguments.callee.addPair;
+
+ this.prototype._each.call(obj, function(pair) {
+ if (!pair.key) return;
+ var value = pair.value;
+
+ if (value && typeof value == 'object') {
+ if (value.constructor == Array) value.each(function(value) {
+ parts.add(pair.key, value);
+ });
+ return;
+ }
+ parts.add(pair.key, value);
+ });
+
+ return parts.join('&');
+ },
+
+ toJSON: function(object) {
+ var results = [];
+ this.prototype._each.call(object, function(pair) {
+ var value = Object.toJSON(pair.value);
+ if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value);
+ });
+ return '{' + results.join(', ') + '}';
+ }
+});
+
+Hash.toQueryString.addPair = function(key, value, prefix) {
+ key = encodeURIComponent(key);
+ if (value === undefined) this.push(key);
+ else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value)));
+}
+
+Object.extend(Hash.prototype, Enumerable);
+Object.extend(Hash.prototype, {
_each: function(iterator) {
- for (key in this) {
+ for (var key in this) {
var value = this[key];
- if (typeof value == 'function') continue;
+ if (value && value == Hash.prototype[key]) continue;
var pair = [key, value];
pair.key = key;
@@ -487,31 +839,66 @@
},
merge: function(hash) {
- return $H(hash).inject($H(this), function(mergedHash, pair) {
+ return $H(hash).inject(this, function(mergedHash, pair) {
mergedHash[pair.key] = pair.value;
return mergedHash;
});
},
+ remove: function() {
+ var result;
+ for(var i = 0, length = arguments.length; i < length; i++) {
+ var value = this[arguments[i]];
+ if (value !== undefined){
+ if (result === undefined) result = value;
+ else {
+ if (result.constructor != Array) result = [result];
+ result.push(value)
+ }
+ }
+ delete this[arguments[i]];
+ }
+ return result;
+ },
+
toQueryString: function() {
- return this.map(function(pair) {
- return pair.map(encodeURIComponent).join('=');
- }).join('&');
+ return Hash.toQueryString(this);
},
inspect: function() {
return '#<Hash:{' + this.map(function(pair) {
return pair.map(Object.inspect).join(': ');
}).join(', ') + '}>';
- }
-}
+ },
+
+ toJSON: function() {
+ return Hash.toJSON(this);
+ }
+});
function $H(object) {
- var hash = Object.extend({}, object || {});
- Object.extend(hash, Enumerable);
- Object.extend(hash, Hash);
- return hash;
-}
+ if (object instanceof Hash) return object;
+ return new Hash(object);
+};
+
+// Safari iterates over shadowed properties
+if (function() {
+ var i = 0, Test = function(value) { this.key = value };
+ Test.prototype.key = 'foo';
+ for (var property in new Test('bar')) i++;
+ return i > 1;
+}()) Hash.prototype._each = function(iterator) {
+ var cache = [];
+ for (var key in this) {
+ var value = this[key];
+ if ((value && value == Hash.prototype[key]) || cache.include(key)) continue;
+ cache.push(key);
+ var pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+};
ObjectRange = Class.create();
Object.extend(ObjectRange.prototype, Enumerable);
Object.extend(ObjectRange.prototype, {
@@ -523,10 +910,10 @@
_each: function(iterator) {
var value = this.start;
- do {
+ while (this.include(value)) {
iterator(value);
value = value.succ();
- } while (this.include(value));
+ }
},
include: function(value) {
@@ -545,9 +932,9 @@
var Ajax = {
getTransport: function() {
return Try.these(
+ function() {return new XMLHttpRequest()},
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
- function() {return new ActiveXObject('Microsoft.XMLHTTP')},
- function() {return new XMLHttpRequest()}
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
) || false;
},
@@ -561,18 +948,18 @@
this.responders._each(iterator);
},
- register: function(responderToAdd) {
- if (!this.include(responderToAdd))
- this.responders.push(responderToAdd);
- },
-
- unregister: function(responderToRemove) {
- this.responders = this.responders.without(responderToRemove);
+ register: function(responder) {
+ if (!this.include(responder))
+ this.responders.push(responder);
+ },
+
+ unregister: function(responder) {
+ this.responders = this.responders.without(responder);
},
dispatch: function(callback, request, transport, json) {
this.each(function(responder) {
- if (responder[callback] && typeof responder[callback] == 'function') {
+ if (typeof responder[callback] == 'function') {
try {
responder[callback].apply(responder, [request, transport, json]);
} catch (e) {}
@@ -587,7 +974,6 @@
onCreate: function() {
Ajax.activeRequestCount++;
},
-
onComplete: function() {
Ajax.activeRequestCount--;
}
@@ -599,19 +985,15 @@
this.options = {
method: 'post',
asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
parameters: ''
}
Object.extend(this.options, options || {});
- },
-
- responseIsSuccess: function() {
- return this.transport.status == undefined
- || this.transport.status == 0
- || (this.transport.status >= 200 && this.transport.status < 300);
- },
-
- responseIsFailure: function() {
- return !this.responseIsSuccess();
+
+ this.options.method = this.options.method.toLowerCase();
+ if (typeof this.options.parameters == 'string')
+ this.options.parameters = this.options.parameters.toQueryParams();
}
}
@@ -620,6 +1002,8 @@
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
+ _complete: false,
+
initialize: function(url, options) {
this.transport = Ajax.getTransport();
this.setOptions(options);
@@ -627,111 +1011,159 @@
},
request: function(url) {
- var parameters = this.options.parameters || '';
- if (parameters.length > 0) parameters += '&_=';
+ this.url = url;
+ this.method = this.options.method;
+ var params = Object.clone(this.options.parameters);
+
+ if (!['get', 'post'].include(this.method)) {
+ // simulate other verbs over post
+ params['_method'] = this.method;
+ this.method = 'post';
+ }
+
+ this.parameters = params;
+
+ if (params = Hash.toQueryString(params)) {
+ // when GET, append parameters to URL
+ if (this.method == 'get')
+ this.url += (this.url.include('?') ? '&' : '?') + params;
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
+ params += '&_=';
+ }
try {
- this.url = url;
- if (this.options.method == 'get' && parameters.length > 0)
- this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
-
+ if (this.options.onCreate) this.options.onCreate(this.transport);
Ajax.Responders.dispatch('onCreate', this, this.transport);
- this.transport.open(this.options.method, this.url,
+ this.transport.open(this.method.toUpperCase(), this.url,
this.options.asynchronous);
- if (this.options.asynchronous) {
- this.transport.onreadystatechange = this.onStateChange.bind(this);
- setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
- }
-
+ if (this.options.asynchronous)
+ setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
+
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
this.setRequestHeaders();
- var body = this.options.postBody ? this.options.postBody : parameters;
- this.transport.send(this.options.method == 'post' ? body : null);
-
- } catch (e) {
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
+ this.transport.send(this.body);
+
+ /* Force Firefox to handle ready state 4 for synchronous requests */
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this.onStateChange();
+
+ }
+ catch (e) {
this.dispatchException(e);
}
- },
-
- setRequestHeaders: function() {
- var requestHeaders =
- ['X-Requested-With', 'XMLHttpRequest',
- 'X-Prototype-Version', Prototype.Version];
-
- if (this.options.method == 'post') {
- requestHeaders.push('Content-type',
- 'application/x-www-form-urlencoded');
-
- /* Force "Connection: close" for Mozilla browsers to work around
- * a bug where XMLHttpReqeuest sends an incorrect Content-length
- * header. See Mozilla Bugzilla #246651.
- */
- if (this.transport.overrideMimeType)
- requestHeaders.push('Connection', 'close');
- }
-
- if (this.options.requestHeaders)
- requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
-
- for (var i = 0; i < requestHeaders.length; i += 2)
- this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
},
onStateChange: function() {
var readyState = this.transport.readyState;
- if (readyState != 1)
+ if (readyState > 1 && !((readyState == 4) && this._complete))
this.respondToReadyState(this.transport.readyState);
},
- header: function(name) {
- try {
- return this.transport.getResponseHeader(name);
- } catch (e) {}
- },
-
- evalJSON: function() {
- try {
- return eval(this.header('X-JSON'));
- } catch (e) {}
- },
-
- evalResponse: function() {
- try {
- return eval(this.transport.responseText);
- } catch (e) {
- this.dispatchException(e);
- }
+ setRequestHeaders: function() {
+ var headers = {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'X-Prototype-Version': Prototype.Version,
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ };
+
+ if (this.method == 'post') {
+ headers['Content-type'] = this.options.contentType +
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
+
+ /* Force "Connection: close" for older Mozilla browsers to work
+ * around a bug where XMLHttpRequest sends an incorrect
+ * Content-length header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType &&
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
+ headers['Connection'] = 'close';
+ }
+
+ // user-defined headers
+ if (typeof this.options.requestHeaders == 'object') {
+ var extras = this.options.requestHeaders;
+
+ if (typeof extras.push == 'function')
+ for (var i = 0, length = extras.length; i < length; i += 2)
+ headers[extras[i]] = extras[i+1];
+ else
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
+ }
+
+ for (var name in headers)
+ this.transport.setRequestHeader(name, headers[name]);
+ },
+
+ success: function() {
+ return !this.transport.status
+ || (this.transport.status >= 200 && this.transport.status < 300);
},
respondToReadyState: function(readyState) {
- var event = Ajax.Request.Events[readyState];
+ var state = Ajax.Request.Events[readyState];
var transport = this.transport, json = this.evalJSON();
- if (event == 'Complete') {
+ if (state == 'Complete') {
try {
+ this._complete = true;
(this.options['on' + this.transport.status]
- || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
|| Prototype.emptyFunction)(transport, json);
} catch (e) {
this.dispatchException(e);
}
- if ((this.header('Content-type') || '').match(/^text\/javascript/i))
- this.evalResponse();
+ var contentType = this.getHeader('Content-type');
+ if (contentType && this.isSameOrigin() && contentType.strip().
+ match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
+ this.evalResponse();
}
try {
- (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
- Ajax.Responders.dispatch('on' + event, this, transport, json);
+ (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
+ Ajax.Responders.dispatch('on' + state, this, transport, json);
} catch (e) {
this.dispatchException(e);
}
- /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
- if (event == 'Complete')
+ if (state == 'Complete') {
+ // avoid memory leak in MSIE: clean up
this.transport.onreadystatechange = Prototype.emptyFunction;
+ }
+ },
+
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == new Template('#{protocol}//#{domain}#{port}').evaluate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
+ getHeader: function(name) {
+ try {
+ return this.transport.getResponseHeader(name);
+ } catch (e) { return null }
+ },
+
+ evalJSON: function() {
+ try {
+ var json = this.getHeader('X-JSON');
+ return json ? json.evalJSON(!this.isSameOrigin()) : null;
+ } catch (e) { return null }
+ },
+
+ evalResponse: function() {
+ try {
+ return eval((this.transport.responseText || '').unfilterJSON());
+ } catch (e) {
+ this.dispatchException(e);
+ }
},
dispatchException: function(exception) {
@@ -744,41 +1176,37 @@
Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
initialize: function(container, url, options) {
- this.containers = {
- success: container.success ? $(container.success) : $(container),
- failure: container.failure ? $(container.failure) :
- (container.success ? null : $(container))
+ this.container = {
+ success: (container.success || container),
+ failure: (container.failure || (container.success ? null : container))
}
this.transport = Ajax.getTransport();
this.setOptions(options);
var onComplete = this.options.onComplete || Prototype.emptyFunction;
- this.options.onComplete = (function(transport, object) {
+ this.options.onComplete = (function(transport, param) {
this.updateContent();
- onComplete(transport, object);
+ onComplete(transport, param);
}).bind(this);
this.request(url);
},
updateContent: function() {
- var receiver = this.responseIsSuccess() ?
- this.containers.success : this.containers.failure;
+ var receiver = this.container[this.success() ? 'success' : 'failure'];
var response = this.transport.responseText;
- if (!this.options.evalScripts)
- response = response.stripScripts();
-
- if (receiver) {
- if (this.options.insertion) {
+ if (!this.options.evalScripts) response = response.stripScripts();
+
+ if (receiver = $(receiver)) {
+ if (this.options.insertion)
new this.options.insertion(receiver, response);
- } else {
- Element.update(receiver, response);
- }
- }
-
- if (this.responseIsSuccess()) {
+ else
+ receiver.update(response);
+ }
+
+ if (this.success()) {
if (this.onComplete)
setTimeout(this.onComplete.bind(this), 10);
}
@@ -807,7 +1235,7 @@
},
stop: function() {
- this.updater.onComplete = undefined;
+ this.updater.options.onComplete = undefined;
clearTimeout(this.timer);
(this.onComplete || Prototype.emptyFunction).apply(this, arguments);
},
@@ -827,60 +1255,254 @@
this.updater = new Ajax.Updater(this.container, this.url, this.options);
}
});
-document.getElementsByClassName = function(className, parentElement) {
+function $(element) {
+ if (arguments.length > 1) {
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
+ elements.push($(arguments[i]));
+ return elements;
+ }
+ if (typeof element == 'string')
+ element = document.getElementById(element);
+ return Element.extend(element);
+}
+
+if (Prototype.BrowserFeatures.XPath) {
+ document._getElementsByXPath = function(expression, parentElement) {
+ var results = [];
+ var query = document.evaluate(expression, $(parentElement) || document,
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
+ results.push(query.snapshotItem(i));
+ return results;
+ };
+
+ document.getElementsByClassName = function(className, parentElement) {
+ var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
+ return document._getElementsByXPath(q, parentElement);
+ }
+
+} else document.getElementsByClassName = function(className, parentElement) {
var children = ($(parentElement) || document.body).getElementsByTagName('*');
- return $A(children).inject([], function(elements, child) {
- if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
- elements.push(child);
- return elements;
- });
-}
+ var elements = [], child, pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");
+ for (var i = 0, length = children.length; i < length; i++) {
+ child = children[i];
+ var elementClassName = child.className;
+ if (elementClassName.length == 0) continue;
+ if (elementClassName == className || elementClassName.match(pattern))
+ elements.push(Element.extend(child));
+ }
+ return elements;
+};
/*--------------------------------------------------------------------------*/
-if (!window.Element) {
- var Element = new Object();
-}
-
-Object.extend(Element, {
+if (!window.Element) var Element = {};
+
+Element.extend = function(element) {
+ var F = Prototype.BrowserFeatures;
+ if (!element || !element.tagName || element.nodeType == 3 ||
+ element._extended || F.SpecificElementExtensions || element == window)
+ return element;
+
+ var methods = {}, tagName = element.tagName, cache = Element.extend.cache,
+ T = Element.Methods.ByTag;
+
+ // extend methods for all tags (Safari doesn't need this)
+ if (!F.ElementExtensions) {
[... 1817 lines stripped ...]
More information about the asterisk-commits
mailing list