

/*  Prototype JavaScript framework, version 1.6.0.3
*  (c) 2005-2008 Sam Stephenson
*
*  Prototype is freely distributable under the terms of an MIT-style license.
*  For details, see the Prototype web site: http://www.prototypejs.org/
*
*--------------------------------------------------------------------------*/
var Prototype = {
Version: '1.6.0.3',
Browser: {
IE:     !!(window.attachEvent &&
navigator.userAgent.indexOf('Opera') === -1),
Opera:  navigator.userAgent.indexOf('Opera') > -1,
WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
Gecko:  navigator.userAgent.indexOf('Gecko') > -1 &&
navigator.userAgent.indexOf('KHTML') === -1,
MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
},
BrowserFeatures: {
XPath: !!document.evaluate,
SelectorsAPI: !!document.querySelector,
ElementExtensions: !!window.HTMLElement,
SpecificElementExtensions:
document.createElement('div')['__proto__'] &&
document.createElement('div')['__proto__'] !==
document.createElement('form')['__proto__']
},
ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
emptyFunction: function() { },
K: function(x) { return x }
};
if (Prototype.Browser.MobileSafari)
Prototype.BrowserFeatures.SpecificElementExtensions = false;
/* Based on Alex Arnell's inheritance implementation. */
var Class = {
create: function() {
var parent = null, properties = $A(arguments);
if (Object.isFunction(properties[0]))
parent = properties.shift();
function klass() {
this.initialize.apply(this, arguments);
}
Object.extend(klass, Class.Methods);
klass.superclass = parent;
klass.subclasses = [];
if (parent) {
var subclass = function() { };
subclass.prototype = parent.prototype;
klass.prototype = new subclass;
parent.subclasses.push(klass);
}
for (var i = 0; i < properties.length; i++)
klass.addMethods(properties[i]);
if (!klass.prototype.initialize)
klass.prototype.initialize = Prototype.emptyFunction;
klass.prototype.constructor = klass;
return klass;
}
};
Class.Methods = {
addMethods: function(source) {
var ancestor   = this.superclass && this.superclass.prototype;
var properties = Object.keys(source);
if (!Object.keys({ toString: true }).length)
properties.push("toString", "valueOf");
for (var i = 0, length = properties.length; i < length; i++) {
var property = properties[i], value = source[property];
if (ancestor && Object.isFunction(value) &&
value.argumentNames().first() == "$super") {
var method = value;
value = (function(m) {
return function() { return ancestor[m].apply(this, arguments) };
})(property).wrap(method);
value.valueOf = method.valueOf.bind(method);
value.toString = method.toString.bind(method);
}
this.prototype[property] = value;
}
return this;
}
};
var Abstract = { };
Object.extend = function(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
};
Object.extend(Object, {
inspect: function(object) {
try {
if (Object.isUndefined(object)) return 'undefined';
if (object === null) return 'null';
return object.inspect ? object.inspect() : String(object);
} catch (e) {
if (e instanceof RangeError) return '...';
throw e;
}
},
toJSON: function(object) {
var type = typeof object;
switch (type) {
case 'undefined':
case 'function':
case 'unknown': return;
case 'boolean': return object.toString();
}
if (object === null) return 'null';
if (object.toJSON) return object.toJSON();
if (Object.isElement(object)) return;
var results = [];
for (var property in object) {
var value = Object.toJSON(object[property]);
if (!Object.isUndefined(value))
results.push(property.toJSON() + ': ' + value);
}
return '{' + results.join(', ') + '}';
},
toQueryString: function(object) {
return $H(object).toQueryString();
},
toHTML: function(object) {
return object && object.toHTML ? object.toHTML() : String.interpret(object);
},
keys: function(object) {
var keys = [];
for (var property in object)
keys.push(property);
return keys;
},
values: function(object) {
var values = [];
for (var property in object)
values.push(object[property]);
return values;
},
clone: function(object) {
return Object.extend({ }, object);
},
isElement: function(object) {
return !!(object && object.nodeType == 1);
},
isArray: function(object) {
return object != null && typeof object == "object" &&
'splice' in object && 'join' in object;
},
isHash: function(object) {
return object instanceof Hash;
},
isFunction: function(object) {
return typeof object == "function";
},
isString: function(object) {
return typeof object == "string";
},
isNumber: function(object) {
return typeof object == "number";
},
isUndefined: function(object) {
return typeof object == "undefined";
}
});
Object.extend(Function.prototype, {
argumentNames: function() {
var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
.replace(/\s+/g, '').split(',');
return names.length == 1 && !names[0] ? [] : names;
},
bind: function() {
if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
var __method = this, args = $A(arguments), object = args.shift();
return function() {
return __method.apply(object, args.concat($A(arguments)));
}
},
bindAsEventListener: function() {
var __method = this, args = $A(arguments), object = args.shift();
return function(event) {
return __method.apply(object, [event || window.event].concat(args));
}
},
curry: function() {
if (!arguments.length) return this;
var __method = this, args = $A(arguments);
return function() {
return __method.apply(this, args.concat($A(arguments)));
}
},
delay: function() {
var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
return window.setTimeout(function() {
return __method.apply(__method, args);
}, timeout);
},
defer: function() {
var args = [0.01].concat($A(arguments));
return this.delay.apply(this, args);
},
wrap: function(wrapper) {
var __method = this;
return function() {
return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
}
},
methodize: function() {
if (this._methodized) return this._methodized;
var __method = this;
return this._methodized = function() {
return __method.apply(null, [this].concat($A(arguments)));
};
}
});
Date.prototype.toJSON = function() {
return '"' + this.getUTCFullYear() + '-' +
(this.getUTCMonth() + 1).toPaddedString(2) + '-' +
this.getUTCDate().toPaddedString(2) + 'T' +
this.getUTCHours().toPaddedString(2) + ':' +
this.getUTCMinutes().toPaddedString(2) + ':' +
this.getUTCSeconds().toPaddedString(2) + 'Z"';
};
var Try = {
these: function() {
var returnValue;
for (var i = 0, length = arguments.length; i < length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
} catch (e) { }
}
return returnValue;
}
};
RegExp.prototype.match = RegExp.prototype.test;
RegExp.escape = function(str) {
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
/*--------------------------------------------------------------------------*/
var PeriodicalExecuter = Class.create({
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
this.currentlyExecuting = false;
this.registerCallback();
},
registerCallback: function() {
this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
execute: function() {
this.callback(this);
},
stop: function() {
if (!this.timer) return;
clearInterval(this.timer);
this.timer = null;
},
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
this.execute();
} finally {
this.currentlyExecuting = false;
}
}
}
});
Object.extend(String, {
interpret: function(value) {
return value == null ? '' : String(value);
},
specialChar: {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'\\': '\\\\'
}
});
Object.extend(String.prototype, {
gsub: function(pattern, replacement) {
var result = '', source = this, match;
replacement = arguments.callee.prepareReplacement(replacement);
while (source.length > 0) {
if (match = source.match(pattern)) {
result += source.slice(0, match.index);
result += String.interpret(replacement(match));
source  = source.slice(match.index + match[0].length);
} else {
result += source, source = '';
}
}
return result;
},
sub: function(pattern, replacement, count) {
replacement = this.gsub.prepareReplacement(replacement);
count = Object.isUndefined(count) ? 1 : count;
return this.gsub(pattern, function(match) {
if (--count < 0) return match[0];
return replacement(match);
});
},
scan: function(pattern, iterator) {
this.gsub(pattern, iterator);
return String(this);
},
truncate: function(length, truncation) {
length = length || 30;
truncation = Object.isUndefined(truncation) ? '...' : truncation;
return this.length > length ?
this.slice(0, length - truncation.length) + truncation : String(this);
},
strip: function() {
return this.replace(/^\s+/, '').replace(/\s+$/, '');
},
stripTags: function() {
return this.replace(/<\/?[^>]+>/gi, '');
},
stripScripts: function() {
return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
},
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.stripTags().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('')
});
String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.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;
try {
this._each(function(value) {
iterator.call(context, value, index++);
});
} catch (e) {
if (e != $break) throw e;
}
return this;
},
eachSlice: function(number, iterator, context) {
var index = -number, slices = [], array = this.toArray();
if (number < 1) return array;
while ((index += number) < array.length)
slices.push(array.slice(index, index+number));
return slices.collect(iterator, context);
},
all: function(iterator, context) {
iterator = iterator || Prototype.K;
var result = true;
this.each(function(value, index) {
result = result && !!iterator.call(context, value, index);
if (!result) throw $break;
});
return result;
},
any: function(iterator, context) {
iterator = iterator || Prototype.K;
var result = false;
this.each(function(value, index) {
if (result = !!iterator.call(context, value, index))
throw $break;
});
return result;
},
collect: function(iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
this.each(function(value, index) {
results.push(iterator.call(context, value, index));
});
return results;
},
detect: function(iterator, context) {
var result;
this.each(function(value, index) {
if (iterator.call(context, value, index)) {
result = value;
throw $break;
}
});
return result;
},
findAll: function(iterator, context) {
var results = [];
this.each(function(value, index) {
if (iterator.call(context, value, index))
results.push(value);
});
return results;
},
grep: function(filter, iterator, context) {
iterator = iterator || Prototype.K;
var results = [];
if (Object.isString(filter))
filter = new RegExp(filter);
this.each(function(value, index) {
if (filter.match(value))
results.push(iterator.call(context, 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) {
this.each(function(value, index) {
memo = iterator.call(context, 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 || Prototype.K;
var result;
this.each(function(value, index) {
value = iterator.call(context, value, index);
if (result == null || value >= result)
result = value;
});
return result;
},
min: function(iterator, context) {
iterator = iterator || Prototype.K;
var result;
this.each(function(value, index) {
value = iterator.call(context, value, index);
if (result == null || value < result)
result = value;
});
return result;
},
partition: function(iterator, context) {
iterator = iterator || Prototype.K;
var trues = [], falses = [];
this.each(function(value, index) {
(iterator.call(context, 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) {
var results = [];
this.each(function(value, index) {
if (!iterator.call(context, value, index))
results.push(value);
});
return results;
},
sortBy: function(iterator, context) {
return this.map(function(value, index) {
return {
value: value,
criteria: iterator.call(context, 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 [];
// In Safari, only use the `toArray` method if it's not a NodeList.
// A NodeList is a function, has an function `item` property, and a numeric
// `length` property. Adapted from Google Doctype.
if (!(typeof iterable === 'function' && typeof iterable.length ===
'number' && typeof iterable.item === 'function') && 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(', ') + ']';
}
});
// use native browser JS 1.6 implementation if available
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, context) {
$R(0, this, true).each(iterator, context);
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) {
// simulating poorly supported hasOwnProperty
if (this._object[key] !== Object.prototype[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.inject([], function(results, pair) {
var key = encodeURIComponent(pair.key), values = pair.value;
if (values && typeof values == 'object') {
if (Object.isArray(values))
return results.concat(values.map(toQueryPair.curry(key)));
} else results.push(toQueryPair(key, values));
return results;
}).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)) {
// simulate other verbs over post
params['_method'] = this.method;
this.method = 'post';
}
this.parameters = params;
if (params = Object.toQueryString(params)) {
// when GET, append parameters to URL
if (this.method == 'get')
this.url += (this.url.include('?') ? '&' : '?') + params;
else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
params += '&_=';
}
try {
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);
/* Force Firefox to handle ready state 4 for synchronous requests */
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 : '');
/* Force "Connection: close" for older Mozilla browsers to work
* around a bug where XMLHttpRequest sends an incorrect
* Content-length header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType &&
(navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
headers['Connection'] = 'close';
}
// user-defined headers
if (typeof this.options.requestHeaders == 'object') {
var extras = this.options.requestHeaders;
if (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') {
// avoid memory leak in MSIE: clean up
this.transport.onreadystatechange = Prototype.emptyFunction;
}
},
isSameOrigin: function() {
var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
return !m || (m[0] == '#{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) {
// DOM level 2 ECMAScript Language Binding
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 || { });
if (element) this.Element.prototype = element.prototype;
}).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 = $(element);
element.style.display = 'none';
return element;
},
show: function(element) {
element = $(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(element, 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);
},
// removes whitespace-only text node children
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);
if (element.compareDocumentPosition)
return (element.compareDocumentPosition(ancestor) & 8) === 8;
if (ancestor.contains)
return ancestor.contains(element) && ancestor !== element;
while (element = element.parentNode)
if (element == ancestor) 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[style];
if (!value || value == 'auto') {
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) // Safari bug
return {width: element.offsetWidth, height: element.offsetHeight};
// All *Width and *Height properties give 0 on elements with display none,
// so enable the element temporarily
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';
// Opera returns the offset relative to the positioning context, when an
// element is position relative but top and left have not been defined
if (Prototype.Browser.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.toUpperCase() == '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 element;
// Position.prepare(); // To be done manually by Scripty when it needs it.
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;
// Position.prepare(); // To be done manually by Scripty when it needs it.
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;
do {
valueT += element.offsetTop  || 0;
valueL += element.offsetLeft || 0;
// Safari fix
if (element.offsetParent == document.body &&
Element.getStyle(element, 'position') == 'absolute') break;
} while (element = element.offsetParent);
element = forElement;
do {
if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
valueT -= element.scrollTop  || 0;
valueL -= element.scrollLeft || 0;
}
} while (element = element.parentNode);
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] || { });
// find page position of source
source = $(source);
var p = source.viewportOffset();
// find coordinate system to use
element = $(element);
var delta = [0, 0];
var parent = null;
// delta [0,0] will do fine with position: fixed elements,
// position:absolute needs offsetParent deltas
if (Element.getStyle(element, 'position') == 'absolute') {
parent = element.getOffsetParent();
delta = parent.viewportOffset();
}
// correct by body offsets (fixes Safari)
if (parent == document.body) {
delta[0] -= document.body.offsetLeft;
delta[1] -= document.body.offsetTop;
}
// set position
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':
// returns '0px' for hidden elements; we want it to return null
if (!Element.visible(element)) return null;
// returns the border-box dimensions rather than the content-box
// dimensions, so we subtract padding and borders from the value
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) {
// IE doesn't report offsets correctly for static elements, so we change them
// to "relative" to get the values, then change them back.
Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
function(proceed, element) {
element = $(element);
// IE throws an error if element is not in document
try { element.offsetParent }
catch(e) { return $(document.body) }
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);
try { element.offsetParent }
catch(e) { return Element._returnOffset(0,0) }
var position = element.getStyle('position');
if (position !== 'static') return proceed(element);
// Trigger hasLayout on the offset parent so that IE6 reports
// accurate offsetTop and offsetLeft values for position: fixed.
var offsetParent = element.getOffsetParent();
if (offsetParent && offsetParent.getStyle('position') === 'fixed')
offsetParent.setStyle({ zoom: 1 });
element.setStyle({ position: 'relative' });
var value = proceed(element);
element.setStyle({ position: position });
return value;
}
);
});
Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
function(proceed, element) {
try { element.offsetParent }
catch(e) { return Element._returnOffset(0,0) }
return proceed(element);
}
);
Element.Methods.getStyle = function(element, style) {
element = $(element);
style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
var value = 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 frameBorder').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.toUpperCase() == 'IMG' && element.width) {
element.width++; element.width--;
} else try {
var n = document.createTextNode(' ');
element.appendChild(n);
element.removeChild(n);
} catch (e) { }
return element;
};
// Safari returns margins on body which is incorrect if the child is absolutely
// positioned.  For performance reasons, redefine Element#cumulativeOffset for
// KHTML/WebKit only.
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) {
// IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
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.toUpperCase(), property, value;
// extend methods for specific tags
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() {
// extend methods for all tags (Safari doesn't need this)
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 = { }, B = Prototype.Browser;
$w('width height').each(function(d) {
var D = d.capitalize();
if (B.WebKit && !document.evaluate) {
// Safari <3.0 needs self.innerWidth/Height
dimensions[d] = self['inner' + D];
} else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
// Opera <9.5 needs document.body.clientWidth/Height
dimensions[d] = document.body['client' + D]
} else {
dimensions[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);
}
};
/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
* part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
* license.  Please see http://www.yui-ext.com/ for more information. */
var Selector = Class.create({
initialize: function(expression) {
this.expression = expression.strip();
if (this.shouldUseSelectorsAPI()) {
this.mode = 'selectorsAPI';
} else if (this.shouldUseXPath()) {
this.mode = 'xpath';
this.compileXPathMatcher();
} else {
this.mode = "normal";
this.compileMatcher();
}
},
shouldUseXPath: function() {
if (!Prototype.BrowserFeatures.XPath) return false;
var e = this.expression;
// Safari 3 chokes on :*-of-type and :empty
if (Prototype.Browser.WebKit &&
(e.include("-of-type") || e.include(":empty")))
return false;
// XPath can't do namespaced attributes, nor can it read
// the "checked" property from DOM nodes
if ((/(\[[\w-]*?:|:checked)/).test(e))
return false;
return true;
},
shouldUseSelectorsAPI: function() {
if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
if (!Selector._div) Selector._div = new Element('div');
// Make sure the browser treats the selector as valid. Test on an
// isolated element to minimize cost of this check.
try {
Selector._div.querySelector(this.expression);
} catch(e) {
return false;
}
return true;
},
compileMatcher: function() {
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;
var e = this.expression, results;
switch (this.mode) {
case 'selectorsAPI':
// querySelectorAll queries document-wide, then filters to descendants
// of the context element. That's not what we want.
// Add an explicit context to the selector if necessary.
if (root !== document) {
var oldId = root.id, id = $(root).identify();
e = "#" + id + " " + e;
}
results = $A(root.querySelectorAll(e)).map(Element.extend);
root.id = oldId;
return results;
case 'xpath':
return document._getElementsByXPath(this.xpath, root);
default:
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)) {
// use the Selector.assertions methods unless the selector
// is too complex.
if (as[i]) {
this.tokens.push([i, Object.clone(m)]);
e = e.replace(m[0], '');
} else {
// reluctantly do a document-wide search
// and look for a match in the array
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)]",
'checked':     "[@checked]",
'disabled':    "[(@disabled) and (@type!='hidden')]",
'enabled':     "[not(@disabled) and (@type!='hidden')]",
'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+)$/)) // digit only
return '[' + fragment + "= " + mm[1] + ']';
if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
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: {
// combinators must be listed first
// (and descendant needs to be last combinator)
laterSibling: /^\s*~\s*/,
child:        /^\s*>\s*/,
adjacent:     /^\s*\+\s*/,
descendant:   /^\s/,
// selectors follow
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]+:)?[\w]+)\]/,
attr:         /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
},
// for Selector.match and Element#match
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: {
// UTILITY FUNCTIONS
// joins two collections
concat: function(a, b) {
for (var i = 0, node; node = b[i]; i++)
a.push(node);
return a;
},
// marks an array of nodes for counting
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;
},
// mark each child node with its position (for nth calls)
// "ofType" flag indicates whether we're indexing for nth-of-type
// rather than nth-child
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++;
}
},
// filters out duplicates and extends all nodes
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);
},
// COMBINATOR FUNCTIONS
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;
},
// TOKEN FUNCTIONS
tagName: function(nodes, root, tagName, combinator) {
var uTagName = tagName.toUpperCase();
var results = [], h = Selector.handlers;
if (nodes) {
if (combinator) {
// fastlane for ordinary descendant combinators
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);
},
// handles the an+b logic
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;
});
},
// handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
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+$/)) { // just a number
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+))?/)) { // an+b
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++) {
// IE treats comments as element nodes
if (node.tagName == '!' || node.firstChild) 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 && (!node.type || node.type !== 'hidden'))
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 == v || nv && nv.startsWith(v); },
'$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
'*=': function(nv, v) { return nv == v || nv && nv.include(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, {
// IE returns comment nodes on getElementsByTagName("*").
// Filter them out.
concat: function(a, b) {
for (var i = 0, node; node = b[i]; i++)
if (node.tagName !== "!") a.push(node);
return a;
},
// IE improperly serializes _countedByPrototype in (inner|outer)HTML.
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 != 'file' && (element.type != 'submit' || (!submitted &&
submit !== false && (!submit || key == submit) && (submitted = true)))) {
if (key in result) {
// a key is already present; construct an array of values
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.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, value) {
if (Object.isUndefined(value))
return this[element.type == 'select-one' ?
'selectOne' : 'selectMany'](element);
else {
var opt, currentValue, single = !Object.isArray(value);
for (var i = 0, length = element.length; i < length; i++) {
opt = element.options[i];
currentValue = this.optionValue(opt);
if (single) {
if (currentValue == value) {
opt.selected = true;
return;
}
}
else opt.selected = value.include(currentValue);
}
}
},
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.options[i];
if (opt.selected) values.push(this.optionValue(opt));
}
return values;
},
optionValue: function(opt) {
// extend element because hasAttribute may not be native
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) {
event = Event.extend(event);
var node          = event.target,
type          = event.type,
currentTarget = event.currentTarget;
if (currentTarget && currentTarget.tagName) {
// Firefox screws up the "click" event when moving between radio buttons
// via arrow keys. It also screws up the "load" and "error" events on images,
// reporting the document as the target instead of the original image.
if (type === 'load' || type === 'error' ||
(type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
&& currentTarget.type === 'radio'))
node = currentTarget;
}
if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
return Element.extend(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) {
var docElement = document.documentElement,
body = document.body || { scrollLeft: 0, scrollTop: 0 };
return {
x: event.pageX || (event.clientX +
(docElement.scrollLeft || body.scrollLeft) -
(docElement.clientLeft || 0)),
y: event.pageY || (event.clientY +
(docElement.scrollTop || body.scrollTop) -
(docElement.clientTop || 0))
};
},
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;
}
// Internet Explorer needs to remove event handlers on page unload
// in order to avoid memory leaks.
if (window.attachEvent) {
window.attachEvent("onunload", destroyCache);
}
// Safari has a dummy event handler on page unload so that it won't
// use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
// object when page is returned to via the back button using its bfcache.
if (Prototype.Browser.WebKit) {
window.addEventListener('unload', Prototype.emptyFunction, false);
}
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() {
/* Support for the DOMContentLoaded event is based on work by Dan Webb,
Matthias Miller, Dean Edwards and John Resig. */
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();
}
};
}
})();
/*------------------------------- DEPRECATED -------------------------------*/
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');
// This should be moved to script.aculo.us; notice the deprecated methods
// further below, that map to the newer Element methods.
var Position = {
// set to true if needed, warning: firefox performance problems
// NOT neeeded for page scrolling, only if draggable contained in
// scrollable elements
includeScrollOffsets: false,
// must be called before calling withinIncludingScrolloffset, every time the
// page is scrolled
prepare: function() {
this.deltaX =  window.pageXOffset
|| document.documentElement.scrollLeft
|| document.body.scrollLeft
|| 0;
this.deltaY =  window.pageYOffset
|| document.documentElement.scrollTop
|| document.body.scrollTop
|| 0;
},
// caches x/y coordinate pair to use with overlap
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);
},
// within must be called directly before
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;
},
// Deprecation layer -- use newer Element methods now (1.5.2).
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();

