﻿/* prototype.js */

// This is patched, see http://dev.rubyonrails.org/ticket/9416 and http://dev.rubyonrails.org/ticket/11051
var Prototype = { Version: '1.6.0.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, MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) }, BrowserFeatures: { XPath: !!document.evaluate, 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; 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 = Object.extend((function(m) { return function() { return ancestor[m].apply(this, arguments) } })(property).wrap(method), { valueOf: function() { return method }, toString: function() { return method.toString() } }) } 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].split(",").invoke("strip"); 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) }, 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))) } } }); Function.prototype.defer = Function.prototype.delay.curry(0.01); 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'), '') }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1] }) }, evalScripts: function() { return this.extractScripts().map(function(script) { return eval(script) }) }, escapeHTML: function() { var self = arguments.callee; self.text.data = this; return self.div.innerHTML }, unescapeHTML: function() { var div = new Element('div'); div.innerHTML = this.stripTags(); 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 (!Object.isArray(hash[key])) hash[key] = [hash[key]]; hash[key].push(value) } else hash[key] = value } return hash }) }, toArray: function() { return this.split('') }, succ: function() { return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1) }, times: function(count) { return count < 1 ? '' : new Array(count + 1).join(this) }, camelize: function() { 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; if (str.blank()) return false; 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) }, interpolate: function(object, pattern) { return new Template(this, pattern).evaluate(object) } }); if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { escapeHTML: function() { return this.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;') }, unescapeHTML: function() { return this.replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>') } }); String.prototype.gsub.prepareReplacement = function(replacement) { if (Object.isFunction(replacement)) return replacement; var template = new Template(replacement); return function(match) { return template.evaluate(match) } }; String.prototype.parseQuery = String.prototype.toQueryParams; Object.extend(String.prototype.escapeHTML, { div: document.createElement('div'), text: document.createTextNode('') }); with (String.prototype.escapeHTML) div.appendChild(text); var Template = Class.create({ initialize: function(template, pattern) { this.template = template.toString(); this.pattern = pattern || Template.Pattern }, evaluate: function(object) { if (Object.isFunction(object.toTemplateReplacements)) object = object.toTemplateReplacements(); return this.template.gsub(this.pattern, function(match) { if (object == null) return ''; var before = match[1] || ''; if (before == '\\') return match[2]; var ctx = object, expr = match[3]; var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; match = pattern.exec(expr); if (match == null) return before; while (match != null) { var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; ctx = ctx[comp]; if (null == ctx || '' == match[3]) break; expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); match = pattern.exec(expr) } return before + String.interpret(ctx) }) } }); Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; var $break = {}; var Enumerable = { each: function(iterator, context) { var index = 0; iterator = iterator.bind(context); try { this._each(function(value) { iterator(value, index++) }) } catch (e) { if (e != $break) throw e; } return this }, eachSlice: function(number, iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var index = -number, slices = [], array = this.toArray(); while ((index += number) < array.length) slices.push(array.slice(index, index + number)); return slices.collect(iterator, context) }, all: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var result = true; this.each(function(value, index) { result = result && !!iterator(value, index); if (!result) throw $break; }); return result }, any: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var result = false; this.each(function(value, index) { if (result = !!iterator(value, index)) throw $break; }); return result }, collect: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var results = []; this.each(function(value, index) { results.push(iterator(value, index)) }); return results }, detect: function(iterator, context) { iterator = iterator.bind(context); var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result }, findAll: function(iterator, context) { iterator = iterator.bind(context); var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value) }); return results }, grep: function(filter, iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var results = []; if (Object.isString(filter)) filter = new RegExp(filter); this.each(function(value, index) { if (filter.match(value)) results.push(iterator(value, index)) }); return results }, include: function(object) { if (Object.isFunction(this.indexOf)) if (this.indexOf(object) != -1) return true; var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found }, inGroupsOf: function(number, fillWith) { fillWith = Object.isUndefined(fillWith) ? null : fillWith; return this.eachSlice(number, function(slice) { while (slice.length < number) slice.push(fillWith); return slice }) }, inject: function(memo, iterator, context) { iterator = iterator.bind(context); this.each(function(value, index) { memo = iterator(memo, value, index) }); return memo }, invoke: function(method) { var args = $A(arguments).slice(1); return this.map(function(value) { return value[method].apply(value, args) }) }, max: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var result; this.each(function(value, index) { value = iterator(value, index); if (result == null || value >= result) result = value }); return result }, min: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var result; this.each(function(value, index) { value = iterator(value, index); if (result == null || value < result) result = value }); return result }, partition: function(iterator, context) { iterator = iterator ? iterator.bind(context) : Prototype.K; var trues = [], falses = []; this.each(function(value, index) { (iterator(value, index) ? trues : falses).push(value) }); return [trues, falses] }, pluck: function(property) { var results = []; this.each(function(value) { results.push(value[property]) }); return results }, reject: function(iterator, context) { iterator = iterator.bind(context); var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value) }); return results }, sortBy: function(iterator, context) { iterator = iterator.bind(context); return this.map(function(value, index) { return { value: value, criteria: iterator(value, index)} }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0 }).pluck('value') }, toArray: function() { return this.map() }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (Object.isFunction(args.last())) iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { return iterator(collections.pluck(index)) }) }, size: function() { return this.toArray().length }, inspect: function() { return '#<Enumerable:' + this.toArray().inspect() + '>' } }; Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, filter: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray, every: Enumerable.all, some: Enumerable.any }); function $A(iterable) { if (!iterable) return []; if (iterable.toArray) return iterable.toArray(); var length = iterable.length || 0, results = new Array(length); while (length--) results[length] = iterable[length]; return results } if (Prototype.Browser.WebKit) { $A = function(iterable) { if (!iterable) return []; if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && iterable.toArray) return iterable.toArray(); var length = iterable.length || 0, results = new Array(length); while (length--) results[length] = iterable[length]; return results } } Array.from = $A; Object.extend(Array.prototype, Enumerable); if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0, length = this.length; i < length; i++) iterator(this[i]) }, clear: function() { this.length = 0; return this }, first: function() { return this[0] }, last: function() { return this[this.length - 1] }, compact: function() { return this.select(function(value) { return value != null }) }, flatten: function() { return this.inject([], function(array, value) { return array.concat(Object.isArray(value) ? value.flatten() : [value]) }) }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value) }) }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse() }, 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 }) }, intersect: function(array) { return this.uniq().findAll(function(item) { return array.detect(function(value) { return item === value }) }) }, 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 (!Object.isUndefined(value)) results.push(value) }); return '[' + results.join(', ') + ']' } }); if (Object.isFunction(Array.prototype.forEach)) Array.prototype._each = Array.prototype.forEach; if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { i || (i = 0); var length = this.length; if (i < 0) i = length + i; for (; i < length; i++) if (this[i] === item) return i; return -1 }; if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; var n = this.slice(0, i).reverse().indexOf(item); return (n < 0) ? n : i - n - 1 }; Array.prototype.toArray = Array.prototype.clone; function $w(string) { if (!Object.isString(string)) return []; 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 (Object.isArray(arguments[i])) { for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) array.push(arguments[i][j]) } else { array.push(arguments[i]) } } return array } } Object.extend(Number.prototype, { toColorPart: function() { return this.toPaddedString(2, 16) }, succ: function() { return this + 1 }, 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' } }); $w('abs round ceil floor').each(function(method) { Number.prototype[method] = Math[method].methodize() }); function $H(object) { return new Hash(object) }; var Hash = Class.create(Enumerable, (function() { function toQueryPair(key, value) { if (Object.isUndefined(value)) return key; return key + '=' + encodeURIComponent(String.interpret(value)) } return { initialize: function(object) { this._object = Object.isHash(object) ? object.toObject() : Object.clone(object) }, _each: function(iterator) { for (var key in this._object) { var value = this._object[key], pair = [key, value]; pair.key = key; pair.value = value; iterator(pair) } }, set: function(key, value) { return this._object[key] = value }, get: function(key) { return this._object[key] }, unset: function(key) { var value = this._object[key]; delete this._object[key]; return value }, toObject: function() { return Object.clone(this._object) }, keys: function() { return this.pluck('key') }, values: function() { return this.pluck('value') }, index: function(value) { var match = this.detect(function(pair) { return pair.value === value }); return match && match.key }, merge: function(object) { return this.clone().update(object) }, update: function(object) { return new Hash(object).inject(this, function(result, pair) { result.set(pair.key, pair.value); return result }) }, toQueryString: function() { return this.map(function(pair) { var key = encodeURIComponent(pair.key), values = pair.value; if (values && typeof values == 'object') { if (Object.isArray(values)) return values.map(toQueryPair.curry(key)).join('&') } return toQueryPair(key, values) }).join('&') }, inspect: function() { return '#<Hash:{' + this.map(function(pair) { return pair.map(Object.inspect).join(': ') }).join(', ') + '}>' }, toJSON: function() { return Object.toJSON(this.toObject()) }, clone: function() { return new Hash(this) } } })()); Hash.prototype.toTemplateReplacements = Hash.prototype.toObject; Hash.from = $H; var ObjectRange = Class.create(Enumerable, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive }, _each: function(iterator) { var value = this.start; while (this.include(value)) { iterator(value); value = value.succ() } }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end } }); var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive) }; var Ajax = { getTransport: function() { return Try.these(function() { return new XMLHttpRequest() }, function() { return new ActiveXObject('Msxml2.XMLHTTP') }, function() { return new ActiveXObject('Microsoft.XMLHTTP') }) || false }, activeRequestCount: 0 }; Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator) }, 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 (Object.isFunction(responder[callback])) { try { responder[callback].apply(responder, [request, transport, json]) } catch (e) { } } }) } }; Object.extend(Ajax.Responders, Enumerable); Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++ }, onComplete: function() { Ajax.activeRequestCount-- } }); Ajax.Base = Class.create({ initialize: function(options) { this.options = { method: 'post', asynchronous: true, contentType: 'application/x-www-form-urlencoded', encoding: 'UTF-8', parameters: '', evalJSON: true, evalJS: true }; Object.extend(this.options, options || {}); this.options.method = this.options.method.toLowerCase(); if (Object.isString(this.options.parameters)) this.options.parameters = this.options.parameters.toQueryParams(); else if (Object.isHash(this.options.parameters)) this.options.parameters = this.options.parameters.toObject() } }); Ajax.Request = Class.create(Ajax.Base, { _complete: false, initialize: function($super, url, options) { $super(options); this.transport = Ajax.getTransport(); this.request(url) }, request: function(url) { this.url = url; this.method = this.options.method; var params = Object.clone(this.options.parameters); if (!['get', 'post'].include(this.method)) { params['_method'] = this.method; this.method = 'post' } this.parameters = params; if (params = Object.toQueryString(params)) { if (this.method == 'get') this.url += (this.url.include('?') ? '&' : '?') + params; else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_=' } try { var response = new Ajax.Response(this); if (this.options.onCreate) this.options.onCreate(response); Ajax.Responders.dispatch('onCreate', this, response); this.transport.open(this.method.toUpperCase(), this.url, this.options.asynchronous); if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); this.transport.onreadystatechange = this.onStateChange.bind(this); this.setRequestHeaders(); this.body = this.method == 'post' ? (this.options.postBody || params) : null; this.transport.send(this.body); if (!this.options.asynchronous && this.transport.overrideMimeType) this.onStateChange() } catch (e) { this.dispatchException(e) } }, onStateChange: function() { var readyState = this.transport.readyState; if (readyState > 1 && !((readyState == 4) && this._complete)) this.respondToReadyState(this.transport.readyState) }, 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 : ''); if (this.transport.overrideMimeType && (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0, 2005])[1] < 2005) headers['Connection'] = 'close' } if (typeof this.options.requestHeaders == 'object') { var extras = this.options.requestHeaders; if (Object.isFunction(extras.push)) 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() { var status = this.getStatus(); return !status || (status >= 200 && status < 300) }, getStatus: function() { try { return this.transport.status || 0 } catch (e) { return 0 } }, respondToReadyState: function(readyState) { var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); if (state == 'Complete') { try { this._complete = true; (this.options['on' + response.status] || this.options['on' + (this.success() ? 'Success' : 'Failure')] || Prototype.emptyFunction)(response, response.headerJSON) } catch (e) { this.dispatchException(e) } var contentType = response.getHeader('Content-type'); if (this.options.evalJS == 'force' || (this.options.evalJS && this.isSameOrigin() && contentType && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) this.evalResponse() } try { (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON) } catch (e) { this.dispatchException(e) } if (state == 'Complete') { this.transport.onreadystatechange = Prototype.emptyFunction } }, isSameOrigin: function() { var m = this.url.match(/^\s*https?:\/\/[^\/]*/); return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ protocol: location.protocol, domain: document.domain, port: location.port ? ':' + location.port : '' })) }, getHeader: function(name) { try { return this.transport.getResponseHeader(name) || null } catch (e) { return null } }, evalResponse: function() { try { return eval((this.transport.responseText || '').unfilterJSON()) } catch (e) { this.dispatchException(e) } }, dispatchException: function(exception) { (this.options.onException || Prototype.emptyFunction)(this, exception); Ajax.Responders.dispatch('onException', this, exception) } }); Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; Ajax.Response = Class.create({ initialize: function(request) { this.request = request; var transport = this.transport = request.transport, readyState = this.readyState = transport.readyState; if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { this.status = this.getStatus(); this.statusText = this.getStatusText(); this.responseText = String.interpret(transport.responseText); this.headerJSON = this._getHeaderJSON() } if (readyState == 4) { var xml = transport.responseXML; this.responseXML = Object.isUndefined(xml) ? null : xml; this.responseJSON = this._getResponseJSON() } }, status: 0, statusText: '', getStatus: Ajax.Request.prototype.getStatus, getStatusText: function() { try { return this.transport.statusText || '' } catch (e) { return '' } }, getHeader: Ajax.Request.prototype.getHeader, getAllHeaders: function() { try { return this.getAllResponseHeaders() } catch (e) { return null } }, getResponseHeader: function(name) { return this.transport.getResponseHeader(name) }, getAllResponseHeaders: function() { return this.transport.getAllResponseHeaders() }, _getHeaderJSON: function() { var json = this.getHeader('X-JSON'); if (!json) return null; json = decodeURIComponent(escape(json)); try { return json.evalJSON(this.request.options.sanitizeJSON || !this.request.isSameOrigin()) } catch (e) { this.request.dispatchException(e) } }, _getResponseJSON: function() { var options = this.request.options; if (!options.evalJSON || (options.evalJSON != 'force' && !(this.getHeader('Content-type') || '').include('application/json')) || this.responseText.blank()) return null; try { return this.responseText.evalJSON(options.sanitizeJSON || !this.request.isSameOrigin()) } catch (e) { this.request.dispatchException(e) } } }); Ajax.Updater = Class.create(Ajax.Request, { initialize: function($super, container, url, options) { this.container = { success: (container.success || container), failure: (container.failure || (container.success ? null : container)) }; options = Object.clone(options); var onComplete = options.onComplete; options.onComplete = (function(response, json) { this.updateContent(response.responseText); if (Object.isFunction(onComplete)) onComplete(response, json) }).bind(this); $super(url, options) }, updateContent: function(responseText) { var receiver = this.container[this.success() ? 'success' : 'failure'], options = this.options; if (!options.evalScripts) responseText = responseText.stripScripts(); if (receiver = $(receiver)) { if (options.insertion) { if (Object.isString(options.insertion)) { var insertion = {}; insertion[options.insertion] = responseText; receiver.insert(insertion) } else options.insertion(receiver, responseText) } else receiver.update(responseText) } } }); Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { initialize: function($super, container, url, options) { $super(options); this.onComplete = this.options.onComplete; this.frequency = (this.options.frequency || 2); this.decay = (this.options.decay || 1); this.updater = {}; this.container = container; this.url = url; this.start() }, start: function() { this.options.onComplete = this.updateComplete.bind(this); this.onTimerEvent() }, stop: function() { this.updater.options.onComplete = undefined; clearTimeout(this.timer); (this.onComplete || Prototype.emptyFunction).apply(this, arguments) }, updateComplete: function(response) { if (this.options.decay) { this.decay = (response.responseText == this.lastText ? this.decay * this.options.decay : 1); this.lastText = response.responseText } this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency) }, onTimerEvent: function() { this.updater = new Ajax.Updater(this.container, this.url, this.options) } }); function $(element) { if (arguments.length > 1) { for (var i = 0, elements = [], length = arguments.length; i < length; i++) elements.push($(arguments[i])); return elements } if (Object.isString(element)) 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(Element.extend(query.snapshotItem(i))); return results } } if (!window.Node) var Node = {}; if (!Node.ELEMENT_NODE) { Object.extend(Node, { ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5, ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12 }) } (function() { var element = this.Element; this.Element = function(tagName, attributes) { attributes = attributes || {}; tagName = tagName.toLowerCase(); var cache = Element.cache; if (Prototype.Browser.IE && attributes.name) { tagName = '<' + tagName + ' name="' + attributes.name + '">'; delete attributes.name; return Element.writeAttribute(document.createElement(tagName), attributes) } if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); return Element.writeAttribute(cache[tagName].cloneNode(false), attributes) }; Object.extend(this.Element, element || {}) }).call(window); Element.cache = {}; Element.Methods = { visible: function(element) { return $(element).style.display != 'none' }, toggle: function(element) { element = $(element); Element[Element.visible(element) ? 'hide' : 'show'](element); return element }, hide: function(element) { $(element).style.display = 'none'; return element }, show: function(element) { $(element).style.display = ''; return element }, remove: function(element) { element = $(element); element.parentNode.removeChild(element); return element }, update: function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) return element.update().insert(content); content = Object.toHTML(content); element.innerHTML = content.stripScripts(); content.evalScripts.bind(content).defer(); return element }, replace: function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); else if (!Object.isElement(content)) { content = Object.toHTML(content); var range = element.ownerDocument.createRange(); range.selectNode(element); content.evalScripts.bind(content).defer(); content = range.createContextualFragment(content.stripScripts()) } element.parentNode.replaceChild(content, element); return element }, insert: function(element, insertions) { element = $(element); if (Object.isString(insertions) || Object.isNumber(insertions) || Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) insertions = { bottom: insertions }; var content, insert, tagName, childNodes; for (var position in insertions) { content = insertions[position]; position = position.toLowerCase(); insert = Element._insertionTranslations[position]; if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) { insert(element, content); continue } content = Object.toHTML(content); tagName = ((position == 'before' || position == 'after') ? element.parentNode : element).tagName.toUpperCase(); childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); if (position == 'top' || position == 'after') childNodes.reverse(); childNodes.each(insert.curry(element)); content.evalScripts.bind(content).defer() } return element }, wrap: function(element, wrapper, attributes) { element = $(element); if (Object.isElement(wrapper)) $(wrapper).writeAttribute(attributes || {}); else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); else wrapper = new Element('div', wrapper); if (element.parentNode) element.parentNode.replaceChild(wrapper, element); wrapper.appendChild(element); return wrapper }, inspect: function(element) { element = $(element); var result = '<' + element.tagName.toLowerCase(); $H({ 'id': 'id', 'className': 'class' }).each(function(pair) { var property = pair.first(), attribute = pair.last(); var value = (element[property] || '').toString(); if (value) result += ' ' + attribute + '=' + value.inspect(true) }); return result + '>' }, recursivelyCollect: function(element, property) { element = $(element); var elements = []; while (element = element[property]) if (element.nodeType == 1) elements.push(Element.extend(element)); return elements }, ancestors: function(element) { return $(element).recursivelyCollect('parentNode') }, descendants: function(element) { return $(element).select("*") }, firstDescendant: function(element) { element = $(element).firstChild; while (element && element.nodeType != 1) element = element.nextSibling; return $(element) }, immediateDescendants: function(element) { if (!(element = $(element).firstChild)) return []; while (element && element.nodeType != 1) element = element.nextSibling; if (element) return [element].concat($(element).nextSiblings()); return [] }, previousSiblings: function(element) { return $(element).recursivelyCollect('previousSibling') }, nextSiblings: function(element) { return $(element).recursivelyCollect('nextSibling') }, siblings: function(element) { element = $(element); return element.previousSiblings().reverse().concat(element.nextSiblings()) }, match: function(element, selector) { if (Object.isString(selector)) selector = new Selector(selector); return selector.match($(element)) }, up: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(element.parentNode); var ancestors = element.ancestors(); return Object.isNumber(expression) ? ancestors[expression] : Selector.findElement(ancestors, expression, index) }, down: function(element, expression, index) { element = $(element); if (arguments.length == 1) return element.firstDescendant(); return Object.isNumber(expression) ? element.descendants()[expression] : element.select(expression)[index || 0] }, previous: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); var previousSiblings = element.previousSiblings(); return Object.isNumber(expression) ? previousSiblings[expression] : Selector.findElement(previousSiblings, expression, index) }, next: function(element, expression, index) { element = $(element); if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); var nextSiblings = element.nextSiblings(); return Object.isNumber(expression) ? nextSiblings[expression] : Selector.findElement(nextSiblings, expression, index) }, select: function() { var args = $A(arguments), element = $(args.shift()); return Selector.findChildElements(element, args) }, adjacent: function() { var args = $A(arguments), element = $(args.shift()); return Selector.findChildElements(element.parentNode, args).without(element) }, identify: function(element) { element = $(element); var id = element.readAttribute('id'), self = arguments.callee; if (id) return id; do { id = 'anonymous_element_' + self.counter++ } while ($(id)); element.writeAttribute('id', id); return id }, readAttribute: function(element, name) { element = $(element); if (Prototype.Browser.IE) { var t = Element._attributeTranslations.read; if (t.values[name]) return t.values[name](element, name); if (t.names[name]) name = t.names[name]; if (name.include(':')) { return (!element.attributes || !element.attributes[name]) ? null : element.attributes[name].value } } return element.getAttribute(name) }, writeAttribute: function(element, name, value) { element = $(element); var attributes = {}, t = Element._attributeTranslations.write; if (typeof name == 'object') attributes = name; else attributes[name] = Object.isUndefined(value) ? true : value; for (var attr in attributes) { name = t.names[attr] || attr; value = attributes[attr]; if (t.values[attr]) name = t.values[attr](element, value); if (value === false || value === null) element.removeAttribute(name); else if (value === true) element.setAttribute(name, name); else element.setAttribute(name, value) } return element }, getHeight: function(element) { return $(element).getDimensions().height }, getWidth: function(element) { return $(element).getDimensions().width }, classNames: function(element) { return new Element.ClassNames(element) }, hasClassName: function(element, className) { if (!(element = $(element))) return; var elementClassName = element.className; return (elementClassName.length > 0 && (elementClassName == className || new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))) }, addClassName: function(element, className) { if (!(element = $(element))) return; if (!element.hasClassName(className)) element.className += (element.className ? ' ' : '') + className; return element }, removeClassName: function(element, className) { if (!(element = $(element))) return; element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); return element }, toggleClassName: function(element, className) { if (!(element = $(element))) return; return element[element.hasClassName(className) ? 'removeClassName' : 'addClassName'](className) }, cleanWhitespace: function(element) { element = $(element); var node = element.firstChild; while (node) { var nextNode = node.nextSibling; if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) element.removeChild(node); node = nextNode } return element }, empty: function(element) { return $(element).innerHTML.blank() }, descendantOf: function(element, ancestor) { element = $(element), ancestor = $(ancestor); var originalAncestor = ancestor; if (element.compareDocumentPosition) return (element.compareDocumentPosition(ancestor) & 8) === 8; if (element.sourceIndex && !Prototype.Browser.Opera) { var e = element.sourceIndex, a = ancestor.sourceIndex, nextAncestor = ancestor.nextSibling; if (!nextAncestor) { do { ancestor = ancestor.parentNode } while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode) } if (nextAncestor && nextAncestor.sourceIndex) return (e > a && e < nextAncestor.sourceIndex) } while (element = element.parentNode) if (element == originalAncestor) return true; return false }, scrollTo: function(element) { element = $(element); var pos = element.cumulativeOffset(); window.scrollTo(pos[0], pos[1]); return element }, getStyle: function(element, style)
	{
		element = $(element); style = style == 'float' ? 'cssFloat' : style.camelize(); var value = (element.style ? element.style[style] : '');
		if (!value) { var css = document.defaultView.getComputedStyle(element, null); value = css ? css[style] : null } if (style == 'opacity') return value ? parseFloat(value) : 1.0; return value == 'auto' ? null : value
	}, getOpacity: function(element) { return $(element).getStyle('opacity') }, setStyle: function(element, styles) { element = $(element); var elementStyle = element.style, match; if (Object.isString(styles)) { element.style.cssText += ';' + styles; return styles.include('opacity') ? element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element } for (var property in styles) if (property == 'opacity') element.setOpacity(styles[property]); else elementStyle[(property == 'float' || property == 'cssFloat') ? (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : property] = styles[property]; return element }, setOpacity: function(element, value) { element = $(element); element.style.opacity = (value == 1 || value === '') ? '' : (value < 0.00001) ? 0 : value; return element }, getDimensions: function(element) { element = $(element); var display = $(element).getStyle('display'); if (display != 'none' && display != null) return { width: element.offsetWidth, height: element.offsetHeight }; var els = element.style; var originalVisibility = els.visibility; var originalPosition = els.position; var originalDisplay = els.display; els.visibility = 'hidden'; els.position = 'absolute'; els.display = 'block'; var originalWidth = element.clientWidth; var originalHeight = element.clientHeight; els.display = originalDisplay; els.position = originalPosition; els.visibility = originalVisibility; return { width: originalWidth, height: originalHeight} }, makePositioned: function(element) { element = $(element); var pos = Element.getStyle(element, 'position'); if (pos == 'static' || !pos) { element._madePositioned = true; element.style.position = 'relative'; if (window.opera) { element.style.top = 0; element.style.left = 0 } } return element }, undoPositioned: function(element) { element = $(element); if (element._madePositioned) { element._madePositioned = undefined; element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '' } return element }, makeClipping: function(element) { element = $(element); if (element._overflow) return element; element._overflow = Element.getStyle(element, 'overflow') || 'auto'; if (element._overflow !== 'hidden') element.style.overflow = 'hidden'; return element }, undoClipping: function(element) { element = $(element); if (!element._overflow) return element; element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; element._overflow = null; return element }, cumulativeOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent } while (element); return Element._returnOffset(valueL, valueT) }, positionedOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; if (element) { if (element.tagName == 'BODY') break; var p = Element.getStyle(element, 'position'); if (p !== 'static') break } } while (element); return Element._returnOffset(valueL, valueT) }, absolutize: function(element) { element = $(element); if (element.getStyle('position') == 'absolute') return; var offsets = element.positionedOffset(); var top = offsets[1]; var left = offsets[0]; var width = element.clientWidth; var height = element.clientHeight; element._originalLeft = left - parseFloat(element.style.left || 0); element._originalTop = top - parseFloat(element.style.top || 0); element._originalWidth = element.style.width; element._originalHeight = element.style.height; element.style.position = 'absolute'; element.style.top = top + 'px'; element.style.left = left + 'px'; element.style.width = width + 'px'; element.style.height = height + 'px'; return element }, relativize: function(element) { element = $(element); if (element.getStyle('position') == 'relative') return; element.style.position = 'relative'; var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); element.style.top = top + 'px'; element.style.left = left + 'px'; element.style.height = element._originalHeight; element.style.width = element._originalWidth; return element }, cumulativeScrollOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.scrollTop || 0; valueL += element.scrollLeft || 0; element = element.parentNode } while (element); return Element._returnOffset(valueL, valueT) }, getOffsetParent: function(element) { if (element.offsetParent) return $(element.offsetParent); if (element == document.body) return $(element); while ((element = element.parentNode) && element != document.body) if (Element.getStyle(element, 'position') != 'static') return $(element); return $(document.body) }, viewportOffset: function(forElement) { var valueT = 0, valueL = 0; var element = forElement; try { do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; if (element.offsetParent == document.body && Element.getStyle(element, 'position') == 'absolute') break } while (element = element.offsetParent); element = forElement; do { if (!Prototype.Browser.Opera || element.tagName == 'BODY') { valueT -= element.scrollTop || 0; valueL -= element.scrollLeft || 0 } } while (element = element.parentNode) } catch (ex) { } return Element._returnOffset(valueL, valueT) }, clonePosition: function(element, source) { var options = Object.extend({ setLeft: true, setTop: true, setWidth: true, setHeight: true, offsetTop: 0, offsetLeft: 0 }, arguments[2] || {}); source = $(source); var p = source.viewportOffset(); element = $(element); var delta = [0, 0]; var parent = null; if (Element.getStyle(element, 'position') == 'absolute') { parent = element.getOffsetParent(); delta = parent.viewportOffset() } if (parent == document.body) { delta[0] -= document.body.offsetLeft; delta[1] -= document.body.offsetTop } if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; if (options.setWidth) element.style.width = source.offsetWidth + 'px'; if (options.setHeight) element.style.height = source.offsetHeight + 'px'; return element }
}; Element.Methods.identify.counter = 1; Object.extend(Element.Methods, { getElementsBySelector: Element.Methods.select, childElements: Element.Methods.immediateDescendants }); Element._attributeTranslations = { write: { names: { className: 'class', htmlFor: 'for' }, values: {}} }; if (Prototype.Browser.Opera) { Element.Methods.getStyle = Element.Methods.getStyle.wrap(function(proceed, element, style) { switch (style) { case 'left': case 'top': case 'right': case 'bottom': if (proceed(element, 'position') === 'static') return null; case 'height': case 'width': if (!Element.visible(element)) return null; var dim = parseInt(proceed(element, style), 10); if (dim !== element['offset' + style.capitalize()]) return dim + 'px'; var properties; if (style === 'height') { properties = ['border-top-width', 'padding-top', 'padding-bottom', 'border-bottom-width'] } else { properties = ['border-left-width', 'padding-left', 'padding-right', 'border-right-width'] } return properties.inject(dim, function(memo, property) { var val = proceed(element, property); return val === null ? memo : memo - parseInt(val, 10) }) + 'px'; default: return proceed(element, style) } }); Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(function(proceed, element, attribute) { if (attribute === 'title') return element.title; return proceed(element, attribute) }) } else if (Prototype.Browser.IE)
{
	Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(function(proceed, element) { element = $(element); var position = element.getStyle('position'); if (position !== 'static') return proceed(element); element.setStyle({ position: 'relative' }); var value = proceed(element); element.setStyle({ position: position }); return value }); $w('positionedOffset viewportOffset').each(function(method) { Element.Methods[method] = Element.Methods[method].wrap(function(proceed, element) { element = $(element); var position = element.getStyle('position'); if (position !== 'static') return proceed(element); var offsetParent = element.getOffsetParent(); if (offsetParent && offsetParent.getStyle && offsetParent.getStyle('position') === 'fixed') offsetParent.setStyle({ zoom: 1 }); element.setStyle({ position: 'relative' }); var value = proceed(element); element.setStyle({ position: position }); return value }) }); Element.Methods.getStyle = function(element, style)
	{
		element = $(element); style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); var value = (element.style ? element.style[style] : '');
		if (!value && element.currentStyle) value = element.currentStyle[style]; if (style == 'opacity') { if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) if (value[1]) return parseFloat(value[1]) / 100; return 1.0 } if (value == 'auto') { if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) return element['offset' + style.capitalize()] + 'px'; return null } return value
	}; Element.Methods.setOpacity = function(element, value) { function stripAlpha(filter) { return filter.replace(/alpha\([^\)]*\)/gi, '') } element = $(element); var currentStyle = element.currentStyle; if ((currentStyle && !currentStyle.hasLayout) || (!currentStyle && element.style.zoom == 'normal')) element.style.zoom = 1; var filter = element.getStyle('filter'), style = element.style; if (value == 1 || value === '') { (filter = stripAlpha(filter)) ? style.filter = filter : style.removeAttribute('filter'); return element } else if (value < 0.00001) value = 0; style.filter = stripAlpha(filter) + 'alpha(opacity=' + (value * 100) + ')'; return element }; Element._attributeTranslations = { read: { names: { 'class': 'className', 'for': 'htmlFor' }, values: { _getAttr: function(element, attribute) { return element.getAttribute(attribute, 2) }, _getAttrNode: function(element, attribute) { var node = element.getAttributeNode(attribute); return node ? node.value : "" }, _getEv: function(element, attribute) { attribute = element.getAttribute(attribute); return attribute ? attribute.toString().slice(23, -2) : null }, _flag: function(element, attribute) { return $(element).hasAttribute(attribute) ? attribute : null }, style: function(element) { return element.style.cssText.toLowerCase() }, title: function(element) { return element.title } }} }; Element._attributeTranslations.write = { names: Object.extend({ cellpadding: 'cellPadding', cellspacing: 'cellSpacing' }, Element._attributeTranslations.read.names), values: { checked: function(element, value) { element.checked = !!value }, style: function(element, value) { element.style.cssText = value ? value : '' } } }; Element._attributeTranslations.has = {}; $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + 'encType maxLength readOnly longDesc').each(function(attr) { Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; Element._attributeTranslations.has[attr.toLowerCase()] = attr }); (function(v) { Object.extend(v, { href: v._getAttr, src: v._getAttr, type: v._getAttr, action: v._getAttrNode, disabled: v._flag, checked: v._flag, readonly: v._flag, multiple: v._flag, onload: v._getEv, onunload: v._getEv, onclick: v._getEv, ondblclick: v._getEv, onmousedown: v._getEv, onmouseup: v._getEv, onmouseover: v._getEv, onmousemove: v._getEv, onmouseout: v._getEv, onfocus: v._getEv, onblur: v._getEv, onkeypress: v._getEv, onkeydown: v._getEv, onkeyup: v._getEv, onsubmit: v._getEv, onreset: v._getEv, onselect: v._getEv, onchange: v._getEv }) })(Element._attributeTranslations.read.values)
} else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { Element.Methods.setOpacity = function(element, value) { element = $(element); element.style.opacity = (value == 1) ? 0.999999 : (value === '') ? '' : (value < 0.00001) ? 0 : value; return element } } else if (Prototype.Browser.WebKit) { Element.Methods.setOpacity = function(element, value) { element = $(element); element.style.opacity = (value == 1 || value === '') ? '' : (value < 0.00001) ? 0 : value; if (value == 1) if (element.tagName == 'IMG' && element.width) { element.width++; element.width-- } else try { var n = document.createTextNode(' '); element.appendChild(n); element.removeChild(n) } catch (e) { } return element }; Element.Methods.cumulativeOffset = function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; if (element.offsetParent == document.body) if (Element.getStyle(element, 'position') == 'absolute') break; element = element.offsetParent } while (element); return Element._returnOffset(valueL, valueT) } } if (Prototype.Browser.IE || Prototype.Browser.Opera) { Element.Methods.update = function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) return element.update().insert(content); content = Object.toHTML(content); var tagName = element.tagName.toUpperCase(); if (tagName in Element._insertionTranslations.tags) { $A(element.childNodes).each(function(node) { element.removeChild(node) }); Element._getContentFromAnonymousElement(tagName, content.stripScripts()).each(function(node) { element.appendChild(node) }) } else element.innerHTML = content.stripScripts(); content.evalScripts.bind(content).defer(); return element } } if ('outerHTML' in document.createElement('div')) { Element.Methods.replace = function(element, content) { element = $(element); if (content && content.toElement) content = content.toElement(); if (Object.isElement(content)) { element.parentNode.replaceChild(content, element); return element } content = Object.toHTML(content); var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); if (Element._insertionTranslations.tags[tagName]) { var nextSibling = element.next(); var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); parent.removeChild(element); if (nextSibling) fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); else fragments.each(function(node) { parent.appendChild(node) }) } else element.outerHTML = content.stripScripts(); content.evalScripts.bind(content).defer(); return element } } Element._returnOffset = function(l, t) { var result = [l, t]; result.left = l; result.top = t; return result }; Element._getContentFromAnonymousElement = function(tagName, html) { var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; if (t) { div.innerHTML = t[0] + html + t[1]; t[2].times(function() { div = div.firstChild }) } else div.innerHTML = html; return $A(div.childNodes) }; Element._insertionTranslations = { before: function(element, node) { element.parentNode.insertBefore(node, element) }, top: function(element, node) { element.insertBefore(node, element.firstChild) }, bottom: function(element, node) { element.appendChild(node) }, after: function(element, node) { element.parentNode.insertBefore(node, element.nextSibling) }, tags: { TABLE: ['<table>', '</table>', 1], TBODY: ['<table><tbody>', '</tbody></table>', 2], TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3], TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4], SELECT: ['<select>', '</select>', 1]} }; (function() { Object.extend(this.tags, { THEAD: this.tags.TBODY, TFOOT: this.tags.TBODY, TH: this.tags.TD }) }).call(Element._insertionTranslations); Element.Methods.Simulated = { hasAttribute: function(element, attribute) { attribute = Element._attributeTranslations.has[attribute] || attribute; var node = $(element).getAttributeNode(attribute); return node && node.specified } }; Element.Methods.ByTag = {}; Object.extend(Element, Element.Methods); if (!Prototype.BrowserFeatures.ElementExtensions && document.createElement('div').__proto__) { window.HTMLElement = {}; window.HTMLElement.prototype = document.createElement('div').__proto__; Prototype.BrowserFeatures.ElementExtensions = true } Element.extend = (function() { if (Prototype.BrowserFeatures.SpecificElementExtensions) return Prototype.K; var Methods = {}, ByTag = Element.Methods.ByTag; var extend = Object.extend(function(element) { if (!element || element._extendedByPrototype || element.nodeType != 1 || element == window) return element; var methods = Object.clone(Methods), tagName = element.tagName, property, value; if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); for (property in methods) { value = methods[property]; if (Object.isFunction(value) && !(property in element)) element[property] = value.methodize() } element._extendedByPrototype = Prototype.emptyFunction; return element }, { refresh: function() { if (!Prototype.BrowserFeatures.ElementExtensions) { Object.extend(Methods, Element.Methods); Object.extend(Methods, Element.Methods.Simulated) } } }); extend.refresh(); return extend })(); Element.hasAttribute = function(element, attribute) { if (element.hasAttribute) return element.hasAttribute(attribute); return Element.Methods.Simulated.hasAttribute(element, attribute) }; Element.addMethods = function(methods) { var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; if (!methods) { Object.extend(Form, Form.Methods); Object.extend(Form.Element, Form.Element.Methods); Object.extend(Element.Methods.ByTag, { "FORM": Object.clone(Form.Methods), "INPUT": Object.clone(Form.Element.Methods), "SELECT": Object.clone(Form.Element.Methods), "TEXTAREA": Object.clone(Form.Element.Methods) }) } if (arguments.length == 2) { var tagName = methods; methods = arguments[1] } if (!tagName) Object.extend(Element.Methods, methods || {}); else { if (Object.isArray(tagName)) tagName.each(extend); else extend(tagName) } function extend(tagName) { tagName = tagName.toUpperCase(); if (!Element.Methods.ByTag[tagName]) Element.Methods.ByTag[tagName] = {}; Object.extend(Element.Methods.ByTag[tagName], methods) } function copy(methods, destination, onlyIfAbsent) { onlyIfAbsent = onlyIfAbsent || false; for (var property in methods) { var value = methods[property]; if (!Object.isFunction(value)) continue; if (!onlyIfAbsent || !(property in destination)) destination[property] = value.methodize() } } function findDOMClass(tagName) { var klass; var trans = { "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": "FrameSet", "IFRAME": "IFrame" }; if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; if (window[klass]) return window[klass]; klass = 'HTML' + tagName + 'Element'; if (window[klass]) return window[klass]; klass = 'HTML' + tagName.capitalize() + 'Element'; if (window[klass]) return window[klass]; window[klass] = {}; window[klass].prototype = document.createElement(tagName).__proto__; return window[klass] } if (F.ElementExtensions) { copy(Element.Methods, HTMLElement.prototype); copy(Element.Methods.Simulated, HTMLElement.prototype, true) } if (F.SpecificElementExtensions) { for (var tag in Element.Methods.ByTag) { var klass = findDOMClass(tag); if (Object.isUndefined(klass)) continue; copy(T[tag], klass.prototype) } } Object.extend(Element, Element.Methods); delete Element.ByTag; if (Element.extend.refresh) Element.extend.refresh(); Element.cache = {} }; document.viewport = { getDimensions: function() { var dimensions = {}; var B = Prototype.Browser; $w('width height').each(function(d) { var D = d.capitalize(); dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] : (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D] }); return dimensions }, getWidth: function() { return this.getDimensions().width }, getHeight: function() { return this.getDimensions().height }, getScrollOffsets: function() { return Element._returnOffset(window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop) } }; var Selector = Class.create({ initialize: function(expression) { this.expression = expression.strip(); this.compileMatcher() }, shouldUseXPath: function() { if (!Prototype.BrowserFeatures.XPath) return false; var e = this.expression; if (Prototype.Browser.WebKit && (e.include("-of-type") || e.include(":empty"))) return false; if ((/(\[[\w-]*?:|:checked)/).test(this.expression)) return false; return true }, compileMatcher: function() { if (this.shouldUseXPath()) return this.compileXPathMatcher(); var e = this.expression, ps = Selector.patterns, h = Selector.handlers, c = Selector.criteria, le, p, m; if (Selector._cache[e]) { this.matcher = Selector._cache[e]; return } this.matcher = ["this.matcher = function(root) {", "var r = root, h = Selector.handlers, c = false, n;"]; while (e && le != e && (/\S/).test(e)) { le = e; for (var i in ps) { p = ps[i]; if (m = e.match(p)) { this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : new Template(c[i]).evaluate(m)); e = e.replace(m[0], ''); break } } } this.matcher.push("return h.unique(n);\n}"); eval(this.matcher.join('\n')); Selector._cache[this.expression] = this.matcher }, compileXPathMatcher: function() { var e = this.expression, ps = Selector.patterns, x = Selector.xpath, le, m; if (Selector._cache[e]) { this.xpath = Selector._cache[e]; return } this.matcher = ['.//*']; while (e && le != e && (/\S/).test(e)) { le = e; for (var i in ps) { if (m = e.match(ps[i])) { this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m)); e = e.replace(m[0], ''); break } } } this.xpath = this.matcher.join(''); Selector._cache[this.expression] = this.xpath }, findElements: function(root) { root = root || document; if (this.xpath) return document._getElementsByXPath(this.xpath, root); return this.matcher(root) }, match: function(element) { this.tokens = []; var e = this.expression, ps = Selector.patterns, as = Selector.assertions; var le, p, m; while (e && le !== e && (/\S/).test(e)) { le = e; for (var i in ps) { p = ps[i]; if (m = e.match(p)) { if (as[i]) { this.tokens.push([i, Object.clone(m)]); e = e.replace(m[0], '') } else { return this.findElements(document).include(element) } } } } var match = true, name, matches; for (var i = 0, token; token = this.tokens[i]; i++) { name = token[0], matches = token[1]; if (!Selector.assertions[name](element, matches)) { match = false; break } } return match }, toString: function() { return this.expression }, inspect: function() { return "#<Selector:" + this.expression.inspect() + ">" } }); Object.extend(Selector, { _cache: {}, xpath: { descendant: "//*", child: "/*", adjacent: "/following-sibling::*[1]", laterSibling: '/following-sibling::*', tagName: function(m) { if (m[1] == '*') return ''; return "[local-name()='" + m[1].toLowerCase() + "' or local-name()='" + m[1].toUpperCase() + "']" }, className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", id: "[@id='#{1}']", attrPresence: function(m) { m[1] = m[1].toLowerCase(); return new Template("[@#{1}]").evaluate(m) }, attr: function(m) { m[1] = m[1].toLowerCase(); m[3] = m[5] || m[6]; return new Template(Selector.xpath.operators[m[2]]).evaluate(m) }, pseudo: function(m) { var h = Selector.xpath.pseudos[m[1]]; if (!h) return ''; if (Object.isFunction(h)) return h(m); return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m) }, operators: { '=': "[@#{1}='#{3}']", '!=': "[@#{1}!='#{3}']", '^=': "[starts-with(@#{1}, '#{3}')]", '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", '*=': "[contains(@#{1}, '#{3}')]", '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" }, pseudos: { 'first-child': '[not(preceding-sibling::*)]', 'last-child': '[not(following-sibling::*)]', 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", 'checked': "[@checked]", 'disabled': "[@disabled]", 'enabled': "[not(@disabled)]", 'not': function(m) { var e = m[6], p = Selector.patterns, x = Selector.xpath, le, v; var exclusion = []; while (e && le != e && (/\S/).test(e)) { le = e; for (var i in p) { if (m = e.match(p[i])) { v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); exclusion.push("(" + v.substring(1, v.length - 1) + ")"); e = e.replace(m[0], ''); break } } } return "[not(" + exclusion.join(" and ") + ")]" }, 'nth-child': function(m) { return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m) }, 'nth-last-child': function(m) { return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m) }, 'nth-of-type': function(m) { return Selector.xpath.pseudos.nth("position() ", m) }, 'nth-last-of-type': function(m) { return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m) }, 'first-of-type': function(m) { m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m) }, 'last-of-type': function(m) { m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m) }, 'only-of-type': function(m) { var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m) }, nth: function(fragment, m) { var mm, formula = m[6], predicate; if (formula == 'even') formula = '2n+0'; if (formula == 'odd') formula = '2n+1'; if (mm = formula.match(/^(\d+)$/)) return '[' + fragment + "= " + mm[1] + ']'; if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { if (mm[1] == "-") mm[1] = -1; var a = mm[1] ? Number(mm[1]) : 1; var b = mm[2] ? Number(mm[2]) : 0; predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + "((#{fragment} - #{b}) div #{a} >= 0)]"; return new Template(predicate).evaluate({ fragment: fragment, a: a, b: b }) } } } }, criteria: { tagName: 'n = h.tagName(n, r, "#{1}", c);      c = false;', className: 'n = h.className(n, r, "#{1}", c);    c = false;', id: 'n = h.id(n, r, "#{1}", c);           c = false;', attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', attr: function(m) { m[3] = (m[5] || m[6]); return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m) }, pseudo: function(m) { if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m) }, descendant: 'c = "descendant";', child: 'c = "child";', adjacent: 'c = "adjacent";', laterSibling: 'c = "laterSibling";' }, patterns: { laterSibling: /^\s*~\s*/, child: /^\s*>\s*/, adjacent: /^\s*\+\s*/, descendant: /^\s/, tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, id: /^#([\w\-\*]+)(\b|$)/, className: /^\.([\w\-\*]+)(\b|$)/, pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/, attrPresence: /^\[([\w]+)\]/, attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ }, assertions: { tagName: function(element, matches) { return matches[1].toUpperCase() == element.tagName.toUpperCase() }, className: function(element, matches) { return Element.hasClassName(element, matches[1]) }, id: function(element, matches) { return element.id === matches[1] }, attrPresence: function(element, matches) { return Element.hasAttribute(element, matches[1]) }, attr: function(element, matches) { var nodeValue = Element.readAttribute(element, matches[1]); return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]) } }, handlers: { concat: function(a, b) { for (var i = 0, node; node = b[i]; i++) a.push(node); return a }, mark: function(nodes) { var _true = Prototype.emptyFunction; for (var i = 0, node; node = nodes[i]; i++) node._countedByPrototype = _true; return nodes }, unmark: function(nodes) { for (var i = 0, node; node = nodes[i]; i++) node._countedByPrototype = undefined; return nodes }, index: function(parentNode, reverse, ofType) { parentNode._countedByPrototype = Prototype.emptyFunction; if (reverse) { for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { var node = nodes[i]; if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++ } } else { for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++ } }, unique: function(nodes) { if (nodes.length == 0) return nodes; var results = [], n; for (var i = 0, l = nodes.length; i < l; i++) if (!(n = nodes[i])._countedByPrototype) { n._countedByPrototype = Prototype.emptyFunction; results.push(Element.extend(n)) } return Selector.handlers.unmark(results) }, descendant: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) h.concat(results, node.getElementsByTagName('*')); return results }, child: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) { for (var j = 0, child; child = node.childNodes[j]; j++) if (child.nodeType == 1 && child.tagName != '!') results.push(child) } return results }, adjacent: function(nodes) { for (var i = 0, results = [], node; node = nodes[i]; i++) { var next = this.nextElementSibling(node); if (next) results.push(next) } return results }, laterSibling: function(nodes) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) h.concat(results, Element.nextSiblings(node)); return results }, nextElementSibling: function(node) { while (node = node.nextSibling) if (node.nodeType == 1) return node; return null }, previousElementSibling: function(node) { while (node = node.previousSibling) if (node.nodeType == 1) return node; return null }, tagName: function(nodes, root, tagName, combinator) { var uTagName = tagName.toUpperCase(); var results = [], h = Selector.handlers; if (nodes) { if (combinator) { if (combinator == "descendant") { for (var i = 0, node; node = nodes[i]; i++) h.concat(results, node.getElementsByTagName(tagName)); return results } else nodes = this[combinator](nodes); if (tagName == "*") return nodes } for (var i = 0, node; node = nodes[i]; i++) if (node.tagName.toUpperCase() === uTagName) results.push(node); return results } else return root.getElementsByTagName(tagName) }, id: function(nodes, root, id, combinator) { var targetNode = $(id), h = Selector.handlers; if (!targetNode) return []; if (!nodes && root == document) return [targetNode]; if (nodes) { if (combinator) { if (combinator == 'child') { for (var i = 0, node; node = nodes[i]; i++) if (targetNode.parentNode == node) return [targetNode] } else if (combinator == 'descendant') { for (var i = 0, node; node = nodes[i]; i++) if (Element.descendantOf(targetNode, node)) return [targetNode] } else if (combinator == 'adjacent') { for (var i = 0, node; node = nodes[i]; i++) if (Selector.handlers.previousElementSibling(targetNode) == node) return [targetNode] } else nodes = h[combinator](nodes) } for (var i = 0, node; node = nodes[i]; i++) if (node == targetNode) return [targetNode]; return [] } return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [] }, className: function(nodes, root, className, combinator) { if (nodes && combinator) nodes = this[combinator](nodes); return Selector.handlers.byClassName(nodes, root, className) }, byClassName: function(nodes, root, className) { if (!nodes) nodes = Selector.handlers.descendant([root]); var needle = ' ' + className + ' '; for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { nodeClassName = node.className; if (nodeClassName.length == 0) continue; if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) results.push(node) } return results }, attrPresence: function(nodes, root, attr, combinator) { if (!nodes) nodes = root.getElementsByTagName("*"); if (nodes && combinator) nodes = this[combinator](nodes); var results = []; for (var i = 0, node; node = nodes[i]; i++) if (Element.hasAttribute(node, attr)) results.push(node); return results }, attr: function(nodes, root, attr, value, operator, combinator) { if (!nodes) nodes = root.getElementsByTagName("*"); if (nodes && combinator) nodes = this[combinator](nodes); var handler = Selector.operators[operator], results = []; for (var i = 0, node; node = nodes[i]; i++) { var nodeValue = Element.readAttribute(node, attr); if (nodeValue === null) continue; if (handler(nodeValue, value)) results.push(node) } return results }, pseudo: function(nodes, name, value, root, combinator) { if (nodes && combinator) nodes = this[combinator](nodes); if (!nodes) nodes = root.getElementsByTagName("*"); return Selector.pseudos[name](nodes, value, root) } }, pseudos: { 'first-child': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { if (Selector.handlers.previousElementSibling(node)) continue; results.push(node) } return results }, 'last-child': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { if (Selector.handlers.nextElementSibling(node)) continue; results.push(node) } return results }, 'only-child': function(nodes, value, root) { var h = Selector.handlers; for (var i = 0, results = [], node; node = nodes[i]; i++) if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) results.push(node); return results }, 'nth-child': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root) }, 'nth-last-child': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root, true) }, 'nth-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root, false, true) }, 'nth-last-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, formula, root, true, true) }, 'first-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, "1", root, false, true) }, 'last-of-type': function(nodes, formula, root) { return Selector.pseudos.nth(nodes, "1", root, true, true) }, 'only-of-type': function(nodes, formula, root) { var p = Selector.pseudos; return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root) }, getIndices: function(a, b, total) { if (a == 0) return b > 0 ? [b] : []; return $R(1, total).inject([], function(memo, i) { if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); return memo }) }, nth: function(nodes, formula, root, reverse, ofType) { if (nodes.length == 0) return []; if (formula == 'even') formula = '2n+0'; if (formula == 'odd') formula = '2n+1'; var h = Selector.handlers, results = [], indexed = [], m; h.mark(nodes); for (var i = 0, node; node = nodes[i]; i++) { if (!node.parentNode._countedByPrototype) { h.index(node.parentNode, reverse, ofType); indexed.push(node.parentNode) } } if (formula.match(/^\d+$/)) { formula = Number(formula); for (var i = 0, node; node = nodes[i]; i++) if (node.nodeIndex == formula) results.push(node) } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { if (m[1] == "-") m[1] = -1; var a = m[1] ? Number(m[1]) : 1; var b = m[2] ? Number(m[2]) : 0; var indices = Selector.pseudos.getIndices(a, b, nodes.length); for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { for (var j = 0; j < l; j++) if (node.nodeIndex == indices[j]) results.push(node) } } h.unmark(nodes); h.unmark(indexed); return results }, 'empty': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) { if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; results.push(node) } return results }, 'not': function(nodes, selector, root) { var h = Selector.handlers, selectorType, m; var exclusions = new Selector(selector).findElements(root); h.mark(exclusions); for (var i = 0, results = [], node; node = nodes[i]; i++) if (!node._countedByPrototype) results.push(node); h.unmark(exclusions); return results }, 'enabled': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) if (!node.disabled) results.push(node); return results }, 'disabled': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) if (node.disabled) results.push(node); return results }, 'checked': function(nodes, value, root) { for (var i = 0, results = [], node; node = nodes[i]; i++) if (node.checked) results.push(node); return results } }, operators: { '=': function(nv, v) { return nv == v }, '!=': function(nv, v) { return nv != v }, '^=': function(nv, v) { return nv.startsWith(v) }, '$=': function(nv, v) { return nv.endsWith(v) }, '*=': function(nv, v) { return nv.include(v) }, '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' ') }, '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-') } }, split: function(expression) { var expressions = []; expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { expressions.push(m[1].strip()) }); return expressions }, matchElements: function(elements, expression) { var matches = $$(expression), h = Selector.handlers; h.mark(matches); for (var i = 0, results = [], element; element = elements[i]; i++) if (element._countedByPrototype) results.push(element); h.unmark(matches); return results }, findElement: function(elements, expression, index) { if (Object.isNumber(expression)) { index = expression; expression = false } return Selector.matchElements(elements, expression || '*')[index || 0] }, findChildElements: function(element, expressions) { expressions = Selector.split(expressions.join(',')); var results = [], h = Selector.handlers; for (var i = 0, l = expressions.length, selector; i < l; i++) { selector = new Selector(expressions[i].strip()); h.concat(results, selector.findElements(element)) } return (l > 1) ? h.unique(results) : results } }); if (Prototype.Browser.IE) { Object.extend(Selector.handlers, { concat: function(a, b) { for (var i = 0, node; node = b[i]; i++) if (node.tagName !== "!") a.push(node); return a }, unmark: function(nodes) { for (var i = 0, node; node = nodes[i]; i++) node.removeAttribute('_countedByPrototype'); return nodes } }) } function $$() { return Selector.findChildElements(document, $A(arguments)) } var Form = { reset: function(form) { $(form).reset(); return form }, serializeElements: function(elements, options) { if (typeof options != 'object') options = { hash: !!options }; else if (Object.isUndefined(options.hash)) options.hash = true; var key, value, submitted = false, submit = options.submit; var data = elements.inject({}, function(result, element) { if (!element.disabled && element.name) { key = element.name; value = $(element).getValue(); if (value != null && (element.type != 'submit' || (!submitted && submit !== false && (!submit || key == submit) && (submitted = true)))) { if (key in result) { if (!Object.isArray(result[key])) result[key] = [result[key]]; result[key].push(value) } else result[key] = value } } return result }); return options.hash ? data : Object.toQueryString(data) } }; Form.Methods = { serialize: function(form, options) { return Form.serializeElements(Form.getElements(form), options) }, getElements: function(form) { return $A($(form).getElementsByTagName('*')).inject([], function(elements, child) { if (Form.Element.Serializers[child.tagName.toLowerCase()]) elements.push(Element.extend(child)); return elements }) }, getInputs: function(form, typeName, name) { form = $(form); var inputs = form.getElementsByTagName('input'); if (!typeName && !name) return $A(inputs).map(Element.extend); for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { var input = inputs[i]; if ((typeName && input.type != typeName) || (name && input.name != name)) continue; matchingInputs.push(Element.extend(input)) } return matchingInputs }, disable: function(form) { form = $(form); Form.getElements(form).invoke('disable'); return form }, enable: function(form) { form = $(form); Form.getElements(form).invoke('enable'); return form }, findFirstElement: function(form) { var elements = $(form).getElements().findAll(function(element) { return 'hidden' != element.type && !element.disabled }); var firstByIndex = elements.findAll(function(element) { return element.hasAttribute('tabIndex') && element.tabIndex >= 0 }).sortBy(function(element) { return element.tabIndex }).first(); return firstByIndex ? firstByIndex : elements.find(function(element) { return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()) }) }, focusFirstElement: function(form) { form = $(form); form.findFirstElement().activate(); return form }, request: function(form, options) { form = $(form), options = Object.clone(options || {}); var params = options.parameters, action = form.readAttribute('action') || ''; if (action.blank()) action = window.location.href; options.parameters = form.serialize(true); if (params) { if (Object.isString(params)) params = params.toQueryParams(); Object.extend(options.parameters, params) } if (form.hasAttribute('method') && !options.method) options.method = form.method; return new Ajax.Request(action, options) } }; Form.Element = { focus: function(element) { $(element).focus(); return element }, select: function(element) { $(element).select(); return element } }; Form.Element.Methods = { serialize: function(element) { element = $(element); if (!element.disabled && element.name) { var value = element.getValue(); if (value != undefined) { var pair = {}; pair[element.name] = value; return Object.toQueryString(pair) } } return '' }, getValue: function(element) { element = $(element); var method = element.tagName.toLowerCase(); return Form.Element.Serializers[method](element) }, setValue: function(element, value) { element = $(element); var method = element.tagName.toLowerCase(); Form.Element.Serializers[method](element, value); return element }, clear: function(element) { $(element).value = ''; return element }, present: function(element) { return $(element).value != '' }, activate: function(element) { element = $(element); try { element.focus(); if (element.select && (element.tagName.toLowerCase() != 'input' || !['button', 'reset', 'submit'].include(element.type))) element.select() } catch (e) { } return element }, disable: function(element) { element = $(element); element.blur(); element.disabled = true; return element }, enable: function(element) { element = $(element); element.disabled = false; return element } }; var Field = Form.Element; var $F = Form.Element.Methods.getValue; Form.Element.Serializers = { input: function(element, value) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': return Form.Element.Serializers.inputSelector(element, value); default: return Form.Element.Serializers.textarea(element, value) } }, inputSelector: function(element, value) { if (Object.isUndefined(value)) return element.checked ? element.value : null; else element.checked = !!value }, textarea: function(element, value) { if (Object.isUndefined(value)) return element.value; else element.value = value }, select: function(element, index) { if (Object.isUndefined(index)) return this[element.type == 'select-one' ? 'selectOne' : 'selectMany'](element); else { var opt, value, single = !Object.isArray(index); for (var i = 0, length = element.length; i < length; i++) { opt = element.options[i]; value = this.optionValue(opt); if (single) { if (value == index) { opt.selected = true; return } } else opt.selected = index.include(value) } } }, selectOne: function(element) { var index = element.selectedIndex; return index >= 0 ? this.optionValue(element.options[index]) : null }, selectMany: function(element) { var values, length = element.length; if (!length) return null; for (var i = 0, values = []; i < length; i++) { var opt = element.soptions[i]; if (opt.selected) values.push(this.optionValue(opt)) } return values }, optionValue: function(opt) { return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text } }; Abstract.TimedObserver = Class.create(PeriodicalExecuter, { initialize: function($super, element, frequency, callback) { $super(callback, frequency); this.element = $(element); this.lastValue = this.getValue() }, execute: function() { var value = this.getValue(); if (Object.isString(this.lastValue) && Object.isString(value) ? this.lastValue != value : String(this.lastValue) != String(value)) { this.callback(this.element, value); this.lastValue = value } } }); Form.Element.Observer = Class.create(Abstract.TimedObserver, { getValue: function() { return Form.Element.getValue(this.element) } }); Form.Observer = Class.create(Abstract.TimedObserver, { getValue: function() { return Form.serialize(this.element) } }); Abstract.EventObserver = Class.create({ initialize: function(element, callback) { this.element = $(element); this.callback = callback; this.lastValue = this.getValue(); if (this.element.tagName.toLowerCase() == 'form') this.registerFormCallbacks(); else this.registerCallback(this.element) }, onElementEvent: function() { var value = this.getValue(); if (this.lastValue != value) { this.callback(this.element, value); this.lastValue = value } }, registerFormCallbacks: function() { Form.getElements(this.element).each(this.registerCallback, this) }, registerCallback: function(element) { if (element.type) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': Event.observe(element, 'click', this.onElementEvent.bind(this)); break; default: Event.observe(element, 'change', this.onElementEvent.bind(this)); break } } } }); Form.Element.EventObserver = Class.create(Abstract.EventObserver, { getValue: function() { return Form.Element.getValue(this.element) } }); Form.EventObserver = Class.create(Abstract.EventObserver, { getValue: function() { return Form.serialize(this.element) } }); if (!window.Event) var Event = {}; Object.extend(Event, { KEY_BACKSPACE: 8, KEY_TAB: 9, KEY_RETURN: 13, KEY_ESC: 27, KEY_LEFT: 37, KEY_UP: 38, KEY_RIGHT: 39, KEY_DOWN: 40, KEY_DELETE: 46, KEY_HOME: 36, KEY_END: 35, KEY_PAGEUP: 33, KEY_PAGEDOWN: 34, KEY_INSERT: 45, cache: {}, relatedTarget: function(event) { var element; switch (event.type) { case 'mouseover': element = event.fromElement; break; case 'mouseout': element = event.toElement; break; default: return null } return Element.extend(element) } }); Event.Methods = (function() { var isButton; if (Prototype.Browser.IE) { var buttonMap = { 0: 1, 1: 4, 2: 2 }; isButton = function(event, code) { return event.button == buttonMap[code] } } else if (Prototype.Browser.WebKit) { isButton = function(event, code) { switch (code) { case 0: return event.which == 1 && !event.metaKey; case 1: return event.which == 1 && event.metaKey; default: return false } } } else { isButton = function(event, code) { return event.which ? (event.which === code + 1) : (event.button === code) } } return { isLeftClick: function(event) { return isButton(event, 0) }, isMiddleClick: function(event) { return isButton(event, 1) }, isRightClick: function(event) { return isButton(event, 2) }, element: function(event) { var node = Event.extend(event).target; return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node) }, findElement: function(event, expression) { var element = Event.element(event); if (!expression) return element; var elements = [element].concat(element.ancestors()); return Selector.findElement(elements, expression, 0) }, pointer: function(event) { return { x: event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)), y: event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop))} }, pointerX: function(event) { return Event.pointer(event).x }, pointerY: function(event) { return Event.pointer(event).y }, stop: function(event) { Event.extend(event); event.preventDefault(); event.stopPropagation(); event.stopped = true } } })(); Event.extend = (function() { var methods = Object.keys(Event.Methods).inject({}, function(m, name) { m[name] = Event.Methods[name].methodize(); return m }); if (Prototype.Browser.IE) { Object.extend(methods, { stopPropagation: function() { this.cancelBubble = true }, preventDefault: function() { this.returnValue = false }, inspect: function() { return "[object Event]" } }); return function(event) { if (!event) return false; if (event._extendedByPrototype) return event; event._extendedByPrototype = Prototype.emptyFunction; var pointer = Event.pointer(event); Object.extend(event, { target: event.srcElement, relatedTarget: Event.relatedTarget(event), pageX: pointer.x, pageY: pointer.y }); return Object.extend(event, methods) } } else { Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; Object.extend(Event.prototype, methods); return Prototype.K } })(); Object.extend(Event, (function() { var cache = Event.cache; function getEventID(element) { if (element._prototypeEventID) return element._prototypeEventID[0]; arguments.callee.id = arguments.callee.id || 1; return element._prototypeEventID = [++arguments.callee.id] } function getDOMEventName(eventName) { if (eventName && eventName.include(':')) return "dataavailable"; return eventName } function getCacheForID(id) { return cache[id] = cache[id] || {} } function getWrappersForEventName(id, eventName) { var c = getCacheForID(id); return c[eventName] = c[eventName] || [] } function createWrapper(element, eventName, handler) { var id = getEventID(element); var c = getWrappersForEventName(id, eventName); if (c.pluck("handler").include(handler)) return false; var wrapper = function(event) { if (!Event || !Event.extend || (event.eventName && event.eventName != eventName)) return false; Event.extend(event); handler.call(element, event) }; wrapper.handler = handler; c.push(wrapper); return wrapper } function findWrapper(id, eventName, handler) { var c = getWrappersForEventName(id, eventName); return c.find(function(wrapper) { return wrapper.handler == handler }) } function destroyWrapper(id, eventName, handler) { var c = getCacheForID(id); if (!c[eventName]) return false; c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)) } function destroyCache() { for (var id in cache) for (var eventName in cache[id]) cache[id][eventName] = null } if (window.attachEvent) { window.attachEvent("onunload", destroyCache) } return { observe: function(element, eventName, handler) { element = $(element); var name = getDOMEventName(eventName); var wrapper = createWrapper(element, eventName, handler); if (!wrapper) return element; if (element.addEventListener) { element.addEventListener(name, wrapper, false) } else { element.attachEvent("on" + name, wrapper) } return element }, stopObserving: function(element, eventName, handler) { element = $(element); var id = getEventID(element), name = getDOMEventName(eventName); if (!handler && eventName) { getWrappersForEventName(id, eventName).each(function(wrapper) { element.stopObserving(eventName, wrapper.handler) }); return element } else if (!eventName) { Object.keys(getCacheForID(id)).each(function(eventName) { element.stopObserving(eventName) }); return element } var wrapper = findWrapper(id, eventName, handler); if (!wrapper) return element; if (element.removeEventListener) { element.removeEventListener(name, wrapper, false) } else { element.detachEvent("on" + name, wrapper) } destroyWrapper(id, eventName, handler); return element }, fire: function(element, eventName, memo) { element = $(element); if (element == document && document.createEvent && !element.dispatchEvent) element = document.documentElement; var event; if (document.createEvent) { event = document.createEvent("HTMLEvents"); event.initEvent("dataavailable", true, true) } else { event = document.createEventObject(); event.eventType = "ondataavailable" } event.eventName = eventName; event.memo = memo || {}; if (document.createEvent) { element.dispatchEvent(event) } else { element.fireEvent(event.eventType, event) } return Event.extend(event) } } })()); Object.extend(Event, Event.Methods); Element.addMethods({ fire: Event.fire, observe: Event.observe, stopObserving: Event.stopObserving }); Object.extend(document, { fire: Element.Methods.fire.methodize(), observe: Element.Methods.observe.methodize(), stopObserving: Element.Methods.stopObserving.methodize(), loaded: false }); (function() { var timer; function fireContentLoadedEvent() { if (document.loaded) return; if (timer) window.clearInterval(timer); document.fire("dom:loaded"); document.loaded = true } if (document.addEventListener) { if (Prototype.Browser.WebKit) { timer = window.setInterval(function() { if (/loaded|complete/.test(document.readyState)) fireContentLoadedEvent() }, 0); Event.observe(window, "load", fireContentLoadedEvent) } else { document.addEventListener("DOMContentLoaded", fireContentLoadedEvent, false) } } else { document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>"); $("__onDOMContentLoaded").onreadystatechange = function() { if (this.readyState == "complete") { this.onreadystatechange = null; fireContentLoadedEvent() } } } })(); Hash.toQueryString = Object.toQueryString; var Toggle = { display: Element.toggle }; Element.Methods.childOf = Element.Methods.descendantOf; var Insertion = { Before: function(element, content) { return Element.insert(element, { before: content }) }, Top: function(element, content) { return Element.insert(element, { top: content }) }, Bottom: function(element, content) { return Element.insert(element, { bottom: content }) }, After: function(element, content) { return Element.insert(element, { after: content }) } }; var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); var Position = { includeScrollOffsets: false, prepare: function() { this.deltaX = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0; this.deltaY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0 }, within: function(element, x, y) { if (this.includeScrollOffsets) return this.withinIncludingScrolloffsets(element, x, y); this.xcomp = x; this.ycomp = y; this.offset = Element.cumulativeOffset(element); return (y >= this.offset[1] && y < this.offset[1] + element.offsetHeight && x >= this.offset[0] && x < this.offset[0] + element.offsetWidth) }, withinIncludingScrolloffsets: function(element, x, y) { var offsetcache = Element.cumulativeScrollOffset(element); this.xcomp = x + offsetcache[0] - this.deltaX; this.ycomp = y + offsetcache[1] - this.deltaY; this.offset = Element.cumulativeOffset(element); return (this.ycomp >= this.offset[1] && this.ycomp < this.offset[1] + element.offsetHeight && this.xcomp >= this.offset[0] && this.xcomp < this.offset[0] + element.offsetWidth) }, overlap: function(mode, element) { if (!mode) return 0; if (mode == 'vertical') return ((this.offset[1] + element.offsetHeight) - this.ycomp) / element.offsetHeight; if (mode == 'horizontal') return ((this.offset[0] + element.offsetWidth) - this.xcomp) / element.offsetWidth }, cumulativeOffset: Element.Methods.cumulativeOffset, positionedOffset: Element.Methods.positionedOffset, absolutize: function(element) { Position.prepare(); return Element.absolutize(element) }, relativize: function(element) { Position.prepare(); return Element.relativize(element) }, realOffset: Element.Methods.cumulativeScrollOffset, offsetParent: Element.Methods.getOffsetParent, page: Element.Methods.viewportOffset, clone: function(source, target, options) { options = options || {}; return Element.clonePosition(target, source, options) } }; if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods) { function iter(name) { return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]" } instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? function(element, className) { className = className.toString().strip(); var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); return cond ? document._getElementsByXPath('.//*' + cond, element) : [] } : function(element, className) { className = className.toString().strip(); var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); if (!classNames && !className) return elements; var nodes = $(element).getElementsByTagName('*'); className = ' ' + className + ' '; for (var i = 0, child, cn; child = nodes[i]; i++) { if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || (classNames && classNames.all(function(name) { return !name.toString().blank() && cn.include(' ' + name + ' ') })))) elements.push(Element.extend(child)) } return elements }; return function(className, parentElement) { return $(parentElement || document.body).getElementsByClassName(className) } } (Element.Methods); Element.ClassNames = Class.create(); Element.ClassNames.prototype = { initialize: function(element) { this.element = $(element) }, _each: function(iterator) { this.element.className.split(/\s+/).select(function(name) { return name.length > 0 })._each(iterator) }, set: function(className) { this.element.className = className }, add: function(classNameToAdd) { if (this.include(classNameToAdd)) return; this.set($A(this).concat(classNameToAdd).join(' ')) }, remove: function(classNameToRemove) { if (!this.include(classNameToRemove)) return; this.set($A(this).without(classNameToRemove).join(' ')) }, toString: function() { return $A(this).join(' ') } }; Object.extend(Element.ClassNames.prototype, Enumerable); Element.addMethods();
/* scriptaculous */

var Scriptaculous = { Version: '1.8.1', require: function(libraryName) { document.write('<script type="text/javascript" src="' + libraryName + '"><\/script>') }, REQUIRED_PROTOTYPE: '1.6.0.2', load: function() { function convertVersionString(versionString) { var v = versionString.replace(/_.*|\./g, ''); v = parseInt(v + '0'.times(4 - v.length)); return versionString.indexOf('_') > -1 ? v - 1 : v } if ((typeof Prototype == 'undefined') || (typeof Element == 'undefined') || (typeof Element.Methods == 'undefined') || (convertVersionString(Prototype.Version) < convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE))) throw ("script.aculo.us requires the Prototype JavaScript framework >= " + Scriptaculous.REQUIRED_PROTOTYPE); } }; Scriptaculous.load();

/* builder.js */

var Builder = { NODEMAP: { AREA: 'map', CAPTION: 'table', COL: 'table', COLGROUP: 'table', LEGEND: 'fieldset', OPTGROUP: 'select', OPTION: 'select', PARAM: 'object', TBODY: 'table', TD: 'table', TFOOT: 'table', TH: 'table', THEAD: 'table', TR: 'table' }, node: function(elementName) { elementName = elementName.toUpperCase(); var parentTag = this.NODEMAP[elementName] || 'div'; var parentElement = document.createElement(parentTag); try { parentElement.innerHTML = "<" + elementName + "></" + elementName + ">" } catch (e) { } var element = parentElement.firstChild || null; if (element && (element.tagName.toUpperCase() != elementName)) element = element.getElementsByTagName(elementName)[0]; if (!element) element = document.createElement(elementName); if (!element) return; if (arguments[1]) if (this._isStringOrNumber(arguments[1]) || (arguments[1] instanceof Array) || arguments[1].tagName) { this._children(element, arguments[1]) } else { var attrs = this._attributes(arguments[1]); if (attrs.length) { try { parentElement.innerHTML = "<" + elementName + " " + attrs + "></" + elementName + ">" } catch (e) { } element = parentElement.firstChild || null; if (!element) { element = document.createElement(elementName); for (attr in arguments[1]) element[attr == 'class' ? 'className' : attr] = arguments[1][attr] } if (element.tagName.toUpperCase() != elementName) element = parentElement.getElementsByTagName(elementName)[0] } } if (arguments[2]) this._children(element, arguments[2]); return element }, _text: function(text) { return document.createTextNode(text) }, ATTR_MAP: { 'className': 'class', 'htmlFor': 'for' }, _attributes: function(attributes) { var attrs = []; for (attribute in attributes) attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) + '="' + attributes[attribute].toString().escapeHTML().gsub(/"/, '&quot;') + '"'); return attrs.join(" ") }, _children: function(element, children) { if (children.tagName) { element.appendChild(children); return } if (typeof children == 'object') { children.flatten().each(function(e) { if (typeof e == 'object') element.appendChild(e); else if (Builder._isStringOrNumber(e)) element.appendChild(Builder._text(e)) }) } else if (Builder._isStringOrNumber(children)) element.appendChild(Builder._text(children)) }, _isStringOrNumber: function(param) { return (typeof param == 'string' || typeof param == 'number') }, build: function(html) { var element = this.node('div'); $(element).update(html.strip()); return element.down() }, dump: function(scope) { if (typeof scope != 'object' && typeof scope != 'function') scope = window; var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " + "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " + "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX " + "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P " + "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD " + "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/); tags.each(function(tag) { scope[tag] = function() { return Builder.node.apply(Builder, [tag].concat($A(arguments))) } }) } };

/* effects.js */

String.prototype.parseColor = function() { var color = '#'; if (this.slice(0, 4) == 'rgb(') { var cols = this.slice(4, this.length - 1).split(','); var i = 0; do { color += parseInt(cols[i]).toColorPart() } while (++i < 3) } else { if (this.slice(0, 1) == '#') { if (this.length == 4) for (var i = 1; i < 4; i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); if (this.length == 7) color = this.toLowerCase() } } return (color.length == 7 ? color : (arguments[0] || this)) }; Element.collectTextNodes = function(element) { return $A($(element).childNodes).collect(function(node) { return (node.nodeType == 3 ? node.nodeValue : (node.hasChildNodes() ? Element.collectTextNodes(node) : '')) }).flatten().join('') }; Element.collectTextNodesIgnoreClass = function(element, className) { return $A($(element).childNodes).collect(function(node) { return (node.nodeType == 3 ? node.nodeValue : ((node.hasChildNodes() && !Element.hasClassName(node, className)) ? Element.collectTextNodesIgnoreClass(node, className) : '')) }).flatten().join('') }; Element.setContentZoom = function(element, percent) { element = $(element); element.setStyle({ fontSize: (percent / 100) + 'em' }); if (Prototype.Browser.WebKit) window.scrollBy(0, 0); return element }; Element.getInlineOpacity = function(element) { return $(element).style.opacity || '' }; Element.forceRerendering = function(element) { try { element = $(element); var n = document.createTextNode(' '); element.appendChild(n); element.removeChild(n) } catch (e) { } }; var Effect = { _elementDoesNotExistError: { name: 'ElementDoesNotExistError', message: 'The specified DOM element does not exist, but is required for this effect to operate' }, Transitions: { linear: Prototype.K, sinoidal: function(pos) { return (-Math.cos(pos * Math.PI) / 2) + .5 }, reverse: function(pos) { return 1 - pos }, flicker: function(pos) { var pos = ((-Math.cos(pos * Math.PI) / 4) + .75) + Math.random() / 4; return pos > 1 ? 1 : pos }, wobble: function(pos) { return (-Math.cos(pos * Math.PI * (9 * pos)) / 2) + .5 }, pulse: function(pos, pulses) { return (-Math.cos((pos * ((pulses || 5) - .5) * 2) * Math.PI) / 2) + .5 }, spring: function(pos) { return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)) }, none: function(pos) { return 0 }, full: function(pos) { return 1 } }, DefaultOptions: { duration: 1.0, fps: 100, sync: false, from: 0.0, to: 1.0, delay: 0.0, queue: 'parallel' }, tagifyText: function(element) { var tagifyStyle = 'position:relative'; if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; element = $(element); $A(element.childNodes).each(function(child) { if (child.nodeType == 3) { child.nodeValue.toArray().each(function(character) { element.insertBefore(new Element('span', { style: tagifyStyle }).update(character == ' ' ? String.fromCharCode(160) : character), child) }); Element.remove(child) } }) }, multiple: function(element, effect) { var elements; if (((typeof element == 'object') || Object.isFunction(element)) && (element.length)) elements = element; else elements = $(element).childNodes; var options = Object.extend({ speed: 0.1, delay: 0.0 }, arguments[2] || {}); var masterDelay = options.delay; $A(elements).each(function(element, index) { new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })) }) }, PAIRS: { 'slide': ['SlideDown', 'SlideUp'], 'blind': ['BlindDown', 'BlindUp'], 'appear': ['Appear', 'Fade'] }, toggle: function(element, effect) { element = $(element); effect = (effect || 'appear').toLowerCase(); var options = Object.extend({ queue: { position: 'end', scope: (element.id || 'global'), limit: 1} }, arguments[2] || {}); Effect[element.visible() ? Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options) } }; Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; Effect.ScopedQueue = Class.create(Enumerable, { initialize: function() { this.effects = []; this.interval = null }, _each: function(iterator) { this.effects._each(iterator) }, add: function(effect) { var timestamp = new Date().getTime(); var position = Object.isString(effect.options.queue) ? effect.options.queue : effect.options.queue.position; switch (position) { case 'front': this.effects.findAll(function(e) { return e.state == 'idle' }).each(function(e) { e.startOn += effect.finishOn; e.finishOn += effect.finishOn }); break; case 'with-last': timestamp = this.effects.pluck('startOn').max() || timestamp; break; case 'end': timestamp = this.effects.pluck('finishOn').max() || timestamp; break } effect.startOn += timestamp; effect.finishOn += timestamp; if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) this.effects.push(effect); if (!this.interval) this.interval = setInterval(this.loop.bind(this), 15) }, remove: function(effect) { this.effects = this.effects.reject(function(e) { return e == effect }); if (this.effects.length == 0) { clearInterval(this.interval); this.interval = null } }, loop: function() { var timePos = new Date().getTime(); for (var i = 0, len = this.effects.length; i < len; i++) this.effects[i] && this.effects[i].loop(timePos) } }); Effect.Queues = { instances: $H(), get: function(queueName) { if (!Object.isString(queueName)) return queueName; return this.instances.get(queueName) || this.instances.set(queueName, new Effect.ScopedQueue()) } }; Effect.Queue = Effect.Queues.get('global'); Effect.Base = Class.create({ position: null, start: function(options) { function codeForEvent(options, eventName) { return ((options[eventName + 'Internal'] ? 'this.options.' + eventName + 'Internal(this);' : '') + (options[eventName] ? 'this.options.' + eventName + '(this);' : '')) } if (options && options.transition === false) options.transition = Effect.Transitions.linear; this.options = Object.extend(Object.extend({}, Effect.DefaultOptions), options || {}); this.currentFrame = 0; this.state = 'idle'; this.startOn = this.options.delay * 1000; this.finishOn = this.startOn + (this.options.duration * 1000); this.fromToDelta = this.options.to - this.options.from; this.totalTime = this.finishOn - this.startOn; this.totalFrames = this.options.fps * this.options.duration; eval('this.render = function(pos){ ' + 'if (this.state=="idle"){this.state="running";' + codeForEvent(this.options, 'beforeSetup') + (this.setup ? 'this.setup();' : '') + codeForEvent(this.options, 'afterSetup') + '};if (this.state=="running"){' + 'pos=this.options.transition(pos)*' + this.fromToDelta + '+' + this.options.from + ';' + 'this.position=pos;' + codeForEvent(this.options, 'beforeUpdate') + (this.update ? 'this.update(pos);' : '') + codeForEvent(this.options, 'afterUpdate') + '}}'); this.event('beforeStart'); if (!this.options.sync) Effect.Queues.get(Object.isString(this.options.queue) ? 'global' : this.options.queue.scope).add(this) }, loop: function(timePos) { if (timePos >= this.startOn) { if (timePos >= this.finishOn) { this.render(1.0); this.cancel(); this.event('beforeFinish'); if (this.finish) this.finish(); this.event('afterFinish'); return } var pos = (timePos - this.startOn) / this.totalTime, frame = (pos * this.totalFrames).round(); if (frame > this.currentFrame) { this.render(pos); this.currentFrame = frame } } }, cancel: function() { if (!this.options.sync) Effect.Queues.get(Object.isString(this.options.queue) ? 'global' : this.options.queue.scope).remove(this); this.state = 'finished' }, event: function(eventName) { if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); if (this.options[eventName]) this.options[eventName](this) }, inspect: function() { var data = $H(); for (property in this) if (!Object.isFunction(this[property])) data.set(property, this[property]); return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>' } }); Effect.Parallel = Class.create(Effect.Base, { initialize: function(effects) { this.effects = effects || []; this.start(arguments[1]) }, update: function(position) { this.effects.invoke('render', position) }, finish: function(position) { this.effects.each(function(effect) { effect.render(1.0); effect.cancel(); effect.event('beforeFinish'); if (effect.finish) effect.finish(position); effect.event('afterFinish') }) } }); Effect.Tween = Class.create(Effect.Base, { initialize: function(object, from, to) { object = Object.isString(object) ? $(object) : object; var args = $A(arguments), method = args.last(), options = args.length == 5 ? args[3] : null; this.method = Object.isFunction(method) ? method.bind(object) : Object.isFunction(object[method]) ? object[method].bind(object) : function(value) { object[method] = value }; this.start(Object.extend({ from: from, to: to }, options || {})) }, update: function(position) { this.method(position) } }); Effect.Event = Class.create(Effect.Base, { initialize: function() { this.start(Object.extend({ duration: 0 }, arguments[0] || {})) }, update: Prototype.emptyFunction }); Effect.Opacity = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw (Effect._elementDoesNotExistError); if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) this.element.setStyle({ zoom: 1 }); var options = Object.extend({ from: this.element.getOpacity() || 0.0, to: 1.0 }, arguments[1] || {}); this.start(options) }, update: function(position) { this.element.setOpacity(position) } }); Effect.Move = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw (Effect._elementDoesNotExistError); var options = Object.extend({ x: 0, y: 0, mode: 'relative' }, arguments[1] || {}); this.start(options) }, setup: function() { this.element.makePositioned(); this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); this.originalTop = parseFloat(this.element.getStyle('top') || '0'); if (this.options.mode == 'absolute') { this.options.x = this.options.x - this.originalLeft; this.options.y = this.options.y - this.originalTop } }, update: function(position) { this.element.setStyle({ left: (this.options.x * position + this.originalLeft).round() + 'px', top: (this.options.y * position + this.originalTop).round() + 'px' }) } }); Effect.MoveBy = function(element, toTop, toLeft) { return new Effect.Move(element, Object.extend({ x: toLeft, y: toTop }, arguments[3] || {})) }; Effect.Scale = Class.create(Effect.Base, { initialize: function(element, percent) { this.element = $(element); if (!this.element) throw (Effect._elementDoesNotExistError); var options = Object.extend({ scaleX: true, scaleY: true, scaleContent: true, scaleFromCenter: false, scaleMode: 'box', scaleFrom: 100.0, scaleTo: percent }, arguments[2] || {}); this.start(options) }, setup: function() { this.restoreAfterFinish = this.options.restoreAfterFinish || false; this.elementPositioning = this.element.getStyle('position'); this.originalStyle = {}; ['top', 'left', 'width', 'height', 'fontSize'].each(function(k) { this.originalStyle[k] = this.element.style[k] } .bind(this)); this.originalTop = this.element.offsetTop; this.originalLeft = this.element.offsetLeft; var fontSize = this.element.getStyle('font-size') || '100%'; ['em', 'px', '%', 'pt'].each(function(fontSizeType) { if (fontSize.indexOf(fontSizeType) > 0) { this.fontSize = parseFloat(fontSize); this.fontSizeType = fontSizeType } } .bind(this)); this.factor = (this.options.scaleTo - this.options.scaleFrom) / 100; this.dims = null; if (this.options.scaleMode == 'box') this.dims = [this.element.offsetHeight, this.element.offsetWidth]; if (/^content/.test(this.options.scaleMode)) this.dims = [this.element.scrollHeight, this.element.scrollWidth]; if (!this.dims) this.dims = [this.options.scaleMode.originalHeight, this.options.scaleMode.originalWidth] }, update: function(position) { var currentScale = (this.options.scaleFrom / 100.0) + (this.factor * position); if (this.options.scaleContent && this.fontSize) this.element.setStyle({ fontSize: this.fontSize * currentScale + this.fontSizeType }); this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale) }, finish: function(position) { if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle) }, setDimensions: function(height, width) { var d = {}; if (this.options.scaleX) d.width = width.round() + 'px'; if (this.options.scaleY) d.height = height.round() + 'px'; if (this.options.scaleFromCenter) { var topd = (height - this.dims[0]) / 2; var leftd = (width - this.dims[1]) / 2; if (this.elementPositioning == 'absolute') { if (this.options.scaleY) d.top = this.originalTop - topd + 'px'; if (this.options.scaleX) d.left = this.originalLeft - leftd + 'px' } else { if (this.options.scaleY) d.top = -topd + 'px'; if (this.options.scaleX) d.left = -leftd + 'px' } } this.element.setStyle(d) } }); Effect.Highlight = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw (Effect._elementDoesNotExistError); var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {}); this.start(options) }, setup: function() { if (this.element.getStyle('display') == 'none') { this.cancel(); return } this.oldStyle = {}; if (!this.options.keepBackgroundImage) { this.oldStyle.backgroundImage = this.element.getStyle('background-image'); this.element.setStyle({ backgroundImage: 'none' }) } if (!this.options.endcolor) this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); if (!this.options.restorecolor) this.options.restorecolor = this.element.getStyle('background-color'); this._base = $R(0, 2).map(function(i) { return parseInt(this.options.startcolor.slice(i * 2 + 1, i * 2 + 3), 16) } .bind(this)); this._delta = $R(0, 2).map(function(i) { return parseInt(this.options.endcolor.slice(i * 2 + 1, i * 2 + 3), 16) - this._base[i] } .bind(this)) }, update: function(position) { this.element.setStyle({ backgroundColor: $R(0, 2).inject('#', function(m, v, i) { return m + ((this._base[i] + (this._delta[i] * position)).round().toColorPart()) } .bind(this)) }) }, finish: function() { this.element.setStyle(Object.extend(this.oldStyle, { backgroundColor: this.options.restorecolor })) } }); Effect.ScrollTo = function(element) { var options = arguments[1] || {}, scrollOffsets = document.viewport.getScrollOffsets(), elementOffsets = $(element).cumulativeOffset(); if (options.offset) elementOffsets[1] += options.offset; return new Effect.Tween(null, scrollOffsets.top, elementOffsets[1], options, function(p) { scrollTo(scrollOffsets.left, p.round()) }) }; Effect.Fade = function(element) { element = $(element); var oldOpacity = element.getInlineOpacity(); var options = Object.extend({ from: element.getOpacity() || 1.0, to: 0.0, afterFinishInternal: function(effect) { if (effect.options.to != 0) return; effect.element.hide().setStyle({ opacity: oldOpacity }) } }, arguments[1] || {}); return new Effect.Opacity(element, options) }; Effect.Appear = function(element) { element = $(element); var options = Object.extend({ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), to: 1.0, afterFinishInternal: function(effect) { effect.element.forceRerendering() }, beforeSetup: function(effect) { effect.element.setOpacity(effect.options.from).show() } }, arguments[1] || {}); return new Effect.Opacity(element, options) }; Effect.Puff = function(element) { element = $(element); var oldStyle = { opacity: element.getInlineOpacity(), position: element.getStyle('position'), top: element.style.top, left: element.style.left, width: element.style.width, height: element.style.height }; return new Effect.Parallel([new Effect.Scale(element, 200, { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), new Effect.Opacity(element, { sync: true, to: 0.0 })], Object.extend({ duration: 1.0, beforeSetupInternal: function(effect) { Position.absolutize(effect.effects[0].element) }, afterFinishInternal: function(effect) { effect.effects[0].element.hide().setStyle(oldStyle) } }, arguments[1] || {})) }; Effect.BlindUp = function(element) { element = $(element); element.makeClipping(); return new Effect.Scale(element, 0, Object.extend({ scaleContent: false, scaleX: false, restoreAfterFinish: true, afterFinishInternal: function(effect) { effect.element.hide().undoClipping() } }, arguments[1] || {})) }; Effect.BlindDown = function(element) { element = $(element); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, 100, Object.extend({ scaleContent: false, scaleX: false, scaleFrom: 0, scaleMode: { originalHeight: elementDimensions.height, originalWidth: elementDimensions.width }, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makeClipping().setStyle({ height: '0px' }).show() }, afterFinishInternal: function(effect) { effect.element.undoClipping() } }, arguments[1] || {})) }; Effect.SwitchOff = function(element) { element = $(element); var oldOpacity = element.getInlineOpacity(); return new Effect.Appear(element, Object.extend({ duration: 0.4, from: 0, transition: Effect.Transitions.flicker, afterFinishInternal: function(effect) { new Effect.Scale(effect.element, 1, { duration: 0.3, scaleFromCenter: true, scaleX: false, scaleContent: false, restoreAfterFinish: true, beforeSetup: function(effect) { effect.element.makePositioned().makeClipping() }, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().undoPositioned().setStyle({ opacity: oldOpacity }) } }) } }, arguments[1] || {})) }; Effect.DropOut = function(element) { element = $(element); var oldStyle = { top: element.getStyle('top'), left: element.getStyle('left'), opacity: element.getInlineOpacity() }; return new Effect.Parallel([new Effect.Move(element, { x: 0, y: 100, sync: true }), new Effect.Opacity(element, { sync: true, to: 0.0 })], Object.extend({ duration: 0.5, beforeSetup: function(effect) { effect.effects[0].element.makePositioned() }, afterFinishInternal: function(effect) { effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle) } }, arguments[1] || {})) }; Effect.Shake = function(element) { element = $(element); var options = Object.extend({ distance: 20, duration: 0.5 }, arguments[1] || {}); var distance = parseFloat(options.distance); var split = parseFloat(options.duration) / 10.0; var oldStyle = { top: element.getStyle('top'), left: element.getStyle('left') }; return new Effect.Move(element, { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance * 2, y: 0, duration: split * 2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: distance * 2, y: 0, duration: split * 2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance * 2, y: 0, duration: split * 2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: distance * 2, y: 0, duration: split * 2, afterFinishInternal: function(effect) { new Effect.Move(effect.element, { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { effect.element.undoPositioned().setStyle(oldStyle) } }) } }) } }) } }) } }) } }) }; Effect.SlideDown = function(element) { element = $(element).cleanWhitespace(); var oldInnerBottom = element.down().getStyle('bottom'); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, 100, Object.extend({ scaleContent: false, scaleX: false, scaleFrom: window.opera ? 0 : 1, scaleMode: { originalHeight: elementDimensions.height, originalWidth: elementDimensions.width }, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makePositioned(); effect.element.down().makePositioned(); if (window.opera) effect.element.setStyle({ top: '' }); effect.element.makeClipping().setStyle({ height: '0px' }).show() }, afterUpdateInternal: function(effect) { effect.element.down().setStyle({ bottom: (effect.dims[0] - effect.element.clientHeight) + 'px' }) }, afterFinishInternal: function(effect) { effect.element.undoClipping().undoPositioned(); effect.element.down().undoPositioned().setStyle({ bottom: oldInnerBottom }) } }, arguments[1] || {})) }; Effect.SlideUp = function(element) { element = $(element).cleanWhitespace(); var oldInnerBottom = element.down().getStyle('bottom'); var elementDimensions = element.getDimensions(); return new Effect.Scale(element, window.opera ? 0 : 1, Object.extend({ scaleContent: false, scaleX: false, scaleMode: 'box', scaleFrom: 100, scaleMode: { originalHeight: elementDimensions.height, originalWidth: elementDimensions.width }, restoreAfterFinish: true, afterSetup: function(effect) { effect.element.makePositioned(); effect.element.down().makePositioned(); if (window.opera) effect.element.setStyle({ top: '' }); effect.element.makeClipping().show() }, afterUpdateInternal: function(effect) { effect.element.down().setStyle({ bottom: (effect.dims[0] - effect.element.clientHeight) + 'px' }) }, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().undoPositioned(); effect.element.down().undoPositioned().setStyle({ bottom: oldInnerBottom }) } }, arguments[1] || {})) }; Effect.Squish = function(element) { return new Effect.Scale(element, window.opera ? 1 : 0, { restoreAfterFinish: true, beforeSetup: function(effect) { effect.element.makeClipping() }, afterFinishInternal: function(effect) { effect.element.hide().undoClipping() } }) }; Effect.Grow = function(element) { element = $(element); var options = Object.extend({ direction: 'center', moveTransition: Effect.Transitions.sinoidal, scaleTransition: Effect.Transitions.sinoidal, opacityTransition: Effect.Transitions.full }, arguments[1] || {}); var oldStyle = { top: element.style.top, left: element.style.left, height: element.style.height, width: element.style.width, opacity: element.getInlineOpacity() }; var dims = element.getDimensions(); var initialMoveX, initialMoveY; var moveX, moveY; switch (options.direction) { case 'top-left': initialMoveX = initialMoveY = moveX = moveY = 0; break; case 'top-right': initialMoveX = dims.width; initialMoveY = moveY = 0; moveX = -dims.width; break; case 'bottom-left': initialMoveX = moveX = 0; initialMoveY = dims.height; moveY = -dims.height; break; case 'bottom-right': initialMoveX = dims.width; initialMoveY = dims.height; moveX = -dims.width; moveY = -dims.height; break; case 'center': initialMoveX = dims.width / 2; initialMoveY = dims.height / 2; moveX = -dims.width / 2; moveY = -dims.height / 2; break } return new Effect.Move(element, { x: initialMoveX, y: initialMoveY, duration: 0.01, beforeSetup: function(effect) { effect.element.hide().makeClipping().makePositioned() }, afterFinishInternal: function(effect) { new Effect.Parallel([new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), new Effect.Scale(effect.element, 100, { scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true })], Object.extend({ beforeSetup: function(effect) { effect.effects[0].element.setStyle({ height: '0px' }).show() }, afterFinishInternal: function(effect) { effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle) } }, options)) } }) }; Effect.Shrink = function(element) { element = $(element); var options = Object.extend({ direction: 'center', moveTransition: Effect.Transitions.sinoidal, scaleTransition: Effect.Transitions.sinoidal, opacityTransition: Effect.Transitions.none }, arguments[1] || {}); var oldStyle = { top: element.style.top, left: element.style.left, height: element.style.height, width: element.style.width, opacity: element.getInlineOpacity() }; var dims = element.getDimensions(); var moveX, moveY; switch (options.direction) { case 'top-left': moveX = moveY = 0; break; case 'top-right': moveX = dims.width; moveY = 0; break; case 'bottom-left': moveX = 0; moveY = dims.height; break; case 'bottom-right': moveX = dims.width; moveY = dims.height; break; case 'center': moveX = dims.width / 2; moveY = dims.height / 2; break } return new Effect.Parallel([new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true }), new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })], Object.extend({ beforeStartInternal: function(effect) { effect.effects[0].element.makePositioned().makeClipping() }, afterFinishInternal: function(effect) { effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle) } }, options)) }; Effect.Pulsate = function(element) { element = $(element); var options = arguments[1] || {}, oldOpacity = element.getInlineOpacity(), transition = options.transition || Effect.Transitions.linear, reverser = function(pos) { return 1 - transition((-Math.cos((pos * (options.pulses || 5) * 2) * Math.PI) / 2) + .5) }; return new Effect.Opacity(element, Object.extend(Object.extend({ duration: 2.0, from: 0, afterFinishInternal: function(effect) { effect.element.setStyle({ opacity: oldOpacity }) } }, options), { transition: reverser })) }; Effect.Fold = function(element) { element = $(element); var oldStyle = { top: element.style.top, left: element.style.left, width: element.style.width, height: element.style.height }; element.makeClipping(); return new Effect.Scale(element, 5, Object.extend({ scaleContent: false, scaleX: false, afterFinishInternal: function(effect) { new Effect.Scale(element, 1, { scaleContent: false, scaleY: false, afterFinishInternal: function(effect) { effect.element.hide().undoClipping().setStyle(oldStyle) } }) } }, arguments[1] || {})) }; Effect.Morph = Class.create(Effect.Base, { initialize: function(element) { this.element = $(element); if (!this.element) throw (Effect._elementDoesNotExistError); var options = Object.extend({ style: {} }, arguments[1] || {}); if (!Object.isString(options.style)) this.style = $H(options.style); else { if (options.style.include(':')) this.style = options.style.parseStyle(); else { this.element.addClassName(options.style); this.style = $H(this.element.getStyles()); this.element.removeClassName(options.style); var css = this.element.getStyles(); this.style = this.style.reject(function(style) { return style.value == css[style.key] }); options.afterFinishInternal = function(effect) { effect.element.addClassName(effect.options.style); effect.transforms.each(function(transform) { effect.element.style[transform.style] = '' }) } } } this.start(options) }, setup: function() { function parseColor(color) { if (!color || ['rgba(0, 0, 0, 0)', 'transparent'].include(color)) color = '#ffffff'; color = color.parseColor(); return $R(0, 2).map(function(i) { return parseInt(color.slice(i * 2 + 1, i * 2 + 3), 16) }) } this.transforms = this.style.map(function(pair) { var property = pair[0], value = pair[1], unit = null; if (value.parseColor('#zzzzzz') != '#zzzzzz') { value = value.parseColor(); unit = 'color' } else if (property == 'opacity') { value = parseFloat(value); if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) this.element.setStyle({ zoom: 1 }) } else if (Element.CSS_LENGTH.test(value)) { var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); value = parseFloat(components[1]); unit = (components.length == 3) ? components[2] : null } var originalValue = this.element.getStyle(property); return { style: property.camelize(), originalValue: unit == 'color' ? parseColor(originalValue) : parseFloat(originalValue || 0), targetValue: unit == 'color' ? parseColor(value) : value, unit: unit} } .bind(this)).reject(function(transform) { return ((transform.originalValue == transform.targetValue) || (transform.unit != 'color' && (isNaN(transform.originalValue) || isNaN(transform.targetValue)))) }) }, update: function(position) { var style = {}, transform, i = this.transforms.length; while (i--) style[(transform = this.transforms[i]).style] = transform.unit == 'color' ? '#' + (Math.round(transform.originalValue[0] + (transform.targetValue[0] - transform.originalValue[0]) * position)).toColorPart() + (Math.round(transform.originalValue[1] + (transform.targetValue[1] - transform.originalValue[1]) * position)).toColorPart() + (Math.round(transform.originalValue[2] + (transform.targetValue[2] - transform.originalValue[2]) * position)).toColorPart() : (transform.originalValue + (transform.targetValue - transform.originalValue) * position).toFixed(3) + (transform.unit === null ? '' : transform.unit); this.element.setStyle(style, true) } }); Effect.Transform = Class.create({ initialize: function(tracks) { this.tracks = []; this.options = arguments[1] || {}; this.addTracks(tracks) }, addTracks: function(tracks) { tracks.each(function(track) { track = $H(track); var data = track.values().first(); this.tracks.push($H({ ids: track.keys().first(), effect: Effect.Morph, options: { style: data} })) } .bind(this)); return this }, play: function() { return new Effect.Parallel(this.tracks.map(function(track) { var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); var elements = [$(ids) || $$(ids)].flatten(); return elements.map(function(e) { return new effect(e, Object.extend({ sync: true }, options)) }) }).flatten(), this.options) } }); Element.CSS_PROPERTIES = $w('backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + 'fontSize fontWeight height left letterSpacing lineHeight ' + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight ' + 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + 'right textIndent top width wordSpacing zIndex'); Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; String.__parseStyleElement = document.createElement('div'); String.prototype.parseStyle = function() { var style, styleRules = $H(); if (Prototype.Browser.WebKit) style = new Element('div', { style: this }).style; else { String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>'; style = String.__parseStyleElement.childNodes[0].style } Element.CSS_PROPERTIES.each(function(property) { if (style[property]) styleRules.set(property, style[property]) }); if (Prototype.Browser.IE && this.include('opacity')) styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); return styleRules }; if (document.defaultView && document.defaultView.getComputedStyle) { Element.getStyles = function(element) { var css = document.defaultView.getComputedStyle($(element), null); return Element.CSS_PROPERTIES.inject({}, function(styles, property) { styles[property] = css[property]; return styles }) } } else { Element.getStyles = function(element) { element = $(element); var css = element.currentStyle, styles; styles = Element.CSS_PROPERTIES.inject({}, function(results, property) { results[property] = css[property]; return results }); if (!styles.opacity) styles.opacity = element.getOpacity(); return styles } } Effect.Methods = { morph: function(element, style) { element = $(element); new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {})); return element }, visualEffect: function(element, effect, options) { element = $(element); var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); new Effect[klass](element, options); return element }, highlight: function(element, options) { element = $(element); new Effect.Highlight(element, options); return element } }; $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown ' + 'pulsate shake puff squish switchOff dropOut').each(function(effect) { Effect.Methods[effect] = function(element, options) { element = $(element); Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); return element } }); $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(function(f) { Effect.Methods[f] = Element[f] }); Element.addMethods(Effect.Methods);

/* dragdrop.js */

if (Object.isUndefined(Effect)) throw ("dragdrop.js requires including script.aculo.us' effects.js library"); var Droppables = { drops: [], remove: function(element) { this.drops = this.drops.reject(function(d) { return d.element == $(element) }) }, add: function(element) { element = $(element); var options = Object.extend({ greedy: true, hoverclass: null, tree: false }, arguments[1] || {}); if (options.containment) { options._containers = []; var containment = options.containment; if (Object.isArray(containment)) { containment.each(function(c) { options._containers.push($(c)) }) } else { options._containers.push($(containment)) } } if (options.accept) options.accept = [options.accept].flatten(); Element.makePositioned(element); options.element = element; this.drops.push(options) }, findDeepestChild: function(drops) { deepest = drops[0]; for (i = 1; i < drops.length; ++i) if (Element.isParent(drops[i].element, deepest.element)) deepest = drops[i]; return deepest }, isContained: function(element, drop) { var containmentNode; if (drop.tree) { containmentNode = element.treeNode } else { containmentNode = element.parentNode } return drop._containers.detect(function(c) { return containmentNode == c }) }, isAffected: function(point, element, drop) { return ((drop.element != element) && ((!drop._containers) || this.isContained(element, drop)) && ((!drop.accept) || (Element.classNames(element).detect(function(v) { return drop.accept.include(v) }))) && Position.within(drop.element, point[0], point[1])) }, deactivate: function(drop) { if (drop.hoverclass) Element.removeClassName(drop.element, drop.hoverclass); this.last_active = null }, activate: function(drop) { if (drop.hoverclass) Element.addClassName(drop.element, drop.hoverclass); this.last_active = drop }, show: function(point, element) { if (!this.drops.length) return; var drop, affected = []; this.drops.each(function(drop) { if (Droppables.isAffected(point, element, drop)) affected.push(drop) }); if (affected.length > 0) drop = Droppables.findDeepestChild(affected); if (this.last_active && this.last_active != drop) this.deactivate(this.last_active); if (drop) { Position.within(drop.element, point[0], point[1]); if (drop.onHover) drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); if (drop != this.last_active) Droppables.activate(drop) } }, fire: function(event, element) { if (!this.last_active) return; Position.prepare(); if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active)) if (this.last_active.onDrop) { this.last_active.onDrop(element, this.last_active.element, event); return true } }, reset: function() { if (this.last_active) this.deactivate(this.last_active) } }; var Draggables = { drags: [], observers: [], register: function(draggable) { if (this.drags.length == 0) { this.eventMouseUp = this.endDrag.bindAsEventListener(this); this.eventMouseMove = this.updateDrag.bindAsEventListener(this); this.eventKeypress = this.keyPress.bindAsEventListener(this); Event.observe(document, "mouseup", this.eventMouseUp); Event.observe(document, "mousemove", this.eventMouseMove); Event.observe(document, "keypress", this.eventKeypress) } this.drags.push(draggable) }, unregister: function(draggable) { this.drags = this.drags.reject(function(d) { return d == draggable }); if (this.drags.length == 0) { Event.stopObserving(document, "mouseup", this.eventMouseUp); Event.stopObserving(document, "mousemove", this.eventMouseMove); Event.stopObserving(document, "keypress", this.eventKeypress) } }, activate: function(draggable) { if (draggable.options.delay) { this._timeout = setTimeout(function() { Draggables._timeout = null; window.focus(); Draggables.activeDraggable = draggable } .bind(this), draggable.options.delay) } else { window.focus(); this.activeDraggable = draggable } }, deactivate: function() { this.activeDraggable = null }, updateDrag: function(event) { if (!this.activeDraggable) return; var pointer = [Event.pointerX(event), Event.pointerY(event)]; if (this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return; this._lastPointer = pointer; this.activeDraggable.updateDrag(event, pointer) }, endDrag: function(event) { if (this._timeout) { clearTimeout(this._timeout); this._timeout = null } if (!this.activeDraggable) return; this._lastPointer = null; this.activeDraggable.endDrag(event); this.activeDraggable = null }, keyPress: function(event) { if (this.activeDraggable) this.activeDraggable.keyPress(event) }, addObserver: function(observer) { this.observers.push(observer); this._cacheObserverCallbacks() }, removeObserver: function(element) { this.observers = this.observers.reject(function(o) { return o.element == element }); this._cacheObserverCallbacks() }, notify: function(eventName, draggable, event) { if (this[eventName + 'Count'] > 0) this.observers.each(function(o) { if (o[eventName]) o[eventName](eventName, draggable, event) }); if (draggable.options[eventName]) draggable.options[eventName](draggable, event) }, _cacheObserverCallbacks: function() { ['onStart', 'onEnd', 'onDrag'].each(function(eventName) { Draggables[eventName + 'Count'] = Draggables.observers.select(function(o) { return o[eventName] }).length }) } }; var Draggable = Class.create({ initialize: function(element) { var defaults = { handle: false, reverteffect: function(element, top_offset, left_offset) { var dur = Math.sqrt(Math.abs(top_offset ^ 2) + Math.abs(left_offset ^ 2)) * 0.02; new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, queue: { scope: '_draggable', position: 'end'} }) }, endeffect: function(element) { var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0; new Effect.Opacity(element, { duration: 0.2, from: 0.7, to: toOpacity, queue: { scope: '_draggable', position: 'end' }, afterFinish: function() { Draggable._dragging[element] = false } }) }, zindex: 1000, revert: false, quiet: false, scroll: false, scrollSensitivity: 20, scrollSpeed: 15, snap: false, delay: 0 }; if (!arguments[1] || Object.isUndefined(arguments[1].endeffect)) Object.extend(defaults, { starteffect: function(element) { element._opacity = Element.getOpacity(element); Draggable._dragging[element] = true; new Effect.Opacity(element, { duration: 0.2, from: element._opacity, to: 0.7 }) } }); var options = Object.extend(defaults, arguments[1] || {}); this.element = $(element); if (options.handle && Object.isString(options.handle)) this.handle = this.element.down('.' + options.handle, 0); if (!this.handle) this.handle = $(options.handle); if (!this.handle) this.handle = this.element; if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { options.scroll = $(options.scroll); this._isScrollChild = Element.childOf(this.element, options.scroll) } Element.makePositioned(this.element); this.options = options; this.dragging = false; this.eventMouseDown = this.initDrag.bindAsEventListener(this); Event.observe(this.handle, "mousedown", this.eventMouseDown); Draggables.register(this) }, destroy: function() { Event.stopObserving(this.handle, "mousedown", this.eventMouseDown); Draggables.unregister(this) }, currentDelta: function() { return ([parseInt(Element.getStyle(this.element, 'left') || '0'), parseInt(Element.getStyle(this.element, 'top') || '0')]) }, initDrag: function(event) { if (!Object.isUndefined(Draggable._dragging[this.element]) && Draggable._dragging[this.element]) return; if (Event.isLeftClick(event)) { var src = Event.element(event); if ((tag_name = src.tagName.toUpperCase()) && (tag_name == 'INPUT' || tag_name == 'SELECT' || tag_name == 'OPTION' || tag_name == 'BUTTON' || tag_name == 'TEXTAREA')) return; var pointer = [Event.pointerX(event), Event.pointerY(event)]; var pos = Position.cumulativeOffset(this.element); this.offset = [0, 1].map(function(i) { return (pointer[i] - pos[i]) }); Draggables.activate(this); Event.stop(event) } }, startDrag: function(event) { this.dragging = true; if (!this.delta) this.delta = this.currentDelta(); if (this.options.zindex) { this.originalZ = parseInt(Element.getStyle(this.element, 'z-index') || 0); this.element.style.zIndex = this.options.zindex } if (this.options.ghosting) { this._clone = this.element.cloneNode(true); this._originallyAbsolute = (this.element.getStyle('position') == 'absolute'); if (!this._originallyAbsolute) Position.absolutize(this.element); this.element.parentNode.insertBefore(this._clone, this.element) } if (this.options.scroll) { if (this.options.scroll == window) { var where = this._getWindowScroll(this.options.scroll); this.originalScrollLeft = where.left; this.originalScrollTop = where.top } else { this.originalScrollLeft = this.options.scroll.scrollLeft; this.originalScrollTop = this.options.scroll.scrollTop } } Draggables.notify('onStart', this, event); if (this.options.starteffect) this.options.starteffect(this.element) }, updateDrag: function(event, pointer) { if (!this.dragging) this.startDrag(event); if (!this.options.quiet) { Position.prepare(); Droppables.show(pointer, this.element) } Draggables.notify('onDrag', this, event); this.draw(pointer); if (this.options.change) this.options.change(this); if (this.options.scroll) { this.stopScrolling(); var p; if (this.options.scroll == window) { with (this._getWindowScroll(this.options.scroll)) { p = [left, top, left + width, top + height] } } else { p = Position.page(this.options.scroll); p[0] += this.options.scroll.scrollLeft + Position.deltaX; p[1] += this.options.scroll.scrollTop + Position.deltaY; p.push(p[0] + this.options.scroll.offsetWidth); p.push(p[1] + this.options.scroll.offsetHeight) } var speed = [0, 0]; if (pointer[0] < (p[0] + this.options.scrollSensitivity)) speed[0] = pointer[0] - (p[0] + this.options.scrollSensitivity); if (pointer[1] < (p[1] + this.options.scrollSensitivity)) speed[1] = pointer[1] - (p[1] + this.options.scrollSensitivity); if (pointer[0] > (p[2] - this.options.scrollSensitivity)) speed[0] = pointer[0] - (p[2] - this.options.scrollSensitivity); if (pointer[1] > (p[3] - this.options.scrollSensitivity)) speed[1] = pointer[1] - (p[3] - this.options.scrollSensitivity); this.startScrolling(speed) } if (Prototype.Browser.WebKit) window.scrollBy(0, 0); Event.stop(event) }, finishDrag: function(event, success) { this.dragging = false; if (this.options.quiet) { Position.prepare(); var pointer = [Event.pointerX(event), Event.pointerY(event)]; Droppables.show(pointer, this.element) } if (this.options.ghosting) { if (!this._originallyAbsolute) Position.relativize(this.element); delete this._originallyAbsolute; Element.remove(this._clone); this._clone = null } var dropped = false; if (success) { dropped = Droppables.fire(event, this.element); if (!dropped) dropped = false } if (dropped && this.options.onDropped) this.options.onDropped(this.element); Draggables.notify('onEnd', this, event); var revert = this.options.revert; if (revert && Object.isFunction(revert)) revert = revert(this.element); var d = this.currentDelta(); if (revert && this.options.reverteffect) { if (dropped == 0 || revert != 'failure') this.options.reverteffect(this.element, d[1] - this.delta[1], d[0] - this.delta[0]) } else { this.delta = d } if (this.options.zindex) this.element.style.zIndex = this.originalZ; if (this.options.endeffect) this.options.endeffect(this.element); Draggables.deactivate(this); Droppables.reset() }, keyPress: function(event) { if (event.keyCode != Event.KEY_ESC) return; this.finishDrag(event, false); Event.stop(event) }, endDrag: function(event) { if (!this.dragging) return; this.stopScrolling(); this.finishDrag(event, true); Event.stop(event) }, draw: function(point) { var pos = Position.cumulativeOffset(this.element); if (this.options.ghosting) { var r = Position.realOffset(this.element); pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY } var d = this.currentDelta(); pos[0] -= d[0]; pos[1] -= d[1]; if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { pos[0] -= this.options.scroll.scrollLeft - this.originalScrollLeft; pos[1] -= this.options.scroll.scrollTop - this.originalScrollTop } var p = [0, 1].map(function(i) { return (point[i] - pos[i] - this.offset[i]) } .bind(this)); if (this.options.snap) { if (Object.isFunction(this.options.snap)) { p = this.options.snap(p[0], p[1], this) } else { if (Object.isArray(this.options.snap)) { p = p.map(function(v, i) { return (v / this.options.snap[i]).round() * this.options.snap[i] } .bind(this)) } else { p = p.map(function(v) { return (v / this.options.snap).round() * this.options.snap } .bind(this)) } } } var style = this.element.style; if ((!this.options.constraint) || (this.options.constraint == 'horizontal')) style.left = p[0] + "px"; if ((!this.options.constraint) || (this.options.constraint == 'vertical')) style.top = p[1] + "px"; if (style.visibility == "hidden") style.visibility = "" }, stopScrolling: function() { if (this.scrollInterval) { clearInterval(this.scrollInterval); this.scrollInterval = null; Draggables._lastScrollPointer = null } }, startScrolling: function(speed) { if (!(speed[0] || speed[1])) return; this.scrollSpeed = [speed[0] * this.options.scrollSpeed, speed[1] * this.options.scrollSpeed]; this.lastScrolled = new Date(); this.scrollInterval = setInterval(this.scroll.bind(this), 10) }, scroll: function() { var current = new Date(); var delta = current - this.lastScrolled; this.lastScrolled = current; if (this.options.scroll == window) { with (this._getWindowScroll(this.options.scroll)) { if (this.scrollSpeed[0] || this.scrollSpeed[1]) { var d = delta / 1000; this.options.scroll.scrollTo(left + d * this.scrollSpeed[0], top + d * this.scrollSpeed[1]) } } } else { this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000 } Position.prepare(); Droppables.show(Draggables._lastPointer, this.element); Draggables.notify('onDrag', this); if (this._isScrollChild) { Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; if (Draggables._lastScrollPointer[0] < 0) Draggables._lastScrollPointer[0] = 0; if (Draggables._lastScrollPointer[1] < 0) Draggables._lastScrollPointer[1] = 0; this.draw(Draggables._lastScrollPointer) } if (this.options.change) this.options.change(this) }, _getWindowScroll: function(w) { var T, L, W, H; with (w.document) { if (w.document.documentElement && documentElement.scrollTop) { T = documentElement.scrollTop; L = documentElement.scrollLeft } else if (w.document.body) { T = body.scrollTop; L = body.scrollLeft } if (w.innerWidth) { W = w.innerWidth; H = w.innerHeight } else if (w.document.documentElement && documentElement.clientWidth) { W = documentElement.clientWidth; H = documentElement.clientHeight } else { W = body.offsetWidth; H = body.offsetHeight } } return { top: T, left: L, width: W, height: H} } }); Draggable._dragging = {}; var SortableObserver = Class.create({ initialize: function(element, observer) { this.element = $(element); this.observer = observer; this.lastValue = Sortable.serialize(this.element) }, onStart: function() { this.lastValue = Sortable.serialize(this.element) }, onEnd: function() { Sortable.unmark(); if (this.lastValue != Sortable.serialize(this.element)) this.observer(this.element) } }); var Sortable = { SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/, sortables: {}, _findRootElement: function(element) { while (element.tagName.toUpperCase() != "BODY") { if (element.id && Sortable.sortables[element.id]) return element; element = element.parentNode } }, options: function(element) { element = Sortable._findRootElement($(element)); if (!element) return; return Sortable.sortables[element.id] }, destroy: function(element) { var s = Sortable.options(element); if (s) { Draggables.removeObserver(s.element); s.droppables.each(function(d) { Droppables.remove(d) }); s.draggables.invoke('destroy'); delete Sortable.sortables[s.element.id] } }, create: function(element) { element = $(element); var options = Object.extend({ element: element, tag: 'li', dropOnEmpty: false, tree: false, treeTag: 'ul', overlap: 'vertical', constraint: 'vertical', containment: element, handle: false, only: false, delay: 0, hoverclass: null, ghosting: false, quiet: false, scroll: false, scrollSensitivity: 20, scrollSpeed: 15, format: this.SERIALIZE_RULE, elements: false, handles: false, onChange: Prototype.emptyFunction, onUpdate: Prototype.emptyFunction }, arguments[1] || {}); this.destroy(element); var options_for_draggable = { revert: true, quiet: options.quiet, scroll: options.scroll, scrollSpeed: options.scrollSpeed, scrollSensitivity: options.scrollSensitivity, delay: options.delay, ghosting: options.ghosting, constraint: options.constraint, handle: options.handle }; if (options.starteffect) options_for_draggable.starteffect = options.starteffect; if (options.reverteffect) options_for_draggable.reverteffect = options.reverteffect; else if (options.ghosting) options_for_draggable.reverteffect = function(element) { element.style.top = 0; element.style.left = 0 }; if (options.endeffect) options_for_draggable.endeffect = options.endeffect; if (options.zindex) options_for_draggable.zindex = options.zindex; var options_for_droppable = { overlap: options.overlap, containment: options.containment, tree: options.tree, hoverclass: options.hoverclass, onHover: Sortable.onHover }; var options_for_tree = { onHover: Sortable.onEmptyHover, overlap: options.overlap, containment: options.containment, hoverclass: options.hoverclass }; Element.cleanWhitespace(element); options.draggables = []; options.droppables = []; if (options.dropOnEmpty || options.tree) { Droppables.add(element, options_for_tree); options.droppables.push(element) } (options.elements || this.findElements(element, options) || []).each(function(e, i) { var handle = options.handles ? $(options.handles[i]) : (options.handle ? $(e).select('.' + options.handle)[0] : e); options.draggables.push(new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); Droppables.add(e, options_for_droppable); if (options.tree) e.treeNode = element; options.droppables.push(e) }); if (options.tree) { (Sortable.findTreeElements(element, options) || []).each(function(e) { Droppables.add(e, options_for_tree); e.treeNode = element; options.droppables.push(e) }) } this.sortables[element.id] = options; Draggables.addObserver(new SortableObserver(element, options.onUpdate)) }, findElements: function(element, options) { return Element.findChildren(element, options.only, options.tree ? true : false, options.tag) }, findTreeElements: function(element, options) { return Element.findChildren(element, options.only, options.tree ? true : false, options.treeTag) }, onHover: function(element, dropon, overlap) { if (Element.isParent(dropon, element)) return; if (overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { return } else if (overlap > 0.5) { Sortable.mark(dropon, 'before'); if (dropon.previousSibling != element) { var oldParentNode = element.parentNode; element.style.visibility = "hidden"; dropon.parentNode.insertBefore(element, dropon); if (dropon.parentNode != oldParentNode) Sortable.options(oldParentNode).onChange(element); Sortable.options(dropon.parentNode).onChange(element) } } else { Sortable.mark(dropon, 'after'); var nextElement = dropon.nextSibling || null; if (nextElement != element) { var oldParentNode = element.parentNode; element.style.visibility = "hidden"; dropon.parentNode.insertBefore(element, nextElement); if (dropon.parentNode != oldParentNode) Sortable.options(oldParentNode).onChange(element); Sortable.options(dropon.parentNode).onChange(element) } } }, onEmptyHover: function(element, dropon, overlap) { var oldParentNode = element.parentNode; var droponOptions = Sortable.options(dropon); if (!Element.isParent(dropon, element)) { var index; var children = Sortable.findElements(dropon, { tag: droponOptions.tag, only: droponOptions.only }); var child = null; if (children) { var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); for (index = 0; index < children.length; index += 1) { if (offset - Element.offsetSize(children[index], droponOptions.overlap) >= 0) { offset -= Element.offsetSize(children[index], droponOptions.overlap) } else if (offset - (Element.offsetSize(children[index], droponOptions.overlap) / 2) >= 0) { child = index + 1 < children.length ? children[index + 1] : null; break } else { child = children[index]; break } } } dropon.insertBefore(element, child); Sortable.options(oldParentNode).onChange(element); droponOptions.onChange(element) } }, unmark: function() { if (Sortable._marker) Sortable._marker.hide() }, mark: function(dropon, position) { var sortable = Sortable.options(dropon.parentNode); if (sortable && !sortable.ghosting) return; if (!Sortable._marker) { Sortable._marker = ($('dropmarker') || Element.extend(document.createElement('DIV'))).hide().addClassName('dropmarker').setStyle({ position: 'absolute' }); document.getElementsByTagName("body").item(0).appendChild(Sortable._marker) } var offsets = Position.cumulativeOffset(dropon); Sortable._marker.setStyle({ left: offsets[0] + 'px', top: offsets[1] + 'px' }); if (position == 'after') if (sortable.overlap == 'horizontal') Sortable._marker.setStyle({ left: (offsets[0] + dropon.clientWidth) + 'px' }); else Sortable._marker.setStyle({ top: (offsets[1] + dropon.clientHeight) + 'px' }); Sortable._marker.show() }, _tree: function(element, options, parent) { var children = Sortable.findElements(element, options) || []; for (var i = 0; i < children.length; ++i) { var match = children[i].id.match(options.format); if (!match) continue; var child = { id: encodeURIComponent(match ? match[1] : null), element: element, parent: parent, children: [], position: parent.children.length, container: $(children[i]).down(options.treeTag) }; if (child.container) this._tree(child.container, options, child); parent.children.push(child) } return parent }, tree: function(element) { element = $(element); var sortableOptions = this.options(element); var options = Object.extend({ tag: sortableOptions.tag, treeTag: sortableOptions.treeTag, only: sortableOptions.only, name: element.id, format: sortableOptions.format }, arguments[1] || {}); var root = { id: null, parent: null, children: [], container: element, position: 0 }; return Sortable._tree(element, options, root) }, _constructIndex: function(node) { var index = ''; do { if (node.id) index = '[' + node.position + ']' + index } while ((node = node.parent) != null); return index }, sequence: function(element) { element = $(element); var options = Object.extend(this.options(element), arguments[1] || {}); return $(this.findElements(element, options) || []).map(function(item) { return item.id.match(options.format) ? item.id.match(options.format)[1] : '' }) }, setSequence: function(element, new_sequence) { element = $(element); var options = Object.extend(this.options(element), arguments[2] || {}); var nodeMap = {}; this.findElements(element, options).each(function(n) { if (n.id.match(options.format)) nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode]; n.parentNode.removeChild(n) }); new_sequence.each(function(ident) { var n = nodeMap[ident]; if (n) { n[1].appendChild(n[0]); delete nodeMap[ident] } }) }, serialize: function(element) { element = $(element); var options = Object.extend(Sortable.options(element), arguments[1] || {}); var name = encodeURIComponent((arguments[1] && arguments[1].name) ? arguments[1].name : element.id); if (options.tree) { return Sortable.tree(element, arguments[1]).children.map(function(item) { return [name + Sortable._constructIndex(item) + "[id]=" + encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)) }).flatten().join('&') } else { return Sortable.sequence(element, arguments[1]).map(function(item) { return name + "[]=" + encodeURIComponent(item) }).join('&') } } }; Element.isParent = function(child, element) { if (!child.parentNode || child == element) return false; if (child.parentNode == element) return true; return Element.isParent(child.parentNode, element) }; Element.findChildren = function(element, only, recursive, tagName) { if (!element.hasChildNodes()) return null; tagName = tagName.toUpperCase(); if (only) only = [only].flatten(); var elements = []; $A(element.childNodes).each(function(e) { if (e.tagName && e.tagName.toUpperCase() == tagName && (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) elements.push(e); if (recursive) { var grandchildren = Element.findChildren(e, only, recursive, tagName); if (grandchildren) elements.push(grandchildren) } }); return (elements.length > 0 ? elements.flatten() : []) }; Element.offsetSize = function(element, type) { return element['offset' + ((type == 'vertical' || type == 'height') ? 'Height' : 'Width')] };

/* controls.js */

if (typeof Effect == 'undefined') throw ("controls.js requires including script.aculo.us' effects.js library"); var Autocompleter = {}; Autocompleter.Base = Class.create({ baseInitialize: function(element, update, options) { element = $(element); this.element = element; this.update = $(update); this.hasFocus = false; this.changed = false; this.active = false; this.index = 0; this.entryCount = 0; this.oldElementValue = this.element.value; if (this.setOptions) this.setOptions(options); else this.options = options || {}; this.options.paramName = this.options.paramName || this.element.name; this.options.tokens = this.options.tokens || []; this.options.frequency = this.options.frequency || 0.4; this.options.minChars = this.options.minChars || 1; this.options.onShow = this.options.onShow || function(element, update) { if (!update.style.position || update.style.position == 'absolute') { update.style.position = 'absolute'; Position.clone(element, update, { setHeight: false, offsetTop: element.offsetHeight }) } Effect.Appear(update, { duration: 0.15 }) }; this.options.onHide = this.options.onHide || function(element, update) { new Effect.Fade(update, { duration: 0.15 }) }; if (typeof (this.options.tokens) == 'string') this.options.tokens = new Array(this.options.tokens); if (!this.options.tokens.include('\n')) this.options.tokens.push('\n'); this.observer = null; this.element.setAttribute('autocomplete', 'off'); Element.hide(this.update); Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)) }, show: function() { if (Element.getStyle(this.update, 'display') == 'none') this.options.onShow(this.element, this.update); if (!this.iefix && (Prototype.Browser.IE) && (Element.getStyle(this.update, 'position') == 'absolute')) { new Insertion.After(this.update, '<iframe id="' + this.update.id + '_iefix" ' + 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'); this.iefix = $(this.update.id + '_iefix') } if (this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50) }, fixIEOverlapping: function() { Position.clone(this.update, this.iefix, { setTop: (!this.update.style.height) }); this.iefix.style.zIndex = 1; this.update.style.zIndex = 2; Element.show(this.iefix) }, hide: function() { this.stopIndicator(); if (Element.getStyle(this.update, 'display') != 'none') this.options.onHide(this.element, this.update); if (this.iefix) Element.hide(this.iefix) }, startIndicator: function() { if (this.options.indicator) Element.show(this.options.indicator) }, stopIndicator: function() { if (this.options.indicator) Element.hide(this.options.indicator) }, onKeyPress: function(event) { if (this.active) switch (event.keyCode) { case Event.KEY_TAB: case Event.KEY_RETURN: this.selectEntry(); Event.stop(event); case Event.KEY_ESC: this.hide(); this.active = false; Event.stop(event); return; case Event.KEY_LEFT: case Event.KEY_RIGHT: return; case Event.KEY_UP: this.markPrevious(); this.render(); Event.stop(event); return; case Event.KEY_DOWN: this.markNext(); this.render(); Event.stop(event); return } else if (event.keyCode == Event.KEY_TAB || event.keyCode == Event.KEY_RETURN || (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; this.changed = true; this.hasFocus = true; if (this.observer) clearTimeout(this.observer); this.observer = setTimeout(this.onObserverEvent.bind(this), this.options.frequency * 1000) }, activate: function() { this.changed = false; this.hasFocus = true; this.getUpdatedChoices() }, onHover: function(event) { var element = Event.findElement(event, 'LI'); if (this.index != element.autocompleteIndex) { this.index = element.autocompleteIndex; this.render() } Event.stop(event) }, onClick: function(event) { var element = Event.findElement(event, 'LI'); this.index = element.autocompleteIndex; this.selectEntry(); this.hide() }, onBlur: function(event) { setTimeout(this.hide.bind(this), 250); this.hasFocus = false; this.active = false }, render: function() { if (this.entryCount > 0) { for (var i = 0; i < this.entryCount; i++) this.index == i ? Element.addClassName(this.getEntry(i), "selected") : Element.removeClassName(this.getEntry(i), "selected"); if (this.hasFocus) { this.show(); this.active = true } } else { this.active = false; this.hide() } }, markPrevious: function() { if (this.index > 0) this.index--; else this.index = this.entryCount - 1; this.getEntry(this.index).scrollIntoView(true) }, markNext: function() { if (this.index < this.entryCount - 1) this.index++; else this.index = 0; this.getEntry(this.index).scrollIntoView(false) }, getEntry: function(index) { return this.update.firstChild.childNodes[index] }, getCurrentEntry: function() { return this.getEntry(this.index) }, selectEntry: function() { this.active = false; this.updateElement(this.getCurrentEntry()) }, updateElement: function(selectedElement) { if (this.options.updateElement) { this.options.updateElement(selectedElement); return } var value = ''; if (this.options.select) { var nodes = $(selectedElement).select('.' + this.options.select) || []; if (nodes.length > 0) value = Element.collectTextNodes(nodes[0], this.options.select) } else value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); var bounds = this.getTokenBounds(); if (bounds[0] != -1) { var newValue = this.element.value.substr(0, bounds[0]); var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); if (whitespace) newValue += whitespace[0]; this.element.value = newValue + value + this.element.value.substr(bounds[1]) } else { this.element.value = value } this.oldElementValue = this.element.value; this.element.focus(); if (this.options.afterUpdateElement) this.options.afterUpdateElement(this.element, selectedElement) }, updateChoices: function(choices) { if (!this.changed && this.hasFocus) { this.update.innerHTML = choices; Element.cleanWhitespace(this.update); Element.cleanWhitespace(this.update.down()); if (this.update.firstChild && this.update.down().childNodes) { this.entryCount = this.update.down().childNodes.length; for (var i = 0; i < this.entryCount; i++) { var entry = this.getEntry(i); entry.autocompleteIndex = i; this.addObservers(entry) } } else { this.entryCount = 0 } this.stopIndicator(); this.index = 0; if (this.entryCount == 1 && this.options.autoSelect) { this.selectEntry(); this.hide() } else { this.render() } } }, addObservers: function(element) { Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); Event.observe(element, "click", this.onClick.bindAsEventListener(this)) }, onObserverEvent: function() { this.changed = false; this.tokenBounds = null; if (this.getToken().length >= this.options.minChars) { this.getUpdatedChoices() } else { this.active = false; this.hide() } this.oldElementValue = this.element.value }, getToken: function() { var bounds = this.getTokenBounds(); return this.element.value.substring(bounds[0], bounds[1]).strip() }, getTokenBounds: function() { if (null != this.tokenBounds) return this.tokenBounds; var value = this.element.value; if (value.strip().empty()) return [-1, 0]; var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); var offset = (diff == this.oldElementValue.length ? 1 : 0); var prevTokenPos = -1, nextTokenPos = value.length; var tp; for (var index = 0, l = this.options.tokens.length; index < l; ++index) { tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); if (tp > prevTokenPos) prevTokenPos = tp; tp = value.indexOf(this.options.tokens[index], diff + offset); if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp } return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]) } }); Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { var boundary = Math.min(newS.length, oldS.length); for (var index = 0; index < boundary; ++index) if (newS[index] != oldS[index]) return index; return boundary }; Ajax.Autocompleter = Class.create(Autocompleter.Base, { initialize: function(element, update, url, options) { this.baseInitialize(element, update, options); this.options.asynchronous = true; this.options.onComplete = this.onComplete.bind(this); this.options.defaultParams = this.options.parameters || null; this.url = url }, getUpdatedChoices: function() { this.startIndicator(); var entry = encodeURIComponent(this.options.paramName) + '=' + encodeURIComponent(this.getToken()); this.options.parameters = this.options.callback ? this.options.callback(this.element, entry) : entry; if (this.options.defaultParams) this.options.parameters += '&' + this.options.defaultParams; new Ajax.Request(this.url, this.options) }, onComplete: function(request) { this.updateChoices(request.responseText) } }); Autocompleter.Local = Class.create(Autocompleter.Base, { initialize: function(element, update, array, options) { this.baseInitialize(element, update, options); this.options.array = array }, getUpdatedChoices: function() { this.updateChoices(this.options.selector(this)) }, setOptions: function(options) { this.options = Object.extend({ choices: 10, partialSearch: true, partialChars: 2, ignoreCase: true, fullSearch: false, selector: function(instance) { var ret = []; var partial = []; var entry = instance.getToken(); var count = 0; for (var i = 0; i < instance.options.array.length && ret.length < instance.options.choices; i++) { var elem = instance.options.array[i]; var foundPos = instance.options.ignoreCase ? elem.toLowerCase().indexOf(entry.toLowerCase()) : elem.indexOf(entry); while (foundPos != -1) { if (foundPos == 0 && elem.length != entry.length) { ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + elem.substr(entry.length) + "</li>"); break } else if (entry.length >= instance.options.partialChars && instance.options.partialSearch && foundPos != -1) { if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos - 1, 1))) { partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" + elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(foundPos + entry.length) + "</li>"); break } } foundPos = instance.options.ignoreCase ? elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : elem.indexOf(entry, foundPos + 1) } } if (partial.length) ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)); return "<ul>" + ret.join('') + "</ul>" } }, options || {}) } }); Field.scrollFreeActivate = function(field) { setTimeout(function() { Field.activate(field) }, 1) }; Ajax.InPlaceEditor = Class.create({ initialize: function(element, url, options) { this.url = url; this.element = element = $(element); this.prepareOptions(); this._controls = {}; arguments.callee.dealWithDeprecatedOptions(options); Object.extend(this.options, options || {}); if (!this.options.formId && this.element.id) { this.options.formId = this.element.id + '-inplaceeditor'; if ($(this.options.formId)) this.options.formId = '' } if (this.options.externalControl) this.options.externalControl = $(this.options.externalControl); if (!this.options.externalControl) this.options.externalControlOnly = false; this._originalBackground = this.element.getStyle('background-color') || 'transparent'; this.element.title = this.options.clickToEditText; this._boundCancelHandler = this.handleFormCancellation.bind(this); this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); this._boundFailureHandler = this.handleAJAXFailure.bind(this); this._boundSubmitHandler = this.handleFormSubmission.bind(this); this._boundWrapperHandler = this.wrapUp.bind(this); this.registerListeners() }, checkForEscapeOrReturn: function(e) { if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; if (Event.KEY_ESC == e.keyCode) this.handleFormCancellation(e); else if (Event.KEY_RETURN == e.keyCode) this.handleFormSubmission(e) }, createControl: function(mode, handler, extraClasses) { var control = this.options[mode + 'Control']; var text = this.options[mode + 'Text']; if ('button' == control) { var btn = document.createElement('input'); btn.type = 'submit'; btn.value = text; btn.className = 'editor_' + mode + '_button'; if ('cancel' == mode) btn.onclick = this._boundCancelHandler; this._form.appendChild(btn); this._controls[mode] = btn } else if ('link' == control) { var link = document.createElement('a'); link.href = '#'; link.appendChild(document.createTextNode(text)); link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; link.className = 'editor_' + mode + '_link'; if (extraClasses) link.className += ' ' + extraClasses; this._form.appendChild(link); this._controls[mode] = link } }, createEditField: function() { var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); var fld; if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { fld = document.createElement('input'); fld.type = 'text'; var size = this.options.size || this.options.cols || 0; if (0 < size) fld.size = size } else { fld = document.createElement('textarea'); fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); fld.cols = this.options.cols || 40 } fld.name = this.options.paramName; fld.value = text; fld.className = 'editor_field'; if (this.options.submitOnBlur) fld.onblur = this._boundSubmitHandler; this._controls.editor = fld; if (this.options.loadTextURL) this.loadExternalText(); this._form.appendChild(this._controls.editor) }, createForm: function() { var ipe = this; function addText(mode, condition) { var text = ipe.options['text' + mode + 'Controls']; if (!text || condition === false) return; ipe._form.appendChild(document.createTextNode(text)) }; this._form = $(document.createElement('form')); this._form.id = this.options.formId; this._form.addClassName(this.options.formClassName); this._form.onsubmit = this._boundSubmitHandler; this.createEditField(); if ('textarea' == this._controls.editor.tagName.toLowerCase()) this._form.appendChild(document.createElement('br')); if (this.options.onFormCustomization) this.options.onFormCustomization(this, this._form); addText('Before', this.options.okControl || this.options.cancelControl); this.createControl('ok', this._boundSubmitHandler); addText('Between', this.options.okControl && this.options.cancelControl); this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); addText('After', this.options.okControl || this.options.cancelControl) }, destroy: function() { if (this._oldInnerHTML) this.element.innerHTML = this._oldInnerHTML; this.leaveEditMode(); this.unregisterListeners() }, enterEditMode: function(e) { if (this._saving || this._editing) return; this._editing = true; this.triggerCallback('onEnterEditMode'); if (this.options.externalControl) this.options.externalControl.hide(); this.element.hide(); this.createForm(); this.element.parentNode.insertBefore(this._form, this.element); if (!this.options.loadTextURL) this.postProcessEditField(); if (e) Event.stop(e) }, enterHover: function(e) { if (this.options.hoverClassName) this.element.addClassName(this.options.hoverClassName); if (this._saving) return; this.triggerCallback('onEnterHover') }, getText: function() { return this.element.innerHTML }, handleAJAXFailure: function(transport) { this.triggerCallback('onFailure', transport); if (this._oldInnerHTML) { this.element.innerHTML = this._oldInnerHTML; this._oldInnerHTML = null } }, handleFormCancellation: function(e) { this.wrapUp(); if (e) Event.stop(e) }, handleFormSubmission: function(e) { var form = this._form; var value = $F(this._controls.editor); this.prepareSubmission(); var params = this.options.callback(form, value) || ''; if (Object.isString(params)) params = params.toQueryParams(); params.editorId = this.element.id; if (this.options.htmlResponse) { var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); Object.extend(options, { parameters: params, onComplete: this._boundWrapperHandler, onFailure: this._boundFailureHandler }); new Ajax.Updater({ success: this.element }, this.url, options) } else { var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); Object.extend(options, { parameters: params, onComplete: this._boundWrapperHandler, onFailure: this._boundFailureHandler }); new Ajax.Request(this.url, options) } if (e) Event.stop(e) }, leaveEditMode: function() { this.element.removeClassName(this.options.savingClassName); this.removeForm(); this.leaveHover(); this.element.style.backgroundColor = this._originalBackground; this.element.show(); if (this.options.externalControl) this.options.externalControl.show(); this._saving = false; this._editing = false; this._oldInnerHTML = null; this.triggerCallback('onLeaveEditMode') }, leaveHover: function(e) { if (this.options.hoverClassName) this.element.removeClassName(this.options.hoverClassName); if (this._saving) return; this.triggerCallback('onLeaveHover') }, loadExternalText: function() { this._form.addClassName(this.options.loadingClassName); this._controls.editor.disabled = true; var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); Object.extend(options, { parameters: 'editorId=' + encodeURIComponent(this.element.id), onComplete: Prototype.emptyFunction, onSuccess: function(transport) { this._form.removeClassName(this.options.loadingClassName); var text = transport.responseText; if (this.options.stripLoadedTextTags) text = text.stripTags(); this._controls.editor.value = text; this._controls.editor.disabled = false; this.postProcessEditField() } .bind(this), onFailure: this._boundFailureHandler }); new Ajax.Request(this.options.loadTextURL, options) }, postProcessEditField: function() { var fpc = this.options.fieldPostCreation; if (fpc) $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']() }, prepareOptions: function() { this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); [this._extraDefaultOptions].flatten().compact().each(function(defs) { Object.extend(this.options, defs) } .bind(this)) }, prepareSubmission: function() { this._saving = true; this.removeForm(); this.leaveHover(); this.showSaving() }, registerListeners: function() { this._listeners = {}; var listener; $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { listener = this[pair.value].bind(this); this._listeners[pair.key] = listener; if (!this.options.externalControlOnly) this.element.observe(pair.key, listener); if (this.options.externalControl) this.options.externalControl.observe(pair.key, listener) } .bind(this)) }, removeForm: function() { if (!this._form) return; this._form.remove(); this._form = null; this._controls = {} }, showSaving: function() { this._oldInnerHTML = this.element.innerHTML; this.element.innerHTML = this.options.savingText; this.element.addClassName(this.options.savingClassName); this.element.style.backgroundColor = this._originalBackground; this.element.show() }, triggerCallback: function(cbName, arg) { if ('function' == typeof this.options[cbName]) { this.options[cbName](this, arg) } }, unregisterListeners: function() { $H(this._listeners).each(function(pair) { if (!this.options.externalControlOnly) this.element.stopObserving(pair.key, pair.value); if (this.options.externalControl) this.options.externalControl.stopObserving(pair.key, pair.value) } .bind(this)) }, wrapUp: function(transport) { this.leaveEditMode(); this._boundComplete(transport, this.element) } }); Object.extend(Ajax.InPlaceEditor.prototype, { dispose: Ajax.InPlaceEditor.prototype.destroy }); Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { initialize: function($super, element, url, options) { this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; $super(element, url, options) }, createEditField: function() { var list = document.createElement('select'); list.name = this.options.paramName; list.size = 1; this._controls.editor = list; this._collection = this.options.collection || []; if (this.options.loadCollectionURL) this.loadCollection(); else this.checkForExternalText(); this._form.appendChild(this._controls.editor) }, loadCollection: function() { this._form.addClassName(this.options.loadingClassName); this.showLoadingText(this.options.loadingCollectionText); var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); Object.extend(options, { parameters: 'editorId=' + encodeURIComponent(this.element.id), onComplete: Prototype.emptyFunction, onSuccess: function(transport) { var js = transport.responseText.strip(); if (!/^\[.*\]$/.test(js)) throw ('Server returned an invalid collection representation.'); this._collection = eval(js); this.checkForExternalText() } .bind(this), onFailure: this.onFailure }); new Ajax.Request(this.options.loadCollectionURL, options) }, showLoadingText: function(text) { this._controls.editor.disabled = true; var tempOption = this._controls.editor.firstChild; if (!tempOption) { tempOption = document.createElement('option'); tempOption.value = ''; this._controls.editor.appendChild(tempOption); tempOption.selected = true } tempOption.update((text || '').stripScripts().stripTags()) }, checkForExternalText: function() { this._text = this.getText(); if (this.options.loadTextURL) this.loadExternalText(); else this.buildOptionList() }, loadExternalText: function() { this.showLoadingText(this.options.loadingText); var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); Object.extend(options, { parameters: 'editorId=' + encodeURIComponent(this.element.id), onComplete: Prototype.emptyFunction, onSuccess: function(transport) { this._text = transport.responseText.strip(); this.buildOptionList() } .bind(this), onFailure: this.onFailure }); new Ajax.Request(this.options.loadTextURL, options) }, buildOptionList: function() { this._form.removeClassName(this.options.loadingClassName); this._collection = this._collection.map(function(entry) { return 2 === entry.length ? entry : [entry, entry].flatten() }); var marker = ('value' in this.options) ? this.options.value : this._text; var textFound = this._collection.any(function(entry) { return entry[0] == marker } .bind(this)); this._controls.editor.update(''); var option; this._collection.each(function(entry, index) { option = document.createElement('option'); option.value = entry[0]; option.selected = textFound ? entry[0] == marker : 0 == index; option.appendChild(document.createTextNode(entry[1])); this._controls.editor.appendChild(option) } .bind(this)); this._controls.editor.disabled = false; Field.scrollFreeActivate(this._controls.editor) } }); Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { if (!options) return; function fallback(name, expr) { if (name in options || expr === undefined) return; options[name] = expr }; fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : options.cancelLink == options.cancelButton == false ? false : undefined))); fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : options.okLink == options.okButton == false ? false : undefined))); fallback('highlightColor', options.highlightcolor); fallback('highlightEndColor', options.highlightendcolor) }; Object.extend(Ajax.InPlaceEditor, { DefaultOptions: { ajaxOptions: {}, autoRows: 3, cancelControl: 'link', cancelText: 'cancel', clickToEditText: 'Click to edit', externalControl: null, externalControlOnly: false, fieldPostCreation: 'activate', formClassName: 'inplaceeditor-form', formId: null, highlightColor: '#ffff99', highlightEndColor: '#ffffff', hoverClassName: '', htmlResponse: true, loadingClassName: 'inplaceeditor-loading', loadingText: 'Loading...', okControl: 'button', okText: 'ok', paramName: 'value', rows: 1, savingClassName: 'inplaceeditor-saving', savingText: 'Saving...', size: 0, stripLoadedTextTags: false, submitOnBlur: false, textAfterControls: '', textBeforeControls: '', textBetweenControls: '' }, DefaultCallbacks: { callback: function(form) { return Form.serialize(form) }, onComplete: function(transport, element) { new Effect.Highlight(element, { startcolor: this.options.highlightColor, keepBackgroundImage: true }) }, onEnterEditMode: null, onEnterHover: function(ipe) { ipe.element.style.backgroundColor = ipe.options.highlightColor; if (ipe._effect) ipe._effect.cancel() }, onFailure: function(transport, ipe) { alert('Error communication with the server: ' + transport.responseText.stripTags()) }, onFormCustomization: null, onLeaveEditMode: null, onLeaveHover: function(ipe) { ipe._effect = new Effect.Highlight(ipe.element, { startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, restorecolor: ipe._originalBackground, keepBackgroundImage: true }) } }, Listeners: { click: 'enterEditMode', keydown: 'checkForEscapeOrReturn', mouseover: 'enterHover', mouseout: 'leaveHover'} }); Ajax.InPlaceCollectionEditor.DefaultOptions = { loadingCollectionText: 'Loading options...' }; Form.Element.DelayedObserver = Class.create({ initialize: function(element, delay, callback) { this.delay = delay || 0.5; this.element = $(element); this.callback = callback; this.timer = null; this.lastValue = $F(this.element); Event.observe(this.element, 'keyup', this.delayedListener.bindAsEventListener(this)) }, delayedListener: function(event) { if (this.lastValue == $F(this.element)) return; if (this.timer) clearTimeout(this.timer); this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); this.lastValue = $F(this.element) }, onTimerEvent: function() { this.timer = null; this.callback(this.element, $F(this.element)) } });

/* slider.js */

if (!Control) var Control = {}; Control.Slider = Class.create({ initialize: function(handle, track, options) { var slider = this; if (Object.isArray(handle)) { this.handles = handle.collect(function(e) { return $(e) }) } else { this.handles = [$(handle)] } this.track = $(track); this.options = options || {}; this.axis = this.options.axis || 'horizontal'; this.increment = this.options.increment || 1; this.step = parseInt(this.options.step || '1'); this.range = this.options.range || $R(0, 1); this.value = 0; this.values = this.handles.map(function() { return 0 }); this.spans = this.options.spans ? this.options.spans.map(function(s) { return $(s) }) : false; this.options.startSpan = $(this.options.startSpan || null); this.options.endSpan = $(this.options.endSpan || null); this.restricted = this.options.restricted || false; this.maximum = this.options.maximum || this.range.end; this.minimum = this.options.minimum || this.range.start; this.alignX = parseInt(this.options.alignX || '0'); this.alignY = parseInt(this.options.alignY || '0'); this.trackLength = this.maximumOffset() - this.minimumOffset(); this.handleLength = this.isVertical() ? (this.handles[0].offsetHeight != 0 ? this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/, "")) : (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth : this.handles[0].style.width.replace(/px$/, "")); this.active = false; this.dragging = false; this.disabled = false; if (this.options.disabled) this.setDisabled(); this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false; if (this.allowedValues) { this.minimum = this.allowedValues.min(); this.maximum = this.allowedValues.max() } this.eventMouseDown = this.startDrag.bindAsEventListener(this); this.eventMouseUp = this.endDrag.bindAsEventListener(this); this.eventMouseMove = this.update.bindAsEventListener(this); this.handles.each(function(h, i) { i = slider.handles.length - 1 - i; slider.setValue(parseFloat((Object.isArray(slider.options.sliderValue) ? slider.options.sliderValue[i] : slider.options.sliderValue) || slider.range.start), i); h.makePositioned().observe("mousedown", slider.eventMouseDown) }); this.track.observe("mousedown", this.eventMouseDown); document.observe("mouseup", this.eventMouseUp); document.observe("mousemove", this.eventMouseMove); this.initialized = true }, dispose: function() { var slider = this; Event.stopObserving(this.track, "mousedown", this.eventMouseDown); Event.stopObserving(document, "mouseup", this.eventMouseUp); Event.stopObserving(document, "mousemove", this.eventMouseMove); this.handles.each(function(h) { Event.stopObserving(h, "mousedown", slider.eventMouseDown) }) }, setDisabled: function() { this.disabled = true }, setEnabled: function() { this.disabled = false }, getNearestValue: function(value) { if (this.allowedValues) { if (value >= this.allowedValues.max()) return (this.allowedValues.max()); if (value <= this.allowedValues.min()) return (this.allowedValues.min()); var offset = Math.abs(this.allowedValues[0] - value); var newValue = this.allowedValues[0]; this.allowedValues.each(function(v) { var currentOffset = Math.abs(v - value); if (currentOffset <= offset) { newValue = v; offset = currentOffset } }); return newValue } if (value > this.range.end) return this.range.end; if (value < this.range.start) return this.range.start; return value }, setValue: function(sliderValue, handleIdx) { if (!this.active) { this.activeHandleIdx = handleIdx || 0; this.activeHandle = this.handles[this.activeHandleIdx]; this.updateStyles() } handleIdx = handleIdx || this.activeHandleIdx || 0; if (this.initialized && this.restricted) { if ((handleIdx > 0) && (sliderValue < this.values[handleIdx - 1])) sliderValue = this.values[handleIdx - 1]; if ((handleIdx < (this.handles.length - 1)) && (sliderValue > this.values[handleIdx + 1])) sliderValue = this.values[handleIdx + 1] } sliderValue = this.getNearestValue(sliderValue); this.values[handleIdx] = sliderValue; this.value = this.values[0]; this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] = this.translateToPx(sliderValue); this.drawSpans(); if (!this.dragging || !this.event) this.updateFinished() }, setValueBy: function(delta, handleIdx) { this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta, handleIdx || this.activeHandleIdx || 0) }, translateToPx: function(value) { return Math.round(((this.trackLength - this.handleLength) / (this.range.end - this.range.start)) * (value - this.range.start)) + "px" }, translateToValue: function(offset) { return ((offset / (this.trackLength - this.handleLength) * (this.range.end - this.range.start)) + this.range.start) }, getRange: function(range) { var v = this.values.sortBy(Prototype.K); range = range || 0; return $R(v[range], v[range + 1]) }, minimumOffset: function() { return (this.isVertical() ? this.alignY : this.alignX) }, maximumOffset: function() { return (this.isVertical() ? (this.track.offsetHeight != 0 ? this.track.offsetHeight : this.track.style.height.replace(/px$/, "")) - this.alignY : (this.track.offsetWidth != 0 ? this.track.offsetWidth : this.track.style.width.replace(/px$/, "")) - this.alignX) }, isVertical: function() { return (this.axis == 'vertical') }, drawSpans: function() { var slider = this; if (this.spans) $R(0, this.spans.length - 1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) }); if (this.options.startSpan) this.setSpan(this.options.startSpan, $R(0, this.values.length > 1 ? this.getRange(0).min() : this.value)); if (this.options.endSpan) this.setSpan(this.options.endSpan, $R(this.values.length > 1 ? this.getRange(this.spans.length - 1).max() : this.value, this.maximum)) }, setSpan: function(span, range) { if (this.isVertical()) { span.style.top = this.translateToPx(range.start); span.style.height = this.translateToPx(range.end - range.start + this.range.start) } else { span.style.left = this.translateToPx(range.start); span.style.width = this.translateToPx(range.end - range.start + this.range.start) } }, updateStyles: function() { this.handles.each(function(h) { Element.removeClassName(h, 'selected') }); Element.addClassName(this.activeHandle, 'selected') }, startDrag: function(event) { if (Event.isLeftClick(event)) { if (!this.disabled) { this.active = true; var handle = Event.element(event); var pointer = [Event.pointerX(event), Event.pointerY(event)]; var track = handle; if (track == this.track) { var offsets = Position.cumulativeOffset(this.track); this.event = event; this.setValue(this.translateToValue((this.isVertical() ? pointer[1] - offsets[1] : pointer[0] - offsets[0]) - (this.handleLength / 2))); var offsets = Position.cumulativeOffset(this.activeHandle); this.offsetX = (pointer[0] - offsets[0]); this.offsetY = (pointer[1] - offsets[1]) } else { while ((this.handles.indexOf(handle) == -1) && handle.parentNode) handle = handle.parentNode; if (this.handles.indexOf(handle) != -1) { this.activeHandle = handle; this.activeHandleIdx = this.handles.indexOf(this.activeHandle); this.updateStyles(); var offsets = Position.cumulativeOffset(this.activeHandle); this.offsetX = (pointer[0] - offsets[0]); this.offsetY = (pointer[1] - offsets[1]) } } } Event.stop(event) } }, update: function(event) { if (this.active) { if (!this.dragging) this.dragging = true; this.draw(event); if (Prototype.Browser.WebKit) window.scrollBy(0, 0); Event.stop(event) } }, draw: function(event) { var pointer = [Event.pointerX(event), Event.pointerY(event)]; var offsets = Position.cumulativeOffset(this.track); pointer[0] -= this.offsetX + offsets[0]; pointer[1] -= this.offsetY + offsets[1]; this.event = event; this.setValue(this.translateToValue(this.isVertical() ? pointer[1] : pointer[0])); if (this.initialized && this.options.onSlide) this.options.onSlide(this.values.length > 1 ? this.values : this.value, this) }, endDrag: function(event) { if (this.active && this.dragging) { this.finishDrag(event, true); Event.stop(event) } this.active = false; this.dragging = false }, finishDrag: function(event, success) { this.active = false; this.dragging = false; this.updateFinished() }, updateFinished: function() { if (this.initialized && this.options.onChange) this.options.onChange(this.values.length > 1 ? this.values : this.value, this); this.event = null } });

