|
/* Prototype JavaScript framework, version 1.6.0.3 |
|
* (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://www.prototypejs.org/ |
|
* |
|
*--------------------------------------------------------------------------*/ |
|
|
|
var Prototype = { |
|
Version: '1.6.0.3', |
|
|
|
Browser: { |
|
IE: !!(window.attachEvent && |
|
navigator.userAgent.indexOf('Opera') === -1), |
|
Opera: navigator.userAgent.indexOf('Opera') > -1, |
|
WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, |
|
Gecko: navigator.userAgent.indexOf('Gecko') > -1 && |
|
navigator.userAgent.indexOf('KHTML') === -1, |
|
MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) |
|
}, |
|
|
|
BrowserFeatures: { |
|
XPath: !!document.evaluate, |
|
SelectorsAPI: !!document.querySelector, |
|
ElementExtensions: !!window.HTMLElement, |
|
SpecificElementExtensions: |
|
document.createElement('div')['__proto__'] && |
|
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 } |
|
}; |
|
|
|
if (Prototype.Browser.MobileSafari) |
|
Prototype.BrowserFeatures.SpecificElementExtensions = false; |
|
|
|
|
|
/* Based on Alex Arnell's inheritance implementation. */ |
|
var Class = { |
|
create: function() { |
|
var parent = null, properties = $A(arguments); |
|
if (Object.isFunction(properties[0])) |
|
parent = properties.shift(); |
|
|
|
function klass() { |
|
this.initialize.apply(this, arguments); |
|
} |
|
|
|
Object.extend(klass, Class.Methods); |
|
klass.superclass = parent; |
|
klass.subclasses = []; |
|
|
|
if (parent) { |
|
var subclass = function() { }; |
|
subclass.prototype = parent.prototype; |
|
klass.prototype = new subclass; |
|
parent.subclasses.push(klass); |
|
} |
|
|
|
for (var i = 0; i < properties.length; i++) |
|
klass.addMethods(properties[i]); |
|
|
|
if (!klass.prototype.initialize) |
|
klass.prototype.initialize = Prototype.emptyFunction; |
|
|
|
klass.prototype.constructor = klass; |
|
|
|
return klass; |
|
} |
|
}; |
|
|
|
Class.Methods = { |
|
addMethods: function(source) { |
|
var ancestor = this.superclass && this.superclass.prototype; |
|
var properties = Object.keys(source); |
|
|
|
if (!Object.keys({ toString: true }).length) |
|
properties.push("toString", "valueOf"); |
|
|
|
for (var i = 0, length = properties.length; i < length; i++) { |
|
var property = properties[i], value = source[property]; |
|
if (ancestor && Object.isFunction(value) && |
|
value.argumentNames().first() == "$super") { |
|
var method = value; |
|
value = (function(m) { |
|
return function() { return ancestor[m].apply(this, arguments) }; |
|
})(property).wrap(method); |
|
|
|
value.valueOf = method.valueOf.bind(method); |
|
value.toString = method.toString.bind(method); |
|
} |
|
this.prototype[property] = value; |
|
} |
|
|
|
return this; |
|
} |
|
}; |
|
|
|
var Abstract = { }; |
|
|
|
Object.extend = function(destination, source) { |
|
for (var property in source) |
|
destination[property] = source[property]; |
|
return destination; |
|
}; |
|
|
|
Object.extend(Object, { |
|
inspect: function(object) { |
|
try { |
|
if (Object.isUndefined(object)) return 'undefined'; |
|
if (object === null) return 'null'; |
|
return object.inspect ? object.inspect() : String(object); |
|
} 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.isElement(object)) return; |
|
|
|
var results = []; |
|
for (var property in object) { |
|
var value = Object.toJSON(object[property]); |
|
if (!Object.isUndefined(value)) |
|
results.push(property.toJSON() + ': ' + value); |
|
} |
|
|
|
return '{' + results.join(', ') + '}'; |
|
}, |
|
|
|
toQueryString: function(object) { |
|
return $H(object).toQueryString(); |
|
}, |
|
|
|
toHTML: function(object) { |
|
return object && object.toHTML ? object.toHTML() : String.interpret(object); |
|
}, |
|
|
|
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); |
|
}, |
|
|
|
isElement: function(object) { |
|
return !!(object && object.nodeType == 1); |
|
}, |
|
|
|
isArray: function(object) { |
|
return object != null && typeof object == "object" && |
|
'splice' in object && 'join' in object; |
|
}, |
|
|
|
isHash: function(object) { |
|
return object instanceof Hash; |
|
}, |
|
|
|
isFunction: function(object) { |
|
return typeof object == "function"; |
|
}, |
|
|
|
isString: function(object) { |
|
return typeof object == "string"; |
|
}, |
|
|
|
isNumber: function(object) { |
|
return typeof object == "number"; |
|
}, |
|
|
|
isUndefined: function(object) { |
|
return typeof object == "undefined"; |
|
} |
|
}); |
|
|
|
Object.extend(Function.prototype, { |
|
argumentNames: function() { |
|
var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1] |
|
.replace(/\s+/g, '').split(','); |
|
return names.length == 1 && !names[0] ? [] : names; |
|
}, |
|
|
|
bind: function() { |
|
if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; |
|
var __method = this, args = $A(arguments), object = args.shift(); |
|
return function() { |
|
return __method.apply(object, args.concat($A(arguments))); |
|
} |
|
}, |
|
|
|
bindAsEventListener: function() { |
|
var __method = this, args = $A(arguments), object = args.shift(); |
|
return function(event) { |
|
return __method.apply(object, [event || window.event].concat(args)); |
|
} |
|
}, |
|
|
|
curry: function() { |
|
if (!arguments.length) return this; |
|
var __method = this, args = $A(arguments); |
|
return function() { |
|
return __method.apply(this, args.concat($A(arguments))); |
|
} |
|
}, |
|
|
|
delay: function() { |
|
var __method = this, args = $A(arguments), timeout = args.shift() * 1000; |
|
return window.setTimeout(function() { |
|
return __method.apply(__method, args); |
|
}, timeout); |
|
}, |
|
|
|
defer: function() { |
|
var args = [0.01].concat($A(arguments)); |
|
return this.delay.apply(this, args); |
|
}, |
|
|
|
wrap: function(wrapper) { |
|
var __method = this; |
|
return function() { |
|
return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); |
|
} |
|
}, |
|
|
|
methodize: function() { |
|
if (this._methodized) return this._methodized; |
|
var __method = this; |
|
return this._methodized = function() { |
|
return __method.apply(null, [this].concat($A(arguments))); |
|
}; |
|
} |
|
}); |
|
|
|
Date.prototype.toJSON = function() { |
|
return '"' + this.getUTCFullYear() + '-' + |
|
(this.getUTCMonth() + 1).toPaddedString(2) + '-' + |
|
this.getUTCDate().toPaddedString(2) + 'T' + |
|
this.getUTCHours().toPaddedString(2) + ':' + |
|
this.getUTCMinutes().toPaddedString(2) + ':' + |
|
this.getUTCSeconds().toPaddedString(2) + 'Z"'; |
|
}; |
|
|
|
var Try = { |
|
these: function() { |
|
var returnValue; |
|
|
|
for (var i = 0, length = arguments.length; i < length; i++) { |
|
var lambda = arguments[i]; |
|
try { |
|
returnValue = lambda(); |
|
break; |
|
} catch (e) { } |
|
} |
|
|
|
return returnValue; |
|
} |
|
}; |
|
|
|
RegExp.prototype.match = RegExp.prototype.test; |
|
|
|
RegExp.escape = function(str) { |
|
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); |
|
}; |
|
|
|
/*--------------------------------------------------------------------------*/ |
|
|
|
var PeriodicalExecuter = Class.create({ |
|
initialize: function(callback, frequency) { |
|
this.callback = callback; |
|
this.frequency = frequency; |
|
this.currentlyExecuting = false; |
|
|
|
this.registerCallback(); |
|
}, |
|
|
|
registerCallback: function() { |
|
this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); |
|
}, |
|
|
|
execute: function() { |
|
this.callback(this); |
|
}, |
|
|
|
stop: function() { |
|
if (!this.timer) return; |
|
clearInterval(this.timer); |
|
this.timer = null; |
|
}, |
|
|
|
onTimerEvent: function() { |
|
if (!this.currentlyExecuting) { |
|
try { |
|
this.currentlyExecuting = true; |
|
this.execute(); |
|
} finally { |
|
this.currentlyExecuting = false; |
|
} |
|
} |
|
} |
|
}); |
|
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 = Object.isUndefined(count) ? 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 String(this); |
|
}, |
|
|
|
truncate: function(length, truncation) { |
|
length = length || 30; |
|
truncation = Object.isUndefined(truncation) ? '...' : truncation; |
|
return this.length > length ? |
|
this.slice(0, length - truncation.length) + truncation : String(this); |
|
}, |
|
|
|
strip: function() { |
|
return this.replace(/^\s+/, '').replace(/\s+$/, ''); |
|
}, |
|
|
|
stripTags: function() { |
|
return this.replace(/<\/?[^>]+>/gi, ''); |
|
}, |
|
|
|
stripScripts: function() { |
|
return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); |
|
}, |
|
|