// script.aculo.us scriptaculous.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// 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.
//
// For details, see the script.aculo.us web site: http://script.aculo.us/
var Scriptaculous = {
Version: '1.8.2',
require: function(libraryName) {
// inserting via DOM fails in Safari 2.0, so brute force approach
document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
},
REQUIRED_PROTOTYPE: '1.6.0.3',
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);
var js = /scriptaculous\.js(\?.*)?$/;
$$('head script[src]').findAll(function(s) {
return s.src.match(js);
}).each(function(s) {
var path = s.src.replace(js, ''),
includes = s.src.match(/\?.*load=([a-z,]*)/);
(includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
function(include) { Scriptaculous.require(path+include+'.js') });
});
}
};
Scriptaculous.load();

// script.aculo.us effects.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// Contributors:
//  Justin Palmer (http://encytemedia.com/)
//  Mark Pilgrim (http://diveintomark.org/)
//  Martin Bialasinki
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
// converts rgb() and #xxx to #xxxxxx format,
// returns self (or first argument) if not convertable
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;
},
elastic: function(pos) {
return -1*Math.pow(4,-8*pos) * Math.sin((pos*6-1)*(2*Math.PI)/2) + 1;
},
swingFrom: function(pos) {
var s = 1.70158;
return pos*pos*((s+1)*pos - s);
},
swingFromTo: function(pos) {
var s = 1.70158;
if ((pos/=0.5) < 1) return 0.5*(pos*pos*(((s*=(1.525))+1)*pos - s));
return 0.5*((pos-=2)*pos*(((s*=(1.525))+1)*pos + s) + 2);
}
},
DefaultOptions: {
duration:   1.0,   // seconds
fps:        100,   // 100= assume 66fps max.
sync:       false, // true for combining
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;
/* ------------- core effects ------------- */
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':
// move unstarted effects after this effect
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':
// start effect after last queued effect has finished
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;
this.render = (function() {
function dispatch(effect, eventName) {
if (effect.options[eventName + 'Internal'])
effect.options[eventName + 'Internal'](effect);
if (effect.options[eventName])
effect.options[eventName](effect);
}
return function(pos) {
if (this.state === "idle") {
this.state = "running";
dispatch(this, 'beforeSetup');
if (this.setup) this.setup();
dispatch(this, 'afterSetup');
}
if (this.state === "running") {
pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
this.position = pos;
dispatch(this, 'beforeUpdate');
if (this.update) this.update(pos);
dispatch(this, '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);
// make this work on IE on elements without 'layout'
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'
});
}
});
// for backwards compatibility
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',        // 'box' or 'contents' or { } with provided values
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() {
// Prevent executing on elements not in the layout flow
if (this.element.getStyle('display')=='none') { this.cancel(); return; }
// Disable background image during the effect
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');
// init color calculations
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()); }
);
};
/* ------------- combination effects ------------- */
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,
// force Safari to render floated elements properly
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();
// SlideDown need to have the content of the element wrapped in a container element with fixed height!
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] || { })
);
};
// Bug in opera makes the TD containing this element expand for a instance after finish
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);

/**
* @author Ryan Johnson <ryan@livepipe.net>
* @copyright 2007 LivePipe LLC
* @package Control.Modal
* @license MIT
* @url http://livepipe.net/projects/control_modal/
* @version 2.2.3
*/
if(typeof(Control) == "undefined")
Control = {};
Control.Modal = Class.create();
Object.extend(Control.Modal,{
loaded: false,
loading: false,
loadingTimeout: false,
overlay: false,
container: false,
current: false,
ie: false,
effects: {
containerFade: false,
containerAppear: false,
overlayFade: false,
overlayAppear: false
},
targetRegexp: /#(.+)$/,
imgRegexp: /\.(jpe?g|gif|png|tiff?)$/i,
overlayStyles: {
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
zIndex: 998
},
overlayIEStyles: {
position: 'absolute',
top: 0,
left: 0,
zIndex: 998
},
disableHoverClose: false,
load: function(){
if(!Control.Modal.loaded){
Control.Modal.loaded = true;
Control.Modal.ie = !(typeof document.body.style.maxHeight != 'undefined');
Control.Modal.overlay = $(document.createElement('div'));
Control.Modal.overlay.id = 'modal_overlay';
Object.extend(Control.Modal.overlay.style,Control.Modal['overlay' + (Control.Modal.ie ? 'IE' : '') + 'Styles']);
Control.Modal.overlay.hide();
Control.Modal.container = $(document.createElement('div'));
Control.Modal.container.id = 'modal_container';
Control.Modal.container.hide();
Control.Modal.loading = $(document.createElement('div'));
Control.Modal.loading.id = 'modal_loading';
Control.Modal.loading.hide();
var body_tag = document.getElementsByTagName('body')[0];
body_tag.appendChild(Control.Modal.overlay);
body_tag.appendChild(Control.Modal.container);
body_tag.appendChild(Control.Modal.loading);
Control.Modal.container.observe('mouseout',function(event){
if(!Control.Modal.disableHoverClose && Control.Modal.current && Control.Modal.current.options.hover && !Position.within(Control.Modal.container,Event.pointerX(event),Event.pointerY(event)))
Control.Modal.close();
});
}
},
open: function(contents,options){
options = options || {};
if(!options.contents)
options.contents = contents;
var modal_instance = new Control.Modal(false,options);
modal_instance.open();
return modal_instance;
},
close: function(force){
if(typeof(force) != 'boolean')
force = false;
if(Control.Modal.current)
Control.Modal.current.close(force);
},
attachEvents: function(){
document.observe('contentloaded', Control.Modal.load);
},
//attachEvents: function(){
//Event.observe(window,'load',Control.Modal.load);
//Event.observe(window,'unload',Event.unloadCache,false);
//},
center: function(element){
if(!element._absolutized){
element.setStyle({
position: 'absolute'
});
element._absolutized = true;
}
var dimensions = element.getDimensions();
Position.prepare();
var offset_left = (Position.deltaX + Math.floor((Control.Modal.getWindowWidth() - dimensions.width) / 2));
var offset_top = (Position.deltaY + ((Control.Modal.getWindowHeight() > dimensions.height) ? Math.floor((Control.Modal.getWindowHeight() - dimensions.height) / 2) : 0));
element.setStyle({
top: ((dimensions.height <= Control.Modal.getDocumentHeight()) ? ((offset_top != null && offset_top > 0) ? offset_top : '0') + 'px' : 0),
left: ((dimensions.width <= Control.Modal.getDocumentWidth()) ? ((offset_left != null && offset_left > 0) ? offset_left : '0') + 'px' : 0)
});
},
getWindowWidth: function(){
return (self.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || 0);
},
getWindowHeight: function(){
return (self.innerHeight ||  document.documentElement.clientHeight || document.body.clientHeight || 0);
},
getDocumentWidth: function(){
return Math.min(document.body.scrollWidth,Control.Modal.getWindowWidth());
},
getDocumentHeight: function(){
return Math.max(document.body.scrollHeight,Control.Modal.getWindowHeight());
},
onKeyDown: function(event){
if(event.keyCode == Event.KEY_ESC)
Control.Modal.close();
}
});
Object.extend(Control.Modal.prototype,{
mode: '',
html: false,
href: '',
element: false,
src: false,
imageLoaded: false,
ajaxRequest: false,
initialize: function(element,options){
this.element = $(element);
this.options = {
beforeOpen: Prototype.emptyFunction,
afterOpen: Prototype.emptyFunction,
afterUpdate: Prototype.emptyFunction,
afterEffect: Prototype.emptyFunction,
beforeClose: Prototype.emptyFunction,
afterClose: Prototype.emptyFunction,
onSuccess: Prototype.emptyFunction,
onFailure: Prototype.emptyFunction,
onException: Prototype.emptyFunction,
beforeImageLoad: Prototype.emptyFunction,
afterImageLoad: Prototype.emptyFunction,
autoOpenIfLinked: true,
contents: false,
loading: false, //display loading indicator
fade: false,
fadeDuration: 0.75,
image: false,
imageCloseOnClick: true,
hover: false,
iframe: false,
iframeTemplate: new Template('<iframe src="#{href}" width="100%" height="100%" frameborder="0" id="#{id}"></iframe>'),
evalScripts: true, //for Ajax, define here instead of in requestOptions
requestOptions: {}, //for Ajax.Request
overlayDisplay: true,
overlayClassName: '',
overlayCloseOnClick: true,
containerClassName: '',
opacity: 0.3,
zIndex: 998,
width: null,
height: null,
offsetLeft: 0, //for use with 'relative'
offsetTop: 0, //for use with 'relative'
position: 'absolute' //'absolute' or 'relative'
};
Object.extend(this.options,options || {});
var target_match = false;
var image_match = false;
if(this.element){
target_match = Control.Modal.targetRegexp.exec(this.element.href);
image_match = Control.Modal.imgRegexp.exec(this.element.href);
}
if(this.options.position == 'mouse')
this.options.hover = true;
if(this.options.contents){
this.mode = 'contents';
}else if(this.options.image || image_match){
this.mode = 'image';
this.src = this.element.href;
}else if(target_match){
this.mode = 'named';
var x = $(target_match[1]);
this.html = x.innerHTML;
x.remove();
this.href = target_match[1];
}else{
this.mode = (this.options.iframe) ? 'iframe' : 'ajax';
this.href = this.element.href;
}
if(this.element){
if(this.options.hover){
this.element.observe('mouseover',this.open.bind(this));
this.element.observe('mouseout',function(event){
if(!Position.within(Control.Modal.container,Event.pointerX(event),Event.pointerY(event)))
this.close();
}.bindAsEventListener(this));
}else{
this.element.onclick = function(event){
this.open();
Event.stop(event);
return false;
}.bindAsEventListener(this);
}
}
var targets = Control.Modal.targetRegexp.exec(window.location);
this.position = function(event){
if(this.options.position == 'absolute')
Control.Modal.center(Control.Modal.container);
else{
var xy = (event && this.options.position == 'mouse' ? [Event.pointerX(event),Event.pointerY(event)] : Position.cumulativeOffset(this.element));
Control.Modal.container.setStyle({
position: 'absolute',
top: xy[1] + (typeof(this.options.offsetTop) == 'function' ? this.options.offsetTop() : this.options.offsetTop) + 'px',
left: xy[0] + (typeof(this.options.offsetLeft) == 'function' ? this.options.offsetLeft() : this.options.offsetLeft) + 'px'
});
}
if(Control.Modal.ie){
Control.Modal.overlay.setStyle({
height: Control.Modal.getDocumentHeight() + 'px',
width: Control.Modal.getDocumentWidth() + 'px'
});
}
}.bind(this);
if(this.mode == 'named' && this.options.autoOpenIfLinked && targets && targets[1] && targets[1] == this.href)
this.open();
},
showLoadingIndicator: function(){
if(this.options.loading){
Control.Modal.loadingTimeout = window.setTimeout(function(){
var modal_image = $('modal_image');
if(modal_image)
modal_image.hide();
Control.Modal.loading.style.zIndex = this.options.zIndex + 1;
Control.Modal.loading.update('<img id="modal_loading" src="' + this.options.loading + '"/>');
Control.Modal.loading.show();
Control.Modal.center(Control.Modal.loading);
}.bind(this),250);
}
},
hideLoadingIndicator: function(){
if(this.options.loading){
if(Control.Modal.loadingTimeout)
window.clearTimeout(Control.Modal.loadingTimeout);
var modal_image = $('modal_image');
if(modal_image)
modal_image.show();
Control.Modal.loading.hide();
}
},
open: function(force){
if(!force && this.notify('beforeOpen') === false)
return;
if(!Control.Modal.loaded)
Control.Modal.load();
//Control.Modal.close();
if(!this.options.hover)
Event.observe($(document.getElementsByTagName('body')[0]),'keydown',Control.Modal.onKeyDown);
Control.Modal.current = this;
if(!this.options.hover)
Control.Modal.overlay.setStyle({
zIndex: this.options.zIndex,
opacity: this.options.opacity
});
Control.Modal.container.setStyle({
zIndex: this.options.zIndex + 1,
width: (this.options.width ? (typeof(this.options.width) == 'function' ? this.options.width() : this.options.width) + 'px' : null),
height: (this.options.height ? (typeof(this.options.height) == 'function' ? this.options.height() : this.options.height) + 'px' : null)
});
if(Control.Modal.ie && !this.options.hover){
$A(document.getElementsByTagName('select')).each(function(select){
select.style.visibility = 'hidden';
});
}
Control.Modal.overlay.addClassName(this.options.overlayClassName);
Control.Modal.container.className = '';
Control.Modal.container.addClassName(this.options.containerClassName);
switch(this.mode){
case 'image':
this.imageLoaded = false;
this.notify('beforeImageLoad');
this.showLoadingIndicator();
var img = document.createElement('img');
img.onload = function(img){
this.hideLoadingIndicator();
this.update([img]);
if(this.options.imageCloseOnClick)
$(img).observe('click',Control.Modal.close);
this.position();
this.notify('afterImageLoad');
img.onload = null;
}.bind(this,img);
img.src = this.src;
img.id = 'modal_image';
break;
case 'ajax':
this.notify('beforeLoad');
var options = {
method: 'post',
onSuccess: function(request){
this.hideLoadingIndicator();
this.update(request.responseText);
this.notify('onSuccess',request);
this.ajaxRequest = false;
}.bind(this),
onFailure: function(){
this.notify('onFailure');
}.bind(this),
onException: function(){
this.notify('onException');
}.bind(this)
};
Object.extend(options,this.options.requestOptions);
this.showLoadingIndicator();
this.ajaxRequest = new Ajax.Request(this.href,options);
break;
case 'iframe':
this.update(this.options.iframeTemplate.evaluate({href: this.href, id: 'modal_iframe'}));
break;
case 'contents':
this.update((typeof(this.options.contents) == 'function' ? this.options.contents() : this.options.contents));
break;
case 'named':
this.update(this.html);
break;
}
if(!this.options.hover){
if(this.options.overlayCloseOnClick && this.options.overlayDisplay)
Control.Modal.overlay.observe('click',Control.Modal.close);
if(this.options.overlayDisplay){
if(this.options.fade){
if(Control.Modal.effects.overlayFade)
Control.Modal.effects.overlayFade.cancel();
Control.Modal.effects.overlayAppear = new Effect.Appear(Control.Modal.overlay,{
queue: {
position: 'front',
scope: 'Control.Modal'
},
to: this.options.opacity,
duration: this.options.fadeDuration / 2,
afterFinish: function() {
this.notify('afterEffect');
}.bind(this)
});
}else
Control.Modal.overlay.show();
}
}
if(this.options.position == 'mouse'){
this.mouseHoverListener = this.position.bindAsEventListener(this);
this.element.observe('mousemove',this.mouseHoverListener);
}
this.notify('afterOpen');
},
update: function(html){
if(typeof(html) == 'string')
Control.Modal.container.update(html);
else{
Control.Modal.container.update('');
(html.each) ? html.each(function(node){
Control.Modal.container.appendChild(node);
}) : Control.Modal.container.appendChild(node);
}
/*
if(this.options.fade){
if(Control.Modal.effects.containerFade)
Control.Modal.effects.containerFade.cancel();
Control.Modal.effects.containerAppear = new Effect.Appear(Control.Modal.container,{
queue: {
position: 'end',
scope: 'Control.Modal'
},
to: 1,
duration: this.options.fadeDuration / 2
});
}else
*/
Control.Modal.container.show();
this.position();
Event.observe(window,'resize',this.position,false);
Event.observe(window,'scroll',this.position,false);
this.notify('afterUpdate');
},
close: function(force){
if(!force && this.notify('beforeClose') === false)
return;
if(this.ajaxRequest)
this.ajaxRequest.transport.abort();
this.hideLoadingIndicator();
if(this.mode == 'image'){
var modal_image = $('modal_image');
if(this.options.imageCloseOnClick && modal_image)
modal_image.stopObserving('click',Control.Modal.close);
}
if(Control.Modal.ie && !this.options.hover){
$A(document.getElementsByTagName('select')).each(function(select){
select.style.visibility = 'visible';
});
}
if(!this.options.hover)
Event.stopObserving(window,'keyup',Control.Modal.onKeyDown);
Control.Modal.current = false;
Event.stopObserving(window,'resize',this.position,false);
Event.stopObserving(window,'scroll',this.position,false);
if(!this.options.hover){
if(this.options.overlayCloseOnClick && this.options.overlayDisplay)
Control.Modal.overlay.stopObserving('click',Control.Modal.close);
if(this.options.overlayDisplay){
if(this.options.fade){
if(Control.Modal.effects.overlayAppear)
Control.Modal.effects.overlayAppear.cancel();
Control.Modal.effects.overlayFade = new Effect.Fade(Control.Modal.overlay,{
queue: {
position: 'end',
scope: 'Control.Modal'
},
from: this.options.opacity,
to: 0,
duration: this.options.fadeDuration / 2
});
}else
Control.Modal.overlay.hide();
}
}
if(this.options.fade){
if(Control.Modal.effects.containerAppear)
Control.Modal.effects.containerAppear.cancel();
Control.Modal.effects.containerFade = new Effect.Fade(Control.Modal.container,{
queue: {
position: 'front',
scope: 'Control.Modal'
},
from: 1,
to: 0,
duration: this.options.fadeDuration / 2,
afterFinish: function(){
Control.Modal.container.update('');
this.resetClassNameAndStyles();
}.bind(this)
});
}else{
Control.Modal.container.hide();
Control.Modal.container.update('');
this.resetClassNameAndStyles();
}
if(this.options.position == 'mouse')
this.element.stopObserving('mousemove',this.mouseHoverListener);
this.notify('afterClose');
},
resetClassNameAndStyles: function(){
Control.Modal.overlay.removeClassName(this.options.overlayClassName);
Control.Modal.container.removeClassName(this.options.containerClassName);
Control.Modal.container.setStyle({
height: null,
width: null,
top: null,
left: null
});
},
notify: function(event_name){
try{
if(this.options[event_name])
return [this.options[event_name].apply(this.options[event_name],$A(arguments).slice(1))];
}catch(e){
if(e != $break)
throw e;
else
return false;
}
}
});
if(typeof(Object.Event) != 'undefined')
Object.Event.extend(Control.Modal);
Control.Modal.attachEvents();