/* sound.js */

Sound = { tracks: {}, _enabled: true, template: new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'), enable: function() { Sound._enabled = true }, disable: function() { Sound._enabled = false }, play: function(url) { if (!Sound._enabled) return; var options = Object.extend({ track: 'global', url: url, replace: false }, arguments[1] || {}); if (options.replace && this.tracks[options.track]) { $R(0, this.tracks[options.track].id).each(function(id) { var sound = $('sound_' + options.track + '_' + id); sound.Stop && sound.Stop(); sound.remove() }); this.tracks[options.track] = null } if (!this.tracks[options.track]) this.tracks[options.track] = { id: 0 }; else this.tracks[options.track].id++; options.id = this.tracks[options.track].id; $$('body')[0].insert(Prototype.Browser.IE ? new Element('bgsound', { id: 'sound_' + options.track + '_' + options.id, src: options.url, loop: 1, autostart: true }) : Sound.template.evaluate(options)) } }; if (Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0) { if (navigator.plugins && $A(navigator.plugins).detect(function(p) { return p.name.indexOf('QuickTime') != -1 })) Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>'); else Sound.play = function() { } }

/* accordian.js */
if (typeof Effect == 'undefined') throw ("accordion.js requires including script.aculo.us' effects.js library!"); var accordion = Class.create(); accordion.prototype = { showAccordion: null, currentAccordion: null, duration: null, effects: [], animating: false, initialize: function(container, options) { if (!$(container)) { throw (container + " doesn't exist!"); return false } this.options = Object.extend({ resizeSpeed: 8, classNames: { toggle: 'accordion_toggle', toggleActive: 'accordion_toggle_active', content: 'accordion_content' }, defaultSize: { height: null, width: null }, direction: 'vertical', onEvent: 'click' }, options || {}); this.duration = ((11 - this.options.resizeSpeed) * 0.15); var accordions = $$('#' + container + ' .' + this.options.classNames.toggle); accordions.each(function(accordion) { Event.observe(accordion, this.options.onEvent, this.activate.bind(this, accordion), false); if (this.options.onEvent == 'click') { accordion.onclick = function() { return false } } if (this.options.direction == 'horizontal') { var options = $H({ width: '0px' }) } else { var options = $H({ height: '0px' }) } options.merge({ display: 'none' }); this.currentAccordion = $(accordion.next(0)).setStyle(options) } .bind(this)) }, activate: function(accordion) { if (this.animating) { return false } this.effects = []; this.currentAccordion = $(accordion.next(0)); this.currentAccordion.setStyle({ display: 'block' }); this.currentAccordion.previous(0).addClassName(this.options.classNames.toggleActive); if (this.options.direction == 'horizontal') { this.scaling = $H({ scaleX: true, scaleY: false }) } else { this.scaling = $H({ scaleX: false, scaleY: true }) } if (this.currentAccordion == this.showAccordion) { this.deactivate() } else { this._handleAccordion() } }, deactivate: function() { var options = $H({ duration: this.duration, scaleContent: false, transition: Effect.Transitions.sinoidal, queue: { position: 'end', scope: 'accordionAnimation' }, scaleMode: { originalHeight: this.options.defaultSize.height ? this.options.defaultSize.height : this.currentAccordion.scrollHeight, originalWidth: this.options.defaultSize.width ? this.options.defaultSize.width : this.currentAccordion.scrollWidth }, afterFinish: function() { this.showAccordion.setStyle({ height: 'auto', display: 'none' }); this.showAccordion = null; this.animating = false } .bind(this) }); options.merge(this.scaling); this.showAccordion.previous(0).removeClassName(this.options.classNames.toggleActive); new Effect.Scale(this.showAccordion, 0, options) }, _handleAccordion: function() { var options = $H({ sync: true, scaleFrom: 0, scaleContent: false, transition: Effect.Transitions.sinoidal, scaleMode: { originalHeight: this.options.defaultSize.height ? this.options.defaultSize.height : this.currentAccordion.scrollHeight, originalWidth: this.options.defaultSize.width ? this.options.defaultSize.width : this.currentAccordion.scrollWidth} }); options.merge(this.scaling); this.effects.push(new Effect.Scale(this.currentAccordion, 100, options)); if (this.showAccordion) { this.showAccordion.previous(0).removeClassName(this.options.classNames.toggleActive); options = $H({ sync: true, scaleContent: false, transition: Effect.Transitions.sinoidal }); options.merge(this.scaling); this.effects.push(new Effect.Scale(this.showAccordion, 0, options)) } new Effect.Parallel(this.effects, { duration: this.duration, queue: { position: 'end', scope: 'accordionAnimation' }, beforeStart: function() { this.animating = true } .bind(this), afterFinish: function() { if (this.showAccordion) { this.showAccordion.setStyle({ display: 'none' }) } $(this.currentAccordion).setStyle({ height: 'auto' }); this.showAccordion = this.currentAccordion; this.animating = false } .bind(this) }) } }

/* rsh.js */
/*
Copyright (c) 2007 Brian Dillard and Brad Neuberg:
Brian Dillard | Project Lead | bdillard@pathf.com | http://blogs.pathf.com/agileajax/
Brad Neuberg | Original Project Creator | http://codinginparadise.org
   
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

/*
dhtmlHistory: An object that provides history, history data, and bookmarking for DHTML and Ajax applications.
	
dependencies:
* the historyStorage object included in this file.

*/
window.dhtmlHistory = {

	/*Public: User-agent booleans*/
	isIE: false,
	isOpera: false,
	isSafari: false,
	isSafari3: false,
	isKonquerer: false,
	isGecko: false,
	isSupported: false,

	/*Public: Create the DHTML history infrastructure*/
	create: function(options)
	{

		/*
		options - object to store initialization parameters
		options.debugMode - boolean that causes hidden form fields to be shown for development purposes.
		options.toJSON - function to override default JSON stringifier
		options.fromJSON - function to override default JSON parser
		*/

		var that = this;

		/*set user-agent flags*/
		var UA = navigator.userAgent.toLowerCase();
		var platform = navigator.platform.toLowerCase();
		var vendor = navigator.vendor || "";
		var version = (UA.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1];
		if (vendor === "KDE")
		{
			this.isKonqueror = true;
			this.isSupported = false;
		} else if (typeof window.opera !== "undefined")
		{
			this.isOpera = true;
			this.isSupported = true;
		} else if (typeof document.all !== "undefined")
		{
			this.isIE = true;
			this.isSupported = true;
		} else if (vendor.indexOf("Apple Computer, Inc.") > -1)
		{
			if (parseInt(version, 10) < 420) {
				this.isSafari = true;
			} else {
				this.isSafari3 = true;
			}
		    this.isSupported = this.isSafari3;
		} else if (UA.indexOf("gecko") != -1)
		{
			this.isGecko = true;
			this.isSupported = true;
		}

		/*Set up the historyStorage object; pass in init parameters*/
		window.historyStorage.setup(options);

		/*Execute browser-specific setup methods*/
		if (this.isSafari)
		{
			this.createSafari();
		} else if (this.isOpera)
		{
			this.createOpera();
		}

		/*Get our initial location*/
		var initialHash = this.getCurrentLocation();

		/*Save it as our current location*/
		this.currentLocation = initialHash;

		/*Now that we have a hash, create IE-specific code*/
		if (this.isIE)
		{
			this.createIE(initialHash);
		}

		/*Add an unload listener for the page; this is needed for FF 1.5+ because this browser caches all dynamic updates to the
		page, which can break some of our logic related to testing whether this is the first instance a page has loaded or whether
		it is being pulled from the cache*/

		var unloadHandler = function()
		{
			that.firstLoad = null;
		};

		this.addEventListener(window, 'unload', unloadHandler);

		/*Determine if this is our first page load; for IE, we do this in this.iframeLoaded(), which is fired on pageload. We do it
		there because we have no historyStorage at this point, which only exists after the page is finished loading in IE*/
		if (this.isIE)
		{
			/*The iframe will get loaded on page load, and we want to ignore this fact*/
			this.ignoreLocationChange = true;
		} else
		{
			if (!historyStorage.hasKey(this.PAGELOADEDSTRING))
			{
				/*This is our first page load, so ignore the location change and add our special history entry*/
				this.ignoreLocationChange = true;
				this.firstLoad = true;
				historyStorage.put(this.PAGELOADEDSTRING, true);
			} else
			{
				/*This isn't our first page load, so indicate that we want to pay attention to this location change*/
				this.ignoreLocationChange = false;
				/*For browsers other than IE, fire a history change event; on IE, the event will be thrown automatically when its
				hidden iframe reloads on page load. Unfortunately, we don't have any listeners yet; indicate that we want to fire
				an event when a listener is added.*/
				this.fireOnNewListener = true;
			}
		}

		/*Other browsers can use a location handler that checks at regular intervals as their primary mechanism; we use it for IE as
		well to handle an important edge case; see checkLocation() for details*/
		var locationHandler = function()
		{
			that.checkLocation();
		};
		setInterval(locationHandler, 100);
	},

	/*Public: Initialize our DHTML history. You must call this after the page is finished loading.*/
	initialize: function()
	{
		/*IE needs to be explicitly initialized. IE doesn't autofill form data until the page is finished loading, so we have to wait*/
		if (this.isIE)
		{
			/*If this is the first time this page has loaded*/
			if (!historyStorage.hasKey(this.PAGELOADEDSTRING))
			{
				/*For IE, we do this in initialize(); for other browsers, we do it in create()*/
				this.fireOnNewListener = false;
				this.firstLoad = true;
				historyStorage.put(this.PAGELOADEDSTRING, true);
			}
			/*Else if this is a fake onload event*/
			else
			{
				this.fireOnNewListener = true;
				this.firstLoad = false;
			}
		}
	},

	/*Public: Adds a history change listener. Note that only one listener is supported at this time.*/
	addListener: function(listener)
	{
		this.listener = listener;
		/*If the page was just loaded and we should not ignore it, fire an event to our new listener now*/
		if (this.fireOnNewListener)
		{
			this.fireHistoryEvent(this.currentLocation);
			this.fireOnNewListener = false;
		}
	},

	/*Public: Generic utility function for attaching events*/
	addEventListener: function(o, e, l)
	{
		if (o.addEventListener)
		{
			o.addEventListener(e, l, false);
		} else if (o.attachEvent)
		{
			o.attachEvent('on' + e, function()
			{
				l(window.event);
			});
		}
	},

	/*Public: Add a history point.*/
	add: function(newLocation, historyData)
	{

		if (this.isSafari)
		{

			/*Remove any leading hash symbols on newLocation*/
			newLocation = this.removeHash(newLocation);

			/*Store the history data into history storage*/
			historyStorage.put(newLocation, historyData);

			/*Save this as our current location*/
			this.currentLocation = newLocation;

			/*Change the browser location*/
			window.location.hash = newLocation;

			/*Save this to the Safari form field*/
			this.putSafariState(newLocation);

		} else
		{

			/*Most browsers require that we wait a certain amount of time before changing the location, such
			as 200 MS; rather than forcing external callers to use window.setTimeout to account for this,
			we internally handle it by putting requests in a queue.*/
			var that = this;
			var addImpl = function()
			{

				/*Indicate that the current wait time is now less*/
				if (that.currentWaitTime > 0)
				{
					that.currentWaitTime = that.currentWaitTime - that.waitTime;
				}

				/*Remove any leading hash symbols on newLocation*/
				newLocation = that.removeHash(newLocation);

				/*IE has a strange bug; if the newLocation is the same as _any_ preexisting id in the
				document, then the history action gets recorded twice; throw a programmer exception if
				there is an element with this ID*/
				if (document.getElementById(newLocation) && that.debugMode)
				{
					var e = "Exception: History locations can not have the same value as _any_ IDs that might be in the document,"
					+ " due to a bug in IE; please ask the developer to choose a history location that does not match any HTML"
					+ " IDs in this document. The following ID is already taken and cannot be a location: " + newLocation;
					throw new Error(e);
				}

				/*Store the history data into history storage*/
				historyStorage.put(newLocation, historyData);

				/*Indicate to the browser to ignore this upcomming location change since we're making it programmatically*/
				that.ignoreLocationChange = true;

				/*Indicate to IE that this is an atomic location change block*/
				that.ieAtomicLocationChange = true;

				/*Save this as our current location*/
				that.currentLocation = newLocation;

				/*Change the browser location*/
				window.location.hash = newLocation;

				/*Change the hidden iframe's location if on IE*/
				if (that.isIE)
				{
					that.iframe.src = "/js/blank.html?" + newLocation;
				}

				/*End of atomic location change block for IE*/
				that.ieAtomicLocationChange = false;
			};

			/*Now queue up this add request*/
			window.setTimeout(addImpl, this.currentWaitTime);

			/*Indicate that the next request will have to wait for awhile*/
			this.currentWaitTime = this.currentWaitTime + this.waitTime;
		}
	},

	/*Public*/
	isFirstLoad: function()
	{
		return this.firstLoad;
	},

	/*Public*/
	getVersion: function()
	{
		return "0.6";
	},

	/*Get browser's current hash location; for Safari, read value from a hidden form field*/

	/*Public*/
	getCurrentLocation: function()
	{
		var r = (this.isSafari
			? this.getSafariState()
			: this.getCurrentHash()
		);
		return r;
	},

	/*Public: Manually parse the current url for a hash; tip of the hat to YUI*/
	getCurrentHash: function()
	{
		var r = window.location.href;
		var i = r.indexOf("#");
		return (i >= 0
			? r.substr(i + 1)
			: ""
		);
	},

	/*- - - - - - - - - - - -*/

	/*Private: Constant for our own internal history event called when the page is loaded*/
	PAGELOADEDSTRING: "DhtmlHistory_pageLoaded",

	/*Private: Our history change listener.*/
	listener: null,

	/*Private: MS to wait between add requests - will be reset for certain browsers*/
	waitTime: 200,

	/*Private: MS before an add request can execute*/
	currentWaitTime: 0,

	/*Private: Our current hash location, without the "#" symbol.*/
	currentLocation: null,

	/*Private: Hidden iframe used to IE to detect history changes*/
	iframe: null,

	/*Private: Flags and DOM references used only by Safari*/
	safariHistoryStartPoint: null,
	safariStack: null,
	safariLength: null,

	/*Private: Flag used to keep checkLocation() from doing anything when it discovers location changes we've made ourselves
	programmatically with the add() method. Basically, add() sets this to true. When checkLocation() discovers it's true,
	it refrains from firing our listener, then resets the flag to false for next cycle. That way, our listener only gets fired on
	history change events triggered by the user via back/forward buttons and manual hash changes. This flag also helps us set up
	IE's special iframe-based method of handling history changes.*/
	ignoreLocationChange: null,

	/*Private: A flag that indicates that we should fire a history change event when we are ready, i.e. after we are initialized and
	we have a history change listener. This is needed due to an edge case in browsers other than IE; if you leave a page entirely
	then return, we must fire this as a history change event. Unfortunately, we have lost all references to listeners from earlier,
	because JavaScript clears out.*/
	fireOnNewListener: null,

	/*Private: A variable that indicates whether this is the first time this page has been loaded. If you go to a web page, leave it
	for another one, and then return, the page's onload listener fires again. We need a way to differentiate between the first page
	load and subsequent ones. This variable works hand in hand with the pageLoaded variable we store into historyStorage.*/
	firstLoad: null,

	/*Private: A variable to handle an important edge case in IE. In IE, if a user manually types an address into their browser's
	location bar, we must intercept this by calling checkLocation() at regular intervals. However, if we are programmatically
	changing the location bar ourselves using the add() method, we need to ignore these changes in checkLocation(). Unfortunately,
	these changes take several lines of code to complete, so for the duration of those lines of code, we set this variable to true.
	That signals to checkLocation() to ignore the change-in-progress. Once we're done with our chunk of location-change code in
	add(), we set this back to false. We'll do the same thing when capturing user-entered address changes in checkLocation itself.*/
	ieAtomicLocationChange: null,

	/*Private: Create IE-specific DOM nodes and overrides*/
	createIE: function(initialHash)
	{
		/*write out a hidden iframe for IE and set the amount of time to wait between add() requests*/
		this.waitTime = 400; /*IE needs longer between history updates*/
		var styles = (historyStorage.debugMode
			? 'width: 800px;height:80px;border:1px solid black;'
			: historyStorage.hideStyles
		);
		var iframeID = "rshHistoryFrame";
		var iframeHTML = '<iframe frameborder="0" id="' + iframeID + '" style="' + styles + '" src="/js/blank.html?' + initialHash + '"></iframe>';
		document.write(iframeHTML);
		this.iframe = document.getElementById(iframeID);
	},

	/*Private: Create Opera-specific DOM nodes and overrides*/
	createOpera: function()
	{
		this.waitTime = 400; /*Opera needs longer between history updates*/
		var imgHTML = '<img src="javascript:location.href=\'javascript:dhtmlHistory.checkLocation();\';" style="' + historyStorage.hideStyles + '" />';
		document.write(imgHTML);
	},

	/*Private: Create Safari-specific DOM nodes and overrides*/
	createSafari: function()
	{
		var formID = "rshSafariForm";
		var stackID = "rshSafariStack";
		var lengthID = "rshSafariLength";
		var formStyles = historyStorage.debugMode ? historyStorage.showStyles : historyStorage.hideStyles;
		var inputStyles = (historyStorage.debugMode
			? 'width:800px;height:20px;border:1px solid black;margin:0;padding:0;'
			: historyStorage.hideStyles
		);
		var safariHTML = '<form id="' + formID + '" style="' + formStyles + '">'
			+ '<input type="text" style="' + inputStyles + '" id="' + stackID + '" value="[]"/>'
			+ '<input type="text" style="' + inputStyles + '" id="' + lengthID + '" value=""/>'
		+ '</form>';
		document.write(safariHTML);
		this.safariStack = document.getElementById(stackID);
		this.safariLength = document.getElementById(lengthID);
		if (!historyStorage.hasKey(this.PAGELOADEDSTRING))
		{
			this.safariHistoryStartPoint = history.length;
			this.safariLength.value = this.safariHistoryStartPoint;
		} else
		{
			this.safariHistoryStartPoint = this.safariLength.value;
		}
	},

	/*Private: Safari method to read the history stack from a hidden form field*/
	getSafariStack: function()
	{
		var r = this.safariStack.value;
		return historyStorage.fromJSON(r);
	},

	/*Private: Safari method to read from the history stack*/
	getSafariState: function()
	{
		var stack = this.getSafariStack();
		var state = stack[history.length - this.safariHistoryStartPoint - 1];
		return state;
	},
	/*Private: Safari method to write the history stack to a hidden form field*/
	putSafariState: function(newLocation)
	{
		var stack = this.getSafariStack();
		stack[history.length - this.safariHistoryStartPoint] = newLocation;
		this.safariStack.value = historyStorage.toJSON(stack);
	},

	/*Private: Notify the listener of new history changes.*/
	fireHistoryEvent: function(newHash)
	{
		/*extract the value from our history storage for this hash*/
		var historyData = historyStorage.get(newHash);
		/*call our listener*/
		this.listener.call(null, newHash, historyData);
	},

	/*Private: See if the browser has changed location. This is the primary history mechanism for Firefox. For IE, we use this to
	handle an important edge case: if a user manually types in a new hash value into their IE location bar and press enter, we want to
	to intercept this and notify any history listener.*/
	checkLocation: function()
	{

		/*Ignore any location changes that we made ourselves for browsers other than IE*/
		if (!this.isIE && this.ignoreLocationChange)
		{
			this.ignoreLocationChange = false;
			return;
		}

		/*If we are dealing with IE and we are in the middle of making a location change from an iframe, ignore it*/
		if (!this.isIE && this.ieAtomicLocationChange)
		{
			return;
		}

		/*Get hash location*/
		var hash = this.getCurrentLocation();

		/*Do nothing if there's been no change*/
		if (hash == this.currentLocation)
		{
			return;
		}

		/*In IE, users manually entering locations into the browser; we do this by comparing the browser's location against the
		iframe's location; if they differ, we are dealing with a manual event and need to place it inside our history, otherwise
		we can return*/
		this.ieAtomicLocationChange = true;

		if (this.isIE && this.getIframeHash() != hash)
		{
			this.iframe.src = "/js/blank.html?" + hash;
		}
		else if (this.isIE)
		{
			/*the iframe is unchanged*/
			return;
		}

		/*Save this new location*/
		this.currentLocation = hash;

		this.ieAtomicLocationChange = false;

		/*Notify listeners of the change*/
		this.fireHistoryEvent(hash);
	},

	/*Private: Get the current location of IE's hidden iframe.*/
	getIframeHash: function()
	{
		var doc = this.iframe.contentWindow.document;
		var hash = String(doc.location.search);
		if (hash.length == 1 && hash.charAt(0) == "?")
		{
			hash = "";
		}
		else if (hash.length >= 2 && hash.charAt(0) == "?")
		{
			hash = hash.substring(1);
		}
		return hash;
	},

	/*Private: Remove any leading hash that might be on a location.*/
	removeHash: function(hashValue)
	{
		var r;
		if (hashValue === null || hashValue === undefined)
		{
			r = null;
		}
		else if (hashValue === "")
		{
			r = "";
		}
		else if (hashValue.length == 1 && hashValue.charAt(0) == "#")
		{
			r = "";
		}
		else if (hashValue.length > 1 && hashValue.charAt(0) == "#")
		{
			r = hashValue.substring(1);
		}
		else
		{
			r = hashValue;
		}
		return r;
	},

	/*Private: For IE, tell when the hidden iframe has finished loading.*/
	iframeLoaded: function(newLocation)
	{
		/*ignore any location changes that we made ourselves*/
		if (this.ignoreLocationChange)
		{
			this.ignoreLocationChange = false;
			return;
		}

		/*Get the new location*/
		var hash = String(newLocation.search);
		if (hash.length == 1 && hash.charAt(0) == "?")
		{
			hash = "";
		}
		else if (hash.length >= 2 && hash.charAt(0) == "?")
		{
			hash = hash.substring(1);
		}
		/*Keep the browser location bar in sync with the iframe hash*/
		window.location.hash = hash;

		/*Notify listeners of the change*/
		this.fireHistoryEvent(hash);
	}

};