/* SWFObject v2.1 <http://code.google.com/p/swfobject/>
Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis
This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
var swfobject=function(){var b="undefined",Q="object",n="Shockwave Flash",p="ShockwaveFlash.ShockwaveFlash",P="application/x-shockwave-flash",m="SWFObjectExprInst",j=window,K=document,T=navigator,o=[],N=[],i=[],d=[],J,Z=null,M=null,l=null,e=false,A=false;var h=function(){var v=typeof K.getElementById!=b&&typeof K.getElementsByTagName!=b&&typeof K.createElement!=b,AC=[0,0,0],x=null;if(typeof T.plugins!=b&&typeof T.plugins[n]==Q){x=T.plugins[n].description;if(x&&!(typeof T.mimeTypes!=b&&T.mimeTypes[P]&&!T.mimeTypes[P].enabledPlugin)){x=x.replace(/^.*\s+(\S+\s+\S+$)/,"$1");AC[0]=parseInt(x.replace(/^(.*)\..*$/,"$1"),10);AC[1]=parseInt(x.replace(/^.*\.(.*)\s.*$/,"$1"),10);AC[2]=/r/.test(x)?parseInt(x.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof j.ActiveXObject!=b){var y=null,AB=false;try{y=new ActiveXObject(p+".7")}catch(t){try{y=new ActiveXObject(p+".6");AC=[6,0,21];y.AllowScriptAccess="always"}catch(t){if(AC[0]==6){AB=true}}if(!AB){try{y=new ActiveXObject(p)}catch(t){}}}if(!AB&&y){try{x=y.GetVariable("$version");if(x){x=x.split(" ")[1].split(",");AC=[parseInt(x[0],10),parseInt(x[1],10),parseInt(x[2],10)]}}catch(t){}}}}var AD=T.userAgent.toLowerCase(),r=T.platform.toLowerCase(),AA=/webkit/.test(AD)?parseFloat(AD.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,q=false,z=r?/win/.test(r):/win/.test(AD),w=r?/mac/.test(r):/mac/.test(AD);/*@cc_on q=true;@if(@_win32)z=true;@elif(@_mac)w=true;@end@*/return{w3cdom:v,pv:AC,webkit:AA,ie:q,win:z,mac:w}}();var L=function(){if(!h.w3cdom){return }f(H);if(h.ie&&h.win){try{K.write("<script id=__ie_ondomload defer=true src=//:><\/script>");J=C("__ie_ondomload");if(J){I(J,"onreadystatechange",S)}}catch(q){}}if(h.webkit&&typeof K.readyState!=b){Z=setInterval(function(){if(/loaded|complete/.test(K.readyState)){E()}},10)}if(typeof K.addEventListener!=b){K.addEventListener("DOMContentLoaded",E,null)}R(E)}();function S(){if(J.readyState=="complete"){J.parentNode.removeChild(J);E()}}function E(){if(e){return }if(h.ie&&h.win){var v=a("span");try{var u=K.getElementsByTagName("body")[0].appendChild(v);u.parentNode.removeChild(u)}catch(w){return }}e=true;if(Z){clearInterval(Z);Z=null}var q=o.length;for(var r=0;r<q;r++){o[r]()}}function f(q){if(e){q()}else{o[o.length]=q}}function R(r){if(typeof j.addEventListener!=b){j.addEventListener("load",r,false)}else{if(typeof K.addEventListener!=b){K.addEventListener("load",r,false)}else{if(typeof j.attachEvent!=b){I(j,"onload",r)}else{if(typeof j.onload=="function"){var q=j.onload;j.onload=function(){q();r()}}else{j.onload=r}}}}}function H(){var t=N.length;for(var q=0;q<t;q++){var u=N[q].id;if(h.pv[0]>0){var r=C(u);if(r){N[q].width=r.getAttribute("width")?r.getAttribute("width"):"0";N[q].height=r.getAttribute("height")?r.getAttribute("height"):"0";if(c(N[q].swfVersion)){if(h.webkit&&h.webkit<312){Y(r)}W(u,true)}else{if(N[q].expressInstall&&!A&&c("6.0.65")&&(h.win||h.mac)){k(N[q])}else{O(r)}}}}else{W(u,true)}}}function Y(t){var q=t.getElementsByTagName(Q)[0];if(q){var w=a("embed"),y=q.attributes;if(y){var v=y.length;for(var u=0;u<v;u++){if(y[u].nodeName=="DATA"){w.setAttribute("src",y[u].nodeValue)}else{w.setAttribute(y[u].nodeName,y[u].nodeValue)}}}var x=q.childNodes;if(x){var z=x.length;for(var r=0;r<z;r++){if(x[r].nodeType==1&&x[r].nodeName=="PARAM"){w.setAttribute(x[r].getAttribute("name"),x[r].getAttribute("value"))}}}t.parentNode.replaceChild(w,t)}}function k(w){A=true;var u=C(w.id);if(u){if(w.altContentId){var y=C(w.altContentId);if(y){M=y;l=w.altContentId}}else{M=G(u)}if(!(/%$/.test(w.width))&&parseInt(w.width,10)<310){w.width="310"}if(!(/%$/.test(w.height))&&parseInt(w.height,10)<137){w.height="137"}K.title=K.title.slice(0,47)+" - Flash Player Installation";var z=h.ie&&h.win?"ActiveX":"PlugIn",q=K.title,r="MMredirectURL="+j.location+"&MMplayerType="+z+"&MMdoctitle="+q,x=w.id;if(h.ie&&h.win&&u.readyState!=4){var t=a("div");x+="SWFObjectNew";t.setAttribute("id",x);u.parentNode.insertBefore(t,u);u.style.display="none";var v=function(){u.parentNode.removeChild(u)};I(j,"onload",v)}U({data:w.expressInstall,id:m,width:w.width,height:w.height},{flashvars:r},x)}}function O(t){if(h.ie&&h.win&&t.readyState!=4){var r=a("div");t.parentNode.insertBefore(r,t);r.parentNode.replaceChild(G(t),r);t.style.display="none";var q=function(){t.parentNode.removeChild(t)};I(j,"onload",q)}else{t.parentNode.replaceChild(G(t),t)}}function G(v){var u=a("div");if(h.win&&h.ie){u.innerHTML=v.innerHTML}else{var r=v.getElementsByTagName(Q)[0];if(r){var w=r.childNodes;if(w){var q=w.length;for(var t=0;t<q;t++){if(!(w[t].nodeType==1&&w[t].nodeName=="PARAM")&&!(w[t].nodeType==8)){u.appendChild(w[t].cloneNode(true))}}}}}return u}function U(AG,AE,t){var q,v=C(t);if(v){if(typeof AG.id==b){AG.id=t}if(h.ie&&h.win){var AF="";for(var AB in AG){if(AG[AB]!=Object.prototype[AB]){if(AB.toLowerCase()=="data"){AE.movie=AG[AB]}else{if(AB.toLowerCase()=="styleclass"){AF+=' class="'+AG[AB]+'"'}else{if(AB.toLowerCase()!="classid"){AF+=" "+AB+'="'+AG[AB]+'"'}}}}}var AD="";for(var AA in AE){if(AE[AA]!=Object.prototype[AA]){AD+='<param name="'+AA+'" value="'+AE[AA]+'" />'}}v.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AF+">"+AD+"</object>";i[i.length]=AG.id;q=C(AG.id)}else{if(h.webkit&&h.webkit<312){var AC=a("embed");AC.setAttribute("type",P);for(var z in AG){if(AG[z]!=Object.prototype[z]){if(z.toLowerCase()=="data"){AC.setAttribute("src",AG[z])}else{if(z.toLowerCase()=="styleclass"){AC.setAttribute("class",AG[z])}else{if(z.toLowerCase()!="classid"){AC.setAttribute(z,AG[z])}}}}}for(var y in AE){if(AE[y]!=Object.prototype[y]){if(y.toLowerCase()!="movie"){AC.setAttribute(y,AE[y])}}}v.parentNode.replaceChild(AC,v);q=AC}else{var u=a(Q);u.setAttribute("type",P);for(var x in AG){if(AG[x]!=Object.prototype[x]){if(x.toLowerCase()=="styleclass"){u.setAttribute("class",AG[x])}else{if(x.toLowerCase()!="classid"){u.setAttribute(x,AG[x])}}}}for(var w in AE){if(AE[w]!=Object.prototype[w]&&w.toLowerCase()!="movie"){F(u,w,AE[w])}}v.parentNode.replaceChild(u,v);q=u}}}return q}function F(t,q,r){var u=a("param");u.setAttribute("name",q);u.setAttribute("value",r);t.appendChild(u)}function X(r){var q=C(r);if(q&&(q.nodeName=="OBJECT"||q.nodeName=="EMBED")){if(h.ie&&h.win){if(q.readyState==4){B(r)}else{j.attachEvent("onload",function(){B(r)})}}else{q.parentNode.removeChild(q)}}}function B(t){var r=C(t);if(r){for(var q in r){if(typeof r[q]=="function"){r[q]=null}}r.parentNode.removeChild(r)}}function C(t){var q=null;try{q=K.getElementById(t)}catch(r){}return q}function a(q){return K.createElement(q)}function I(t,q,r){t.attachEvent(q,r);d[d.length]=[t,q,r]}function c(t){var r=h.pv,q=t.split(".");q[0]=parseInt(q[0],10);q[1]=parseInt(q[1],10)||0;q[2]=parseInt(q[2],10)||0;return(r[0]>q[0]||(r[0]==q[0]&&r[1]>q[1])||(r[0]==q[0]&&r[1]==q[1]&&r[2]>=q[2]))?true:false}function V(v,r){if(h.ie&&h.mac){return }var u=K.getElementsByTagName("head")[0],t=a("style");t.setAttribute("type","text/css");t.setAttribute("media","screen");if(!(h.ie&&h.win)&&typeof K.createTextNode!=b){t.appendChild(K.createTextNode(v+" {"+r+"}"))}u.appendChild(t);if(h.ie&&h.win&&typeof K.styleSheets!=b&&K.styleSheets.length>0){var q=K.styleSheets[K.styleSheets.length-1];if(typeof q.addRule==Q){q.addRule(v,r)}}}function W(t,q){var r=q?"visible":"hidden";if(e&&C(t)){C(t).style.visibility=r}else{V("#"+t,"visibility:"+r)}}function g(s){var r=/[\\\"<>\.;]/;var q=r.exec(s)!=null;return q?encodeURIComponent(s):s}var D=function(){if(h.ie&&h.win){window.attachEvent("onunload",function(){var w=d.length;for(var v=0;v<w;v++){d[v][0].detachEvent(d[v][1],d[v][2])}var t=i.length;for(var u=0;u<t;u++){X(i[u])}for(var r in h){h[r]=null}h=null;for(var q in swfobject){swfobject[q]=null}swfobject=null})}}();return{registerObject:function(u,q,t){if(!h.w3cdom||!u||!q){return }var r={};r.id=u;r.swfVersion=q;r.expressInstall=t?t:false;N[N.length]=r;W(u,false)},getObjectById:function(v){var q=null;if(h.w3cdom){var t=C(v);if(t){var u=t.getElementsByTagName(Q)[0];if(!u||(u&&typeof t.SetVariable!=b)){q=t}else{if(typeof u.SetVariable!=b){q=u}}}}return q},embedSWF:function(x,AE,AB,AD,q,w,r,z,AC){if(!h.w3cdom||!x||!AE||!AB||!AD||!q){return }AB+="";AD+="";if(c(q)){W(AE,false);var AA={};if(AC&&typeof AC===Q){for(var v in AC){if(AC[v]!=Object.prototype[v]){AA[v]=AC[v]}}}AA.data=x;AA.width=AB;AA.height=AD;var y={};if(z&&typeof z===Q){for(var u in z){if(z[u]!=Object.prototype[u]){y[u]=z[u]}}}if(r&&typeof r===Q){for(var t in r){if(r[t]!=Object.prototype[t]){if(typeof y.flashvars!=b){y.flashvars+="&"+t+"="+r[t]}else{y.flashvars=t+"="+r[t]}}}}f(function(){U(AA,y,AE);if(AA.id==AE){W(AE,true)}})}else{if(w&&!A&&c("6.0.65")&&(h.win||h.mac)){A=true;W(AE,false);f(function(){var AF={};AF.id=AF.altContentId=AE;AF.width=AB;AF.height=AD;AF.expressInstall=w;k(AF)})}}},getFlashPlayerVersion:function(){return{major:h.pv[0],minor:h.pv[1],release:h.pv[2]}},hasFlashPlayerVersion:c,createSWF:function(t,r,q){if(h.w3cdom){return U(t,r,q)}else{return undefined}},removeSWF:function(q){if(h.w3cdom){X(q)}},createCSS:function(r,q){if(h.w3cdom){V(r,q)}},addDomLoadEvent:f,addLoadEvent:R,getQueryParamValue:function(v){var u=K.location.search||K.location.hash;if(v==null){return g(u)}if(u){var t=u.substring(1).split("&");for(var r=0;r<t.length;r++){if(t[r].substring(0,t[r].indexOf("="))==v){return g(t[r].substring((t[r].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(A&&M){var q=C(m);if(q){q.parentNode.replaceChild(M,q);if(l){W(l,true);if(h.ie&&h.win){M.style.display="block"}}M=null;l=null;A=false}}}}}();

//  Prototip 1.1.0
//  by Nick Stakenburg - http://www.nickstakenburg.com
//  08-11-2007
//
//  More information on this project:
//  http://www.nickstakenburg.com/projects/prototip/
//
//  Licensed under the Creative Commons Attribution 3.0 License
//  http://creativecommons.org/licenses/by/3.0/
//
var Prototip = {
Version: '1.1.0',
REQUIRED_Prototype: '1.6.0',
REQUIRED_Scriptaculous: '1.8.0',
start: function() { this.require('Prototype'); },
require: function(library) {
if ((typeof window[library] == 'undefined') ||
(this.convertVersionString(window[library].Version) < this.convertVersionString(this['REQUIRED_' + library])))
throw('Prototip requires ' + library + ' >= ' + this['REQUIRED_' + library]);
},
// based on Scriptaculous' implementation
convertVersionString: function(versionString) {
var r = versionString.split('.');
return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
},
// fixed viewport.getDimensions. Also excludes scrollbars in firefox. Valid doctype required.
viewport : {
getDimensions: function() {
var dimensions = { };
var B = Prototype.Browser;
$w('width height').each(function(d) {
var D = d.capitalize();
if (B.Opera) dimensions[d] = document.body['client' + D];
else if (B.WebKit) dimensions[d] = self['inner' + D];
else dimensions[d] = document.documentElement['client' + D];
});
return dimensions;
}
}
};
Prototip.start();
var Tips = {
// Configuration
closeButtons: false,
zIndex: 12000,
fixIE: (function(agent){
var version = new RegExp('MSIE ([\\d.]+)').exec(agent);
return version ? (parseFloat(version[1]) <= 6) : false;
})(navigator.userAgent),
tips : [],
visible : [],
add: function(tip) {
this.tips.push(tip);
},
remove: function(element) {
var tip = this.tips.find(function(t){ return t.element == $(element); });
if (tip) {
tip.deactivate();
if (tip.tooltip) {
tip.wrapper.remove();
if (Tips.fixIE) tip.iframeShim.remove();
}
this.tips = this.tips.without(tip);
}
},
zIndexRestore : 12000,
raise: function(tip) {
var highestZ = this.zIndexHighest();
if (!highestZ) {
tip.style.zIndex = this.zIndexRestore;
return;
}
var newZ = (tip.style.zIndex != highestZ) ? highestZ + 1 : highestZ;
this.tips.pluck('wrapper').invoke('removeClassName', 'highest');
tip.setStyle({ zIndex : newZ }).addClassName('highest');
},
zIndexHighest: function() {
var highestZ = $$('.prototip').max(function(v) {
return parseInt(v.style.zIndex);
});
return highestZ;
},
addVisibile: function(tip) {
this.removeVisible(tip);
this.visible.push(tip);
},
removeVisible: function(tip) {
this.visible = this.visible.without(tip);
}
};
var Tip = Class.create({
initialize: function(element, content) {
this.element = $(element);
Tips.remove(this.element);
this.content = content;
var isHooking = (arguments[2] && arguments[2].hook);
var isShowOnClick = (arguments[2] && arguments[2].showOn == 'click');
this.options = Object.extend({
className: 'default',                 // see css, this will lead to .prototip .default
closeButton: Tips.closeButtons,       // true, false
delay: !isShowOnClick ? 0.2 : false,  // seconds before tooltip appears
duration: 0.3,                        // duration of the effect
effect: false,                        // false, 'appear' or 'blind'
hideOn: 'mouseout',
hook: false,                          // { element: topLeft|topRight|bottomLeft|bottomRight, tip: see element }
offset: isHooking ? {x:0, y:0} : {x:16, y:16},
fixed: isHooking ? true : false,      // follow the mouse if false
showOn: 'mousemove',
target: this.element,                 // or another element
title: false,
viewport: isHooking ? false : true    // keep within viewport if mouse is followed
}, arguments[2] || {});
this.target = $(this.options.target);
this.setup();
if (this.options.effect) {
Prototip.require('Scriptaculous');
this.queue = { position: 'end', limit: 1, scope: this.wrapper.identify() }
}
Tips.add(this);
this.activate();
},
setup: function() {
// Everything that needs to be build for observing is done here
this.wrapper = new Element('div', { 'class' : 'prototip' }).setStyle({
display: 'none', zIndex: Tips.zIndex++ });
this.wrapper.identify();
if (Tips.fixIE) {
this.iframeShim = new Element('iframe', { 'class' : 'iframeShim', src: 'javascript:false;' }).setStyle({
display: 'none', zIndex: Tips.zIndexRestore - 1 });
}
this.tip = new Element('div', { 'class' : 'tipcontent' }).update(this.content);
this.tip.insert(new Element('div').setStyle({ clear: 'both' }));
if (this.options.closeButton || (this.options.hideOn.element && this.options.hideOn.element == 'closeButton'))
this.closeButton = new Element('a', { href: 'javascript:;', 'class' : 'close' });
},
build: function() {
if (Tips.fixIE) document.body.appendChild(this.iframeShim).setOpacity(0);
// effects go smooth with extra wrapper
var wrapper = 'wrapper';
if (this.options.effect) {
this.effectWrapper = this.wrapper.appendChild(new Element('div', { 'class' : 'effectWrapper' }));
wrapper = 'effectWrapper';
}
this.tooltip = this[wrapper].appendChild(new Element('div', { 'class' : 'tooltip ' + this.options.className }));
if (this.options.title || this.options.closeButton) {
this.toolbar = this.tooltip.appendChild(new Element('div', { 'class' : 'toolbar' }));
this.title = this.toolbar.appendChild(new Element('div', { 'class' : 'title' }).update(this.options.title || ' '));
}
this.tooltip.insert(this.tip);
document.body.appendChild(this.wrapper);
// fixate elements for better positioning and effects
var fixate = (this.options.effect) ? [this.wrapper, this.effectWrapper]: [this.wrapper];
if (Tips.fixIE) fixate.push(this.iframeShim);
// fix width
var fixedWidth = this.wrapper.getWidth();
fixate.invoke('setStyle', { width: fixedWidth + 'px' });
// make toolbar width fixed
if(this.toolbar) {
this.wrapper.setStyle({ visibility : 'hidden' }).show();
this.toolbar.setStyle({ width: this.toolbar.getWidth() + 'px'});
this.wrapper.hide().setStyle({ visibility : 'visible' });
}
// add close button
if (this.closeButton)
this.title.insert({ top: this.closeButton }).insert(new Element('div').setStyle({ clear: 'both' }));
var fixedHeight = this.wrapper.getHeight();
fixate.invoke('setStyle', { width: fixedWidth + 'px', height: fixedHeight + 'px' });
this[this.options.effect ? wrapper : 'tooltip'].hide();
},
activate: function() {
this.eventShow = this.showDelayed.bindAsEventListener(this);
this.eventHide = this.hide.bindAsEventListener(this);
// if fixed use mouseover instead of mousemove for less event calls
if (this.options.fixed && this.options.showOn == 'mousemove') this.options.showOn = 'mouseover';
if(this.options.showOn == this.options.hideOn) {
this.eventToggle = this.toggle.bindAsEventListener(this);
this.element.observe(this.options.showOn, this.eventToggle);
}
this.hideElement = Object.isUndefined(this.options.hideOn.element) ? 'element' : this.options.hideOn.element;
var hideOptions = {
'element': this.eventToggle ? [] : [this.element],
'target': this.eventToggle ? [] : [this.target],
'tip': this.eventToggle ? [] : [this.wrapper],
'closeButton': [],
'.close' : this.tip.select('.close')
}
this.hideTargets = hideOptions[this.hideElement];
// add show and hide observers
if (this.options.showOn.include(':') && this.element && !this.eventToggle)
this.element.observe(this.options.showOn, this.showDelayed.bindAsEventListener(this));
else if (this.element && !this.eventToggle) 
this.element.observe(this.options.showOn, this.eventShow);
this.hideAction = (this.options.hideOn.event || this.options.hideOn);
if (this.hideAction.include(':')) this.element.observe(this.hideAction, this.hide.bindAsEventListener(this));
else if (this.hideTargets) this.hideTargets.invoke('observe', this.hideAction, this.eventHide);
// add position observer if not fixed
if (!this.options.fixed && this.options.showOn == 'click') {
this.eventPosition = this.position.bindAsEventListener(this);
this.element.observe('mousemove', this.eventPosition);
}
// add hide observers to close button and non click elements when they are not the close (delay needs this)
if (this.closeButton) this.closeButton.observe('click', this.eventHide);
if (this.options.showOn != 'click' && this.hideElement != 'element') {
this.eventCheckDelay = this.checkDelay.bindAsEventListener(this);
this.element.observe('mouseout', this.eventCheckDelay);
}
// observe wrapper to raise zIndex
this.wrapper.observe('mouseover', function(){ Tips.raise(this.wrapper); }.bind(this));
},
deactivate: function() {
if(this.options.showOn == this.options.hideOn)
this.element.stopObserving(this.options.showOn, this.eventToggle);
else {
this.element.stopObserving(this.options.showOn, this.eventShow);
this.hideTargets.invoke('stopObserving', this.hideAction, this.eventHide);
}
if (this.eventPosition) this.element.stopObserving('mousemove', this.eventPosition);
if (this.closeButton) this.closeButton.stopObserving();
if (this.eventCheckDelay) this.element.stopObserving('mouseout', this.eventCheckDelay);
this.wrapper.stopObserving();
},
showDelayed: function(event){
if (!this.tooltip) this.build();
if (event.memo) this.tip.down('.tip').update(event.memo);
this.position(event); // follow mouse
if (this.wrapper.visible()) return;
this.checkDelay();
this.timer = this.show.bind(this).delay(this.options.delay);
},
checkDelay: function(){
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
},
show: function(){
if (this.wrapper.visible() && this.options.effect != 'appear') return;
if (Tips.fixIE) this.iframeShim.show();
Tips.addVisibile(this.wrapper);
this.wrapper.show();
if (!this.options.effect) this.tooltip.show();
else {
if (this.activeEffect) Effect.Queues.get(this.queue.scope).remove(this.activeEffect);
this.activeEffect = Effect[Effect.PAIRS[this.options.effect][0]](this.effectWrapper,
{ duration: this.options.duration, queue: this.queue, afterSetup: function() {
if (typeof(DD_roundies) == 'object') DD_roundies.roundify.call(this.tip.down('.tip'), [3,3,3,3]);        
}.bind(this) });
}
if (Object.isFunction(this.options.onShow)) this.options.onShow(this.tip);
},
hide: function(){
this.checkDelay();
if(!this.wrapper.visible()) return;
if (!this.options.effect) {
if (Tips.fixIE) this.iframeShim.hide();
this.tooltip.hide();
this.wrapper.hide();
Tips.removeVisible(this.wrapper);
}
else {
if (this.activeEffect) Effect.Queues.get(this.queue.scope).remove(this.activeEffect);
this.activeEffect = Effect[Effect.PAIRS[this.options.effect][1]](this.effectWrapper,
{ duration: this.options.duration, queue: this.queue, afterFinish: function(){
if (Tips.fixIE) this.iframeShim.hide();
this.wrapper.hide();
Tips.removeVisible(this.wrapper);
}.bind(this)});
}
if (Object.isFunction(this.options.onHide)) this.options.onHide();
},
toggle: function(event){
if (this.wrapper && this.wrapper.visible()) this.hide(event);
else this.showDelayed(event);
},
position: function(event){
if (!this.wrapper.hasClassName('highest')) Tips.raise(this.wrapper);
var offset = {left: this.options.offset.x, top: this.options.offset.y};
var targetPosition = Position.cumulativeOffset(this.target);
var tipd = this.wrapper.getDimensions();
var pos = { left: (this.options.fixed) ? targetPosition[0] : Event.pointerX(event),
top: (this.options.fixed) ? targetPosition[1] : Event.pointerY(event) };
// add offsets
pos.left += offset.left;
pos.top += offset.top;
if (this.options.hook) {
var dims = {target: this.target.getDimensions(), tip: tipd}
var hooks = {target: Position.cumulativeOffset(this.target), tip: Position.cumulativeOffset(this.target)}
for(var z in hooks) {
switch(this.options.hook[z]){
case 'topRight':
hooks[z][0] += dims[z].width;
break;
case 'topMiddle':
hooks[z][0] += (dims[z].width / 2);
break;
case 'rightMiddle':
hooks[z][0] += dims[z].width;
hooks[z][1] += (dims[z].height / 2);
break;
case 'bottomLeft':
hooks[z][1] += dims[z].height;
break;
case 'bottomRight':
hooks[z][0] += dims[z].width;
hooks[z][1] += dims[z].height;
break;
case 'bottomMiddle':
hooks[z][0] += (dims[z].width / 2);
hooks[z][1] += dims[z].height;
break;
case 'leftMiddle':
hooks[z][1] += (dims[z].height / 2);
break;
}
}
// move based on hooks
pos.left += -1*(hooks.tip[0] - hooks.target[0]);
pos.top += -1*(hooks.tip[1] - hooks.target[1]);
}
// move tooltip when there is a different target
if (!this.options.fixed && this.element !== this.target) {
var elementPosition = Position.cumulativeOffset(this.element);
pos.left += -1*(elementPosition[0] - targetPosition[0]);
pos.top += -1*(elementPosition[1] - targetPosition[1]);
}
if (!this.options.fixed && this.options.viewport) {
var scroll = document.viewport.getScrollOffsets();
var viewport = Prototip.viewport.getDimensions();
var pair = {left: 'width', top: 'height'};
for(var z in pair) {
if ((pos[z] + tipd[pair[z]] - scroll[z]) > viewport[pair[z]])
pos[z] = pos[z] - tipd[pair[z]] - 2*offset[z];
}
}
var finalPosition = { left: pos.left + 'px', top: pos.top + 'px' };
this.wrapper.setStyle(finalPosition);
if (Tips.fixIE) this.iframeShim.setStyle(finalPosition);
}
});

if (!window.MvcSkel) { var MvcSkel = new Object(); }
Object.extend(MvcSkel, {
getVar: function(name) {
return ( $(name)) ?  $(name).value : false;
}
});
ErrorManager = Class.create({
initialize: function(obj) {
if (!window.__errors) { __errors = new Object(); };
if (!window.__errors_count) { __errors_count = 0 };
this.errWin = null;
if (typeof(obj) != 'undefined') {
obj.errors.each(function(el) {
el.msg.each(function(msg) {
this.raise(el.label, msg);
}.bind(this));
}.bind(this));
}
},
raise: function(label, description) {
if (typeof __errors[label] != 'object') {
__errors[label] = new Array();
}
__errors[label].push(description);
__errors_count++;
},
clear: function() {
__errors = new Object();
__errors_count = 0;
},
haveErrors: function() {
return __errors_count ? true : false;  
},
getErrorsAlert: function() {
if (!__errors_count) { return false; };
var content = i18n('errorsTitle') + ':' + "\n";
for(err in __errors) {
f = true;
__errors[err].each(function(e) {
if (f) {
content += "\n" + err + ':' + "\n";
f = false;
}
content += "\t" + '- ' + e + "\n";
});
}
alert(content);
this.clear();
return true;
},
getHtmlContent: function() {
var content = '<div class="header">'
content += '<h2>' + i18n('errorsTitle') + '</h2>';
content += '<div class="close"><a id="errorsClose" href="javascript:void(0);">' + i18n('errorsClose') + '</a></div>'
content += '</div>';
content += '<table class="errors" cellpadding="0" cellspacing="0" border="0">';
content += '<tbody>';
for(err in __errors) {
f = true;
__errors[err].each(function(e) {
content += '<tr>';
if (f) {
content += '<td class="label" rowspan="' + __errors[err].size() + '">' + err + ':</td>';
f = false;
}
content += '<td class="description">- ' + e + '</td>';
content += '</tr>';
});
content += '<tr><td class="space" colspan="2"></td></tr>';
}
content += '</tbody>';
content += '</table>';
return content;
},
getErrors: function() {
if (!__errors_count) { return false; };
this.errWin = new Control.Modal(false, {
contents: this.getHtmlContent(),
fade: true, fadeDuration: 0.5, opacity: 0.8,
width: 450,
containerClassName: 'mfmodal',
afterOpen: function() {
Event.observe('errorsClose', 'click', function() {
this.errWin.close();
}.bind(this));
}.bind(this)
});
this.errWin.open();
this.clear();
return true;
},
checkEmail: function(email) {
var regexp = new RegExp('^[\\w\\-\\.]+@[a-zA-Z0-9\\-\\.]+\\.[a-zA-Z0-9\\-]+$');
if (!regexp.test(email)) {
this.raise(i18n('errorEmail'), i18n('errorWrongEmail'));
}
}
});
GameAutocomplete = Class.create({
initialize: function() {
if (!$('autocompleteGames')) return false;
this.limit = 15;
var url = new UrlConstructor('search/autocomplete');
url.addVar('limit', this.limit);
var options = {
script:url.construct() + '?',
varname:'input',
json:true, noresults: i18n('autocompleteNoResults'),
shownoresults:false, maxresults:this.limit, minchars: 3,
setWidth:true, minWidth:270, maxWidth:350,
afterShow: this.pngFix.bind(this),
callback: this.redirect.bind(this)
};
var json = new AutoComplete('autocompleteGames', options);
this.defaultText();
},
pngFix: function(div) {
if (typeof(DD_belatedPNG) != 'object') return;
['.ac_corner', '.ac_bar', '.ac_footer', '.ac_header'].each(function(val) { DD_belatedPNG.fix(val); });
},
redirect: function(obj) {
var s = new UrlSeoConstructor('GAME_PRESENTATION');
s.addSeoVar('game_name', obj.value.replace(/\s+|[^\w]+/ig, '-'));
s.addSeoVar('game_id', obj.id);
s.addSeoVar('game_category_id', 0);
window.location = s.construct();
},
defaultText: function() {
var form = $('searchGamesForm');
if (!form) return;
var autoInput = form.down('input');
autoInput.observe('click', function() {
if (!autoInput.hasClassName('firstEnterText')) return;
autoInput.removeClassName('firstEnterText');
if (autoInput.next()) { autoInput.next().addClassName('cancelSearch'); }
autoInput.value = '';
}.bind(this));
autoInput.observe('blur', function() {
if (autoInput.value == '') {
autoInput.addClassName('firstEnterText');
if (autoInput.next()) { autoInput.next().removeClassName('cancelSearch'); }
autoInput.value = i18n('search_box_default_text');
}
}.bind(this));
}
});
UrlConstructor = Class.create();
UrlConstructor.prototype = {
initialize: function(url) {
this.action = false;
this.vars = new Hash();
this.url = url;
},
setAction: function(isAction) {
this.action = isAction;
},
addVar: function(name, value) {
this.vars.set(name, encodeURIComponent(value));
},
construct: function() {
var url = MvcSkel.getVar('rootUrl');
if (this.action) {
url += "actionController/";
}
url += (this.url) ? this.url : '';
this.vars.each(function(pair) {
url += '/' + pair.key + '/' + pair.value;
});
return url;
}
}
UrlSeoConstructor = Class.create({
initialize: function(view) {
this.vars = new Hash();
this.seo = new Hash();
this.view = view;
},
addVar: function(name, value) {
this.vars.set(name, value);
},
addSeoVar: function(name, value) {
this.seo.set(name, value);
},
construct: function() {
var url = seourl.get(this.view);
this.seo.each(function(pair) {
var re = new RegExp("%" + pair.key + "%", "ig");
url = url.replace(re, pair.value);
});
if (query = this.vars.toQueryString()) { url += '?' + query; }
return url;
}
});
ImageUploader = Class.create();
ImageUploader.prototype = {
initialize: function() {
this.options = {
baseClass: 'uploader',
baseProgress: 'progress',
action: 'change'
};
this.form = null;
this.timer = null;
this.initAction();
},
initAction: function() {
$$('input.' + this.options.baseClass).each(function(uploaderInput) {
Event.observe(uploaderInput, this.options.action, function(event) {
clearTimeout(this.timer);
this.timer = this.activateUpload.bind(this).delay(5, Event.element(event));
}.bind(this));
}.bind(this));
},
activateUpload: function(activeInput) {
var suffix = activeInput.up('form').id.match(/-(.*)$/)[1];
this.form = $(this.options.baseClass + '-' + suffix);
this.hideForm(suffix);
this.form.submit();
},
hideForm: function(suffix) {
this.form.hide();
var prg = $(this.options.baseProgress + '-' + suffix);
if (!prg) {
this.form.up().appendChild(new Element('span', {
'class': 'progressBar',
id: this.options.baseProgress + '-' + suffix
}).update('progress'));
} else {
prg.show();
}
},
showForm: function(suffix) {
$(this.options.baseProgress + '-' + suffix).hide();
this.form.show();
this.form.down('.uploader').value = '';
},
uploadComplete: function(suffix, file, url) {
//        alert(suffix + '-' + file + '-' + url);
$(suffix + '-uploadedimg').src = url;
this.showForm(suffix);
this.form.down('.save').writeAttribute('value', file);
},
uploadError: function() {
alert("Error");
}
}
WaitWindow = Class.create({
initialize: function() {
if (typeof(ww) != 'undefined' && ww) return ;
this.def = {
overlayCloseOnClick: false,
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
containerClassName: 'ajaxLoader'
}
this.modal = null;
this.opened = false;
},
show: function(afterOpen) {
var waitContent = new Element('div', {id: 'boxProcess'});
var opt = { 
contents: [waitContent],
afterEffect: function() { if (Object.isFunction(afterOpen)) afterOpen(); },
afterOpen: function() { this.opened = true; }.bind(this)
};
this.modal = new Control.Modal(false, Object.extend(this.def, opt));
this.modal.open();
},
hide: function() {
if (this.opened) this.modal.close();
}
});
InitSWFobjects = Class.create({
initialize: function() {
this.swf = new Array();
this.swfobjects = new Array();
$$('input.swf').each(function(swfInput, idx) {
this.initObject(idx, swfInput.name, swfInput.value);
}.bind(this));
this.createObjects();
},
initObject: function(idx, prefix, target) {
this.swf[idx] = {
target: target,
object: null,
id: null,
x: 0,
y: 0,
version: 0,
variables: {},
param: {}
};
$$('input.' + prefix).each(function(el) {
if (/param/.test(el.className)) {
eval('var obj = {' + el.name + ' : \'' + el.value + '\'}');
Object.extend(this.swf[idx].param, obj);
} else if (/variable/.test(el.className)) {
eval('var obj = {' + el.name + ' : \'' + el.value + '\'}');
Object.extend(this.swf[idx].variables, obj);
} else {
switch (el.name) {
case 'swfobject': this.swf[idx].object = el.value; break;
case 'swfid': this.swf[idx].id = el.value; break;
case 'swfx': this.swf[idx].x = el.value; break;
case 'swfy': this.swf[idx].y = el.value; break;
case 'swfversion': this.swf[idx].version = el.value; break;
}
}
}.bind(this));
},
createObjects: function() {
this.swf.each(function(swfobj, idx) {
var params = {};
for (i in swfobj.param) {
eval('var tmp = {' + i + ': \'' + swfobj.param[i] + '\'};');
Object.extend(params, tmp);
}
var flashvars = {};
for (k in swfobj.variables) {
eval('var tmp = {' + k + ': \'' + swfobj.variables[k] + '\'};');
Object.extend(flashvars, tmp);
}
var attributes = {
id: swfobj.id
};
swfobject.embedSWF(
swfobj.object,
swfobj.target,
swfobj.x,
swfobj.y,
swfobj.version,
"expressInstall.swf",
flashvars,
params,
attributes
);
}.bind(this));
}
});
CategoryDropDownList = Class.create({
initialize: function(id) {
this.button = $(id);
if (!this.button) return false;
this.list = $(this.button.className.match(/list-(\w+)\s?/)[1]);
if (!this.list) return false;
this.myEffects = {
updown: 0.4
};
this.delay = 2000;
this.timer = null;
this.open = false;
this.initAction();
},
initAction: function() {
this.button.observe('click', this.openList.bind(this));
this.button.observe('mouseover', this.clearTimer.bind(this));
this.button.observe('mouseout', this.setTimer.bind(this));
this.list.observe('mouseover', this.clearTimer.bind(this));
this.list.observe('mouseout', this.setTimer.bind(this));
},
openList: function() {
if (this.open) {
this.closeList();
} else {
this.open = true;
new Effect.BlindDown(this.list, {duration: this.myEffects.updown, transition: Effect.Transitions.sinoidal});
}
},
closeList: function() {
new Effect.BlindUp(this.list, {duration: this.myEffects.updown, transition: Effect.Transitions.sinoidal});
this.open = false;
},
clearTimer: function() {
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
},
setTimer: function() {
if (!this.timer && this.open) {
this.timer = setTimeout(function() {
this.closeList();
this.timer = null;
}.bind(this), this.delay);
}
}
});
MFTooltip = Class.create({
initialize: function() {
$$('.tooltip').each(this.initTip.bind(this));
},
getContent: function(content) {
var el = new Element('div');
var elSpan = new Element('span', {'class': 'tip'}).update(content);
var elDiv = new Element('div', {'class': 'pointer'}).update('pointer');
el.appendChild(elSpan);
el.appendChild(elDiv);
return el;
},
initTip: function(imgTip) {
if (!imgTip.title.blank()) {
var cName = 'righttip';
var offsetX = 0;
if (/lefttip/.test(imgTip.className)) {
cName = 'lefttip';
offsetX = -220;
}
var txt = imgTip.title.strip();
imgTip.title = '';
new Tip(
imgTip,
this.getContent(txt),
{
className: cName,
effect: 'appear',
duration: 0.2,
delay: 0.2,
offset: {x: 14 + offsetX, y: -10},
onShow: function () {},
onHide: function () {}
}
);
}
}
});
SimpleDebug = Class.create({
initialize: function() {
this.level = 10;
this.history = new Hash();
this.saveInHistory = true;
},
onLoadInit: function(level) {
this.saveInHistory = false;
this.level = level ? level : 0;
if (this.level == 0) {
_Debug = false;
}
this.win = this.create();
if (this.level != 0) {
this.history.each(function(pair){
this.add(pair.value.m, pair.value.c);
}.bind(this));
}
this.docScroll();
},
create: function() {
var main = new Element('div', {id: 'debugWrapper'}).setStyle({
position: 'absolute', bottom: '0', right: '0', height: '100px', width: '800px', 
textAlign: 'left', backgroundColor: '#FFFFFF', zIndex: 1000
}).hide();
var content = new Element('div', {id: 'debugOut'}).setStyle({
overflow: 'auto', height: '80px', marginTop: '5px'
});
var h = new Element('div').update('Debug window');
var close = new Element('a').observe('click', this.closeDebug.bind(this)).update('[X]');
close.setStyle({'float': 'right', cursor: 'pointer'});
var clear = new Element('a').observe('click', this.clearDebug.bind(this)).update('[CLEAR]');
clear.setStyle({'float': 'right', cursor: 'pointer'});
var copy  = new Element('a').observe('click', this.copyDebug.bind(this)).update('[COPY (FF only)]');
copy.setStyle({'float': 'right', cursor: 'pointer'});
main.insert(close);
main.insert(clear);
main.insert(copy);
main.insert(h);
main.insert(content);
$(document.body).insert(main);
Event.observe(window, 'scroll', this.docScroll.bind(this), false);
return main;
},
docScroll: function() {
this.win.setStyle({bottom : -this.win.cumulativeScrollOffset().top + 'px'});
},
closeDebug: function() {
this.win.hide();
},
clearDebug: function() {
$('debugOut').update();
},
copyDebug: function() {
var text = '';
$('debugOut').select('div').each(function(logLine) {
text += logLine.innerHTML + "\n";
});
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"].getService();
if (clipboard) clipboard = clipboard.QueryInterface(Components.interfaces.nsIClipboard);
var transferable = Components.classes["@mozilla.org/widget/transferable;1"].createInstance();
if (transferable) transferable = transferable.QueryInterface(Components.interfaces.nsITransferable);
transferable.addDataFlavor("text/unicode");
var textObj = new Object();
var textObj = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
if (textObj) {
textObj.data = text;
transferable.setTransferData("text/unicode", textObj, text.length*2);
var clipid=Components.interfaces.nsIClipboard;
clipboard.setData(transferable,null,clipid.kGlobalClipboard);
}       
},
decode: function(msg) {
if (msg.inspect) {
//msg = msg.inspect();
} else if (msg.message && msg.name) {
msg = msg.name.toString() + ': ' + msg.message.toString();
} else if (msg.toString) {
msg = msg.toString();
}
return msg.escapeHTML();
},
stop: function(msg) {
if (this.level >= 4) {
this.add(msg, 'green');
alert('Log: ' + msg);
} else if (this.level == -1) this.console(msg);
},
debug: function(msg) {
if (this.level >= 3) this.add(msg, 'black');
else if (this.level == -1) this.console(msg);
},
info: function(msg) {
if (this.level >= 2) this.add(msg, 'gray');
else if (this.level == -1) this.console(msg);
},
err: function(msg) {
if (this.level >= 1) this.add(msg, 'red');
else if (this.level == -1) this.console(msg);
},
add: function(msg, color) {
if (this.saveInHistory) {
this.history.set(this.history.size() + 1, {m: msg, c: color});
} else {
this.win.show();
var cd = new Date();
var line = new Element('div').setStyle({color: color});
line.insert(new Element('b').update(
formatNumber(cd.getDate()) + '/' + formatNumber(cd.getMonth() + 1) + '/' + cd.getFullYear() + ' ' +
formatNumber(cd.getHours()) + ':' + formatNumber(cd.getMinutes()) + ':' + formatNumber(cd.getSeconds()) +
':&nbsp;'));
line.insert(this.decode(msg))
this.win.down('div', 1).insert(line);
}
},
console: function(msg) {
try {
if (typeof(console.log) == 'function') console.log(msg);
} catch(e) { }
}
});
ModalErrorWindow = Class.create({
initialize: function(errorCode) {
this.modal = new Control.Modal(false, {
contents: function() {
var showError = new UrlConstructor('error/by_code');
showError.addVar('code', errorCode);
new Ajax.Request(showError.construct(), {
onComplete: function(request) {
this.modal.update(request.responseText);
$('modalClose').observe('click', this.close.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
afterClose: this.afterClose.bind(this),
beforeOpen: this.beforeOpen.bind(this),
fade: true, fadeDuration: 0.4, opacity: 0.8, width: 500, containerClassName: 'mfmodal'
});
},
open: function() {
this.modal.open();        
},
close: function() {
this.modal.close();
},
afterClose: function() {
if ($('browserPlayer')) $('browserPlayer').show();
},
beforeOpen: function() {
if ($('browserPlayer')) $('browserPlayer').hide();
}
});
SubmitFormByLink = Class.create({
initialize: function() {
this.defaultClass = 'submitFormByLink';
$$('.submitFormByLink').each(function(el) {
el.observe('click', function() {
var form = el.up('form');
if (!form.down('.search_text').hasClassName('firstEnterText')) form.submit();
else {
var url = new UrlSeoConstructor('CATEGORY_INDEX_ALL');
window.location = url.construct();
}  
});    
});
}
});
function parseUri(str) {
var o   = parseUri.options,
m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
uri = {},
i   = 14;
while (i--) uri[o.key[i]] = m[i] || "";
uri[o.q.name] = {};
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
if ($1) uri[o.q.name][$1] = $2;
});
return uri;
};
parseUri.options = {
strictMode: false,
key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
q:   {
name:   "queryKey",
parser: /(?:^|&)([^&=]*)=?([^&]*)/g
},
parser: {
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
}
};
function i18n(key, hash) {
var t = lang.get(key);
if (!t && Object.isFunction(l)) l('i18n constant not defined. Const: ' + key);
if (hash) {
hash.each(function(r) {
t = t.replace(new RegExp('(%' + r.key + '%)', 'i'), r.value);
});
}
return t;
}
function getLocale() {
var lang = null;
try {
if (Prototype.Browser.IE) {
lang = $$('meta[httpEquiv="Content-Language"]').first().content.toLowerCase();
} else {
lang = $$('meta[http-equiv="Content-Language"]').first().content.toLowerCase();
}
} catch (e) {
lang = 'fr';
}
var path = '';
if (lang == 'en') {
path = '/en';
} else if (lang == 'de') {
path = '/de';
} else if (lang == 'it') {
path = '/it';
} else if (lang == 'sv') {
path = '/sv';
}
return {lang: lang, path: path};
}
function getPortalId() {
if (portal = $('portalId')) {
return portal.getValue();
}
return false;
}
function formatNumber(num) {
return (num < 10) ? '0' + num : num;
}
function l(log) {
if (typeof(console) == 'object' && DEFINE.get('IS_DEV')) console.log(log);
}

/** 
* Author and Version Information {{{
* author: Antonio Ramirez http://webeaters.blogspot.com
*
* class: AutoComplete for Prototype 1.6.0
*
* version: 1.2.1 - 2007-11-11 
* (based on AutoSuggest 2.1.3 - 2007-07-19)
* version: 1.3.0 - 2008-01-03 by Andrew Nicols <andrew@nicols.co.uk>
*  - Fixed incorrect title-casing - CSS is Case Sensitive!!!
*  - Adjusted the way in which the Notifier images are loaded.
*  - Changed json code to pass all json variables back instead of just id, value and name
*  - Fixed 'GMAIL' code such that if valueSep is undefined, it is ignored
*  - Changed the default for valueSep to null
*  - Fixed the resetTimeout function
*
* REFERENCES AND THANKS 
* this class is based on the work in AutoSuggest.js of
* Timothy Groves - http://www.brandspankingnew.net
* and adapted for use with prototype 1.6.0
*
* UPDATED by R��da HADJOUTI
* GMAIL like AutoComplete (semicolon separator) Update
*
}}}*/
var AutoComplete = Class.create();
AutoComplete.prototype = { // {{{
Version: '1.3.0',
REQUIRED_PROTOTYPE: '1.6.0',
initialize: function (id, param) { // {{{
// check whether we have the appropiate javascript libraries
this.PROTOTYPE_CHECK();
// Get the field we're watching.
// It needs to be a valid field so throw an error if it's not valid or can't be found.
this.fld = $(id);
if (!this.fld)
{
throw("AutoComplete requires a field id to initialize");
}
// Init variables
this.sInp = ""; // input value 
this.nInpC = 0;// input value length
this.aSug = []; // suggestions array 
this.iHigh = 0;// level of list selection 
// Parameter Handling {{{
// Set the use specified options
this.options = param ? param : {};
// These are the default settings {{{
var k, def = {
valueSep:null,
minchars:1,
meth:"get",
varname:"input",
className:"autocomplete",
timeout:8000,
delay:500,
offsety:-5,
shownoresults: true,
noresults: "No results were found.",
maxheight: 250,
cache: true,
maxentries: 25,
onAjaxError:null,
setWidth: false,
minWidth: 100,
maxWidth: 200,
useNotifier: true
};
//}}}
// Overlay any values which weren't user specified.
for (k in def) 
{
if (typeof(this.options[k]) != typeof(def[k]))
this.options[k] = def[k];
}
// End of Parameter Handling }}}
// Not everyone wants to use the Notifier. Give them the option
if (this.options.useNotifier)
{
this.fld.addClassName('ac_field');
}
// set keyup handler for field
// and prevent AutoComplete from client
var p = this;
// NOTE: not using addEventListener because UpArrow fired twice in Safari
this.fld.onkeypress = function(ev){ return p.onKeyPress(ev); };
this.fld.onkeyup      = function(ev){ return p.onKeyUp(ev); };
// ARN-DEBUG Chances are we want to reset the timeout when they lose focus, at least that's what I prefer
this.fld.onblur  = function(ev){ p.resetTimeout(); return true; };
// ARN-DEBUG Not sure what this is about!
this.fld.setAttribute("AutoComplete","off");
}, //}}}
convertVersionString: function (versionString){ // {{{
var r = versionString.split('.');
return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]);
}, // }}}
PROTOTYPE_CHECK: function() { // {{{
if((typeof Prototype=='undefined') || 
(typeof Element == 'undefined') || 
(typeof Element.Methods=='undefined') ||
(this.convertVersionString(Prototype.Version) < 
this.convertVersionString(this.REQUIRED_PROTOTYPE)))
throw("AutoComplete requires the Prototype JavaScript framework >= " +
this.REQUIRED_PROTOTYPE);
}, // }}}
// set responses to keypress events in the field
// this allows the user to use the arrow keys to scroll through the results
// ESCAPE clears the list
// RETURN sets the current highlighted value
// UP/DOWN move around the list
onKeyPress: function (e) { // {{{
if (!e) e = window.event;
var key= e.keyCode || e.wich;
switch(key)
{
case Event.KEY_RETURN:
if (this.iHigh > 0) {
this.setHighlightedValue();
Event.stop(e);
}
break;
case Event.KEY_TAB:
this.setHighlightedValue();
//Event.stop(e);
break;
case Event.KEY_ESC:
this.clearSuggestions();
break;
}
return true;
}, //}}}
onKeyUp: function (e) { // {{{
if (!e) e = window.event;
var key = e.keyCode || e.wich;
if (key == Event.KEY_UP || key == Event.KEY_DOWN) 
{
this.changeHighlight(key);
Event.stop(e);
}
else this.getSuggestions(this.fld.value);
return true;
}, //}}}
getSuggestions: function(val) { // {{{
// input the same? do nothing
if(val==this.sInp) return false;
// kill the old list
if($(this.acID)) $(this.acID).remove();
this.sInp = val;
// input length is less than the min required to trigger a request
// do nothing
if (val.length < this.options.minchars)
{
this.aSug = [];
this.nInpC= val.length; 
return false;
}
// Here we will detect if there is a comma and the splitted value has a value to check
// comma stars a new search and val is converted to the new value after the comma
var ol= this.nInpC; // old length
this.nInpC= val.length ? val.length : 0;
// if caching enabled, and we didn't receive the maxentries value
// and user is typing (ie. length of input is increasing)
// filter results out of suggestions from last request
var l = this.aSug.length;
if( this.options.cache && ( this.nInpC > ol ) && l && ( l < this.options.maxentries ) )
{
var arr = new Array();
for (var i=0;i<l;i++) {
if (this.aSug[i].value.toLowerCase().indexOf(val.toLowerCase()) != -1)
{
arr.push(this.aSug[i]);
}
}
this.aSug = arr;
// recreate the list
this.createList(this.aSug);
} else {
// do new request
var p = this;
//var input= this.sInp; // send the converted new value (comma)
clearTimeout(this.ajID); // ajax id timer
this.ajID = setTimeout( function () {p.doAjaxRequest(p.sInp)}, this.options.delay);
}
document.helper = this;
return false;
}, // }}}
getLastInput : function(str) { // {{{
var ret = str;
if (undefined != this.options.valueSep) {
var idx = ret.lastIndexOf(this.options.valueSep);
ret = idx == -1 ? ret : ret.substring(idx + 1, ret.length);
}
return ret;
}, // }}}
doAjaxRequest: function (input) { // {{{
// we have to check here if there is a new splitted value (, or ;)
// always check against the last part of the comma and then check
// saved input is still the value of the field
if (input != this.fld.value) 
return false;
// Gmail like : get only the last user's input
this.sInp = this.getLastInput(this.sInp);
// create ajax request
// do we need to call a function to recreate the url?
if (typeof this.options.script == 'function')
var url = this.options.script(encodeURIComponent(this.sInp));
else
var url = this.options.script+this.options.varname+'='+encodeURIComponent(this.sInp);
if(!url) return false;
var p = this;
var m = this.options.meth;  // get or post?
var options = {
method: m,
onSuccess: function (req) { // {{{
if( p.options.useNotifier )
{
p.fld.removeClassName('ac_field_busy');
p.fld.addClassName('ac_field');
};
p.setSuggestions(req,input);
}, // }}}
onFailure: (typeof p.options.onAjaxError == 'function')? function (status) { // {{{
if (p.options.useNotifier)
{
p.fld.removeClassName('ac_field_busy');
p.fld.addClassName('ac_field');
}
p.options.onAjaxError(status)
} : // }}}
function (status) { // {{{
if (p.options.useNotifier)
{
p.fld.removeClassName('ac_field_busy');
p.fld.addClassName('ac_field');
}
alert("AJAX error: "+status); 
} // }}}
}
// make new ajax request
new Ajax.Request(url, options);
}, // }}}
setSuggestions: function (req, input) { // {{{
// if field input no longer matches what was passed to the request
// don't show the suggestions
// here we need to check against the splitted values if any (, or ;)
if (input != this.fld.value)
return false;
this.aSug = [];
if(this.options.json) 
{ // response in json format?
var jsondata = eval('(' + req.responseText + ')');
this.aSug = jsondata.results;
} else {
// response in xml format?
var results = req.responseXML.getElementsByTagName('results')[0].childNodes;
for(var i=0;i<results.length;i++)
{
if(results[i].hasChildNodes())
this.aSug.push(  { 'id':results[i].getAttribute('id'), 'value':results[i].childNodes[0].nodeValue, 'info':results[i].getAttribute('info') }  );
}
}
this.acID = 'ac_'+this.fld.id;
this.createList(this.aSug);
}, // }}}
createDOMElement: function ( type, attr, cont, html ) { // {{{
var ne = document.createElement( type );
if (!ne)
return 0;
for (var a in attr)
ne[a] = attr[a];
var t = typeof(cont);
if (t == "string" && !html)
ne.appendChild( document.createTextNode(cont) );
else if (t == "string" && html)
ne.innerHTML = cont;
else if (t == "object")
ne.appendChild( cont );
return ne;
}, // }}}
createList:function(arr) { // {{{
// get rid of the old list if any  
if($(this.acID)) $(this.acID).remove();
// clear list removal timeout
this.killTimeout();
// if no results, and showNoResults is false, do nothing
if (arr.length == 0 && !this.options.shownoresults) return false;
// create holding div
var div= this.createDOMElement('div', {id:this.acID, className:this.options.className});
// create div header
var hcorner = this.createDOMElement('div', {className: 'ac_corner'});
var hbar= this.createDOMElement('div', {className: 'ac_bar'});
var header= this.createDOMElement('div', {className: 'ac_header'});
header.appendChild(hcorner);
header.appendChild(hbar);
div.appendChild(header);
// create and populate ul
var ul= this.createDOMElement('ul', {id:'ac_ul'});
var p = this; // pointer that we will need later on
// no results?
if (arr.length == 0 && this.options.shownoresults)
{
var li = this.createDOMElement('li', {className: 'ac_warning'}, this.options.noresults );
ul.appendChild(li);
} else {
// loop through arr of suggestions creating an LI element for each of them
for (var i=0,l = arr.length; i<l; i++)
{
// format output with the input enclosed in a EM elementFromPoint
// (as HTML not DOM)
var val = arr[i].value;
var st = val.toLowerCase().indexOf(this.sInp.toLowerCase()); // HERE WE CHECK AGAINST THE SPLITTED VALUE IF ANY***
var output = val.substring(0,st) + '<em>' + val.substring(st,st+this.sInp.length) + '</em>' + val.substring(st+this.sInp.length);
var span= this.createDOMElement('span',{},output,true); // type of, properties, output, isHTML?
if(arr[i].info != '') // do we need to add extra info?
{
var br= this.createDOMElement('br',{});
span.appendChild(br);
var small = this.createDOMElement('small',{}, arr[i].info);
span.appendChild(small);
}
var a = this.createDOMElement('a',{href:'#'});
var tl= this.createDOMElement('span',{className:'tl'},'&nbsp;',true);
var tr= this.createDOMElement('span',{className:'tr'},'&nbsp;',true);
a.appendChild(tl);
a.appendChild(tr);
a.appendChild(span); // add the object span into the link
a.name = i+1;
a.onclick = function () { // {{{
p.setHighlightedValue();
return false; 
}; // }}}
a.onmouseover= function () { // {{{
p.setHighlight(this.name); 
}; // }}} 
if (l-i == 1) {
var li = this.createDOMElement('li', {className:'last'}, a);
} else {
var li = this.createDOMElement('li', {}, a); // add the link element to a li element
}
// finally add the newly created li element to the ul element 
ul.appendChild(li);
}
}
div.appendChild(ul); // add the newly created list to the div element
// create div footer
var fcorner = this.createDOMElement('div', {className: 'ac_corner'});
var fbar= this.createDOMElement('div', {className: 'ac_bar'});
var footer= this.createDOMElement('div', {className: 'ac_footer'});
footer.appendChild(fcorner);
footer.appendChild(fbar);
div.appendChild(footer);
// get position of target textfield
// position holding div below it
// set width of holding div to width of field 
// if 
var pos         = this.fld.cumulativeOffset();
div.style.left = pos[0] + "px";
div.style.top = pos[1] + this.fld.offsetHeight + "px";
var w = 
(
this.options.setWidth && this.fld.offsetWidth < this.options.minWidth
)
? this.options.minWidth : 
(
this.options.setWidth && this.fld.offsetWidth > this.options.maxWidth
)
? this.options.maxWidth : 
this.fld.offsetWidth;
div.style.width = w + "px";
// set mouseover functions for div
// when mouse pointer leaves div, set a timeout to remove the list after an interval
// when mouse enters div, kill the timeout so the list won't be removed
//
div.onmouseover = function(){ p.killTimeout() };
div.onmouseout = function(){ p.resetTimeout() };
// add DIV to document
document.getElementsByTagName("body")[0].appendChild(div);
this.options.afterShow(div);
// highlight first item
this.iHigh = 0;
//this.setHighlight(1);
// remove list after interval
this.toID= setTimeout(
function () {
p.clearSuggestions() 
}, this.options.timeout
);
if( this.options.useNotifier )
{
this.fld.removeClassName('ac_field');
this.fld.addClassName('ac_field_busy');
};
}, // }}}
changeHighlight:function(key) { // {{{
var list = $("ac_ul");
if (!list)
return false;
var n;
n = (key == Event.KEY_DOWN || key == Event.KEY_TAB)? this.iHigh + 1 : this.iHigh - 1; // false assumed to be Event.KEY_UP
n = (n > list.childNodes.length)? list.childNodes.length : ((n < 1)? 1 : n);
this.setHighlight(n);
}, // }}}
setHighlight:function(n) { // {{{
var list = $('ac_ul');
if (!list) return false;
if (this.iHigh > 0) this.clearHighlight();
this.iHigh = Number(n);
list.childNodes[this.iHigh-1].className = 'ac_highlight';
this.killTimeout();
}, // }}}
clearHighlight:function() { // {{{
var list = $('ac_ul');
if(!list) return false;
if(this.iHigh > 0)
{
list.childNodes[this.iHigh-1].className = '';
this.iHigh = 0;
}
}, // }}}
setHighlightedValue:function() { // {{{
if (this.iHigh)
{
// HERE WE NEED TO IMPLEMENT THE GMAIL LIKE SPLITTED VALUE
if (!this.aSug[this.iHigh - 1]) return;
// Gmail like
if (undefined != this.options.valueSep) {
var str = this.getLastInput(this.fld.value);
var idx = this.fld.value.lastIndexOf(str);
str = this.aSug[ this.iHigh -1 ].value + this.options.valueSep;
this.sInp = this.fld.value = idx == -1 ? str : this.fld.value.substring(0, idx) + str;
} else {
var str = this.getLastInput(this.fld.value);
var idx = this.fld.value.lastIndexOf(str);
str = this.aSug[ this.iHigh -1 ].value;
this.sInp = this.fld.value = idx == -1 ? str : this.fld.value.substring(0, idx) + str;
}
// move cursor to end of input (safari)
this.fld.focus();
if(this.fld.selectionStart)
this.fld.setSelectionRange(this.sInp.length, this.sInp.length);
this.clearSuggestions();
// pass selected object to callback function, if exists
if (typeof this.options.callback == 'function')
this.options.callback(this.aSug[this.iHigh-1]); // the object has the properties we want, it will depend of
}
}, // }}}
killTimeout:function() { // {{{
clearTimeout(this.toID);
}, // }}}
resetTimeout:function() { // {{{
this.killTimeout();
var p = this;
this.toID = setTimeout(
function () { 
p.clearSuggestions();
}, p.options.timeout
);
// ARN-DEBUG Added p.options.timeout back :|
}, // }}}
clearSuggestions:function () { // {{{
this.killTimeout();
if ($(this.acID))
{
this.fadeOut(300,function () {
$(this.acID).remove();
} );
}
}, // }}}
fadeOut:function (milliseconds, callback) { // {{{
this._fadeFrom = 1;
this._fadeTo= 0;
this._afterUpdateInternal = callback;
this._fadeDuration= milliseconds;
this._fadeInterval = 50;
this._fadeTime = 0;
var p = this;
this._fadeIntervalID = setInterval(
function() {
p._changeOpacity()
}, this._fadeInterval
);
}, // }}}
_changeOpacity: function() { // {{{
if (!$(this.acID))
{
this._fadeIntervalID=clearInterval(this._fadeIntervalID);
return;
} 
this._fadeTime += this._fadeInterval;
var ieop = Math.round( (this._fadeFrom + ((this._fadeTo - this._fadeFrom) * (this._fadeTime/this._fadeDuration))) * 100)
var op = ieop / 100;
var el = $(this.acID);
if (el.filters) // internet explorer
{
try {
el.filters.item("DXImageTransform.Microsoft.Alpha").opacity = ieop;
} catch (e) { 
// If it is not set initially, the browser will throw an error.
// This will set it if it is not set yet.
el.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity='+ieop+')';
}
} else{
el.style.opacity = op;
}
if (this._fadeTime >= this._fadeDuration)
{
clearInterval( this._fadeIntervalID );
if (typeof this._afterUpdateInternal == 'function')
this._afterUpdateInternal();
}
} // }}}
} // }}}
// vim: set filetype=javascript foldmethod=marker foldlevel=5:


var __meta = true;
Press = Class.create({
initialize: function() {
this.objects = $$('img.pictopress');
if ((this.objects.size() == 0) || (!$('boxPress_prev')) || (!$('boxPress_next')) ) {return false};
this.objects.first().setStyle({display: 'block'});
$('boxPress_totalPage').update((this.objects.size() < 10) ? '0' + this.objects.size() : this.objects.size());
this.currentPage = 0;
this.initActions();
this.render();
},
render: function() {
this.objects.each(function(el) {
el.setStyle({display: 'none'});
});
this.objects[this.currentPage].setStyle({display: 'block'});
var displayCurrent = this.currentPage + 1;
$('boxPress_currentPage').update((displayCurrent < 10) ? '0' + displayCurrent : displayCurrent);
if (this.currentPage == 0) {
$('boxPress_prev').addClassName('inactive');
} else if (this.currentPage == (this.objects.size() - 1)) {
$('boxPress_next').addClassName('inactive');
} else {
$('boxPress_prev', 'boxPress_next').each(function(el) {
el.removeClassName('inactive');
});
}
},
initActions: function() {
$('boxPress_next').observe('click', function(){
if (this.currentPage < (this.objects.size() - 1)) {
this.currentPage++;
this.render();
}
}.bind(this));
$('boxPress_prev').observe('click', function(){
if (this.currentPage > 0) {
this.currentPage--;
this.render();
}
}.bind(this));
}
});
Newsletter = Class.create({
initialize: function() {
$$('.formnews').each(function(fm) {
this.initElements(fm);
fm.observe('submit', function(event) {
this.showDialog(Event.element(event).down('img'));
Event.stop(event);
}.bind(this));
}.bind(this));
this.modal = null;
},
initElements: function(fm) {
fm.down('input').observe('focus', function(event) {
var elInput = Event.element(event);
if (elInput.hasClassName('defaultText')) {
elInput.value = '';
elInput.removeClassName('defaultText');
}
}.bind(this));
fm.down('label').observe('click', function(event) {
this.showDialog(Event.element(event));
}.bind(this));
},
showDialog: function(elImg) {
var email = elImg.up('.formnews').down('input').getValue();
var err = new ErrorManager();
err.checkEmail(email);
if (err.getErrors()) {
return false;
}
var url = new UrlConstructor('Newsletter/Dialog');
url.addVar('email', email);
this.modal = new Control.Modal(false, {
contents: function() {
new Ajax.Request(url.construct(), {
onComplete: function(request){
this.modal.update(request.responseText);
this.initDialogAction();
Event.observe('modalClose', 'click', function() {
this.modal.close();
}.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
width: 500,
containerClassName: 'mfmodal'
});
this.modal.open();
},
initDialogAction: function() {
$('saveemailok').observe('click', function() {
var url = new UrlConstructor('newsletter/subscribe');
url.setAction(true);
$('saveemail').getElements().each(function(el) {
url.addVar(el.readAttribute('name'), $F(el));
});
new Ajax.Request(url.construct(), {
onSuccess: function(transport) {
var obj = transport.responseText.evalJSON();
var er = new ErrorManager(obj);
if (er.haveErrors()) {
this.modal.update(er.getHtmlContent());
Event.observe('errorsClose', 'click', function() {
this.modal.close();
}.bind(this));                       
} else {
alert(i18n('newsletter_alert_part1') + obj.email + i18n('newsletter_alert_part2'));
$$('.formnews').each(function(fm) {
var elInput = fm.down('input');
if (!elInput.hasClassName('defaultText')) {
elInput.value = '';
}
});
this.modal.close();
}
}.bind(this)
});
}.bind(this));
}
});
VideoScreeenShot = Class.create({
initialize: function() {
if (!$('thumbnailContent')) {return false;}
if ($('thumbnailContent').offsetWidth < $('thumbnailContent').offsetHeight) {
this.scrollLength = 340; // vertical scroll
} else {
this.scrollLength = 85;  // horizontal scroll
}
if ($('video-0').height <= 30) {
$('video-0').src = 'http://img.metaboli.fr/common/V4/images/videoNo_sm.jpg';
}
$('video-0').addClassName('goodSizeVideo');
this.countElements = $('thumbnailContent').childElements().size();
this.countPages = Math.ceil(this.countElements/4);
this.currentPage = 1;
this.buttonNavUp = $('buttonNavUp');
this.buttonNavDown = $('buttonNavDown');
var sDiv = $('thumbnailContent').down();
if ($('selectedItem').getValue() != 0) {
var screen = parseInt($('selectedItem').getValue());
sDiv = sDiv.next(screen - 1);
if (screen > 3) {
this.currentPage = Math.ceil(parseInt($('selectedItem').getValue()) / this.countPages);
}
}
this.render();
this.buttonNavDown.observe('click', function(event) {
if (/downInactive/.test(Event.element(event).className)) {
return false;
}
this.currentPage++;
this.render();
}.bind(this));
this.buttonNavUp.observe('click', function(event) {
if (/upInactive/.test(Event.element(event).className)) {
return false;
}
this.currentPage--;
this.render();
}.bind(this));
$('viewScreenshot').observe('click', this.modalView);
$('thumbnailContent').select('img').each(function(elImg) {
Event.observe(elImg, 'click', function(event) {
var elImg = Event.element(event);
this.selectItem(elImg);
}.bind(this));
}.bind(this));
sDiv.addClassName('thumbSelected');
this.selectItem(sDiv.down('img'));
},
render: function() {
$('thumbnailContent').setStyle({
marginTop: -(this.currentPage * this.scrollLength) + 'px'
});
$('thumbnailContent').setStyle({
marginTop: -((this.currentPage - 1) * this.scrollLength) + 'px'
});
if (this.currentPage == 1) {
this.buttonNavUp.addClassName('upInactive');
} else {
this.buttonNavUp.removeClassName('upInactive');
}
if (this.currentPage == this.countPages) {
this.buttonNavDown.addClassName('downInactive');
} else {
this.buttonNavDown.removeClassName('downInactive');
}
},
selectItem: function(elImg) {
$('thumbnailContent').childElements().each(function(el) {
el.removeClassName('thumbSelected');
}.bind(this));
if (/screen/.test(elImg.id)) {
$('videoScript').update();
$('productVideo').setStyle({display: 'none'});
var container = $('productScreenshot');
var r = elImg.src.match(/^(.*)_sm(.*)$/);
container.down('img').src = r[1] + r[2];
container.setStyle({display: 'block'});
} else if (/video/.test(elImg.id)) {
$('productScreenshot').setStyle({display: 'none'});
if ($('videoScript')) {
var video = elImg.src.match(/^(.*)_sm.*$/)[1] + '.flv';
$('videoScript').innerHTML = '<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ' +
'codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" ' +
'WIDTH="450" HEIGHT="450">' +
'<PARAM NAME=movie VALUE="' + $('videoPlayerUrl').getValue() + '">' +
'<PARAM NAME=quality VALUE=high>' +
'<PARAM NAME=bgcolor VALUE=#000000>' +
'<PARAM NAME=wmode VALUE=transparent>' +
'<PARAM NAME=flashvars VALUE="videoPath=' + video + '&lang=' + getLocale().lang + '">' +
'<EMBED FLASHVARS="videoPath=' + video + '&lang=' + getLocale().lang + '" src="' + $('videoPlayerUrl').getValue() + '"' +
'quality=high bgcolor="#000000" ' +
'WIDTH="450" HEIGHT="450" NAME="" ALIGN="" wmode="transparent" ' +
'TYPE="application/x-shockwave-flash" ' +
'PLUGINSPAGE="http://www.macromedia.com/go/getflashplayer">' +
'</EMBED>' +
'</OBJECT>';
}
$('productVideo').setStyle({display: 'block'});
}
this.render();
elImg.up('div').addClassName('thumbSelected');
},
modalView: function(event) {
var elImg = Event.element(event);
//         var a = Builder.node('a', {href: elImg.src});
var a = new Element('a', {href: elImg.src});
this.modal = new Control.Modal(a, {
fade: true,
image: true,
containerClassName: 'viewFullScrennShot'
});
this.modal.open();
}
});
Product = Class.create({
initialize: function() {
this.initFavorites('addGame');
this.initFavorites('listGame');
this.initAddRemoveFavorites();
this.initParentalControlInfo();
},
initFavorites: function(elId) {
if (!$(elId)) {return false;}
Event.observe(elId, 'mouseover', function(event) {
clearTimeout(this.ftimer);
this.showFavoriteTip(elId);
}.bind(this));
Event.observe(elId, 'mouseout', function(event) {
this.closeFavoriteTip(elId);
}.bind(this));
},
showFavoriteTip: function(el) {
$(el).down('div').setStyle({display: 'block'});
},
closeFavoriteTip: function(el) {
this.ftimer = setTimeout(function() {
$(el).down('div').setStyle({display: 'none'});
}, 1000);
},
initAddRemoveFavorites: function() {
if (!$('addGame') || !$('listGame')) {return false;}
this.gameId = $('gameId').getValue();
Event.observe('addGame', 'click', function() {
var url = new UrlConstructor('favorite/add');
url.setAction(true);
url.addVar('id', this.gameId);
new Ajax.Request(url.construct(), {
onSuccess: function(transport, json) {
this.toggleFavoritesIcon();
}.bind(this)
});
}.bind(this));
Event.observe('listGame', 'click', function() {
var url = new UrlConstructor('favorite/remove');
url.setAction(true);
url.addVar('id', this.gameId);
new Ajax.Request(url.construct(), {
onSuccess: function(transport, json) {
this.toggleFavoritesIcon();
}.bind(this)
});
}.bind(this));
},
toggleFavoritesIcon: function() {
if ($('addGame').getStyle('display') == 'block') {
$('addGame').setStyle({display: 'none'});
$('listGame').setStyle({display: 'block'});
} else {
$('addGame').setStyle({display: 'block'});
$('listGame').setStyle({display: 'none'});
}
},
initParentalControlInfo: function() {
var modalId = $('parentalControlButton');
if (!modalId) return false;
var modal = new Control.Modal(modalId, {
fade: true, opacity: 0.8, width: 500, containerClassName: 'mfmodal',
onSuccess: function() {
Event.observe('modalClose', 'click', function() {modal.close();});
}
});
}
});
function getMovie(movieName) {
if (Prototype.Browser.IE) {
return window[movieName];
} else {
return document[movieName];
}
}
function triggerVideo() {
try {
var homeFlash = getMovie('flashObjectVideo');
homeFlash.pageFinishedLoading();
} catch (e) {
setTimeout(triggerVideo, 1000);
}
}
SimpleInPlaceEditor = Class.create({
initialize: function(mainId) {
this.main = $(mainId);
if (!this.main) return ;
this.btnEdit = this.main.down('a.edit');
this.btnSave = this.main.down('a.save');
this.btnCancel = this.main.down('a.cancel');
Event.observe(this.btnEdit, 'click', this.toEditState.bind(this)); 
Event.observe(this.btnCancel, 'click', this.toViewState.bind(this)); 
Event.observe(this.btnSave, 'click', this.saveAction.bind(this)); 
},
saveAction: function() {
this.main.request({
onSuccess: function(transport) {
var obj = transport.responseText.evalJSON();
var er = new ErrorManager(obj);
if (er.getErrors()) 
return false;
for (i in obj) {
if ($(i)) $(i).update(obj[i]);
}
this.toViewState();
}.bind(this)            
});
},
toEditState: function() {
this.main.down('ul').addClassName('edit');
this.btnEdit.hide();
this.btnSave.removeClassName('displayNone');
this.btnCancel.removeClassName('displayNone');
this.main.select('p.value').invoke('hide');
var editors = this.main.select('p.editor');
editors.each(function(el) {
el.removeClassName('displayNone');
if (el.hasClassName('isDate')) {
var arr = el.previous().innerHTML.match(/(\d+)\/(\d+)\/(\d+)/);
if (arr) {
el.down('select').value = parseInt(arr[1], 10);
el.down('select', 1).value = parseInt(arr[2], 10);
el.down('select', 2).value = parseInt(arr[3], 10);
}
} else if (el.hasClassName('isPassword')) {
if (el.down('input')) el.down('input').value = '';
this.main.select('li.isPassword').invoke('removeClassName', 'displayNone');
} else {
if (el.down('input')) el.down('input').value = el.previous().innerHTML;
}
}.bind(this));
},
toViewState: function() {
this.main.down('ul').removeClassName('edit');
this.btnEdit.show();
this.btnSave.addClassName('displayNone');
this.btnCancel.addClassName('displayNone');
this.main.select('p.value').invoke('show');
var editors = this.main.select('p.editor');
editors.each(function(el) {
el.addClassName('displayNone');
if (el.hasClassName('isPassword')) {
this.main.select('li.isPassword').invoke('addClassName', 'displayNone');   
}
}.bind(this)); 
}
});
Profile = Class.create({
initialize: function() {
this.personalInfo = new SimpleInPlaceEditor('personalInfoEdit');
this.passwordEdit = new SimpleInPlaceEditor('passwordEdit');
this.newsletterEdit = new SimpleInPlaceEditor('newsletterEdit');
this.cancelInfo();
this.cancelGuide();
},
cancelGuide: function() {
var link = $('cancel_account');
if (link) {
link.observe('click', function() {
var url = new UrlConstructor('Profile/CancelGuide');
this.modal = new Control.Modal(false, {
contents: function() {
new Ajax.Request(url.construct(), {
onComplete: function(request){
this.modal.update(request.responseText);
Event.observe('modalClose', 'click', function() {
this.modal.close();
}.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
width: 380,
height: 190,
containerClassName: 'mfmodal'
});
this.modal.open();
});
}
},
cancelInfo: function() {
var containerId = $('cancelErrorContainer');
if (!containerId) return ;
var contents = containerId.innerHTML;
containerId.update();
var modal = new Control.Modal(false, {
contents: contents, fade: true, fadeDuration: 0.4, opacity: 0.8, width: 600, containerClassName: 'mfmodal',
afterOpen: function() {
Event.observe('modalClose', 'click', function() {modal.close();});
}
});
modal.open();        
}
});
function toggleFavorite(gameId) {
var url = new UrlConstructor('profile/toggle_favorite');
url.addVar('gameId', gameId);
new Ajax.Request(url.construct(), {
method: 'get',
onSuccess: function(transport) {
var obj = transport.responseText.evalJSON();
if (obj.status != 0) {
userGames.toggleFavorite(gameId, obj.status);
userGames.setFavorite(obj.favorite);
}
}
});
}
function showManual(gameId) {
var url = new UrlConstructor('game/show_manual');
url.addVar('gameId', gameId);
new Ajax.Request(url.construct(), {
method: 'get',
onSuccess: function(transport) {
var obj = transport.responseText.evalJSON();
var er = new ErrorManager(obj);
if (!er.getErrors()) {
window.open(obj.manualHref);
}
}
});
}
InDownload = Class.create({
initialize: function() {
this.exentId = null;
this.langPrefix = getLocale().path;
if (playerReady()) {
try {
var gameList = writeInDownloadListGames();
var r = new XMLDoc(gameList, function(e) {alert(e);});
var list = r.docNode;
var listSize = list.getAttribute('ListSize');
if (listSize != 0) {
var games = list.getElements('ContentDescriptor');
for(i = 0; i < games.length; i++) {
var game = new Game(GetGameInfo(games[i].getAttribute('Id')));
if (game.isDownloadNow()) {
this.exentId = game.getExentId();
this.gameActive();
break;
}
}
}
//this.exentId = 462052;
//this.gameActive();
//this.initUpdateInfo();
} catch(e) {
}
}
},
addHeader: function(game) {
var url = new UrlSeoConstructor('PROFILE_GAMES');
return '<div class="topH3 boxBorderRight">' +
'<h3 class="uni05_63">' + i18n('addHeaderGame1') + ' "' + game.getGameName() + '"</h3>' +
'<p><span class="text">[ <a href="' + url.construct() +'">' + i18n('addHeaderGame2') + '</a> ]</span></p>' +
'</div>';
},
addGradient: function() {
return '<img src="' + $('skin').value + 'img/gradient.gif" alt="" class="gradientBG"></img>';
},
addBoxShot: function(game) {
return '<img alt="Downloading..." class="game"' +
'src="http://img.metaboli.fr/products/' + game.getId() + this.langPrefix + '/sm_box.jpg">' +
'</img>' +
'<a class="manual" href="javascript:showManual(' + game.getId() + ');">' + i18n('addBoxShot') + '</a>';
},
addInfoText: function() {
return '<p class="infoText">' +
i18n('addInfoText') +
'</p>';
},
addProgresssBar: function(game) {
return '<div id="progressBarBG">' +
'<div id="progressBarFill" style="width: ' + game.downloadedPercent() + '%;"></div>' +
'<div id="progressBarMark" style="margin-left: ' + game.minDownloadedPercent() + '%;"></div>' +
'</div>';
},
downloadInfo: function(game) {
return '<p class="downloadText">' +
'<span id="current_percent">' + game.downloadedPercent() + '%</span>' +
' (<span id="current_downloaded">' + game.getDownloadedSize() + '</span>/' +
'<span id="current_total">' + game.getFullSize() + '</span>) ' +
' - ' +
'<strong id="current_time">00:00:00 ' + i18n('ElapsedTime_result') + '</strong>' +
'</p>';
},
explainText: function() {
return '<p class="explainText">' + i18n('explainText') + '</p>';
},
buttonStartStop: function() {
return '<div class="buttonContainer">' +
'<a id="buttonPause" class="buttonPause" href="javascript:buttonPauseDownloadList();">' + i18n('pauseDownloadList') + '</a>' +
'<a id="buttonContinue" class="buttonContinue" href="javascript:buttonStartDownloadList();">' + i18n('startDownloadList') + '</a>' +
'</div>';
},
buttonPlay: function(game) {
return '<div id="buttonPlay_inactive" class="buttonPlay_inactive" style="display: block;"></div>' +
'<a id="buttonPlay_active" class="buttonPlay_active" href="javascript:gemeLauncher(' + game.getExentId() + ', 1);" style="display: none;"></a>';
},
setStatus: function() {
if (this.exentId) {
var game = new Game(GetGameInfo(this.exentId));
if (game.isDownloadNow()) {
$('buttonPause').setStyle({
display: 'block'
});
$('buttonContinue').setStyle({
display: 'none'
});
this.initUpdateInfo();
} else {
$('buttonPause').setStyle({
display: 'none'
});
$('buttonContinue').setStyle({
display: 'block'
});
}
}
},
gameActive: function() {
var userGame = new Game(GetGameInfo(this.exentId));
var html = new String();
html += '<div class="boxDownload block">';
html += this.addHeader(userGame);
html += '<div class="boxDownloadContent">';
html += this.addGradient();
html += this.addBoxShot(userGame);
html += this.addInfoText();
html += this.addProgresssBar(userGame);
html += this.downloadInfo(userGame);
html += this.explainText();
html += this.buttonStartStop();
html += this.buttonPlay(userGame);
html += '</div>';
html += '</div>';
$('boxDownloadContainer').insert(html);
this.initUpdateInfo();
},
initUpdateInfo: function() {
new PeriodicalExecuter(function(pe) {
var game = new Game(GetGameInfo(this.exentId));
if (game.isDownloadNow()) {
$('progressBarFill').setStyle({width: game.downloadedPercent() + '%'});
$('current_percent').update(game.downloadedPercent() + '%');
$('current_downloaded').update(game.getDownloadedSize());
$('current_total').update(game.getFullSize());
$('current_time').update(game.getElapsedTime());
if (game.isReady()) {
$('buttonPlay_inactive').setStyle({display: 'none'});
$('buttonPlay_active').setStyle({display: 'block'});
if (game.isFullyCached()) {
$('buttonPause').setStyle({display: 'none'});
$('buttonContinue').setStyle({display: 'none'});
}
}
} else {
pe.stop();
}
}.bind(this), 1);
}
});
Comingsoon = Class.create({
initialize: function() {
if (!$('rowWidth')) {return false;}
this.gameCellWidth = 160;
this.minMargin = 0;
this.rowWidth = $('rowWidth').offsetWidth;
this.run();
},
run: function() {
var cellNumber = 0;
var margin = 0;
if ((this.rowWidth - (this.gameCellWidth + this.minMargin)) >= 0) {
do {
this.rowWidth = this.rowWidth - (this.gameCellWidth + this.minMargin);
cellNumber++;
} while ((this.rowWidth - (this.gameCellWidth + this.minMargin)) >= 0);
this.rowWidth = this.rowWidth + this.minMargin;
margin = Math.floor(this.rowWidth / (cellNumber - 1));
}
margin = margin + this.minMargin;
document.write("<style>." + 'gameCell' + "{margin-right:" + margin + "px ! important;}</style>");
}
});
Offer = Class.create({
initialize: function() {
this.initPCSpopup();
},
initPCSpopup: function() {
var popupPCS = $('morePCS');
if (popupPCS) {
popupPCS.observe('click', function() {
var url = new UrlConstructor('Index/PresentationPCS');
var valuePopupHeight = 710;
var browserHeight = window.innerHeight;
if (browserHeight < 710) {
valuePopupHeight = browserHeight - 10; 
}
this.modal = new Control.Modal(false, {
contents: function() {
new Ajax.Request(url.construct(), {
onComplete: function(request){
this.modal.update(request.responseText);
if (browserHeight < 710) {
$('modal_container').down('.containerPresentationPCS').setStyle({
height: (valuePopupHeight - 30) + 'px'
});
}
Event.observe('modalClose', 'click', function() {
this.modal.close();
}.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
width: 850,
height: valuePopupHeight,
containerClassName: 'mfmodal'
});
this.modal.open();
});
}
}    
});
PromoConditions = Class.create({
initialize: function() {
this.initPopup();
},
initPopup: function() {
var popupConditions = $('seeConditions');
if (popupConditions) {
popupConditions.observe('click', function() {
var url = new UrlConstructor('Promo/Conditions');
this.modal = new Control.Modal(false, {
contents: function() {
new Ajax.Request(url.construct(), {
onComplete: function(request){
this.modal.update(request.responseText);
Event.observe('modalClose', 'click', function() {
this.modal.close();
}.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
width: 580,
height: 395,
containerClassName: 'mfmodal'
});
this.modal.open();
});
}
}
});
Registration = Class.create({
initialize: function() {
if (MvcSkel.getVar('portalId') == 'ohde' || MvcSkel.getVar('portalId') == 'ohfr') {
this.offsetY = 230;
} else {
this.offsetY = 0;
}
this.modalErrors();
this.promoModal();
this.initCrypto();
this.initTypeCard();
this.promoError();
this.cancel();
this.initCompatibility();
this.orangeInit();
this.offerPromotionReloadInit();
},
modalErrors: function() {
if ($('regModalError')) {
var erm = new ErrorManager();
erm.raise(i18n('error'), $('regModalError').innerHTML);
erm.getErrors();
}
},
offerPromotionReloadInit: function() {
$$('.offerChange').invoke('observe', 'click', this.reloadByChangeOffer.bind(this));
},
reloadByChangeOffer: function(event) {
var el = event.element();
window.location = el.previous('input').value;
},
orangeInit: function() {
if (!(this.cpForm   = $('customPaymetForm'))) return false;
this.cpActivationForm = $('activationForm');
this.cpErrorClose     = $('cpErrorClose');
this.cpCancel = $('customPaymentCancel');
this.cpSubmit = $('customPaymentSubmit');
this.cpAmount = $('cpAmount');
this.cpClose  = $('cpClose');
this.cpError  = $('cpError');
this.cpPhone  = $('cpPhone');
this.cpConfirm  = $('cpConfirm');
this.cpComplete = $('cpComplete');
this.cpForm.observe('submit', this.submitRequest.bind(this));
this.cpSubmit.observe('click', this.submitRequest.bind(this));
this.cpCancel.observe('click', function() {
this.cpForm.getElements().each(function(el) {
el.value = '';
});
}.bind(this));
this.cpClose.observe('click', function() {
this.cpComplete.hide();
}.bind(this));
this.cpErrorClose.observe('click', function() {
this.cpError.hide();
}.bind(this));
this.cpActivationForm.observe('submit', this.confirmRequest.bind(this));
this.cpConfirm.observe('click', this.confirmRequest.bind(this));
},
submitRequest: function(event) {
event.stop();
this.cpSubmit.focus();
this.cpForm.request({
onSuccess: function(transport) {
var obj = transport.responseText.evalJSON();
var er = new ErrorManager(obj);
if (!er.getErrors()) {
this.cpAmount.update(obj.price);
this.cpPhone.update(obj.phone);
this.cpActivationForm.down('.transactionMetaboliId').value = obj.transactionMetaboliId;
this.cpComplete.show();
}
}.bind(this)
});
},
confirmRequest: function(event) {
event.stop();
this.cpActivationForm.request({
onSuccess: function(transport) {
var obj = transport.responseText.evalJSON();
if (parseInt(obj.success) && obj.redirect) {
this.cpComplete.hide();
window.location = obj.redirect;
} else {
var er = new ErrorManager(obj);
if (!er.getErrors()) {
this.cpComplete.hide();
this.cpError.show();
}
}
}.bind(this)
});
},
cancel: function() {
if (!$('cancelSubscription')) {return false;}
Event.observe('cancelSubscription', 'click', function() {
var form = $$('form[name="resiliationchoix"]').first();
var curr = form.getInputs('radio', 'reason').find(function(radio) { return radio.checked; });
var txta = form.select('textarea[name="reason-autor"]').first().getValue();
if (!curr || (curr.value == 114 && txta.empty())) {
var erm = new ErrorManager();
erm.raise(i18n('error'), i18n('registrationCancelChooseReason'));
erm.getErrors();
return false;
}
var url = new UrlConstructor('registration/confirm_cancel');
var modal = new Control.Modal(false, {
contents: function() {
new Ajax.Request(url.construct(), {
onComplete: function(request){
modal.update(request.responseText);
Event.observe('modalClose', 'click', function() {
modal.close();
}.bind(this));
Event.observe('validate_cancel', 'click', function() {
var url = new UrlConstructor('registration/validate_cancel');
url.addVar('code', $('number').getValue());
new Ajax.Request(url.construct(), {
onSuccess: function(transport) {
var obj = transport.responseText.evalJSON();
if (obj.validation == 0) {
$('number_text').addClassName('errorText');
$('number_alert').writeAttribute('title', obj.msg);
$('number_alert').setStyle({
display: 'block'
});
new MFTooltip();
} else {
$('transactionId').value = obj.tId;
modal.close();
}
}.bind(this)
});
});
}
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.3,
opacity: 0.8,
width: 510,
containerClassName: 'mfmodal',
afterClose: function() {
if ($('transactionId').value != '') {
setTimeout(function() {
$('transactionId').up('form').submit();
}, 500);
}
}
});
modal.open();
});
},
initCrypto: function() {
var cryptoInput = $('cryptoInfo');
if (cryptoInput) {
cryptoInput.observe('click', function() {
var url = new UrlConstructor('Registration/Crypto');
this.modal = new Control.Modal(false, {
contents: function() {
new Ajax.Request(url.construct(), {
onComplete: function(request){
this.modal.update(request.responseText);
Event.observe('modalClose', 'click', function() {
this.modal.close();
}.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
width: 550,
height: 300,
containerClassName: 'mfmodal'
});
this.modal.open();
});
}
},
initCompatibility: function() {
var compatibilityInput = $('compatibilityInfo');
if (compatibilityInput) {
compatibilityInput.observe('click', function() {
var url = new UrlConstructor('Registration/Compatibility');
this.modal = new Control.Modal(false, {
contents: function() {
new Ajax.Request(url.construct(), {
onComplete: function(request){
this.modal.update(request.responseText);
Event.observe('closeButton', 'click', function() {
this.modal.close();
}.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.4,
opacity: 0.6,
width: 390,
height: 230,
containerClassName: 'mfmodal'
});
this.modal.open();
});
}
},
getValueFromInput: function(id, def) {
try {
return $(id).getValue();
} catch (e) {
return def;
}
},
promoModal: function() {
var promoInput = null;
this.modalOffer = null;
if (promoInput = $('promoValid')) {
var url = new UrlConstructor('registration/promo_info');
url.addVar('promoCode', promoInput.getValue());
var promoOfferId = $('promoOfferId');
var promoClasse = $('promoClasse');
if (promoOfferId && !promoOfferId.getValue().empty()) url.addVar('promoOfferId', promoOfferId.getValue());
if (promoClasse && !promoClasse.getValue().empty()) url.addVar('promoClasse', promoClasse.getValue());
this.modalOffer = new Control.Modal(false, {
contents: function() {
new Ajax.Request(url.construct(), {
onComplete: function(request){
this.modalOffer.update(request.responseText);
Event.observe('modalClose', 'click', function() {
this.modalOffer.close();
}.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
width: this.getValueFromInput('promoModalWidth', 550),
height: this.getValueFromInput('promoModalHeight', 280),
containerClassName: 'mfmodal'
});
this.modalOffer.open();
}
},
promoError: function() {
if ($('promoError')) {
var erm = new ErrorManager();
erm.raise(i18n('registrationPromoLabel'), $('promoError').innerHTML);
erm.getErrors();
}
},
initTypeCard: function() {
var select = 'carte_paiement';
if (!$(select)) {return false;}
$(select).observe('change', function() {
this.changeTypeCard(select);
}.bind(this));
this.changeTypeCard(select);
},
changeTypeCard: function(id) {
if (['SOLO_GB-SSL', 'MAESTRO-SSL'].indexOf($(id).value) !== -1) {
this.hideFields();
this.showPayment1();
} else if (['ELV-SSL'].indexOf($(id).value) !== -1) {
this.hideFields();
this.showPayment2();
} else if (['TPAY'].indexOf($(id).value) !== -1) {
this.hideFields();
this.showPaymentTpay();
} else if (['PAYPAL'].indexOf($(id).value) !== -1) {
this.hideFields();
this.showPaymentPayPal();
} else if (['AOL'].indexOf($(id).value) !== -1) {
this.hideFields();
this.showPaymentAol();
} else if (['FHA'].indexOf($(id).value) !== -1) {
this.hideFields();
this.showPaymentFha();
} else {
this.hidePayment();
}
},
showPaymentTpay: function() {
new Effect.Morph('clientForm', {
style: {height: '281px'},
duration: 0.2,
afterFinish: function(){
['textnumcard', 'textdateexp', 'textcrypto', 'inputCardNumber', 'optionsExpire', 'inputCrypto', 'buttonSubmit'].each(function(el) {
if (!$(el)) {return false;}
$(el).addClassName('displayNone');
});
['tpay'].each(function(el) {
if (!$(el)) {return false;}
$(el).removeClassName('displayNone')
});
}
});
new Effect.Morph('clientInfoBox', {
style: {height: (350 + this.offsetY) + 'px'},
duration: 0.2
});
new Effect.Morph('containerRight', {
style: {height: (360 + this.offsetY) + 'px'},
duration: 0.2
});
if ($('errorMessage')) {
new Effect.Morph('errorMessage', {
style: {top: (240 + this.offsetY) + 'px'},
duration: 0.2
});
}
},
showPaymentPayPal: function() {
new Effect.Morph('clientForm', {
style: {height: '281px'},
duration: 0.2,
afterFinish: function(){
['textnumcard', 'textdateexp', 'textcrypto', 'inputCardNumber', 'optionsExpire', 'inputCrypto', 'buttonSubmit'].each(function(el) {
if (!$(el)) {return false;}
$(el).addClassName('displayNone');
});
['paypal'].each(function(el) {
if (!$(el)) {return false;}
$(el).removeClassName('displayNone')
});
}
});
new Effect.Morph('clientInfoBox', {
style: {height: (350 + this.offsetY) + 'px'},
duration: 0.2
});
new Effect.Morph('containerRight', {
style: {height: (360 + this.offsetY) + 'px'},
duration: 0.2
});
if ($('errorMessage')) {
new Effect.Morph('errorMessage', {
style: {top: (240 + this.offsetY) + 'px'},
duration: 0.2
});
}
},
showPaymentAol: function() {
new Effect.Morph('clientForm', {
style: {height: '281px'},
duration: 0.2,
afterFinish: function(){
['textnumcard', 'textdateexp', 'textcrypto', 'inputCardNumber', 'optionsExpire', 'inputCrypto', 'buttonSubmit'].each(function(el) {
if (!$(el)) {return false;}
$(el).addClassName('displayNone');
});
['aol'].each(function(el) {
if (!$(el)) {return false;}
$(el).removeClassName('displayNone')
});
}
});
new Effect.Morph('clientInfoBox', {
style: {height: (350 + this.offsetY) + 'px'},
duration: 0.2
});
new Effect.Morph('containerRight', {
style: {height: (360 + this.offsetY) + 'px'},
duration: 0.2
});
if ($('errorMessage')) {
new Effect.Morph('errorMessage', {
style: {top: (240 + this.offsetY) + 'px'},
duration: 0.2
});
}
},
showPaymentFha: function() {
new Effect.Morph('clientForm', {
style: {height: '300px'},
duration: 0.2,
afterFinish: function(){
['textnumcard', 'textdateexp', 'textcrypto', 'inputCardNumber', 'optionsExpire', 'inputCrypto', 'buttonSubmit'].each(function(el) {
if (!$(el)) {return false;}
$(el).addClassName('displayNone');
});
['fha', 'fhaBtn'].each(function(el) {
if (!$(el)) {return false;}
$(el).removeClassName('displayNone')
});
}
});
new Effect.Morph('clientInfoBox', {
style: {height: (369 + this.offsetY) + 'px'},
duration: 0.2
});
new Effect.Morph('containerRight', {
style: {height: (379 + this.offsetY) + 'px'},
duration: 0.2
});
if ($('errorMessage')) {
new Effect.Morph('errorMessage', {
style: {top: (240 + this.offsetY) + 'px'},
duration: 0.2
});
}
},
showPayment2: function() {
new Effect.Morph('clientForm', {
style: {height: '471px'},
duration: 0.2,
afterFinish: function() {
['textnumcard', 'textdateexp', 'textcrypto', 'inputCardNumber', 'optionsExpire', 'inputCrypto'].each(function(el) {
$(el).addClassName('displayNone');
});
['elv', 'elvInfo', 'redInfo'].each(function(el) {$(el).removeClassName('displayNone')});
}
});
new Effect.Morph('clientInfoBox', {
style: {height: (540 + this.offsetY) + 'px'},
duration: 0.2
});
new Effect.Morph('containerRight', {
style: {height: (550 + this.offsetY) + 'px'},
duration: 0.2
});
if ($('errorMessage')) {
new Effect.Morph('errorMessage', {
style: {top: (300 + this.offsetY) + 'px'},
duration: 0.2
});
}
},
showPayment1 : function() {
if (!$('clientForm')) {return false;}
new Effect.Morph('clientForm', {
style: {height: '321px'},
duration: 0.2,
afterFinish: function() {
$$('.sPayment1').each(function(el) {
el.removeClassName('displayNone');
});
}
});
new Effect.Morph('clientInfoBox', {
style: {height: (390 + this.offsetY) + 'px'},
duration: 0.2
});
new Effect.Morph('containerRight', {
style: {height: (400 + this.offsetY) + 'px'},
duration: 0.2
});
if ($('errorMessage')) {
new Effect.Morph('errorMessage', {
style: {top: (290 + this.offsetY) + 'px'},
duration: 0.2
});
}
//errorMessage//containerRight//clientInfoBox//clientForm
},
hideFields: function() {
$$('.sPayment1').each(function(el) {
el.addClassName('displayNone');
});
['textnumcard', 'textdateexp', 'textcrypto', 'inputCardNumber', 'optionsExpire', 'inputCrypto', 'buttonSubmit'].each(function(el) {
if ($(el)) {$(el).removeClassName('displayNone');}
});
['elv', 'elvInfo', 'redInfo', 'tpay', 'paypal', 'fha', 'fhaBtn', 'aol'].each(function(el) {
if ($(el)) {$(el).addClassName('displayNone');}
});
},
hidePayment : function() {
if (!$('clientForm')) {return false;}
new Effect.Morph('clientForm', {
style: {height: '241px'},
duration: 0.2,
beforeStart: this.hideFields
});
new Effect.Morph('clientInfoBox', {
style: {height: (310 + this.offsetY) + 'px'},
duration: 0.2
});
new Effect.Morph('containerRight', {
style: {height: (320 + this.offsetY) + 'px'},
duration: 0.2
});
if ($('errorMessage')) {
new Effect.Morph('errorMessage', {
style: {top: (220 + this.offsetY) + 'px'},
duration: 0.2
});
}
}
});
function GetListFromXml( strXml, strTag ) {
try{
var xmlDoc = getXmlDoc(strXml, false);
var liste = xmlDoc.getElementsByTagName( strTag );
return liste;
} catch( e ) {
return "Exception";
}
}
var modalCfgProcess = null;
function sendCheckConfigClient(xml) {
if ($('isAuth').getValue() == 0 || !isOk) {
var url = new UrlSeoConstructor('PROFILE_GAMES');
window.location = url.construct();
} else {
modalCfgProcess = new Control.Modal(false, {
contents: function(){
return '<span>' + i18n('detectionInProcess') + '</span>';
},
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
width: 500,
overlayCloseOnClick: false,
containerClassName: 'mfmodalCfgProcess',
afterOpen: function(){
setTimeout(function(){
ckeckConfigClient(xml, '5,0,0,2', '5.0.76.0', '255.255.0.0', null, null, null);
}, 2000);
}
});
modalCfgProcess.open();
}
}
function ckeckConfigClient(strComponentsGame, strPortalActiveXVersion, strClientVersion, strClientVersionMask, strSkinId, strSkinVersion, strSkinVersionMask) {
if(isTechnoPresent(strPortalActiveXVersion, strClientVersion, strClientVersionMask, strSkinId, strSkinVersion, strSkinVersionMask)) {
var strClient = GPlayerApi_GetPCDependences();
var arrSwHw = compareSWHWdependency(strComponentsGame, strClient);
printDependencyMCE(arrSwHw, 'NT', '');
}
modalCfgProcess.close();
}
function isTechnoPresent(strPortalActiveXVersion, strClientVersion, strClientVersionMask, strSkinId, strSkinVersion, strSkinVersionMask) {
try {
var techno = GPlayerApi_IsActiveXInstalled(strPortalActiveXVersion);
if(techno) {
techno = GPlayerApi_IsPlayerInstalled(strClientVersion, strClientVersionMask, strSkinId, strSkinVersion, strSkinVersionMask);
}
return techno;
} catch(e) {
return false;
}
}
Options = Class.create({
initialize: function() {
this.delay = 2000;
this.timer = new Array();
this.actions();
},
actions: function() {
$$('div.buttonOptions').each(function(el) {
var exentId = el.id.match(/options-(\d+)/)[1];
var optionsList = $('expand-' + exentId);
Event.observe(el, 'click', function() {
this.toggleOptions(el, optionsList, exentId);
}.bind(this));
Event.observe(optionsList, 'mouseover', function() {
if (typeof(this.timer[exentId]) != 'undefined') {
clearTimeout(this.timer[exentId]);
}
}.bind(this));
Event.observe(optionsList, 'mouseout', function() {
this.delayedToggle(el, optionsList, exentId);
}.bind(this));
}.bind(this));
$$('li > a.optionSet').each(function(aEl) {
Event.observe(aEl, 'click', function(event) {
var el = Event.element(event);
var optionId = el.href.match(/option_(\d+)/)[1];
var technoId = el.up('div.optionExpand').id.match(/expand-(\d+)/)[1];
this.up($('options-' + technoId), el.up('div.optionExpand'), technoId);
if (typeof(gameManager) == 'object')
gameManager.launch(technoId, 'exent', optionId);
else
gemeLauncher(technoId, optionId);
}.bind(this));
}.bind(this));
},
delayedToggle: function(el, optionsList, exentId) {
this.timer[exentId] = setTimeout(function() {
this.toggleOptions(el, optionsList, exentId);
}.bind(this), this.delay);
},
toggleOptions: function(el, optionsList, exentId) {
if (el.down('a') && el.down('a').href.match(/_inaccessibly/)) return;
var left = el.positionedOffset().left;
var top = el.positionedOffset().top;
if (el.hasClassName('mygames')) {
var li = el.up('li');
offsetLeft = offsetTop = 0;
left += li.positionedOffset().left;
top += li.positionedOffset().top;
var btDownloaded = el.up('div.downloadedButtons');
if (btDownloaded) {
offsetLeft = btDownloaded.positionedOffset().left;
offsetTop = btDownloaded.positionedOffset().top;
}
var btDownloading = el.up('div.downloadingButtons');
if (btDownloading) {
offsetLeft = btDownloading.positionedOffset().left;
offsetTop = btDownloading.positionedOffset().top;
}
left += offsetLeft;
top += offsetTop;
}
if (el.hasClassName('buttonOnFavorite')) {
var item = el.up('div.boxfavourite');
left += item.positionedOffset().left;
top += item.positionedOffset().top;
}
if (el.hasClassName('buttonOnGame')) {
var item = el.up('div.buttonContainer');
var item2 = $('containerRight');
left += item.positionedOffset().left - 14;
top += item.positionedOffset().top;
}
optionsList.setStyle({
top: top + 'px',
left: left + 'px'
});
if (!el.hasClassName('expanded')) {
this.down(el, optionsList, exentId);
} else {
this.up(el, optionsList, exentId);
}
},
up: function(el, optionsList, exentId) {
new Effect.Fade(optionsList, {
duration: 0.4,
afterFinish: function() {
el.removeClassName('expanded');
if (typeof(this.timer[exentId]) != 'undefined') {
clearTimeout(this.timer[exentId]);
}
}.bind(this)
});
},
down: function(el, optionsList, exentId) {
new Effect.Appear(optionsList, {
duration: 0.4,
afterFinish: function() {
el.addClassName('expanded');
this.delayedToggle(el, optionsList, exentId);
}.bind(this)
});
}
});
OnCloseMessage = Class.create({
initialize: function() {
this.clickOnLink = false;
try {
if (affPopback != 0) {
this.initPopback();
}
} catch(e) {
}
},
initPopback: function() {
Event.observe(window.document.body, 'click', function(event) {
try {
var ela = Event.findElement(event, 'a');
if (ela != document && !ela.href.match(/\#/)) {
this.clickOnLink = true;
}
} catch(e) {
}
}.bind(this));
Event.observe(window, 'beforeunload', function(event) {
if (!this.clickOnLink && (Event.pointerY(event) < 0 || isNaN(Event.pointerY(event)))) {
var popbackCount = getCookie('aPopback');
if (popbackCount == null) {
setCookie('aPopback', 1, 30, '/');
} else if (popbackCount >= 4) {
return;
} else {
setCookie('aPopback', parseInt(popbackCount)+1, 30, '/');
}
event.returnValue = i18n('initPopback');
var url = new UrlSeoConstructor('REGISTRATION_POPBACK');
url.addVar('status', 'from_alert');
window.location = url.construct();
}
}.bind(this));
}
});
Popback = Class.create({
initialize: function() {
this.inProcess = false;
this.initAction();
this.initInfo();
this.clearFieldOnClick();
},
initInfo: function() {
if (!$('popback-info')) {return false;}
Event.observe('popback-info', 'click', function() {
var url = new UrlConstructor('registration/popback_info');
this.modal = new Control.Modal(false, {
contents: function() {
new Ajax.Request(url.construct(), {
onComplete: function(request){
this.modal.update(request.responseText);
Event.observe('modalClose', 'click', function() {
this.modal.close();
}.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
width: 600,
containerClassName: 'mfmodal'
});
this.modal.open();
});
},
initAction: function() {
if (!$('popbackAction')) {return false;}
Event.observe('popbackAction', 'click', function() {
if (!this.inProcess) {
this.process();
}
}.bind(this));
},
clearFieldOnClick: function() {
if (!$('email')) {return false;}
$('email').observe('focus', function(event) {
var elInput = Event.element(event);
if (elInput.hasClassName('defaultText')) {
elInput.value = '';
elInput.removeClassName('defaultText');
}
}.bind(this));
},
process: function() {
this.inProcess = true;
var url = new UrlConstructor('registration/popback_action');
url.setAction(true);
url.addVar('email', $('email').getValue());
url.addVar('confirm', $('confirm').getValue());
url.addVar('gameId', $('gameId').getValue());
new Ajax.Request(url.construct(), {
onSuccess: function(transport) {
var obj = transport.responseText.evalJSON();
var er = new ErrorManager(obj);
this.inProcess = false;
if (!er.getErrors()) {
this.showFinish(obj.content);
}
}.bind(this)
});
},
showFinish: function(content) {
var modal = new Control.Modal(false, {
contents: content,
fade: true,
fadeDuration: 0.3,
opacity: 0.8,
width: 510,
containerClassName: 'mfmodal',
afterClose: function() {
setTimeout(function() {
var url = new UrlConstructor('home.html?status=email_has_been_added');
window.location = url.construct();
}, 500);
}
});
modal.open();
Event.observe('modalClose', 'click', function() {
modal.close();
});
}
});
function getCookieVal(offset) {
var endstr = document.cookie.indexOf (";", offset);
if (endstr == -1) {endstr = document.cookie.length;}
return unescape(document.cookie.substring(offset, endstr));
}
function getCookie(name) {
var arg = name + "=";
var alen = arg.length;
var clen = document.cookie.length;
var i = 0;
while (i < clen) {
var j = i + alen;
if (document.cookie.substring(i, j) == arg) {
return getCookieVal(j);
}
i = document.cookie.indexOf(" ", i) + 1;
if (i == 0) break;
}
return null;
}
function setCookie(name, value, expires, path, domain, secure) {
var today = new Date();
today.setTime(today.getTime());
if (expires) {
expires = expires * 1000 * 60 * 60 * 24;
}
var expires_date = new Date(today.getTime() + (expires));
document.cookie = name + "=" + escape (value) +
((expires) ? "; expires=" + expires_date.toGMTString() : "") +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
((secure) ? "; secure" : "");
}
Welcome = Class.create({
initialize: function() {
this.initConfirm();
this.initUac();
this.initFirewall();
this.initDisplayProperties();
this.initPlay();
this.initInstallStatus();
if ($('vista') && isVista()) {
$('vista').value = 1;
}
},
initInstallStatus: function() {
if (!$('playerStatusContent')) {return false;}
var sContext = null;
if (playerReady()) {
sContext = 'player_installed';
} else {
sContext = 'player_not_installed';
}
var browser = null;
if (Prototype.Browser.IE) {
browser = 'ie';
} else if (Prototype.Browser.Gecko) {
browser = 'gecko';
}
var url = new UrlConstructor('welcome/' + sContext);
url.addVar('browser', browser);
url.addVar('vista', isVista() ? 1 : 0);
new Ajax.Request(url.construct(), {
onSuccess: function(transport) {
$('playerStatusContent').update(transport.responseText);
if (isVista()) {
$('dxVista').value = 1;
}
}.bind(this)
});
},
initUac: function() {
if (!$('uacShow')) {return false;}
Event.observe('uacShow', 'click', function() {
var url = new UrlConstructor('welcome/vista_uac');
this.modal = new Control.Modal(false, {
contents: function() {
new Ajax.Request(url.construct(), {
onComplete: function(request){
this.modal.update(request.responseText);
Event.observe('modalClose', 'click', function() {
this.modal.close();
}.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
width: 950,
containerClassName: 'mfmodal'
});
this.modal.open();
});
},
initFirewall: function() {
if (!$('firewallShow')) {return false;}
Event.observe('firewallShow', 'click', function() {
var url = new UrlConstructor('welcome/firewall_info');
url.addVar('type', $('selectedFirewall').getValue());
this.modal = new Control.Modal(false, {
contents: function() {
new Ajax.Request(url.construct(), {
onComplete: function(request){
this.modal.update(request.responseText);
Event.observe('modalClose', 'click', function() {
this.modal.close();
}.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
width: 850,
containerClassName: 'mfmodal'
});
this.modal.open();
});
},
initDisplayProperties: function() {
if (!$('showDisplayProperties')) {return false;}
Event.observe('showDisplayProperties', 'click', function() {
var url = new UrlConstructor('welcome/display_properties');
url.addVar('isVista', (isVista()) ? 1 : 0);
this.modal = new Control.Modal(false, {
contents: function() {
new Ajax.Request(url.construct(), {
onComplete: function(request){
this.modal.update(request.responseText);
Event.observe('modalClose', 'click', function() {
this.modal.close();
}.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
width: 850,
containerClassName: 'mfmodal'
});
this.modal.open();
});
},
initPlay: function() {
if (!$('addToDownloadUrl') || !$('technoGameId')) {return false;}
$$('a.add_to_download_list').each(function(el) {
el.observe('click', function() {
if (playerReady()) {
if (playerVersionCheck(function() {
downloadLauncher($('technoGameId').getValue(), 1);
})) {
downloadLauncher($('technoGameId').getValue(), 1);
} else {
return false;
}
} else {
var url = new UrlSeoConstructor('PROFILE_GAMES');
window.location = url.construct();
}
});
});
},
initConfirm: function() {
if (!$('confirm')) {return false;}
Event.observe('confirm', 'click', function(event) {
var el = Event.element(event);
if (el.checked) {
this.active($('continue'));
} else {
this.unactive($('continue'));
}
}.bind(this));
},
active: function(el) {
el.src = el.src.replace(/_un/, '_');
el.disabled = false;
},
unactive: function(el) {
el.src = el.src.replace(/_a/, '_una');
el.disabled = true;
}
});
function playerReady() {
return  DEFINE.get('TYPE') == 'META' &&
isTheGoodVersionInstalledMultiTechno(DEFINE.get('PLAYER_EXENT_VERSION'),
DEFINE.get('PLAYER_YUMMY_VERSION'));
}
function isVista() {
return navigator.userAgent.match(/windows\s+nt\s+6\.\d+;/i) ? true : false;
}
MultiPlayerKey  = Class.create({
initialize: function() {
this.modal = null;
this.initMultiPlayerKey();
},
initMultiPlayerKey: function() {
$$('a.getMultiplayerKey').each(function(el) {
Event.observe(el, 'click', function(event) {
var link = Event.element(event);
if (link.up('a')) {
link = link.up('a');
}
var gameId = link.href.match(/.*?_(\d+)/)[1];
this.show(gameId);
}.bind(this));
}.bind(this));
},
show: function(gameId) {
this.modal = new Control.Modal(false, {
contents: function() {
var url = new UrlConstructor('game/multiplayer_key');
url.addVar('gameId', gameId);
new Ajax.Request(url.construct(), {
onComplete: function(request){
this.modal.update(request.responseText);
Event.observe('modalClose', 'click', function() {
this.modal.close();
}.bind(this));
Event.observe('fmMultiPlayer', 'submit', function(event) {
this.getMultiplayerKey(gameId);
Event.stop(event);
}.bind(this));
Event.observe('sendKey', 'click', function() {
this.getMultiplayerKey(gameId);
}.bind(this));
}.bind(this)
});
return i18n('loadingDialog');
}.bind(this),
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
width: 500,
containerClassName: 'mfmodal'
});
this.modal.open();
},
getMultiplayerKey: function(gameId) {
var url = new UrlConstructor('game/get_multiplayer_key');
url.setAction(true);
url.addVar('email', $('keyEmail').getValue());
url.addVar('gameId', gameId);
new Ajax.Request(url.construct(), {
onComplete: function(transport) {
var obj = transport.responseText.evalJSON();
var er = new ErrorManager(obj);
if (!er.getErrorsAlert()) {
alert(i18n('getMultiplayerKey'));
this.modal.close();
}
}.bind(this)
});
}
});
Help  = Class.create({
initialize: function() {
this.support();
},
support: function() {
if (!$('problemType')) {return false;}
Event.observe('problemType', 'change', function(event) {
this.supShow($('problemType').getValue());
this.setSubject($('problemType').options[$('problemType').selectedIndex].text);
}.bind(this));
Event.observe('text', 'focus', function(event) {
var tArea = Event.element(event);
if (!tArea.hasClassName('changed')) {
tArea.value = '';
tArea.addClassName('changed');
}
});
},
setSubject: function(subject) {
$('subject').value = subject;
},
supShow: function(showId) {
$$('.supItem').each(function(item) {
item.addClassName('displayNone');
$('supLabel').addClassName('displayNone');
});
if (show = $(showId)) {
$('supLabel').removeClassName('displayNone');
show.removeClassName('displayNone');
}
}
});
function getExternalUrl(protocol) {
if (url = $('externalUrl')) {
url = url.getValue();
if (typeof(protocol) != 'undefined' && protocol) {
url = url.replace(/^http|https/i, protocol);
}
return url;
}
return false;
}
function isDEAvsCheck() {
return $('isDEAvsCheck') ? true : false;
}
MEDEAvs = Class.create({
initialize: function(exentId) {
this.exentId = new String(exentId);
this.gameId = this.exentId.match(/^(.+).{2}$/)[1];
this.modal = null;
this.avsRequestId = 'avsRequest';
this.avsPinRequestId = 'avsPinRequest';
this.avsShowPinFormId = 'avsShowPinForm';
this.toAvsFormId = 'toAvsForm';
this.toAvsPinFormId = 'toAvsPinForm';
this.errorCheckboxId = 'checkBoxInfo';
this.modalOptions = {
width: 750,
fade: true,
fadeDuration: 0.4,
opacity: 0.8,
overlayCloseOnClick: false,
containerClassName: 'mfmodal',
afterUpdate: function() {
this.initClose();
}.bind(this)
};
this.callback = Prototype.emptyFunction;
//this.getAvsForm();
},
cb: function(func) {
if (typeof(func) == 'function')
this.callback = func;
},
run: function() {
if (typeof(this.callback) == 'function')
this.callback();
},
initClose: function() {
$('modalClose').observe('click', function() {
this.modal.close();
}.bind(this));
},
checkEsrbCode: function() {
var urlGameInfo = new UrlConstructor('profile/games_get_game_info');
urlGameInfo.addVar('geoip', 1);
new Ajax.Request(urlGameInfo.construct(), {
method: 'post',
parameters: 'games=' + new Array(this.exentId).toJSON(),
onSuccess: function(transport) {
var obj = transport.responseText.evalJSON();
var esrbCode = obj.esrbCode[this.exentId];
var countryCode = obj.geoip[this.exentId].countryCode;
if (parseInt(esrbCode.code) >= 18 && countryCode == 'DE') {
this.getAvsForm();
} else {
this.run();
}
}.bind(this)
});
},
getAvsForm: function() {
var urlAvsForm = new UrlConstructor('mede/avs_form');
new Ajax.Request(urlAvsForm.construct(), {
onSuccess: function(transport) {
this.showAvsForm(transport.responseText);
}.bind(this)
});
},
showAvsForm: function(content) {
if (this.modal) {
this.modal.update(content);
} else {
this.modal = new Control.Modal(false, Object.extend(this.modalOptions, {contents: content}));
this.modal.open();
}
if (fm = $(this.avsRequestId)) {
fm.observe('submit', this.avsRequest.bind(this));
}
if (gp = $(this.avsShowPinFormId)) {
gp.observe('click', this.avsShowPinForm.bind(this));
}
},
avsRequest: function(event) {
Event.stop(event);
$(this.avsRequestId).request({
onSuccess: function(transport) {
var obj = transport.responseText.evalJSON();
if (obj.errors.size()) {
this.avsFailed();
} else {
this.modal.close();
this.run()
}
}.bind(this)
});
},
avsFailed: function() {
$(this.avsRequestId).select('input[type="text"]').invoke('addClassName', 'errInput');
$(this.avsRequestId).down('div.avsError').removeClassName('displayNone');
},
avsShowPinForm: function() {
var c = parseInt(getCookie('tp'));
if (c >= 3) {
this.avsPinFailed();
return false;
}
var urlAvsPinForm = new UrlConstructor('mede/avs_pin_form');
new Ajax.Request(urlAvsPinForm.construct(), {
onSuccess: function(transport) {
this.showAvsPinForm(transport.responseText);
}.bind(this)
});
},
showAvsPinForm: function(content) {
this.modal.update(content);
if (toAvs = $(this.toAvsFormId)) {
toAvs.observe('click', this.getAvsForm.bind(this));
}
if (fm = $(this.avsPinRequestId)) {
fm.observe('submit', this.avsPinRequest.bind(this));
}
},
avsPinRequest: function(event) {
Event.stop(event);
if (!$(this.avsPinRequestId).down('input[type="checkbox"]').getValue()) {
$(this.errorCheckboxId).addClassName('errText');
return false;
}
$(this.avsPinRequestId).request({
onSuccess: function(transport) {
var obj = transport.responseText.evalJSON();
if (obj.errors.size()) {
this.avsPinFailed();
} else {
this.pinRequestSuccess();
}
}.bind(this)
});
},
avsPinFailed: function() {
var c = parseInt(getCookie('tp'));
c = c ? c + 1 : 1;
setCookie('tp', c, 1, '/');
var urlAvsPinFailed = new UrlConstructor('mede/avs_pin_request_failed');
urlAvsPinFailed.addVar('failed', c);
new Ajax.Request(urlAvsPinFailed.construct(), {
onSuccess: function(transport) {
this.modal.update(transport.responseText);
if (toAvsPin = $(this.toAvsPinFormId)) {
if (c >= 3)
toAvsPin.observe('click', this.getAvsForm.bind(this));
else
toAvsPin.observe('click', this.avsShowPinForm.bind(this));
}
}.bind(this)
});
},
pinRequestSuccess: function() {
var urlAvsPin = new UrlConstructor('mede/avs_pin_request_success');
new Ajax.Request(urlAvsPin.construct(), {
onSuccess: function(transport) {
this.modal.update(transport.responseText);
$('medeAvs').down('input').observe('click', function() {
this.modal.close();
}.bind(this));
}.bind(this)
});
}
});
SubmitFormByClick = Class.create({
initialize: function(fmId) {
this.fmSubmit = $(fmId);
if (!this.fmSubmit) return ;
this.fmSubmit.select('input').each(function(el) {
el.observe('click', this.fmAction.bind(this));
}.bind(this));
this.fmSubmit.select('img').each(function(el) {
el.observe('click', function() {
var x64 = this.fmSubmit.select('input').first();
x64.checked = !x64.checked;
this.fmAction();
}.bind(this));
}.bind(this));
},
fmAction: function() {
this.fmSubmit.submit();
return false;
}
});
var newWindow = '';
function openPopup(url, w, h) {
if (!w) {w = '640';}
if (!h) {h = '480';}
if (!newWindow.closed && newWindow.location) {
newWindow.location.href = url;
} else {
newWindow = window.open(url, 'name', 'width=' + w + ',height=' + h + ',menubar=no,toolbar=no,location=no,scrollbars=yes');
if (!newWindow.opener) {newWindow.opener = self;}
}
if (window.focus) {newWindow.focus();}
return false;
}
InDownloadGlde = Class.create(InDownload, {
addHeader: function(game) {
var url = new UrlSeoConstructor('PROFILE_GAMES');
return '<div class="topH3 boxBorderRight">' +
'<h3 class="uni05_63">' +
'<strong>' + i18n('addHeaderGame1') + ' "' + game.getGameName() + '"</strong>' +
'<em>' + i18n('addHeaderGame1') + ' "' + game.getGameName() + '"</em>' +
'</h3>' +
'<div class="topH3Right pngFix"></div>' +
'<p><span class="text">[ <a href="' + url.construct() + '">' + i18n('addHeaderGame2') + '</a> ]</span></p>' +
'</div>';
}
})
WojHeaderResize = Class.create({
headerId: 'hframe',
wojmenu: 'wojframe',
initialize: function() {
if (!$(this.headerId)) return;
Event.observe(document.getElementById(this.wojmenu).contentWindow.document.getElementById('menuHeader'), 'mouseover', this.show.bind(this));
Event.observe(document.getElementById(this.wojmenu).contentWindow.document.getElementById('menuHeader'), 'mouseout', this.hide.bind(this));
},
show: function(){
this.resizeFrame(400);
},
hide: function(){
this.resizeFrame(50);
},
resizeFrame: function(value) {
$(this.headerId).setStyle({height:value + 'px'});
}
})
function GPlayerApi_InvokeCB(notification) {
if (typeof(gameManager) == 'object') { 
gameManager.exentNotification(notification); 
return; 
} else {
log.err('Old player deprecated');
}
}
function publisherErrorLoad(el) {
el = $(el);
el.hide();
el.next().removeClassName('displayNone');
}
var ww = null;
var log = null;
log = new SimpleDebug();
Event.observe(window, 'load', function() {
var logLevel = null;
try { 
logLevel = DEFINE.get('LOG_LEVEL');
} catch(e) { 
logLevel = 0; 
}
log.onLoadInit(logLevel);
if (typeof(redirectStepWait) == 'function') {
new InitSWFobjects();
redirectStepWait();
return true;
}
var cntx = $('context').getValue();
ww = new WaitWindow();
if (/profile_games/.test(cntx)) {
myGames = new MyGames();
}
if (/woj_changenewsletter/.test(cntx)) {
new Registration();
} 
if (/index_offer/.test(cntx)) {
new Offer();
}
new PromoConditions();
switch (document.body.className) {
case 'game':
new Options();
new MultiPlayerKey();
new VideoScreeenShot();
if (MvcSkel.getVar('portalId') != 'glde') {
new Product();
} else {
new GamePage();
}
break;
case 'index':
new Press();
break;
case 'registration':
new Registration();
new Popback();
break;
case 'profile':
new Profile();
new MultiPlayerKey();
break;
case 'welcome':
new Welcome();
break;
case 'help':
new Help();
break;
}
if (MvcSkel.getVar('portalId') == 'woj_') {
new WojHeaderResize();
}
['dropdownGenre', 'dropdownAlpha', 'dropdownSubscription'].each(function(el) {new CategoryDropDownList(el)});
['fmX64'].each(function(el) {new SubmitFormByClick(el);});
new GameAutocomplete();
new SubmitFormByLink();
new InitSWFobjects();
new Newsletter();
new MFTooltip();
new OnCloseMessage();
if ($('flashObjectVideo')) {
triggerVideo();
}
});


function getElementsByClass(searchClass,node,tag) {
var classElements = new Array();
if ( node == null )
node = document;
if ( tag == null )
tag = '*';
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp('(^|\\s)'+searchClass+'(\\s|$)');
for (i = 0, j = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
}
function sameHeight(className){
var classElements = new Array();
var maxHeight=0;
classElements = getElementsByClass(className);
maxHeight=0;
for(var i=0; i<classElements.length; i++){
if(maxHeight < classElements[i].offsetHeight){ 
maxHeight = classElements[i].offsetHeight;
}
else if(maxHeight < classElements[i].pixelHeight){ 
maxHeight = classElements[i].pixelHeight;
}
}
for(var i=0; i<classElements.length; i++){
classElements[i].style.height = maxHeight + 'px';
}
}
function fontOutline(className){
var classElements = new Array();
var htmlContent = '';
var newHtml = '';
classElements = getElementsByClass(className);
for(i=0; i<classElements.length; i++){
htmlContent = classElements[i].innerHTML;
newHtml='';
for (j=0; j<8; j++){
if (j==0)
newHtml = newHtml + "<span style='position:absolute; top:2px; left:0px'>" + htmlContent + "</span>";
else if (j==1)
newHtml = newHtml + "<span style='position:absolute; top:1px; left:1px'>" + htmlContent + "</span>";
else if (j==2)
newHtml = newHtml + "<span style='position:absolute; top:0px; left:2px'>" + htmlContent + "</span>";
else if (j==3)
newHtml = newHtml + "<span style='position:absolute; top:-1px; left:1px'>" + htmlContent + "</span>";
else if (j==4)
newHtml = newHtml + "<span style='position:absolute; top:-2px; left:0px'>" + htmlContent + "</span>";
else if (j==5)
newHtml = newHtml + "<span style='position:absolute; top:-1px; left:-1px'>" + htmlContent + "</span>";
else if (j==6)
newHtml = newHtml + "<span style='position:absolute; top:0px; left:-2px'>" + htmlContent + "</span>";
else if (j==7)
newHtml = newHtml + "<span style='position:absolute; top:1px; left:-1px'>" + htmlContent + "</span>"
}
classElements[i].innerHTML = newHtml;
}
}


//Offer page horizontal scroll menu for games
var scrollIncrement = 12;
var scrollPosition = new Array(0, 0);
var scrollTimer;
function containerWidth(targetIndex){
var centerContainerObj = document.getElementById('centerContainer' + targetIndex);
var widthValue = 0;
if(centerContainerObj.offsetWidth){ 
widthValue=centerContainerObj.offsetWidth; 
} 
else if(centerContainerObj.style.pixelWidth){ 
widthValue=centerContainerObj.style.pixelWidth; 
} 
return widthValue;
}
function scrollingRight(targetIndex){
var gamesObj = document.getElementById('gamesContainer' + targetIndex);
var endMarkerObj = document.getElementById('endMarker' + targetIndex);
var buttonRightObj = document.getElementById('buttonNavRight' + targetIndex);
var buttonLeftObj = document.getElementById('buttonNavLeft' + targetIndex);
//not at the end of the list, scroll right
if ((scrollPosition[targetIndex] + containerWidth(targetIndex) + scrollIncrement) < endMarkerObj.offsetLeft){
scrollPosition[targetIndex] = scrollPosition[targetIndex] + scrollIncrement;
gamesObj.style.left = (scrollPosition[targetIndex]*-1) + 'px';
scrollTimer = setTimeout('scrollingRight(' + targetIndex + ')', 33);
buttonLeftObj.className = 'buttonNavLeft';
}
//at the end of the list
else{
if (endMarkerObj.offsetLeft > containerWidth(targetIndex)){
scrollPosition[targetIndex] = endMarkerObj.offsetLeft - containerWidth(targetIndex);
gamesObj.style.left = (scrollPosition[targetIndex]*-1) + 'px';
}
buttonRightObj.className = 'buttonNavRight navRightInactive';
}
}
function scrollingLeft(targetIndex){
var gamesObj = document.getElementById('gamesContainer' + targetIndex);
var buttonRightObj = document.getElementById('buttonNavRight' + targetIndex);
var buttonLeftObj = document.getElementById('buttonNavLeft' + targetIndex);
//at the beginning of the list
if (scrollPosition[targetIndex] - scrollIncrement <= 0){
scrollPosition[targetIndex] = 0;
gamesObj.style.left = '0px';
buttonLeftObj.className = 'buttonNavLeft navLeftInactive';
}
//not at the beginning of the list, scroll left
else{
scrollPosition[targetIndex] = scrollPosition[targetIndex] - scrollIncrement;
gamesObj.style.left = (scrollPosition[targetIndex]*-1) + 'px';
scrollTimer = setTimeout('scrollingLeft(' + targetIndex + ')', 33);
buttonRightObj.className = 'buttonNavRight';
}
}
function scrollingStop(){
clearTimeout(scrollTimer);
}