/*
historyStorage: An object that uses a hidden form to store history state across page loads. The mechanism for doing so relies on
the fact that browsers save the text in form data for the life of the browser session, which means the text is still there when
the user navigates back to the page. This object can be used independently of the dhtmlHistory object for caching of Ajax
session information.
	
dependencies: 
* json2007.js (included in a separate file) or alternate JSON methods passed in through an options bundle.
*/
window.historyStorage = {

	/*Public: Set up our historyStorage object for use by dhtmlHistory or other objects*/
	setup: function(options)
	{

		/*
		options - object to store initialization parameters - passed in from dhtmlHistory or directly into historyStorage
		options.debugMode - boolean that causes hidden form fields to be shown for development purposes.
		options.toJSON - function to override default JSON stringifier
		options.fromJSON - function to override default JSON parser
		*/

		/*process init parameters*/
		if (typeof options !== "undefined")
		{
			if (options.debugMode)
			{
				this.debugMode = options.debugMode;
			}
			if (options.toJSON)
			{
				this.toJSON = options.toJSON;
			}
			if (options.fromJSON)
			{
				this.fromJSON = options.fromJSON;
			}
		}

		/*write a hidden form and textarea into the page; we'll stow our history stack here*/
		var formID = "rshStorageForm";
		var textareaID = "rshStorageField";
		var formStyles = this.debugMode ? historyStorage.showStyles : historyStorage.hideStyles;
		var textareaStyles = (historyStorage.debugMode
			? 'width: 800px;height:80px;border:1px solid black;'
			: historyStorage.hideStyles
		);
		var textareaHTML = '<form id="' + formID + '" style="' + formStyles + '">'
			+ '<textarea id="' + textareaID + '" style="' + textareaStyles + '"></textarea>'
		+ '</form>';
		document.write(textareaHTML);
		this.storageField = document.getElementById(textareaID);
		if (typeof window.opera !== "undefined")
		{
			this.storageField.focus(); /*Opera needs to focus this element before persisting values in it*/
		}
	},

	/*Public*/
	put: function(key, value)
	{
		this.assertValidKey(key);
		/*if we already have a value for this, remove the value before adding the new one*/
		if (this.hasKey(key))
		{
			this.remove(key);
		}
		/*store this new key*/
		this.storageHash[key] = value;
		/*save and serialize the hashtable into the form*/
		this.saveHashTable();
	},

	/*Public*/
	get: function(key)
	{
		this.assertValidKey(key);
		/*make sure the hash table has been loaded from the form*/
		this.loadHashTable();
		var value = this.storageHash[key];
		if (value === undefined)
		{
			value = null;
		}
		return value;
	},

	/*Public*/
	remove: function(key)
	{
		this.assertValidKey(key);
		/*make sure the hash table has been loaded from the form*/
		this.loadHashTable();
		/*delete the value*/
		delete this.storageHash[key];
		/*serialize and save the hash table into the form*/
		this.saveHashTable();
	},

	/*Public: Clears out all saved data.*/
	reset: function()
	{
		this.storageField.value = "";
		this.storageHash = {};
	},

	/*Public*/
	hasKey: function(key)
	{
		this.assertValidKey(key);
		/*make sure the hash table has been loaded from the form*/
		this.loadHashTable();
		return (typeof this.storageHash[key] !== "undefined");
	},

	/*Public*/
	isValidKey: function(key)
	{
		return (typeof key === "string");
	},

	/*Public - CSS strings utilized by both objects to hide or show behind-the-scenes DOM elements*/
	showStyles: 'border:0;margin:0;padding:0;',
	hideStyles: 'left:-1000px;top:-1000px;width:1px;height:1px;border:0;position:absolute;',

	/*Public - debug mode flag*/
	debugMode: false,

	/*- - - - - - - - - - - -*/

	/*Private: Our hash of key name/values.*/
	storageHash: {},

	/*Private: If true, we have loaded our hash table out of the storage form.*/
	hashLoaded: false,

	/*Private: DOM reference to our history field*/
	storageField: null,

	/*Private: Assert that a key is valid; throw an exception if it not.*/
	assertValidKey: function(key)
	{
		var isValid = this.isValidKey(key);
		if (!isValid && this.debugMode)
		{
			throw new Error("Please provide a valid key for window.historyStorage. Invalid key = " + key + ".");
		}
	},

	/*Private: Load the hash table up from the form.*/
	loadHashTable: function()
	{
		if (!this.hashLoaded)
		{
			var serializedHashTable = this.storageField.value;
			if (serializedHashTable !== "" && serializedHashTable !== null)
			{
				this.storageHash = this.fromJSON(serializedHashTable);
				this.hashLoaded = true;
			}
		}
	},
	/*Private: Save the hash table into the form.*/
	saveHashTable: function()
	{
		this.loadHashTable();
		var serializedHashTable = this.toJSON(this.storageHash);
		this.storageField.value = serializedHashTable;
	},
	/*Private: Bridges for our JSON implementations - both rely on 2007 JSON.org library - can be overridden by options bundle*/
	toJSON: function(o)
	{
		return o.toJSONString();
	},
	fromJSON: function(s)
	{
		return s.parseJSON();
	}
};

Ajax.CachedRequest = Class.create(Ajax.Request, {
	initialize: function($super, url, options)
	{
		options = options || {};
		var onSuccess = options.onSuccess || Prototype.K;

		if (!Ajax.CachedRequest.cache[url + '?' + Object.toQueryString(options.parameters)] || options.reload)
		{
			options.onSuccess = function(transport)
			{
				Ajax.CachedRequest.cache[url + '?' + Object.toQueryString(options.parameters)] = transport.responseText;
				onSuccess(transport);
			}
			$super(url, options);
		}
		else
		{
			this.dispatch.defer();
			onSuccess(Ajax.CachedRequest.cache[url + '?' + Object.toQueryString(options.parameters)]);
			
			//[onSuccess, options.onComplete].each(function(m) { m && m() });
		}
	},

	dispatch: function()
	{
		Ajax.Responders.dispatch('onComplete', null);
	}
});

Ajax.CachedRequest.cache = {};

/**
* SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
*
* SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
*/
if (typeof deconcept == "undefined") { var deconcept = new Object(); } if (typeof deconcept.util == "undefined") { deconcept.util = new Object(); } if (typeof deconcept.SWFObjectUtil == "undefined") { deconcept.SWFObjectUtil = new Object(); } deconcept.SWFObject = function(_1, id, w, h, _5, c, _7, _8, _9, _a) { if (!document.getElementById) { return; } this.DETECT_KEY = _a ? _a : "detectflash"; this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY); this.params = new Object(); this.variables = new Object(); this.attributes = new Array(); if (_1) { this.setAttribute("swf", _1); } if (id) { this.setAttribute("id", id); } if (w) { this.setAttribute("width", w); } if (h) { this.setAttribute("height", h); } if (_5) { this.setAttribute("version", new deconcept.PlayerVersion(_5.toString().split("."))); } this.installedVer = deconcept.SWFObjectUtil.getPlayerVersion(); if (!window.opera && document.all && this.installedVer.major > 7) { deconcept.SWFObject.doPrepUnload = true; } if (c) { this.addParam("bgcolor", c); } var q = _7 ? _7 : "high"; this.addParam("quality", q); this.setAttribute("useExpressInstall", false); this.setAttribute("doExpressInstall", false); var _c = (_8) ? _8 : window.location; this.setAttribute("xiRedirectUrl", _c); this.setAttribute("redirectUrl", ""); if (_9) { this.setAttribute("redirectUrl", _9); } }; deconcept.SWFObject.prototype = { useExpressInstall: function(_d) { this.xiSWFPath = !_d ? "expressinstall.swf" : _d; this.setAttribute("useExpressInstall", true); }, setAttribute: function(_e, _f) { this.attributes[_e] = _f; }, getAttribute: function(_10) { return this.attributes[_10]; }, addParam: function(_11, _12) { this.params[_11] = _12; }, getParams: function() { return this.params; }, addVariable: function(_13, _14) { this.variables[_13] = _14; }, getVariable: function(_15) { return this.variables[_15]; }, getVariables: function() { return this.variables; }, getVariablePairs: function() { var _16 = new Array(); var key; var _18 = this.getVariables(); for (key in _18) { _16[_16.length] = key + "=" + _18[key]; } return _16; }, getSWFHTML: function() { var _19 = ""; if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) { if (this.getAttribute("doExpressInstall")) { this.addVariable("MMplayerType", "PlugIn"); this.setAttribute("swf", this.xiSWFPath); } _19 = "<embed type=\"application/x-shockwave-flash\" src=\"" + this.getAttribute("swf") + "\" width=\"" + this.getAttribute("width") + "\" height=\"" + this.getAttribute("height") + "\" style=\"" + this.getAttribute("style") + "\""; _19 += " id=\"" + this.getAttribute("id") + "\" name=\"" + this.getAttribute("id") + "\" "; var _1a = this.getParams(); for (var key in _1a) { _19 += [key] + "=\"" + _1a[key] + "\" "; } var _1c = this.getVariablePairs().join("&"); if (_1c.length > 0) { _19 += "flashvars=\"" + _1c + "\""; } _19 += "/>"; } else { if (this.getAttribute("doExpressInstall")) { this.addVariable("MMplayerType", "ActiveX"); this.setAttribute("swf", this.xiSWFPath); } _19 = "<object id=\"" + this.getAttribute("id") + "\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\"" + this.getAttribute("width") + "\" height=\"" + this.getAttribute("height") + "\" style=\"" + this.getAttribute("style") + "\">"; _19 += "<param name=\"movie\" value=\"" + this.getAttribute("swf") + "\" />"; var _1d = this.getParams(); for (var key in _1d) { _19 += "<param name=\"" + key + "\" value=\"" + _1d[key] + "\" />"; } var _1f = this.getVariablePairs().join("&"); if (_1f.length > 0) { _19 += "<param name=\"flashvars\" value=\"" + _1f + "\" />"; } _19 += "</object>"; } return _19; }, write: function(_20) { if (this.getAttribute("useExpressInstall")) { var _21 = new deconcept.PlayerVersion([6, 0, 65]); if (this.installedVer.versionIsValid(_21) && !this.installedVer.versionIsValid(this.getAttribute("version"))) { this.setAttribute("doExpressInstall", true); this.addVariable("MMredirectURL", escape(this.getAttribute("xiRedirectUrl"))); document.title = document.title.slice(0, 47) + " - Flash Player Installation"; this.addVariable("MMdoctitle", document.title); } } if (this.skipDetect || this.getAttribute("doExpressInstall") || this.installedVer.versionIsValid(this.getAttribute("version"))) { var n = (typeof _20 == "string") ? document.getElementById(_20) : _20; n.innerHTML = this.getSWFHTML(); return true; } else { if (this.getAttribute("redirectUrl") != "") { document.location.replace(this.getAttribute("redirectUrl")); } } return false; } }; deconcept.SWFObjectUtil.getPlayerVersion = function() { var _23 = new deconcept.PlayerVersion([0, 0, 0]); if (navigator.plugins && navigator.mimeTypes.length) { var x = navigator.plugins["Shockwave Flash"]; if (x && x.description) { _23 = new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/, "").replace(/(\s+r|\s+b[0-9]+)/, ".").split(".")); } } else { if (navigator.userAgent && navigator.userAgent.indexOf("Windows CE") >= 0) { var axo = 1; var _26 = 3; while (axo) { try { _26++; axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + _26); _23 = new deconcept.PlayerVersion([_26, 0, 0]); } catch (e) { axo = null; } } } else { try { var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"); } catch (e) { try { var axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"); _23 = new deconcept.PlayerVersion([6, 0, 21]); axo.AllowScriptAccess = "always"; } catch (e) { if (_23.major == 6) { return _23; } } try { axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); } catch (e) { } } if (axo != null) { _23 = new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(",")); } } } return _23; }; deconcept.PlayerVersion = function(_29) { this.major = _29[0] != null ? parseInt(_29[0]) : 0; this.minor = _29[1] != null ? parseInt(_29[1]) : 0; this.rev = _29[2] != null ? parseInt(_29[2]) : 0; }; deconcept.PlayerVersion.prototype.versionIsValid = function(fv) { if (this.major < fv.major) { return false; } if (this.major > fv.major) { return true; } if (this.minor < fv.minor) { return false; } if (this.minor > fv.minor) { return true; } if (this.rev < fv.rev) { return false; } return true; }; deconcept.util = { getRequestParameter: function(_2b) { var q = document.location.search || document.location.hash; if (_2b == null) { return q; } if (q) { var _2d = q.substring(1).split("&"); for (var i = 0; i < _2d.length; i++) { if (_2d[i].substring(0, _2d[i].indexOf("=")) == _2b) { return _2d[i].substring((_2d[i].indexOf("=") + 1)); } } } return ""; } }; deconcept.SWFObjectUtil.cleanupSWFs = function() { var _2f = document.getElementsByTagName("OBJECT"); for (var i = _2f.length - 1; i >= 0; i--) { _2f[i].style.display = "none"; for (var x in _2f[i]) { if (typeof _2f[i][x] == "function") { _2f[i][x] = function() { }; } } } }; if (deconcept.SWFObject.doPrepUnload) { if (!deconcept.unloadSet) { deconcept.SWFObjectUtil.prepUnload = function() { __flash_unloadHandler = function() { }; __flash_savedUnloadHandler = function() { }; window.attachEvent("onunload", deconcept.SWFObjectUtil.cleanupSWFs); }; window.attachEvent("onbeforeunload", deconcept.SWFObjectUtil.prepUnload); deconcept.unloadSet = true; } } if (!document.getElementById && document.all) { document.getElementById = function(id) { return document.all[id]; }; } var getQueryParamValue = deconcept.util.getRequestParameter; var FlashObject = deconcept.SWFObject; var SWFObject = deconcept.SWFObject;