var cxlEnv = new Object();
cxlEnv.sitePath = "http://www.econoaruba.com/";
cxlEnv.server = "www.econoaruba.com/";
cxlEnv.domain = cxlEnv.server.replace(/^[0-9a-zA-Z]+\./,"");
cxlEnv.domain = cxlEnv.domain.replace("/",'');
cxlEnv.subdomain = "";
cxlEnv.context = "";
cxlEnv.protocol = "";
cxlEnv.bodyClass= "privacy-policy";
cxlEnv.imageBase = "/images/";
cxlEnv.styleBase = "/styles/";
cxlEnv.scriptBase = "/scripts/";
cxlEnv.categories= "";
/*
Script: Core.js
MooTools - My Object Oriented JavaScript Tools.
License:
MIT-style license.
Copyright:
Copyright (c) 2006-2007 Valerio Proietti, <http://mad4milk.net/>
Code & Documentation:
The MooTools production team <http://mootools.net/developers/>.
Inspiration:
- Class implementation inspired by Base.js <http://dean.edwards.name/weblog/2006/03/base/> Copyright (c) 2006 Dean Edwards, GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- Some functionality inspired by Prototype.js <http://prototypejs.org> Copyright (c) 2005-2007 Sam Stephenson, MIT License <http://opensource.org/licenses/mit-license.php>
*/
var MooTools = {
'version': '1.2dev',
'build': '1.2b2'
};
var Native = function(options){
options = options || {};
var afterImplement = options.afterImplement || function(){};
var generics = options.generics;
generics = (generics !== false);
var legacy = options.legacy;
var initialize = options.initialize;
var protect = options.protect;
var name = options.name;
var object = initialize || legacy;
object.constructor = Native;
object.$family = {name: 'native'};
if (legacy && initialize) object.prototype = legacy.prototype;
object.prototype.constructor = object;
if (name){
var family = name.toLowerCase();
object.prototype.$family = {name: family};
Native.typize(object, family);
}
var add = function(obj, name, method, force){
if (!protect || force || !obj.prototype[name]) obj.prototype[name] = method;
if (generics) Native.genericize(obj, name, protect);
afterImplement.call(obj, name, method);
return obj;
};
object.implement = function(a1, a2, a3){
if (typeof a1 == 'string') return add(this, a1, a2, a3);
for (var p in a1) add(this, p, a1[p], a2);
return this;
};
object.alias = function(existing, property, force){
existing = this.prototype[existing];
if (existing) add(this, property, existing, force);
return this;
};
return object;
};
Native.implement = function(objects, properties){
for (var i = 0, l = objects.length; i < l; i++) objects[i].implement(properties);
};
Native.genericize = function(object, property, check){
if ((!check || !object[property]) && typeof object.prototype[property] == 'function') object[property] = function(){
var args = Array.prototype.slice.call(arguments);
return object.prototype[property].apply(args.shift(), args);
};
};
Native.typize = function(object, family){
if (!object.type) object.type = function(item){
return ($type(item) === family);
};
};
(function(objects){
for (var name in objects) Native.typize(objects[name], name.toLowerCase());
})({'Boolean': Boolean, 'Native': Native, 'Object': Object});
(function(objects){
for (var name in objects) new Native({name: name, initialize: objects[name], protect: true});
})({'String': String, 'Function': Function, 'Number': Number, 'Array': Array, 'RegExp': RegExp, 'Date': Date});
(function(object, methods){
for (var i = 0, l = methods.length; i < l; i++) Native.genericize(object, methods[i], true);
return arguments.callee;
})
(Array, ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', 'toString', 'valueOf', 'indexOf', 'lastIndexOf'])
(String, ['charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'replace', 'search', 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase', 'valueOf']);
function $chk(obj){
return !!(obj || obj === 0);
};
function $clear(timer){
clearTimeout(timer);
clearInterval(timer);
return null;
};
function $defined(obj){
return (obj != undefined);
};
function $empty(){};
function $arguments(i){
return function(){
return arguments[i];
};
};
function $lambda(value){
return (typeof value == 'function') ? value : function(){
return value;
};
};
function $extend(original, extended){
for (var key in (extended || {})) original[key] = extended[key];
return original;
};
function $unlink(object){
var unlinked = null;
switch ($type(object)){
case 'object':
unlinked = {};
for (var p in object) unlinked[p] = $unlink(object[p]);
break;
case 'array':
unlinked = [];
for (var i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]);
break;
default: return object;
}
return unlinked;
};
function $merge(){
var mix = {};
for (var i = 0, l = arguments.length; i < l; i++){
var object = arguments[i];
if ($type(object) != 'object') continue;
for (var key in object){
var op = object[key], mp = mix[key];
mix[key] = (mp && $type(op) == 'object' && $type(mp) == 'object') ? $merge(mp, op) : $unlink(op);
}
}
return mix;
};
function $pick(){
for (var i = 0, l = arguments.length; i < l; i++){
if ($defined(arguments[i])) return arguments[i];
}
return null;
};
function $random(min, max){
return Math.floor(Math.random() * (max - min + 1) + min);
};
function $splat(obj){
var type = $type(obj);
return (type) ? ((type != 'array' && type != 'arguments') ? [obj] : obj) : [];
};
var $time = Date.now || function(){
return new Date().getTime();
};
function $try(fn, bind, args){
try {
return fn.apply(bind, $splat(args));
} catch(e){
return false;
}
};
function $type(obj){
if (obj == undefined) return false;
if (obj.$family) return (obj.$family.name == 'number' && !isFinite(obj)) ? false : obj.$family.name;
if (obj.nodeName){
switch (obj.nodeType){
case 1: return 'element';
case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
}
} else if (typeof obj.length == 'number'){
if (obj.callee) return 'arguments';
else if (obj.item) return 'collection';
}
return typeof obj;
};
var Hash = new Native({
name: 'Hash',
initialize: function(object){
if ($type(object) == 'hash') object = $unlink(object.getClean());
for (var key in object){
if (!this[key]) this[key] = object[key];
}
return this;
}
});
Hash.implement({
getLength: function(){
var length = 0;
for (var key in this){
if (this.hasOwnProperty(key)) length++;
}
return length;
},
forEach: function(fn, bind){
for (var key in this){
if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this);
}
},
getClean: function(){
var clean = {};
for (var key in this){
if (this.hasOwnProperty(key)) clean[key] = this[key];
}
return clean;
}
});
Hash.alias('forEach', 'each');
function $H(object){
return new Hash(object);
};
Array.implement({
forEach: function(fn, bind){
for (var i = 0, l = this.length; i < l; i++) fn.call(bind, this[i], i, this);
}
});
Array.alias('forEach', 'each');
function $A(iterable){
if ($type(iterable) == 'collection'){
var array = [];
for (var i = 0, l = iterable.length; i < l; i++) array[i] = iterable[i];
return array;
}
return Array.prototype.slice.call(iterable);
};
function $each(iterable, fn, bind){
var type = $type(iterable);
((type == 'arguments' || type == 'collection' || type == 'array') ? Array : Hash).each(iterable, fn, bind);
};
/*
Script: Browser.js
The Browser Core. Contains Browser initialization, Window and Document, and the Browser Hash.
License:
MIT-style license.
*/
var Browser = new Hash({
Engine: {name: 'unknown', version: ''},
Platform: {name: (navigator.platform.match(/mac|win|linux|nix/i) || ['other'])[0].toLowerCase()},
Features: {xhr: !!(window.XMLHttpRequest), xpath: !!(document.evaluate), air: !!(window.runtime)}
});
if (window.opera) Browser.Engine.name = 'presto';
else if (window.ActiveXObject) Browser.Engine = {name: 'trident', version: (Browser.Features.xhr) ? 5 : 4};
else if (!navigator.taintEnabled) Browser.Engine = {name: 'webkit', version: (Browser.Features.xpath) ? 420 : 419};
else if (document.getBoxObjectFor != null) Browser.Engine.name = 'gecko';
Browser.Engine[Browser.Engine.name] = Browser.Engine[Browser.Engine.name + Browser.Engine.version] = true;
Browser.Platform[Browser.Platform.name] = true;
function $exec(text){
if (!text) return text;
if (window.execScript){
window.execScript(text);
} else {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.text = text;
document.head.appendChild(script);
document.head.removeChild(script);
}
return text;
};
Native.UID = 0;
var Window = new Native({
name: 'Window',
legacy: window.Window,
initialize: function(win){
if (!win.Element){
win.Element = $empty;
if (Browser.Engine.webkit) win.document.createElement("iframe"); //fixes safari 2
win.Element.prototype = (Browser.Engine.webkit) ? window["[[DOMElement.prototype]]"] : {};
}
win.uid = Native.UID++;
return $extend(win, Window.Prototype);
},
afterImplement: function(property, value){
window[property] = Window.Prototype[property] = value;
}
});
Window.Prototype = {$family: {name: 'window'}};
new Window(window);
var Document = new Native({
name: 'Document',
legacy: window.Document,
initialize: function(doc){
doc.head = doc.getElementsByTagName('head')[0];
doc.html = doc.getElementsByTagName('html')[0];
doc.window = doc.defaultView || doc.parentWindow;
if (Browser.Engine.trident4) $try(function(){
doc.execCommand("BackgroundImageCache", false, true);
});
doc.uid = Native.UID++;
return $extend(doc, Document.Prototype);
},
afterImplement: function(property, value){
document[property] = Document.Prototype[property] = value;
}
});
Document.Prototype = {$family: {name: 'document'}};
new Document(document);
/*
Script: Array.js
Contains Array Prototypes like copy, each, contains, and remove.
License:
MIT-style license.
*/
Array.implement({
every: function(fn, bind){
for (var i = 0, l = this.length; i < l; i++){
if (!fn.call(bind, this[i], i, this)) return false;
}
return true;
},
filter: function(fn, bind){
var results = [];
for (var i = 0, l = this.length; i < l; i++){
if (fn.call(bind, this[i], i, this)) results.push(this[i]);
}
return results;
},
clean: function() {
return this.filter($arguments(0));
},
indexOf: function(item, from){
var len = this.length;
for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
if (this[i] === item) return i;
}
return -1;
},
map: function(fn, bind){
var results = [];
for (var i = 0, l = this.length; i < l; i++) results[i] = fn.call(bind, this[i], i, this);
return results;
},
some: function(fn, bind){
for (var i = 0, l = this.length; i < l; i++){
if (fn.call(bind, this[i], i, this)) return true;
}
return false;
},
associate: function(keys){
var obj = {}, length = Math.min(this.length, keys.length);
for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
return obj;
},
link: function(object){
var result = {};
for (var i = 0, l = this.length; i < l; i++){
for (var key in object){
if (object[key](this[i])){
result[key] = this[i];
delete object[key];
break;
}
}
}
return result;
},
contains: function(item, from){
return this.indexOf(item, from) != -1;
},
extend: function(array){
for (var i = 0, j = array.length; i < j; i++) this.push(array[i]);
return this;
},
getLast: function(){
return (this.length) ? this[this.length - 1] : null;
},
getRandom: function(){
return (this.length) ? this[$random(0, this.length - 1)] : null;
},
include: function(item){
if (!this.contains(item)) this.push(item);
return this;
},
merge: function(array){
for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
return this;
},
remove: function(item){
for (var i = this.length; i--; i){
if (this[i] === item) this.splice(i, 1);
}
return this;
},
empty: function(){
this.length = 0;
return this;
},
flatten: function(){
var array = [];
for (var i = 0, l = this.length; i < l; i++){
var type = $type(this[i]);
if (!type) continue;
array = array.concat((type == 'array' || type == 'collection' || type == 'arguments') ? Array.flatten(this[i]) : this[i]);
}
return array;
},
hexToRgb: function(array){
if (this.length != 3) return null;
var rgb = this.map(function(value){
if (value.length == 1) value += value;
return value.toInt(16);
});
return (array) ? rgb : 'rgb(' + rgb + ')';
},
rgbToHex: function(array){
if (this.length < 3) return null;
if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
var hex = [];
for (var i = 0; i < 3; i++){
var bit = (this[i] - 0).toString(16);
hex.push((bit.length == 1) ? '0' + bit : bit);
}
return (array) ? hex : '#' + hex.join('');
}
});
/*
Script: Function.js
Contains Function Prototypes like create, bind, pass, and delay.
License:
MIT-style license.
*/
Function.implement({
extend: function(properties){
for (var property in properties) this[property] = properties[property];
return this;
},
create: function(options){
var self = this;
options = options || {};
return function(event){
var args = options.arguments;
args = $defined(args) ? $splat(args) : Array.slice(arguments, (options.event) ? 1 : 0);
if (options.event) args = [event || window.event].extend(args);
var returns = function(){
return self.apply(options.bind || null, args);
};
if (options.delay) return setTimeout(returns, options.delay);
if (options.periodical) return setInterval(returns, options.periodical);
if (options.attempt) return $try(returns);
return returns();
};
},
pass: function(args, bind){
return this.create({'arguments': args, 'bind': bind});
},
attempt: function(args, bind){
return this.create({'arguments': args, 'bind': bind, 'attempt': true})();
},
bind: function(bind, args){
return this.create({'bind': bind, 'arguments': args});
},
bindWithEvent: function(bind, args){
return this.create({'bind': bind, 'event': true, 'arguments': args});
},
delay: function(delay, bind, args){
return this.create({'delay': delay, 'bind': bind, 'arguments': args})();
},
periodical: function(interval, bind, args){
return this.create({'periodical': interval, 'bind': bind, 'arguments': args})();
},
run: function(args, bind){
return this.apply(bind, $splat(args));
}
});
/*
Script: Number.js
Contains Number Prototypes like limit, round, times, and ceil.
License:
MIT-style license.
*/
Number.implement({
limit: function(min, max){
return Math.min(max, Math.max(min, this));
},
round: function(precision){
precision = Math.pow(10, precision || 0);
return Math.round(this * precision) / precision;
},
times: function(fn, bind){
for (var i = 0; i < this; i++) fn.call(bind, i, this);
},
toFloat: function(){
return parseFloat(this);
},
toInt: function(base){
return parseInt(this, base || 10);
}
});
Number.alias('times', 'each');
(function(math){
var methods = {};
math.each(function(name){
if (!Number[name]) methods[name] = function(){
return Math[name].apply(null, [this].concat($A(arguments)));
};
});
Number.implement(methods);
})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
/*
Script: String.js
Contains String Prototypes like camelCase, capitalize, test, and toInt.
License:
MIT-style license.
*/
String.implement({
test: function(regex, params){
return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this);
},
contains: function(string, separator){
return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
},
trim: function(){
return this.replace(/^\s+|\s+$/g, '');
},
clean: function(){
return this.replace(/\s+/g, ' ').trim();
},
camelCase: function(){
return this.replace(/-\D/g, function(match){
return match.charAt(1).toUpperCase();
});
},
hyphenate: function(){
return this.replace(/[A-Z]/g, function(match){
return ('-' + match.charAt(0).toLowerCase());
});
},
capitalize: function(){
return this.replace(/\b[a-z]/g, function(match){
return match.toUpperCase();
});
},
escapeRegExp: function(){
return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
},
toInt: function(base){
return parseInt(this, base || 10);
},
toFloat: function(){
return parseFloat(this);
},
hexToRgb: function(array){
var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
return (hex) ? hex.slice(1).hexToRgb(array) : null;
},
rgbToHex: function(array){
var rgb = this.match(/\d{1,3}/g);
return (rgb) ? rgb.rgbToHex(array) : null;
},
stripScripts: function(option){
var scripts = '';
var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
scripts += arguments[1] + '\n';
return '';
});
if (option === true) $exec(scripts);
else if ($type(option) == 'function') option(scripts, text);
return text;
}
});
/*
Script: Hash.js
Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects.
License:
MIT-style license.
*/
Hash.implement({
has: Object.prototype.hasOwnProperty,
keyOf: function(value){
for (var key in this){
if (this.hasOwnProperty(key) && this[key] === value) return key;
}
return null;
},
hasValue: function(value){
return (Hash.keyOf(this, value) !== null);
},
extend: function(properties){
Hash.each(properties, function(value, key){
Hash.set(this, key, value);
}, this);
return this;
},
merge: function(properties){
Hash.each(properties, function(value, key){
Hash.include(this, key, value);
}, this);
return this;
},
remove: function(key){
if (this.hasOwnProperty(key)) delete this[key];
return this;
},
get: function(key){
return (this.hasOwnProperty(key)) ? this[key] : null;
},
set: function(key, value){
if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
return this;
},
empty: function(){
Hash.each(this, function(value, key){
delete this[key];
}, this);
return this;
},
include: function(key, value){
var k = this[key];
if (!$defined(k)) this[key] = value;
return this;
},
map: function(fn, bind){
var results = new Hash;
Hash.each(this, function(value, key){
results.set(key, fn.call(bind, value, key, this));
}, this);
return results;
},
filter: function(fn, bind){
var results = new Hash;
Hash.each(this, function(value, key){
if (fn.call(bind, value, key, this)) results.set(key, value);
}, this);
return results;
},
every: function(fn, bind){
for (var key in this){
if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false;
}
return true;
},
some: function(fn, bind){
for (var key in this){
if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true;
}
return false;
},
getKeys: function(){
var keys = [];
Hash.each(this, function(value, key){
keys.push(key);
});
return keys;
},
getValues: function(){
var values = [];
Hash.each(this, function(value){
values.push(value);
});
return values;
},
toQueryString: function(){
var queryString = [];
Hash.each(this, function(value, key){
$splat(value).each(function(val){
queryString.push(key + '=' + encodeURIComponent(val));
});
});
return queryString.join('&');
}
});
Hash.alias('keyOf', 'indexOf').alias('hasValue', 'contains').alias('remove', 'erase');
/*
Script: Event.js
Contains the Event Native, to make the event object completely crossbrowser.
License:
MIT-style license.
*/
var Event = new Native({
name: 'Event',
initialize: function(event, win){
win = win || window;
event = event || win.event;
if (event.$extended) return event;
this.$extended = true;
var type = event.type;
var target = event.target || event.srcElement;
while (target && target.nodeType == 3) target = target.parentNode;
if (type.match(/DOMMouseScroll|mousewheel/)){
var wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
} else if (type.test(/key/)){
var code = event.which || event.keyCode;
var key = Event.Keys.keyOf(code);
if (type == 'keydown'){
var fKey = code - 111;
if (fKey > 0 && fKey < 13) key = 'f' + fKey;
}
key = key || String.fromCharCode(code).toLowerCase();
} else if (type.match(/(click|mouse|menu)/i)){
var page = {
x: event.pageX || event.clientX + win.document.documentElement.scrollLeft,
y: event.pageY || event.clientY + win.document.documentElement.scrollTop
};
var client = {
x: event.pageX ? event.pageX - win.pageXOffset : event.clientX,
y: event.pageY ? event.pageY - win.pageYOffset : event.clientY
};
var rightClick = (event.which == 3) || (event.button == 2);
var related = null;
if (type.match(/over|out/)){
switch (type){
case 'mouseover': related = event.relatedTarget || event.fromElement; break;
case 'mouseout': related = event.relatedTarget || event.toElement;
}
if ((function(){
while (related && related.nodeType == 3) related = related.parentNode;
}).create({attempt: Browser.Engine.gecko})() === false) related = false;
}
}
return $extend(this, {
event: event,
type: type,
page: page,
client: client,
rightClick: rightClick,
wheel: wheel,
relatedTarget: related,
target: target,
code: code,
key: key,
shift: event.shiftKey,
control: event.ctrlKey,
alt: event.altKey,
meta: event.metaKey
});
}
});
Event.Keys = new Hash({
'enter': 13,
'up': 38,
'down': 40,
'left': 37,
'right': 39,
'esc': 27,
'space': 32,
'backspace': 8,
'tab': 9,
'delete': 46
});
Event.implement({
stop: function(){
return this.stopPropagation().preventDefault();
},
stopPropagation: function(){
if (this.event.stopPropagation) this.event.stopPropagation();
else this.event.cancelBubble = true;
return this;
},
preventDefault: function(){
if (this.event.preventDefault) this.event.preventDefault();
else this.event.returnValue = false;
return this;
}
});
/*
Script: Class.js
Contains the Class Function for easily creating, extending, and implementing reusable Classes.
License:
MIT-style license.
*/
var Class = new Native({
name: 'Class',
initialize: function(properties){
properties = properties || {};
var klass = function(){
for (var property in this) this[property] = $unlink(this[property]);
this.parent = null;
['Implements', 'Extends'].each(function(Property){
if (!this[Property]) return;
Class[Property](this, this[Property]);
delete this[Property];
}, this);
this.constructor = klass;
var self = (arguments[0] !== $empty && this.initialize) ? this.initialize.apply(this, arguments) : this;
if (this.options && this.options.initialize) this.options.initialize.call(this);
return self;
};
$extend(klass, this);
klass.constructor = Class;
klass.prototype = properties;
return klass;
}
});
Class.implement({
implement: function(){
Class.Implements(this.prototype, Array.slice(arguments));
return this;
}
});
Class.Implements = function(self, klasses){
$splat(klasses).each(function(klass){
$extend(self, ($type(klass) == 'class') ? new klass($empty) : klass);
});
};
Class.Extends = function(self, klass){
klass = new klass($empty);
for (var property in klass){
var kp = klass[property];
var sp = self[property];
self[property] = (function(previous, current){
if ($defined(current) && previous != current){
var type = $type(current);
if (type != $type(previous)) return current;
switch (type){
case 'function':
return function(){
current.parent = self.parent = previous.bind(this);
var value = current.apply(this, arguments);
self.parent = current.parent;
return value;
};
case 'object': return $merge(previous, current);
default: return current;
}
}
return previous;
})(kp, sp);
}
};
//legacy .extend support
Class.prototype.extend = function(properties){
properties.Extends = this;
return new Class(properties);
};
/*
Script: Class.Extras.js
Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.
License:
MIT-style license.
*/
var Chain = new Class({
chain: function(){
this.$chain = (this.$chain || []).extend(arguments);
return this;
},
callChain: function(){
if (this.$chain && this.$chain.length) this.$chain.shift().apply(this, arguments);
return this;
},
clearChain: function(){
if (this.$chain) this.$chain.empty();
return this;
}
});
var Events = new Class({
addEvent: function(type, fn, internal){
if (fn != $empty){
this.$events = this.$events || {};
this.$events[type] = this.$events[type] || [];
this.$events[type].include(fn);
if (internal) fn.internal = true;
}
return this;
},
addEvents: function(events){
for (var type in events) this.addEvent(type, events[type]);
return this;
},
fireEvent: function(type, args, delay){
if (!this.$events || !this.$events[type]) return this;
this.$events[type].each(function(fn){
fn.create({'bind': this, 'delay': delay, 'arguments': args})();
}, this);
return this;
},
removeEvent: function(type, fn){
if (!this.$events || !this.$events[type]) return this;
if (!fn.internal) this.$events[type].remove(fn);
return this;
},
removeEvents: function(type){
for (var e in this.$events){
if (type && type != e) continue;
var fns = this.$events[e];
for (var i = fns.length; i--; i) this.removeEvent(e, fns[i]);
}
return this;
}
});
var Options = new Class({
setOptions: function(){
this.options = $merge.run([this.options].extend(arguments));
if (!this.addEvent) return this;
for (var option in this.options){
if ($type(this.options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
this.addEvent(option, this.options[option]);
delete this.options[option];
}
return this;
}
});
/*
Script: Element.js
One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser,
time-saver methods to let you easily work with HTML Elements.
License:
MIT-style license.
*/
Document.implement({
newElement: function(tag, props){
if (Browser.Engine.trident && props){
['name', 'type', 'checked'].each(function(attribute){
if (!props[attribute]) return;
tag += ' ' + attribute + '="' + props[attribute] + '"';
if (attribute != 'checked') delete props[attribute];
});
tag = '<' + tag + '>';
}
return $.element(this.createElement(tag)).set(props);
},
newTextNode: function(text){
return this.createTextNode(text);
},
getDocument: function(){
return this;
},
getWindow: function(){
return this.defaultView || this.parentWindow;
}
});
var Element = new Native({
name: 'Element',
legacy: window.Element,
initialize: function(tag, props){
var konstructor = Element.Constructors.get(tag);
if (konstructor) return konstructor(props);
if (typeof tag == 'string') return document.newElement(tag, props);
return $(tag).set(props);
},
afterImplement: function(key, value){
if (!Array[key]) Elements.implement(key, Elements.multi(key));
Element.Prototype[key] = value;
}
});
Element.Prototype = {$family: {name: 'element'}};
Element.Constructors = new Hash;
var IFrame = new Native({
name: 'IFrame',
generics: false,
initialize: function(){
Native.UID++;
var params = Array.link(arguments, {properties: Object.type, iframe: $defined});
var props = params.properties || {};
var iframe = $(params.iframe) || false;
var onload = props.onload || $empty;
delete props.onload;
props.id = props.name = $pick(props.id, props.name, iframe.id, iframe.name, 'IFrame_' + Native.UID);
((iframe = iframe || new Element('iframe'))).set(props);
var onFrameLoad = function(){
var host = $try(function(){
return iframe.contentWindow.location.host;
});
if (host && host == window.location.host){
iframe.window = iframe.contentWindow;
var win = new Window(iframe.window);
var doc = new Document(iframe.window.document);
$extend(win.Element.prototype, Element.Prototype);
}
onload.call(iframe.contentWindow);
};
(!window.frames[props.id]) ? iframe.addListener('load', onFrameLoad) : onFrameLoad();
return iframe;
}
});
var Elements = new Native({
initialize: function(elements, options){
options = $extend({ddup: true, cash: true}, options);
elements = elements || [];
if (options.ddup || options.cash){
var uniques = {};
var returned = [];
for (var i = 0, l = elements.length; i < l; i++){
var el = $.element(elements[i], !options.cash);
if (options.ddup){
if (uniques[el.uid]) continue;
uniques[el.uid] = true;
}
returned.push(el);
}
elements = returned;
}
return (options.cash) ? $extend(elements, this) : elements;
}
});
Elements.implement({
filterBy: function(filter){
if (!filter) return this;
return new Elements(this.filter((typeof filter == 'string') ? function(item){
return item.match(filter);
} : filter));
}
});
Elements.multi = function(property){
return function(){
var items = [];
var elements = true;
for (var i = 0, j = this.length; i < j; i++){
var returns = this[i][property].apply(this[i], arguments);
items.push(returns);
if (elements) elements = ($type(returns) == 'element');
}
return (elements) ? new Elements(items) : items;
};
};
Window.implement({
$: function(el, notrash){
if (el && el.$attributes) return el;
var type = $type(el);
return ($[type]) ? $[type](el, notrash, this.document) : null;
},
$$: function(selector){
if (arguments.length == 1 && typeof selector == 'string') return this.document.getElements(selector);
var elements = [];
var args = Array.flatten(arguments);
for (var i = 0, l = args.length; i < l; i++){
var item = args[i];
switch ($type(item)){
case 'element': item = [item]; break;
case 'string': item = this.document.getElements(item, true); break;
default: item = false;
}
if (item) elements.extend(item);
}
return new Elements(elements);
},
getDocument: function(){
return this.document;
},
getWindow: function(){
return this;
}
});
$.string = function(id, notrash, doc){
id = doc.getElementById(id);
return (id) ? $.element(id, notrash) : null;
};
$.element = function(el, notrash){
el.uid = el.uid || [Native.UID++];
if (!notrash && Garbage.collect(el) && !el.$family) $extend(el, Element.Prototype);
return el;
};
$.textnode = $.window = $.document = $arguments(0);
$.number = function(uid){
return Garbage.Elements[uid] || null;
};
Native.implement([Element, Document], {
getElement: function(selector, notrash){
return $(this.getElements(selector, true)[0] || null, notrash);
},
getElements: function(tags, nocash){
tags = tags.split(',');
var elements = [];
var ddup = (tags.length > 1);
tags.each(function(tag){
var partial = this.getElementsByTagName(tag.trim());
(ddup) ? elements.extend(partial) : elements = partial;
}, this);
return new Elements(elements, {ddup: ddup, cash: !nocash});
}
});
Element.Storage = {
get: function(uid){
return (this[uid] = this[uid] || {});
}
};
Element.Inserters = new Hash({
before: function(context, element){
if (element.parentNode) element.parentNode.insertBefore(context, element);
},
after: function(context, element){
if (!element.parentNode) return;
var next = element.nextSibling;
(next) ? element.parentNode.insertBefore(context, next) : element.parentNode.appendChild(context);
},
bottom: function(context, element){
element.appendChild(context);
},
top: function(context, element){
var first = element.firstChild;
(first) ? element.insertBefore(context, first) : element.appendChild(context);
}
});
Element.Inserters.inside = Element.Inserters.bottom;
Element.Inserters.each(function(value, key){
var Key = key.capitalize();
Element.implement('inject' + Key, function(el){
Element.Inserters[key](this, $(el, true));
return this;
});
Element.implement('grab' + Key, function(el){
Element.Inserters[key]($(el, true), this);
return this;
});
});
Element.implement({
getDocument: function(){
return this.ownerDocument;
},
getWindow: function(){
return this.ownerDocument.getWindow();
},
getElementById: function(id, nocash){
var el = this.ownerDocument.getElementById(id);
if (!el) return null;
for (var parent = el.parentNode; parent != this; parent = parent.parentNode){
if (!parent) return null;
}
return $.element(el, nocash);
},
set: function(prop, value){
switch ($type(prop)){
case 'object':
for (var p in prop) this.set(p, prop[p]);
break;
case 'string':
var property = Element.Properties.get(prop);
(property && property.set) ? property.set.apply(this, Array.slice(arguments, 1)) : this.setProperty(prop, value);
}
return this;
},
get: function(prop){
var property = Element.Properties.get(prop);
return (property && property.get) ? property.get.apply(this, Array.slice(arguments, 1)) : this.getProperty(prop);
},
erase: function(prop){
var property = Element.Properties.get(prop);
(property && property.erase) ? property.erase.apply(this, Array.slice(arguments, 1)) : this.removeProperty(prop);
return this;
},
match: function(tag){
return (!tag || Element.get(this, 'tag') == tag);
},
inject: function(el, where){
Element.Inserters.get(where || 'bottom')(this, $(el, true));
return this;
},
wraps: function(el, where){
el = $(el, true);
return this.replaces(el).grab(el);
},
grab: function(el, where){
Element.Inserters.get(where || 'bottom')($(el, true), this);
return this;
},
appendText: function(text, where){
return this.grab(this.getDocument().newTextNode(text), where);
},
adopt: function(){
Array.flatten(arguments).each(function(element){
this.appendChild($(element, true));
}, this);
return this;
},
dispose: function(){
return this.parentNode.removeChild(this);
},
clone: function(contents){
var temp = new Element('div').grab(this.cloneNode(contents !== false));
Array.each(temp.getElementsByTagName('*'), function(element){
if (element.id) element.removeAttribute('id');
});
return new Element('div').set('html', temp.innerHTML).getFirst();
},
replaces: function(el){
el = $(el, true);
el.parentNode.replaceChild(this, el);
return this;
},
hasClass: function(className){
return this.className.contains(className, ' ');
},
addClass: function(className){
if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
return this;
},
removeClass: function(className){
this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean();
return this;
},
toggleClass: function(className){
return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
},
getComputedStyle: function(property){
var result = null;
if (this.currentStyle){
result = this.currentStyle[property.camelCase()];
} else {
var computed = this.getWindow().getComputedStyle(this, null);
if (computed) result = computed.getPropertyValue([property.hyphenate()]);
}
return result;
},
empty: function(){
var elements = $A(this.getElementsByTagName('*'));
elements.each(function(element){
$try(Element.prototype.dispose, element);
});
Garbage.trash(elements);
$try(Element.prototype.set, this, ['html', '']);
return this;
},
destroy: function(){
Garbage.kill(this.empty().dispose());
return null;
},
toQueryString: function(){
var queryString = [];
this.getElements('input, select, textarea', true).each(function(el){
var name = el.name, type = el.type, value = Element.get(el, 'value');
if (value === false || !name || el.disabled) return;
$splat(value).each(function(val){
queryString.push(name + '=' + encodeURIComponent(val));
});
});
return queryString.join('&');
},
getProperty: function(attribute){
var EA = Element.Attributes, key = EA.Props[attribute];
var value = (key) ? this[key] : this.getAttribute(attribute);
return (EA.Bools[attribute]) ? !!value : value;
},
getProperties: function(){
var args = $A(arguments);
return args.map(function(attr){
return this.getProperty(attr);
}, this).associate(args);
},
setProperty: function(attribute, value){
var EA = Element.Attributes, key = EA.Props[attribute], hasValue = $defined(value);
if (key && EA.Bools[attribute]) value = (value || !hasValue) ? true : false;
else if (!hasValue) return this.removeProperty(attribute);
(key) ? this[key] = value : this.setAttribute(attribute, value);
return this;
},
setProperties: function(attributes){
for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
return this;
},
removeProperty: function(attribute){
var EA = Element.Attributes, key = EA.Props[attribute], isBool = (key && EA.Bools[attribute]);
(key) ? this[key] = (isBool) ? false : '' : this.removeAttribute(attribute);
return this;
},
removeProperties: function(){
Array.each(arguments, this.removeProperty, this);
return this;
}
});
(function(){
var walk = function(element, walk, start, match, all, nocash){
var el = element[start || walk];
var elements = [];
while (el){
if (el.nodeType == 1 && Element.match(el, match)){
elements.push(el);
if (!all) break;
}
el = el[walk];
}
return (all) ? new Elements(elements, {ddup: false, cash: !nocash}) : $(elements[0], nocash);
};
Element.implement({
getPrevious: function(match, nocash){
return walk(this, 'previousSibling', null, match, false, nocash);
},
getAllPrevious: function(match, nocash){
return walk(this, 'previousSibling', null, match, true, nocash);
},
getNext: function(match, nocash){
return walk(this, 'nextSibling', null, match, false, nocash);
},
getAllNext: function(match, nocash){
return walk(this, 'nextSibling', null, match, true, nocash);
},
getFirst: function(match, nocash){
return walk(this, 'nextSibling', 'firstChild', match, false, nocash);
},
getLast: function(match, nocash){
return walk(this, 'previousSibling', 'lastChild', match, false, nocash);
},
getParent: function(match, nocash){
return walk(this, 'parentNode', null, match, false, nocash);
},
getParents: function(match, nocash){
return walk(this, 'parentNode', null, match, true, nocash);
},
getChildren: function(match, nocash){
return walk(this, 'nextSibling', 'firstChild', match, true, nocash);
},
hasChild: function(el){
if (!(el = $(el, true))) return false;
return Element.getParents(el, this.get('tag'), true).contains(this);
}
});
})();
Element.alias('dispose', 'remove').alias('getLast', 'getLastChild');
Element.Properties = new Hash;
Element.Properties.style = {
set: function(style){
this.style.cssText = style;
},
get: function(){
return this.style.cssText;
},
erase: function(){
this.style.cssText = '';
}
};
Element.Properties.value = {get: function(){
switch (Element.get(this, 'tag')){
case 'select':
var values = [];
Array.each(this.options, function(option){
if (option.selected) values.push(option.value);
});
return (this.multiple) ? values : values[0];
case 'input': if (['checkbox', 'radio'].contains(this.type) && !this.checked) return false;
default: return $pick(this.value, false);
}
}};
Element.Properties.tag = {get: function(){
return this.tagName.toLowerCase();
}};
Element.Properties.html = {set: function(){
return this.innerHTML = Array.flatten(arguments).join('');
}};
Element.implement({
getText: function(){
return this.get('text');
},
setText: function(text){
return this.set('text', text);
},
setHTML: function(){
return this.set('html', arguments);
},
getHTML: function(){
return this.get('html');
},
getTag: function(){
return this.get('tag');
}
});
Native.implement([Element, Window, Document], {
addListener: function(type, fn){
if (this.addEventListener) this.addEventListener(type, fn, false);
else this.attachEvent('on' + type, fn);
return this;
},
removeListener: function(type, fn){
if (this.removeEventListener) this.removeEventListener(type, fn, false);
else this.detachEvent('on' + type, fn);
return this;
},
retrieve: function(property, dflt){
var storage = Element.Storage.get(this.uid);
var prop = storage[property];
if ($defined(dflt) && !$defined(prop)) prop = storage[property] = dflt;
return $pick(prop);
},
store: function(property, value){
var storage = Element.Storage.get(this.uid);
storage[property] = value;
return this;
},
eliminate: function(property){
var storage = Element.Storage.get(this.uid);
delete storage[property];
return this;
}
});
Element.Attributes = new Hash({
Props: {'html': 'innerHTML', 'class': 'className', 'for': 'htmlFor', 'text': (Browser.Engine.trident) ? 'innerText' : 'textContent'},
Bools: ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readonly', 'multiple', 'selected', 'noresize', 'defer'],
Camels: ['value', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', 'rowSpan', 'tabIndex', 'useMap']
});
(function(EA){
var EAB = EA.Bools, EAC = EA.Camels;
EA.Bools = EAB = EAB.associate(EAB);
Hash.extend(Hash.merge(EA.Props, EAB), EAC.associate(EAC.map(function(v){
return v.toLowerCase();
})));
EA.remove('Camels');
})(Element.Attributes);
var Garbage = {
Elements: {},
ignored: {object: 1, embed: 1, OBJECT: 1, EMBED: 1},
collect: function(el){
if (el.$attributes) return true;
if (Garbage.ignored[el.tagName]) return false;
Garbage.Elements[el.uid] = el;
el.$attributes = {};
return true;
},
trash: function(elements){
for (var i = elements.length, el; i--; i) Garbage.kill(elements[i]);
},
kill: function(el){
if (!el || !el.$attributes) return;
delete Garbage.Elements[el.uid];
if (el.retrieve('events')) el.removeEvents();
for (var p in el.$attributes) el.$attributes[p] = null;
if (Browser.Engine.trident){
for (var d in Element.Prototype) el[d] = null;
}
el.$attributes = el.uid = null;
},
empty: function(){
for (var uid in Garbage.Elements) Garbage.kill(Garbage.Elements[uid]);
}
};
window.addListener('beforeunload', function(){
window.addListener('unload', Garbage.empty);
if (Browser.Engine.trident) window.addListener('unload', CollectGarbage);
});
/*
Script: Element.Event.js
Contains Element methods for dealing with events, and custom Events.
License:
MIT-style license.
*/
Element.Properties.events = {set: function(events){
this.addEvents(events);
}};
Native.implement([Element, Window, Document], {
addEvent: function(type, fn){
var events = this.retrieve('events', {});
events[type] = events[type] || {'keys': [], 'values': []};
if (events[type].keys.contains(fn)) return this;
events[type].keys.push(fn);
var realType = type, custom = Element.Events.get(type), condition = fn, self = this;
if (custom){
if (custom.onAdd) custom.onAdd.call(this, fn);
if (custom.condition){
condition = function(event){
if (custom.condition.call(this, event)) return fn.call(this, event);
return false;
};
}
realType = custom.base || realType;
}
var defn = function(){
return fn.call(self);
};
var nativeEvent = Element.NativeEvents[realType] || 0;
if (nativeEvent){
if (nativeEvent == 2){
defn = function(event){
event = new Event(event, self.getWindow());
if (condition.call(self, event) === false) event.stop();
};
}
this.addListener(realType, defn);
}
events[type].values.push(defn);
return this;
},
removeEvent: function(type, fn){
var events = this.retrieve('events');
if (!events || !events[type]) return this;
var pos = events[type].keys.indexOf(fn);
if (pos == -1) return this;
var key = events[type].keys.splice(pos, 1)[0];
var value = events[type].values.splice(pos, 1)[0];
var custom = Element.Events.get(type);
if (custom){
if (custom.onRemove) custom.onRemove.call(this, fn);
type = custom.base || type;
}
return (Element.NativeEvents[type]) ? this.removeListener(type, value) : this;
},
addEvents: function(events){
for (var event in events) this.addEvent(event, events[event]);
return this;
},
removeEvents: function(type){
var events = this.retrieve('events');
if (!events) return this;
if (!type){
for (var evType in events) this.removeEvents(evType);
events = null;
} else if (events[type]){
while (events[type].keys[0]) this.removeEvent(type, events[type].keys[0]);
events[type] = null;
}
return this;
},
fireEvent: function(type, args, delay){
var events = this.retrieve('events');
if (!events || !events[type]) return this;
events[type].keys.each(function(fn){
fn.create({'bind': this, 'delay': delay, 'arguments': args})();
}, this);
return this;
},
cloneEvents: function(from, type){
from = $(from);
var fevents = from.retrieve('events');
if (!fevents) return this;
if (!type){
for (var evType in fevents) this.cloneEvents(from, evType);
} else if (fevents[type]){
fevents[type].keys.each(function(fn){
this.addEvent(type, fn);
}, this);
}
return this;
}
});
Element.NativeEvents = {
'click': 2, 'dblclick': 2, 'mouseup': 2, 'mousedown': 2, 'contextmenu': 2, //mouse buttons
'mousewheel': 2, 'DOMMouseScroll': 2, //mouse wheel
'mouseover': 2, 'mouseout': 2, 'mousemove': 2, 'selectstart': 2, 'selectend': 2, //mouse movement
'keydown': 2, 'keypress': 2, 'keyup': 2, //keyboard
'focus': 2, 'blur': 2, 'change': 2, 'reset': 2, 'select': 2, 'submit': 2, //form elements
'load': 1, 'unload': 1, 'beforeunload': 1, 'resize': 1, 'move': 1, 'DOMContentLoaded': 1, 'readystatechange': 1, //window
'error': 1, 'abort': 1, 'scroll': 1 //misc
};
(function(){
var checkRelatedTarget = function(event){
var related = event.relatedTarget;
if (!related) return true;
return ($type(this) != 'document' && related != this && related.prefix != 'xul' && !this.hasChild(related));
};
Element.Events = new Hash({
mouseenter: {
base: 'mouseover',
condition: checkRelatedTarget
},
mouseleave: {
base: 'mouseout',
condition: checkRelatedTarget
},
mousewheel: {
base: (Browser.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel'
}
});
})();
/*
Script: Element.Style.js
Contains methods for interacting with the styles of Elements in a fashionable way.
License:
MIT-style license.
*/
Element.Properties.styles = {set: function(styles){
this.setStyles(styles);
}};
Element.Properties.opacity = {
set: function(opacity, novisibility){
if (!novisibility){
if (opacity == 0){
if (this.style.visibility != 'hidden') this.style.visibility = 'hidden';
} else {
if (this.style.visibility != 'visible') this.style.visibility = 'visible';
}
}
if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;
if (Browser.Engine.trident) this.style.filter = (opacity == 1) ? '' : 'alpha(opacity=' + opacity * 100 + ')';
this.style.opacity = opacity;
this.store('opacity', opacity);
},
get: function(){
return this.retrieve('opacity', 1);
}
};
Element.implement({
setOpacity: function(value){
return this.set('opacity', value, true);
},
getOpacity: function(){
return this.get('opacity');
},
setStyle: function(property, value){
switch (property){
case 'opacity': return this.set('opacity', parseFloat(value));
case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat';
}
property = property.camelCase();
if ($type(value) != 'string'){
var map = (Element.Styles.get(property) || '@').split(' ');
value = $splat(value).map(function(val, i){
if (!map[i]) return '';
return ($type(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;
}).join(' ');
} else if (value == String(Number(value))){
value = Math.round(value);
}
this.style[property] = value;
return this;
},
getStyle: function(property){
switch (property){
case 'opacity': return this.get('opacity');
case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat';
}
property = property.camelCase();
var result = this.style[property];
if (!$chk(result)){
result = [];
for (var style in Element.ShortStyles){
if (property != style) continue;
for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s));
return result.join(' ');
}
result = this.getComputedStyle(property);
}
if (result){
result = String(result);
var color = result.match(/rgba?\([\d\s,]+\)/);
if (color) result = result.replace(color[0], color[0].rgbToHex());
}
if (Browser.Engine.presto || (Browser.Engine.trident && !$chk(parseInt(result)))){
if (property.test(/^(height|width)$/)){
var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
values.each(function(value){
size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt();
}, this);
return this['offset' + property.capitalize()] - size + 'px';
}
if (Browser.Engine.presto && String(result).test('px')) return result;
if (property.test(/(border(.+)Width|margin|padding)/)) return '0px';
}
return result;
},
setStyles: function(styles){
for (var style in styles) this.setStyle(style, styles[style]);
return this;
},
getStyles: function(){
var result = {};
Array.each(arguments, function(key){
result[key] = this.getStyle(key);
}, this);
return result;
}
});
Element.Styles = new Hash({
width: '@px', height: '@px', left: '@px', top: '@px', bottom: '@px', right: '@px', maxWidth: '@px', maxHeight: '@px',
backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)',
fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)',
margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',
borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',
zIndex: '@', 'zoom': '@', fontWeight: '@',
textIndent: '@px', opacity: '@'
});
Element.ShortStyles = {'margin': {}, 'padding': {}, 'border': {}, 'borderWidth': {}, 'borderStyle': {}, 'borderColor': {}};
['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
var Short = Element.ShortStyles;
var All = Element.Styles;
['margin', 'padding'].each(function(style){
var sd = style + direction;
Short[style][sd] = All[sd] = '@px';
});
var bd = 'border' + direction;
Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';
Short[bd] = {};
Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';
Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';
Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)';
});
/*
Script: Element.Dimensions.js
Contains methods to work with size, scroll, or positioning of Elements and the window object.
License:
MIT-style license.
Note:
Dimensions requires an XHTML doctype.
*/
(function(){
function $body(el){
return el.tagName.toLowerCase() == 'body';
};
Element.implement({
positioned: function(){
if ($body(this)) return true;
return (Element.getComputedStyle(this, 'position') != 'static');
},
getOffsetParent: function(){
if ($body(this)) return null;
if (!Browser.Engine.trident) return $(this.offsetParent);
var el = this;
while ((el = el.parentNode)){
if (Element.positioned(el)) return $(el);
}
return null;
},
getSize: function(){
if ($body(this)) return this.getWindow().getSize();
return {x: this.offsetWidth, y: this.offsetHeight};
},
getScrollSize: function(){
if ($body(this)) return this.getWindow().getScrollSize();
return {x: this.scrollWidth, y: this.scrollHeight};
},
getScroll: function(){
if ($body(this)) return this.getWindow().getScroll();
return {x: this.scrollLeft, y: this.scrollTop};
},
scrollTo: function(x, y){
if ($body(this)) return this.getWindow().scrollTo(x, y);
this.scrollLeft = x;
this.scrollTop = y;
return this;
},
getPosition: function(relative){
if ($body(this)) return {x: 0, y: 0};
var el = this, position = {x: 0, y: 0};
while (el){
position.x += el.offsetLeft;
position.y += el.offsetTop;
el = el.offsetParent;
}
var rpos = (relative) ? $(relative).getPosition() : {x: 0, y: 0};
return {x: position.x - rpos.x, y: position.y - rpos.y};
},
getCoordinates: function(element){
if ($body(this)) return this.getWindow().getCoordinates();
var position = this.getPosition(element), size = this.getSize();
var obj = {'top': position.y, 'left': position.x, 'width': size.x, 'height': size.y};
obj.right = obj.left + obj.width;
obj.bottom = obj.top + obj.height;
return obj;
},
getRelativePosition: function(){
return this.getPosition(this.getOffsetParent());
},
computePosition: function(obj){
return {
left: obj.x - (this.getComputedStyle('margin-left').toInt() || 0),
top: obj.y - (this.getComputedStyle('margin-top').toInt() || 0)
};
},
position: function(obj){
return this.setStyles(this.computePosition(obj));
}
});
})();
Native.implement([Window, Document], {
getSize: function(){
var body = this.getDocument().body, html = this.getDocument().documentElement;
if (Browser.Engine.webkit419) return {x: this.innerWidth, y: this.innerHeight};
return {x: html.clientWidth, y: html.clientHeight};
},
getScroll: function(){
var html = this.getDocument().documentElement;
return {x: $pick(this.pageXOffset, html.scrollLeft), y: $pick(this.pageYOffset, html.scrollTop)};
},
getScrollSize: function(){
var html = this.getDocument().documentElement, body = this.getDocument().body;
if (Browser.Engine.trident) return {x: Math.max(html.clientWidth, html.scrollWidth), y: Math.max(html.clientHeight, html.scrollHeight)};
if (Browser.Engine.webkit) return {x: body.scrollWidth, y: body.scrollHeight};
return {x: html.scrollWidth, y: html.scrollHeight};
},
getPosition: function(){
return {x: 0, y: 0};
},
getCoordinates: function(){
var size = this.getSize();
return {top: 0, left: 0, height: size.y, width: size.x, bottom: size.y, right: size.x};
}
});
Native.implement([Window, Document, Element], {
getHeight: function(){
return this.getSize().y;
},
getWidth: function(){
return this.getSize().x;
},
getScrollTop: function(){
return this.getScroll().y;
},
getScrollLeft: function(){
return this.getScroll().x;
},
getScrollHeight: function(){
return this.getScrollSize().y;
},
getScrollWidth: function(){
return this.getScrollSize().x;
},
getTop: function(){
return this.getPosition().y;
},
getLeft: function(){
return this.getPosition().x;
}
});
/*
Script: Selectors.js
Adds advanced CSS Querying capabilities for selecting elements.
License:
MIT-style license.
*/
Native.implement([Element, Document], {
getElements: function(selectors, nocash){
var Local = {};
selectors = selectors.split(',');
var elements = [], j = selectors.length;
var ddup = (j > 1);
for (var i = 0; i < j; i++){
var selector = selectors[i], items = [], separators = [];
selector = selector.trim().replace(Selectors.sRegExp, function(match){
if (match.charAt(2)) match = match.trim();
separators.push(match.charAt(0));
return ':)' + match.charAt(1);
}).split(':)');
for (var k = 0, l = selector.length; k < l; k++){
var sel = Selectors.parse(selector[k]);
if (!sel) return [];
var temp = Selectors.Method.getParam(items, separators[k - 1] || false, this, sel, Local);
if (!temp) break;
items = temp;
}
var partial = Selectors.Method.getItems(items, this);
elements = (ddup) ? elements.concat(partial) : partial;
}
return new Elements(elements, {ddup: ddup, cash: !nocash});
}
});
Window.implement({
$E: function(selector){
return this.document.getElement(selector);
}
});
var Selectors = {
regExp: (/:([^-:(]+)[^:(]*(?:\((["']?)(.*?)\2\))?|\[(\w+)(?:([!*^$~|]?=)(["']?)(.*?)\6)?\]|\.[\w-]+|#[\w-]+|\w+|\*/g),
sRegExp: (/\s*([+>~\s])[a-zA-Z#.*\s]/g)
};
Selectors.parse = function(selector){
var params = {tag: '*', id: null, classes: [], attributes: [], pseudos: []};
selector = selector.replace(Selectors.regExp, function(bit){
switch (bit.charAt(0)){
case '.': params.classes.push(bit.slice(1)); break;
case '#': params.id = bit.slice(1); break;
case '[': params.attributes.push([arguments[4], arguments[5], arguments[7]]); break;
case ':':
var xparser = Selectors.Pseudo.get(arguments[1]);
if (!xparser){
params.attributes.push([arguments[1], arguments[3] ? '=' : '', arguments[3]]);
break;
}
var pseudo = {'name': arguments[1], 'parser': xparser, 'argument': (xparser.parser) ? xparser.parser(arguments[3]) : arguments[3]};
params.pseudos.push(pseudo);
break;
default: params.tag = bit;
}
return '';
});
return params;
};
Selectors.Pseudo = new Hash;
Selectors.XPath = {
getParam: function(items, separator, context, params){
var temp = '';
switch (separator){
case ' ': temp += '//'; break;
case '>': temp += '/'; break;
case '+': temp += '/following-sibling::*[1]/self::'; break;
case '~': temp += '/following-sibling::'; break;
}
temp += (context.namespaceURI) ? 'xhtml:' + params.tag : params.tag;
var i;
for (i = params.pseudos.length; i--; i){
var pseudo = params.pseudos[i];
if (pseudo.parser && pseudo.parser.xpath) temp += pseudo.parser.xpath(pseudo.argument);
else temp += ($chk(pseudo.argument)) ? '[@' + pseudo.name + '="' + pseudo.argument + '"]' : '[@' + pseudo.name + ']';
}
if (params.id) temp += '[@id="' + params.id + '"]';
for (i = params.classes.length; i--; i) temp += '[contains(concat(" ", @class, " "), " ' + params.classes[i] + ' ")]';
for (i = params.attributes.length; i--; i){
var bits = params.attributes[i];
switch (bits[1]){
case '=': temp += '[@' + bits[0] + '="' + bits[2] + '"]'; break;
case '*=': temp += '[contains(@' + bits[0] + ', "' + bits[2] + '")]'; break;
case '^=': temp += '[starts-with(@' + bits[0] + ', "' + bits[2] + '")]'; break;
case '$=': temp += '[substring(@' + bits[0] + ', string-length(@' + bits[0] + ') - ' + bits[2].length + ' + 1) = "' + bits[2] + '"]'; break;
case '!=': temp += '[@' + bits[0] + '!="' + bits[2] + '"]'; break;
case '~=': temp += '[contains(concat(" ", @' + bits[0] + ', " "), " ' + bits[2] + ' ")]'; break;
case '|=': temp += '[contains(concat("-", @' + bits[0] + ', "-"), "-' + bits[2] + '-")]'; break;
default: temp += '[@' + bits[0] + ']';
}
}
items.push(temp);
return items;
},
getItems: function(items, context){
var elements = [];
var doc = context.getDocument();
var xpath = doc.evaluate('.//' + items.join(''), context, Selectors.XPath.resolver, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0, j = xpath.snapshotLength; i < j; i++) elements[i] = xpath.snapshotItem(i);
return elements;
},
resolver: function(prefix){
return (prefix == 'xhtml') ? 'http://www.w3.org/1999/xhtml' : false;
}
};
Selectors.Filter = {
getParam: function(items, separator, context, params, Local){
var found = [];
var tag = params.tag;
if (separator){
var uniques = {}, child, children, item, k, l;
var add = function(child){
child.uid = child.uid || [Native.UID++];
if (!uniques[child.uid] && Selectors.Filter.match(child, params, Local)){
uniques[child.uid] = true;
found.push(child);
return true;
}
return false;
};
for (var i = 0, j = items.length; i < j; i++){
item = items[i];	
switch(separator){
case ' ':
children = item.getElementsByTagName(tag);
params.tag = false;
for (k = 0, l = children.length; k < l; k++) add(children[k]);
break;
case '>':
children = item.childNodes;
for (k = 0, l = children.length; k < l; k++){
if (children[k].nodeType == 1) add(children[k]);
}
break;
case '+':
while ((item = item.nextSibling)){
if (item.nodeType == 1){
add(item);
break;
}
}
break;
case '~':
while ((item = item.nextSibling)){
if (item.nodeType == 1 && add(item)) break;
}
break;
}
}	
return found;
}
if (params.id){
el = context.getElementById(params.id, true);
params.id = false;
return (el && Selectors.Filter.match(el, params, Local)) ? [el] : false;
} else {
items = context.getElementsByTagName(tag);
params.tag = false;
for (var m = 0, n = items.length; m < n; m++){
if (Selectors.Filter.match(items[m], params, Local)) found.push(items[m]);
}
}
return found;
},
getItems: $arguments(0)
};
Selectors.Filter.match = function(el, params, Local){
Local = Local || {};
if (params.id && params.id != el.id) return false;
if (params.tag && params.tag != '*' && params.tag != el.tagName.toLowerCase()) return false;
var i;
for (i = params.classes.length; i--; i){
if (!el.className || !el.className.contains(params.classes[i], ' ')) return false;
}
for (i = params.attributes.length; i--; i){
var bits = params.attributes[i];
var result = Element.prototype.getProperty.call(el, bits[0]);
if (!result) return false;
if (!bits[1]) continue;
var condition;
switch (bits[1]){
case '=': condition = (result == bits[2]); break;
case '*=': condition = (result.contains(bits[2])); break;
case '^=': condition = (result.substr(0, bits[2].length) == bits[2]); break;
case '$=': condition = (result.substr(result.length - bits[2].length) == bits[2]); break;
case '!=': condition = (result != bits[2]); break;
case '~=': condition = result.contains(bits[2], ' '); break;
case '|=': condition = result.contains(bits[2], '-');
}
if (!condition) return false;
}
for (i = params.pseudos.length; i--; i){
if (!params.pseudos[i].parser.filter.call(el, params.pseudos[i].argument, Local)) return false;
}
return true;
};
Selectors.Method = (Browser.Features.xpath) ? Selectors.XPath : Selectors.Filter;
Element.implement({
match: function(selector){
return (!selector || Selectors.Filter.match(this, Selectors.parse(selector)));
}
});
/*
Script: Selectors.Pseudo.js
Adds CSS3 and other custom pseudo selectors support for selecting elements.
License:
MIT-style license.
See Also:
<http://www.w3.org/TR/2005/WD-css3-selectors-20051215/#pseudo-classes>
*/
Selectors.Pseudo.enabled = {
xpath: function(){
return '[not(@disabled)]';
},
filter: function(){
return !(this.disabled);
}
};
Selectors.Pseudo.empty = {
xpath: function(){
return '[not(node())]';
},
filter: function(){
return !(this.innerText || this.textContent || '').length;
}
};
Selectors.Pseudo.contains = {
xpath: function(argument){
return '[contains(text(), "' + argument + '")]';
},
filter: function(argument){
for (var i = this.childNodes.length; i--; i){
var child = this.childNodes[i];
if (child.nodeName && child.nodeType == 3 && child.nodeValue.contains(argument)) return true;
}
return false;
}
};
Selectors.Pseudo.nth = {
parser: function(argument){
argument = (argument) ? argument.match(/^([+-]?\d*)?([devon]+)?([+-]?\d*)?$/) : [null, 1, 'n', 0];
if (!argument) return false;
var inta = parseInt(argument[1]);
var a = ($chk(inta)) ? inta : 1;
var special = argument[2] || false;
var b = parseInt(argument[3]) || 0;
b = b - 1;
while (b < 1) b += a;
while (b >= a) b -= a;
switch (special){
case 'n': return {'a': a, 'b': b, 'special': 'n'};
case 'odd': return {'a': 2, 'b': 0, 'special': 'n'};
case 'even': return {'a': 2, 'b': 1, 'special': 'n'};
case 'first': return {'a': 0, 'special': 'index'};
case 'last': return {'special': 'last'};
case 'only': return {'special': 'only'};
default: return {'a': (a - 1), 'special': 'index'};
}
},
xpath: function(argument){
switch (argument.special){
case 'n': return '[count(preceding-sibling::*) mod ' + argument.a + ' = ' + argument.b + ']';
case 'last': return '[count(following-sibling::*) = 0]';
case 'only': return '[not(preceding-sibling::* or following-sibling::*)]';
default: return '[count(preceding-sibling::*) = ' + argument.a + ']';
}
},
filter: function(argument, Local){
var count = 0, el = this;
switch (argument.special){
case 'n':
Local.Positions = Local.Positions || {};
if (!Local.Positions[this.uid]){
var children = this.parentNode.childNodes;
for (var i = 0, l = children.length; i < l; i++){
var child = children[i];
if (child.nodeType != 1) continue;
child.uid = child.uid || [Native.UID++];
Local.Positions[child.uid] = count++;
}
}
return (Local.Positions[this.uid] % argument.a == argument.b);
case 'last':
while ((el = el.nextSibling)){
if (el.nodeType == 1) return false;
}
return true;
case 'only':
var prev = el;
while((prev = prev.previousSibling)){
if (prev.nodeType == 1) return false;
}
var next = el;
while ((next = next.nextSibling)){
if (next.nodeType == 1) return false;
}
return true;
case 'index':
while ((el = el.previousSibling)){
if (el.nodeType == 1 && ++count > argument.a) return false;
}
return true;
}
return false;
}
};
Selectors.Pseudo.extend({
'even': {
parser: function(){
return {'a': 2, 'b': 1, 'special': 'n'};
},
xpath: Selectors.Pseudo.nth.xpath,
filter: Selectors.Pseudo.nth.filter
},
'odd': {
parser: function(){
return {'a': 2, 'b': 0, 'special': 'n'};
},
xpath: Selectors.Pseudo.nth.xpath,
filter: Selectors.Pseudo.nth.filter
},
'first': {
parser: function(){
return {'a': 0, 'special': 'index'};
},
xpath: Selectors.Pseudo.nth.xpath,
filter: Selectors.Pseudo.nth.filter
},
'last': {
parser: function(){
return {'special': 'last'};
},
xpath: Selectors.Pseudo.nth.xpath,
filter: Selectors.Pseudo.nth.filter
},
'only': {
parser: function(){
return {'special': 'only'};
},
xpath: Selectors.Pseudo.nth.xpath,
filter: Selectors.Pseudo.nth.filter
}
});
/*
Script: Domready.js
Contains the domready custom event.
License:
MIT-style license.
*/
Element.Events.domready = {
onAdd: function(fn){
if (Browser.loaded) return fn.call(this);
var self = this, win = this.getWindow(), doc = this.getDocument();
var domready = function(){
if (!arguments.callee.done){
arguments.callee.done = true;
fn.call(self);
};
return true;
};
var states = (Browser.Engine.webkit) ? ['loaded', 'complete'] : 'complete';
var check = function(context){
if (states.contains(context.readyState)) return domready();
return false;
};
if (doc.readyState && Browser.Engine.webkit){
(function(){
if (!check(doc)) arguments.callee.delay(50);
})();
} else if (doc.readyState && Browser.Engine.trident){
var script = $('ie_domready');
if (!script){
var src = (win.location.protocol == 'https:') ? '//:' : 'javascript:void(0)';
doc.write('<script id="ie_domready" defer src="' + src + '"></script>');
script = $('ie_domready');
}
if (!check(script)) script.addEvent('readystatechange', check.pass(script));
} else {
win.addEvent('load', domready);
doc.addEvent('DOMContentLoaded', domready);
}
return null;
}
};
window.addEvent('domready', function(){
Browser.loaded = true;
});
/*
Script: JSON.js
JSON encoder and decoder.
License:
MIT-style license.
See Also:
<http://www.json.org/>
*/
var JSON = new Hash({
encode: function(obj){
switch ($type(obj)){
case 'string':
return '"' + obj.replace(/[\x00-\x1f\\"]/g, JSON.$replaceChars) + '"';
case 'array':
return '[' + String(obj.map(JSON.encode).filter($defined)) + ']';
case 'object': case 'hash':
var string = [];
Hash.each(obj, function(value, key){
var json = JSON.encode(value);
if (json) string.push(JSON.encode(key) + ':' + json);
});
return '{' + String(string) + '}';
case 'number': case 'boolean': return String(obj);
case false: return 'null';
}
return null;
},
$specialChars: {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'},
$replaceChars: function(chr){
return JSON.$specialChars[chr] || '\\u00' + Math.floor(chr.charCodeAt() / 16).toString(16) + (chr.charCodeAt() % 16).toString(16);
},
decode: function(string, secure){
if ($type(string) != 'string' || !string.length) return null;
if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null;
return eval('(' + string + ')');
}
});
Native.implement([Hash, Array, String, Number], {
toJSON: function(){
return JSON.encode(this);
}
});
/*
Script: Cookie.js
Class for creating, loading, and saving browser Cookies.
License:
MIT-style license.
Credits:
Based on the functions by Peter-Paul Koch (http://quirksmode.org).
*/
var Cookie = new Class({
Implements: Options,
options: {
path: false,
domain: false,
duration: false,
secure: false,
document: document
},
initialize: function(key, options){
this.key = key;
this.setOptions(options);
},
write: function(value){
value = encodeURIComponent(value);
if (this.options.domain) value += '; domain=' + this.options.domain;
if (this.options.path) value += '; path=' + this.options.path;
if (this.options.duration){
var date = new Date();
date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
value += '; expires=' + date.toGMTString();
}
if (this.options.secure) value += '; secure';
this.options.document.cookie = this.key + '=' + value;
return this;
},
read: function(){
var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)');
return value ? decodeURIComponent(value[1]) : null;
},
erase: function(){
new Cookie(this.key, $merge(this.options, {duration: -1})).write('');
return this;
}
});
Cookie.set = function(key, value, options){
return new Cookie(key, options).write(value);
};
Cookie.get = function(key){
return new Cookie(key).read();
};
Cookie.remove = function(key, options){
return new Cookie(key, options).erase();
};
/*
Script: Color.js
Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa.
License:
MIT-style license.
*/
var Color = new Native({
initialize: function(color, type){
if (arguments.length >= 3){
type = "rgb"; color = Array.slice(arguments, 0, 3);
} else if (typeof color == 'string'){
if (color.match(/rgb/)) color = color.rgbToHex().hexToRgb(true);
else if (color.match(/hsb/)) color = color.hsbToRgb();
else color = color.hexToRgb(true);
}
type = type || 'rgb';
switch (type){
case 'hsb':
var old = color;
color = color.hsbToRgb();
color.hsb = old;
break;
case 'hex': color = color.hexToRgb(true); break;
}
color.rgb = color.slice(0, 3);
color.hsb = color.hsb || color.rgbToHsb();
color.hex = color.rgbToHex();
return $extend(color, this);
}
});
Color.implement({
mix: function(){
var colors = Array.slice(arguments);
var alpha = ($type(colors.getLast()) == 'number') ? colors.pop() : 50;
var rgb = this.slice();
colors.each(function(color){
color = new Color(color);
for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha));
});
return new Color(rgb, 'rgb');
},
invert: function(){
return new Color(this.map(function(value){
return 255 - value;
}));
},
setHue: function(value){
return new Color([value, this.hsb[1], this.hsb[2]], 'hsb');
},
setSaturation: function(percent){
return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb');
},
setBrightness: function(percent){
return new Color([this.hsb[0], this.hsb[1], percent], 'hsb');
}
});
function $RGB(r, g, b){
return new Color([r, g, b], 'rgb');
};
function $HSB(h, s, b){
return new Color([h, s, b], 'hsb');
};
function $HEX(hex){
return new Color(hex, 'hex');
};
Array.implement({
rgbToHsb: function(){
var red = this[0], green = this[1], blue = this[2];
var hue, saturation, brightness;
var max = Math.max(red, green, blue), min = Math.min(red, green, blue);
var delta = max - min;
brightness = max / 255;
saturation = (max != 0) ? delta / max : 0;
if (saturation == 0){
hue = 0;
} else {
var rr = (max - red) / delta;
var gr = (max - green) / delta;
var br = (max - blue) / delta;
if (red == max) hue = br - gr;
else if (green == max) hue = 2 + rr - br;
else hue = 4 + gr - rr;
hue /= 6;
if (hue < 0) hue++;
}
return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)];
},
hsbToRgb: function(){
var br = Math.round(this[2] / 100 * 255);
if (this[1] == 0){
return [br, br, br];
} else {
var hue = this[0] % 360;
var f = hue % 60;
var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255);
var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255);
var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255);
switch (Math.floor(hue / 60)){
case 0: return [br, t, p];
case 1: return [q, br, p];
case 2: return [p, br, t];
case 3: return [p, q, br];
case 4: return [t, p, br];
case 5: return [br, p, q];
}
}
return false;
}
});
String.implement({
rgbToHsb: function(){
var rgb = this.match(/\d{1,3}/g);
return (rgb) ? hsb.rgbToHsb() : null;
},
hsbToRgb: function(){
var hsb = this.match(/\d{1,3}/g);
return (hsb) ? hsb.hsbToRgb() : null;
}
});
/*
Script: Swiff.js
Wrapper for embedding SWF movies. Supports (and fixes) External Interface Communication.
License:
MIT-style license.
Credits:
Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject.
*/
var Swiff = function(path, options){
if (!Swiff.fixed) Swiff.fix();
var instance = 'Swiff_' + Native.UID++;
options = $merge({
id: instance,
height: 1,
width: 1,
container: null,
properties: {},
params: {
quality: 'high',
allowScriptAccess: 'always',
wMode: 'transparent',
swLiveConnect: true
},
events: {},
vars: {}
}, options);
var params = options.params, vars = options.vars, id = options.id;
var properties = $extend({height: options.height, width: options.width}, options.properties);
Swiff.Events[instance] = {};
for (var event in options.events){
Swiff.Events[instance][event] = function(){
options.events[event].call($(options.id));
};
vars[event] = 'Swiff.Events.' + instance + '.' + event;
}
params.flashVars = Hash.toQueryString(vars);
if (Browser.Engine.trident){
properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
params.movie = path;
} else {
properties.type = 'application/x-shockwave-flash';
properties.data = path;
}
var build = '<object id="' + options.id + '"';
for (var property in properties) build += ' ' + property + '="' + properties[property] + '"';
build += '>';
for (var param in params) build += '<param name="' + param + '" value="' + params[param] + '" />';
build += '</object>';
return ($(options.container) || new Element('div')).set('html', build).firstChild;
};
Swiff.extend({
Events: {},
remote: function(obj, fn){
var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');
return eval(rs);
},
getVersion: function(){
if (!$defined(Swiff.pluginVersion)){
var version;
if (navigator.plugins && navigator.mimeTypes.length){
version = navigator.plugins["Shockwave Flash"];
if (version && version.description) version = version.description;
} else if (Browser.Engine.trident){
version = $try(function(){
return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version");
});
}
Swiff.pluginVersion = (typeof version == 'string') ? parseInt(version.match(/\d+/)[0]) : 0;
}
return Swiff.pluginVersion;
},
fix: function(){
Swiff.fixed = true;
window.addEvent('beforeunload', function(){
__flash_unloadHandler = __flash_savedUnloadHandler = $empty;
});
if (!Browser.Engine.trident) return;
window.addEvent('unload', function(){
Array.each(document.getElementsByTagName('object'), function(obj){
obj.style.display = 'none';
for (var p in obj){
if (typeof obj[p] == 'function') obj[p] = $empty;
}
});
});
}
});
/*
Script: Group.js
Class for monitoring collections of events
License:
MIT-style license.
*/
var Group = new Class({
initialize: function(){
this.instances = Array.flatten(arguments);
this.events = {};
this.checker = {};
},
addEvent: function(type, fn){
this.checker[type] = this.checker[type] || {};
this.events[type] = this.events[type] || [];
if (this.events[type].contains(fn)) return false;
else this.events[type].push(fn);
this.instances.each(function(instance, i){
instance.addEvent(type, this.check.bind(this, [type, instance, i]));
}, this);
return this;
},
check: function(type, instance, i){
this.checker[type][i] = true;
var every = this.instances.every(function(current, j){
return this.checker[type][j] || false;
}, this);
if (!every) return;
this.checker[type] = {};
this.events[type].each(function(event){
event.call(this, this.instances, instance);
}, this);
}
});
/*
Script: Fx.js
Contains the basic animation logic to be extended by all other Fx Classes.
License:
MIT-style license.
*/
var Fx = new Class({
Implements: [Chain, Events, Options],
options: {
/*
onStart: $empty,
onCancel: $empty,
onComplete: $empty,
*/
fps: 50,
unit: false,
duration: 500,
link: 'ignore',
transition: function(p){
return -(Math.cos(Math.PI * p) - 1) / 2;
}
},
initialize: function(options){
this.pass = this.pass || this;
this.setOptions(options);
this.options.duration = Fx.Durations[this.options.duration] || this.options.duration.toInt();
var wait = this.options.wait;
if (wait === false) this.options.link = 'cancel';
},
step: function(){
var time = $time();
if (time < this.time + this.options.duration){
var delta = this.options.transition((time - this.time) / this.options.duration);
this.set(this.compute(this.from, this.to, delta));
} else {
this.set(this.compute(this.from, this.to, 1));
this.complete();
}
},
set: function(now){
return now;
},
compute: function(from, to, delta){
return Fx.compute(from, to, delta);
},
check: function(){
if (!this.timer) return true;
switch (this.options.link){
case 'cancel': this.cancel(); return true;
case 'chain': this.chain(this.start.bind(this, arguments)); return false;
}
return false;
},
start: function(from, to){
if (!this.check(from, to)) return this;
this.from = from;
this.to = to;
this.time = 0;
this.startTimer();
this.onStart();
return this;
},
complete: function(){
return (!this.stopTimer()) ? this : this.onComplete();
},
cancel: function(){
return (!this.stopTimer()) ? this : this.onCancel();
},
onStart: function(){
return this.fireEvent('onStart', this.pass);
},
onComplete: function(){
return this.fireEvent('onComplete', this.pass).callChain();
},
onCancel: function(){
return this.fireEvent('onCancel', this.pass).clearChain();
},
pause: function(){
this.stopTimer();
return this;
},
resume: function(){
this.startTimer();
return this;
},
stopTimer: function(){
if (!this.timer) return false;
this.time = $time() - this.time;
this.timer = $clear(this.timer);
return true;
},
startTimer: function(){
if (this.timer) return false;
this.time = $time() - this.time;
this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this);
return true;
}
});
Fx.compute = function(from, to, delta){
return (to - from) * delta + from;
};
Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000};
/*
Script: Fx.CSS.js
Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements.
License:
MIT-style license.
*/
Fx.CSS = new Class({
Extends: Fx,
//prepares the base from/to object
prepare: function(element, property, values){
values = $splat(values);
var values1 = values[1];
if (!$chk(values1)){
values[1] = values[0];
values[0] = element.getStyle(property);
}
var parsed = values.map(this.parse);
return {from: parsed[0], to: parsed[1]};
},
//parses a value into an array
parse: function(value){
value = $lambda(value)();
value = (typeof value == 'string') ? value.split(' ') : $splat(value);
return value.map(function(val){
val = String(val);
var found = false;
Fx.CSS.Parsers.each(function(parser, key){
if (found) return;
var parsed = parser.parse(val);
if ($chk(parsed)) found = {'value': parsed, 'parser': parser};
});
found = found || {value: val, parser: Fx.CSS.Parsers.String};
return found;
});
},
//computes by a from and to prepared objects, using their parsers.
compute: function(from, to, delta){
var computed = [];
(Math.min(from.length, to.length)).times(function(i){
computed.push({'value': from[i].parser.compute(from[i].value, to[i].value, delta), 'parser': from[i].parser});
});
computed.$family = {name: 'fx:css:value'};
return computed;
},
//serves the value as settable
serve: function(value, unit){
if ($type(value) != 'fx:css:value') value = this.parse(value);
var returned = [];
value.each(function(bit){
returned = returned.concat(bit.parser.serve(bit.value, unit));
});
return returned;
},
//renders the change to an element
render: function(element, property, value){
element.setStyle(property, this.serve(value, this.options.unit));
},
//searches inside the page css to find the values for a selector
search: function(selector){
var to = {};
Array.each(document.styleSheets, function(sheet, j){
var rules = sheet.rules || sheet.cssRules;
Array.each(rules, function(rule, i){
if (!rule.style || !rule.selectorText || !rule.selectorText.test('^' + selector + '$')) return;
Element.Styles.each(function(value, style){
if (!rule.style[style] || Element.ShortStyles[style]) return;
value = rule.style[style];
to[style] = (value.test(/^rgb/)) ? value.rgbToHex() : value;
});
});
});
return to;
}
});
Fx.CSS.Parsers = new Hash({
Color: {
parse: function(value){
if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);
return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false;
},
compute: function(from, to, delta){
return from.map(function(value, i){
return Math.round(Fx.compute(from[i], to[i], delta));
});
},
serve: function(value){
return value.map(Number);
}
},
Number: {
parse: function(value){
return parseFloat(value);
},
compute: function(from, to, delta){
return Fx.compute(from, to, delta);
},
serve: function(value, unit){
return (unit) ? value + unit : value;
}
},
String: {
parse: $lambda(false),
compute: $arguments(1),
serve: $arguments(0)
}
});
/*
Script: Fx.Tween.js
Formerly Fx.Style, effect to transition any CSS property for an element.
License:
MIT-style license.
*/
Fx.Tween = new Class({
Extends: Fx.CSS,
initialize: function(element, property, options){
this.element = this.pass = $(element);
this.property = property;
arguments.callee.parent(options);
},
set: function(now){
this.render(this.element, this.property, now);
return this;
},
start: function(){
var fromto = Array.slice(arguments);
if (!this.check(fromto)) return this;
var parsed = this.prepare(this.element, this.property, fromto);
return arguments.callee.parent(parsed.from, parsed.to);
}
});
Element.Properties.tween = {
set: function(options){
var tween = this.retrieve('tween');
if (tween) tween.cancel();
return this.store('tween', new Fx.Tween(this, null, $extend({link: 'cancel'}, options)));
},
get: function(property, options){
if (options || !this.retrieve('tween')) this.set('tween', options);
var tween = this.retrieve('tween');
tween.property = property;
return tween;
}
};
Element.implement({
tween: function(property){
var tween = this.get('tween', property);
tween.start.apply(tween, Array.slice(arguments, 1));
return this;
},
fade: function(how){
var fade = this.get('tween', 'opacity');
how = $pick(how, 'toggle');
switch (how){
case 'in': fade.start(1); break;
case 'out': fade.start(0); break;
case 'show': fade.set(1); break;
case 'hide': fade.set(0); break;
case 'toggle': fade.start((function(){
return (this.getStyle('visibility') == 'hidden') ? 1 : 0;
}).bind(this)); break;
default: fade.start.apply(fade, arguments);
}
return this;
},
highlight: function(start, end){
if (!end){
var style = this.getStyle('background-color');
end = (style == 'transparent') ? '#ffffff' : style;
}
this.get('tween', 'background-color').start(start || '#ffff88', end);
return this;
},
effect: function(property, options){
return new Fx.Tween(this, property, options);
}
});
/*
Script: Fx.Morph.js
Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules.
License:
MIT-style license.
*/
Fx.Morph = new Class({
Extends: Fx.CSS,
initialize: function(element, options){
this.element = this.pass = $(element);
arguments.callee.parent(options);
},
set: function(now){
if (typeof now == 'string') now = this.search(now);
for (var p in now) this.render(this.element, p, now[p]);
return this;
},
compute: function(from, to, delta){
var now = {};
for (var p in from) now[p] = arguments.callee.parent(from[p], to[p], delta);
return now;
},
start: function(properties){
if (!this.check(properties)) return this;
if (typeof properties == 'string') properties = this.search(properties);
var from = {}, to = {};
for (var p in properties){
var parsed = this.prepare(this.element, p, properties[p]);
from[p] = parsed.from;
to[p] = parsed.to;
}
return arguments.callee.parent(from, to);
}
});
Element.Properties.morph = {
set: function(options){
var morph = this.retrieve('morph');
if (morph) morph.cancel();
return this.store('morph', new Fx.Morph(this, $extend({link: 'cancel'}, options)));
},
get: function(options){
if (options || !this.retrieve('morph')) this.set('morph', options);
return this.retrieve('morph');
}
};
Element.implement({
morph: function(props){
this.get('morph').start(props);
return this;
},
effects: function(options){
return new Fx.Morph(this, options);
}
});
/*
Script: Fx.Slide.js
Effect to slide an element in and out of view.
License:
MIT-style license.
Note:
Fx.Slide requires an XHTML doctype.
*/
Fx.Slide = new Class({
Extends: Fx,
options: {
mode: 'vertical'
},
initialize: function(element, options){
this.addEvent('onComplete', function(){
this.open = (this.wrapper['offset' + this.layout.capitalize()] != 0);
if (this.open){
this.wrapper.setStyle(this.layout, 'auto');
if (Browser.Engine.webkit419) this.element.dispose().inject(this.wrapper);
}
}, true);
this.element = this.pass = $(element);
arguments.callee.parent(options);
var wrapper = this.element.retrieve('wrapper');
this.wrapper = wrapper || new Element('div', {
styles: $extend(this.element.getStyles('margin', 'position'), {'overflow': 'hidden'})
}).wraps(this.element);
this.element.store('wrapper', this.wrapper).setStyle('margin', 0);
this.now = [];
this.open = true;
},
vertical: function(){
this.margin = 'margin-top';
this.layout = 'height';
this.offset = this.element.offsetHeight;
},
horizontal: function(){
this.margin = 'margin-left';
this.layout = 'width';
this.offset = this.element.offsetWidth;
},
set: function(now){
this.element.setStyle(this.margin, now[0]);
this.wrapper.setStyle(this.layout, now[1]);
return this;
},
compute: function(from, to, delta){
var now = [];
(2).times(function(i){
now[i] = Fx.compute(from[i], to[i], delta);
});
return now;
},
start: function(how, mode){
if (!this.check(how, mode)) return this;
this[mode || this.options.mode]();
var margin = this.element.getStyle(this.margin).toInt();
var layout = this.wrapper.getStyle(this.layout).toInt();
var caseIn = [[margin, layout], [0, this.offset]];
var caseOut = [[margin, layout], [-this.offset, 0]];
var start;
switch(how){
case 'in': start = caseIn; break;
case 'out': start = caseOut; break;
case 'toggle': start = (this.wrapper['offset' + this.layout.capitalize()] == 0) ? caseIn : caseOut;
}
return arguments.callee.parent(start[0], start[1]);
},
slideIn: function(mode){
return this.start('in', mode);
},
slideOut: function(mode){
return this.start('out', mode);
},
hide: function(mode){
this[mode || this.options.mode]();
this.open = false;
return this.set([-this.offset, 0]);
},
show: function(mode){
this[mode || this.options.mode]();
this.open = true;
return this.set([0, this.offset]);
},
toggle: function(mode){
return this.start('toggle', mode);
}
});
Element.Properties.slide = {
set: function(options){
var slide = this.retrieve('slide');
if (slide) slide.cancel();
return this.store('slide', new Fx.Slide(this, $extend({link: 'cancel'}, options)));
},
get: function(options){
if (options || !this.retrieve('slide')) this.set('slide', options);
return this.retrieve('slide');
}
};
Element.implement({
slide: function(how){
how = how || 'toggle';
var slide = this.get('slide');
switch(how){
case 'hide': slide.hide(); break;
case 'show': slide.show(); break;
default: slide.start(how);
}
return this;
}
});
/*
Script: Fx.Scroll.js
Effect to smoothly scroll any element, including the window.
License:
MIT-style license.
Note:
Fx.Scroll requires an XHTML doctype.
*/
Fx.Scroll = new Class({
Extends: Fx,
options: {
offset: {'x': 0, 'y': 0},
wheelStops: true
},
initialize: function(element, options){
this.element = this.pass = $(element);
arguments.callee.parent(options);
var cancel = this.cancel.bind(this, false);
if ($type(this.element) != 'element') this.element = $(this.element.getDocument().body);
var stopper = this.element;
if (this.options.wheelStops){
this.addEvent('onStart', function(){
stopper.addEvent('mousewheel', cancel);
}, true);
this.addEvent('onComplete', function(){
stopper.removeEvent('mousewheel', cancel);
}, true);
}
},
set: function(){
var now = Array.flatten(arguments);
this.element.scrollTo(now[0], now[1]);
},
compute: function(from, to, delta){
var now = [];
(2).times(function(i){
now.push(Fx.compute(from[i], to[i], delta));
});
return now;
},
start: function(x, y){
if (!this.check(x, y)) return this;
var offsetSize = this.element.getSize(), scrollSize = this.element.getScrollSize(), scroll = this.element.getScroll(), values = {'x': x, 'y': y};
for (var z in values){
var max = scrollSize[z] - offsetSize[z];
if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? values[z].limit(0, max) : max;
else values[z] = scroll[z];
values[z] += this.options.offset[z];
}
return arguments.callee.parent([scroll.x, scroll.y], [values.x, values.y]);
},
toTop: function(){
return this.start(false, 0);
},
toLeft: function(){
return this.start(0, false);
},
toRight: function(){
return this.start('right', false);
},
toBottom: function(){
return this.start(false, 'bottom');
},
toElement: function(el){
var position = $(el).getPosition(this.element);
return this.start(position.x, position.y);
}
});
/*
Script: Fx.Transitions.js
Contains a set of advanced transitions to be used with any of the Fx Classes.
License:
MIT-style license.
Credits:
Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools.
*/
(function(){
var old = Fx.prototype.initialize;
Fx.prototype.initialize = function(options){
old.call(this, options);
var trans = this.options.transition;
if (typeof trans == 'string' && (trans = trans.split(':'))){
var base = Fx.Transitions;
base = base[trans[0]] || base[trans[0].capitalize()];
if (trans[1]) base = base['ease' + trans[1].capitalize() + (trans[2] ? trans[2].capitalize() : '')];
this.options.transition = base;
}
};
})();
Fx.Transition = function(transition, params){
params = $splat(params);
return $extend(transition, {
easeIn: function(pos){
return transition(pos, params);
},
easeOut: function(pos){
return 1 - transition(1 - pos, params);
},
easeInOut: function(pos){
return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2;
}
});
};
Fx.Transitions = new Hash({
linear: $arguments(0)
});
Fx.Transitions.extend = function(transitions){
for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
};
Fx.Transitions.extend({
Pow: function(p, x){
return Math.pow(p, x[0] || 6);
},
Expo: function(p){
return Math.pow(2, 8 * (p - 1));
},
Circ: function(p){
return 1 - Math.sin(Math.acos(p));
},
Sine: function(p){
return 1 - Math.sin((1 - p) * Math.PI / 2);
},
Back: function(p, x){
x = x[0] || 1.618;
return Math.pow(p, 2) * ((x + 1) * p - x);
},
Bounce: function(p){
var value;
for (var a = 0, b = 1; 1; a += b, b /= 2){
if (p >= (7 - 4 * a) / 11){
value = - Math.pow((11 - 6 * a - 11 * p) / 4, 2) + b * b;
break;
}
}
return value;
},
Elastic: function(p, x){
return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3);
}
});
['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
Fx.Transitions[transition] = new Fx.Transition(function(p){
return Math.pow(p, [i + 2]);
});
});
/*
Script: Request.js
Powerful all purpose Request Class. Uses XMLHTTPRequest.
License:
MIT-style license.
*/
var Request = new Class({
Implements: [Chain, Events, Options],
options: {/*
onRequest: $empty,
onSuccess: $empty,
onFailure: $empty,
onException: $empty,*/
url: '',
data: '',
headers: {},
async: true,
method: 'post',
link: 'ignore',
isSuccess: null,
emulation: true,
urlEncoded: true,
encoding: 'utf-8',
evalScripts: false,
evalResponse: false
},
getXHR: function(){
return (window.XMLHttpRequest) ? new XMLHttpRequest() : ((window.ActiveXObject) ? new ActiveXObject('Microsoft.XMLHTTP') : false);
},
initialize: function(options){
if (!(this.xhr = this.getXHR())) return;
this.setOptions(options);
this.options.isSuccess = this.options.isSuccess || this.isSuccess;
this.headers = new Hash(this.options.headers).extend({
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
});
},
onStateChange: function(){
if (this.xhr.readyState != 4 || !this.running) return;
this.running = false;
this.status = 0;
$try(function(){
this.status = this.xhr.status;
}, this);
if (this.options.isSuccess.call(this, this.status)){
this.response = {text: this.xhr.responseText, xml: this.xhr.responseXML};
this.success(this.response.text, this.response.xml);
} else {
this.response = {text: null, xml: null};
this.failure();
}
this.xhr.onreadystatechange = $empty;
},
isSuccess: function(){
return ((this.status >= 200) && (this.status < 300));
},
processScripts: function(text){
if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return $exec(text);
return text.stripScripts(this.options.evalScripts);
},
success: function(text, xml){
this.onSuccess(this.processScripts(text), xml);
},
onSuccess: function(){
this.fireEvent('onComplete', arguments).fireEvent('onSuccess', arguments).callChain();
},
failure: function(){
this.onFailure();
},
onFailure: function(){
this.fireEvent('onComplete').fireEvent('onFailure', this.xhr);
},
setHeader: function(name, value){
this.headers.set(name, value);
return this;
},
getHeader: function(name){
return $try(function(){
return this.getResponseHeader(name);
}, this.xhr) || null;
},
check: function(){
if (!this.running) return true;
switch (this.options.link){
case 'cancel': this.cancel(); return true;
case 'chain': this.chain(this.send.bind(this, arguments)); return false;
}
return false;
},
send: function(options){
if (!this.check(options)) return this;
this.running = true;
var type = $type(options);
if (type == 'string' || type == 'element') options = {data: options};
var old = this.options;
options = $extend({data: old.data, url: old.url, method: old.method}, options);
var data = options.data, url = options.url, method = options.method;
switch($type(data)){
case 'element': data = $(data).toQueryString(); break;
case 'object': case 'hash': data = Hash.toQueryString(data);
}
if (this.options.emulation && ['put', 'delete'].contains(method)){
var _method = '_method=' + method;
data = (data) ? _method + '&' + data : _method;
method = 'post';
}
if (this.options.urlEncoded && method == 'post'){
var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
this.headers.set('Content-type', 'application/x-www-form-urlencoded' + encoding);
}
if (data && method == 'get'){
url = url + (url.contains('?') ? '&' : '?') + data;
data = null;
}
this.xhr.open(method.toUpperCase(), url, this.options.async);
this.xhr.onreadystatechange = this.onStateChange.bind(this);
this.headers.each(function(value, key){
try{
this.xhr.setRequestHeader(key, value);
} catch(e){
this.fireEvent('onException', [e, key, value]);
}
}, this);
this.fireEvent('onRequest');
this.xhr.send(data);
if (!this.options.async) this.onStateChange();
return this;
},
cancel: function(){
if (!this.running) return this;
this.running = false;
this.xhr.abort();
this.xhr.onreadystatechange = $empty;
this.xhr = this.getXHR();
this.fireEvent('onCancel');
return this;
}
});
(function(){
var methods = {};
['get', 'post', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){
methods[method] = function(){
var params = Array.link(arguments, {url: String.type, data: $defined});
return this.send($extend(params, {method: method.toLowerCase()}));
};
});
Request.implement(methods);
})();
Element.Properties.send = {
get: function(options){
if (options || !this.retrieve('send')) this.set('send', options);
return this.retrieve('send');
},
set: function(options){
var send = this.retrieve('send');
if (send) send.cancel();
return this.store('send', new Request($extend({
data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action')
}, options)));
}
};
Element.implement({
send: function(url){
var sender = this.get('send');
sender.send({data: this, url: url || sender.options.url});
return this;
}
});
/*
Script: Request.HTML.js
Extends the basic Request Class with additional methods for interacting with HTML responses.
License:
MIT-style license.
*/
Request.HTML = new Class({
Extends: Request,
options: {
update: false,
evalScripts: true,
filter: false
},
processHTML: function(text){
var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
return (match) ? match[1] : text;
},
success: function(text){
var opts = this.options, res = this.response;
res.html = this.processHTML(text).stripScripts(function(script){
res.javascript = script;
});
var node = new Element('div', {html: res.html});
res.elements = node.getElements('*');
res.tree = (opts.filter) ? res.elements.filterBy(opts.filter) : $A(node.childNodes).filter(function(el){
return ($type(el) != 'whitespace');
});
if (opts.update) $(opts.update).empty().adopt(res.tree);
if (opts.evalScripts) $exec(res.javascript);
this.onSuccess(res.tree, res.elements, res.html, res.javascript);
}
});
Element.Properties.load = {
get: function(options){
if (options || !this.retrieve('load')) this.set('load', options);
return this.retrieve('load');
},
set: function(options){
var load = this.retrieve('load');
if (load) load.cancel();
return this.store('load', new Request.HTML($extend({link: 'cancel', update: this, method: 'get'}, options)));
}
};
Element.implement({
load: function(){
this.get('load').send(Array.link(arguments, {data: Object.type, url: String.type}));
return this;
}
});
/*
Script: Request.JSON.js
Extends the basic Request Class with additional methods for sending and receiving JSON data.
License:
MIT-style license.
*/
Request.JSON = new Class({
Extends: Request,
options: {
secure: true
},
initialize: function(options){
arguments.callee.parent(options);
this.headers.extend({'Accept': 'application/json', 'X-Request': 'JSON'});
},
success: function(text){
this.response.json = JSON.decode(text, this.options.secure);
this.onSuccess(this.response.json, text);
}
});
/*
Script: Drag.js
The base Drag Class. Can be used to drag and resize Elements using mouse events.
License:
MIT-style license.
Note:
This Script requires an XHTML doctype.
*/
var Drag = new Class({
Implements: [Events, Options],
options: {/*
onBeforeStart: $empty,
onStart: $empty,
onDrag: $empty,
onCancel: $empty,
onComplete: $empty,*/
snap: 6,
unit: 'px',
grid: false,
limit: false,
handle: false,
modifiers: {x: 'left', y: 'top'}
},
initialize: function(){
var params = Array.link(arguments, {'options': Object.type, 'element': $defined});
this.element = $(params.element);
this.document = this.element.getDocument();
this.setOptions(params.options || {});
var htype = $type(this.options.handle);
this.handles = (htype == 'array' || htype == 'collection') ? $$(this.options.handle) : $(this.options.handle) || this.element;
this.mouse = {'now': {}, 'pos': {}};
this.value = {'start': {}, 'now': {}};
this.selection = (Browser.Engine.trident) ? 'selectstart' : 'mousedown';
this.bound = {
start: this.start.bind(this),
check: this.check.bind(this),
drag: this.drag.bind(this),
stop: this.stop.bind(this),
cancel: this.cancel.bind(this),
eventStop: $lambda(false)
};
this.attach();
},
attach: function(){
this.handles.addEvent('mousedown', this.bound.start);
return this;
},
detach: function(){
this.handles.removeEvent('mousedown', this.bound.start);
return this;
},
start: function(event){
this.fireEvent('onBeforeStart', this.element);
this.mouse.start = event.page;
var limit = this.options.limit;
this.limit = {'x': [], 'y': []};
for (var z in this.options.modifiers){
if (!this.options.modifiers[z]) continue;
this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt();
this.mouse.pos[z] = event.page[z] - this.value.now[z];
if (limit && limit[z]){
for (var i = 2; i--; i){
if ($chk(limit[z][i])) this.limit[z][i] = $lambda(limit[z][i])();
}
}
}
if ($type(this.options.grid) == 'number') this.options.grid = {'x': this.options.grid, 'y': this.options.grid};
this.document.addEvents({mousemove: this.bound.check, mouseup: this.bound.cancel});
this.document.addEvent(this.selection, this.bound.eventStop);
},
check: function(event){
var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));
if (distance > this.options.snap){
this.cancel();
this.document.addEvents({
mousemove: this.bound.drag,
mouseup: this.bound.stop
});
this.fireEvent('onStart', this.element).fireEvent('onSnap', this.element);
}
},
drag: function(event){
this.mouse.now = event.page;
for (var z in this.options.modifiers){
if (!this.options.modifiers[z]) continue;
this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
if (this.options.limit && this.limit[z]){
if ($chk(this.limit[z][1]) && (this.value.now[z] > this.limit[z][1])){
this.value.now[z] = this.limit[z][1];
} else if ($chk(this.limit[z][0]) && (this.value.now[z] < this.limit[z][0])){
this.value.now[z] = this.limit[z][0];
}
}
if (this.options.grid[z]) this.value.now[z] -= (this.value.now[z] % this.options.grid[z]);
this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit);
}
this.fireEvent('onDrag', this.element);
},
cancel: function(event){
this.document.removeEvent('mousemove', this.bound.check);
this.document.removeEvent('mouseup', this.bound.cancel);
if (event){
this.document.removeEvent(this.selection, this.bound.eventStop);
this.fireEvent('onCancel', this.element);
}
},
stop: function(event){
this.document.removeEvent(this.selection, this.bound.eventStop);
this.document.removeEvent('mousemove', this.bound.drag);
this.document.removeEvent('mouseup', this.bound.stop);
if (event) this.fireEvent('onComplete', this.element);
}
});
Element.implement({
makeResizable: function(options){
return new Drag(this, $merge({modifiers: {'x': 'width', 'y': 'height'}}, options));
}
});
/*
Script: Drag.Move.js
A Drag extension that provides support for the constraining of draggables to containers and droppables.
License:
MIT-style license.
Note:
Drag.Move requires an XHTML doctype.
*/
Drag.Move = new Class({
Extends: Drag,
options: {
droppables: [],
container: false
},
initialize: function(element, options){
arguments.callee.parent(element, options);
this.droppables = $$(this.options.droppables);
this.container = $(this.options.container);
var position = (this.element.positioned()) ? this.element.getStyle('position') : 'absolute';
this.element.position(this.element.getRelativePosition()).setStyle('position', position);
},
start: function(event){
if (this.overed){
this.overed.fireEvent('leave', [this.element, this]);
this.overed = null;
}
if (this.container){
var el = this.element, cont = this.container, ccoo = cont.getCoordinates(el.getOffsetParent()), cps = {}, ems = {};
['top', 'right', 'bottom', 'left'].each(function(pad){
cps[pad] = cont.getStyle('padding-' + pad).toInt();
ems[pad] = el.getStyle('margin-' + pad).toInt();
}, this);
var width = el.offsetWidth + ems.left + ems.right, height = el.offsetHeight + ems.top + ems.bottom;
var x = [ccoo.left + cps.left, ccoo.right - cps.right - width];
var y = [ccoo.top + cps.top, ccoo.bottom - cps.bottom - height];
this.options.limit = {x: x, y: y};
}
arguments.callee.parent(event);
},
checkAgainst: function(el){
el = el.getCoordinates();
var now = this.mouse.now;
return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
},
checkDroppables: function(){
var overed = this.droppables.filter(this.checkAgainst, this).getLast();
if (this.overed != overed){
if (this.overed) this.overed.fireEvent('leave', [this.element, this]);
this.overed = overed ? overed.fireEvent('over', [this.element, this]) : null;
}
},
drag: function(event){
arguments.callee.parent(event);
if (this.droppables.length) this.checkDroppables();
},
stop: function(event){
this.checkDroppables();
if (this.overed) this.overed.fireEvent('drop', [this.element, this]);
else this.element.fireEvent('emptydrop', this);
return arguments.callee.parent(event);
}
});
Element.implement({
makeDraggable: function(options){
return new Drag.Move(this, options);
}
});
/*
Script: Selectors.Children.js
Adds the :children selector for selecting ranges of children of an element.
License:
MIT-style license.
*/
Selectors.Pseudo.children = {
parser: function(argument){
argument = (argument) ? argument.match(/^([-+]?\d*)?([\-+:])?([-+]?\d*)?$/) : [null, 0, false, 0];
if (!argument) return false;
argument[1] = parseInt(argument[1]) || 0;
var int1 = parseInt(argument[3]);
argument[3] = ($chk(int1)) ? int1 : 0;
switch (argument[2]){
case '-': case '+': case ':': return {'a': argument[1], 'b': argument[3], 'special': argument[2]};
default: return {'a': argument[1], 'b': 0, 'special': 'index'};
}
},
xpath: function(argument){
var include = '';
var len = 'count(../child::*)';
var a = argument.a + ' + ' + ((argument.a < 0) ? len : 0);
var b = argument.b + ' + ' + ((argument.b < 0) ? len : 0);
var pos = 'position()';
switch (argument.special){
case '-':
b = '((' + a + ' - ' + b + ') mod (' + len + '))';
a += ' + 1';
b += ' + 1';
include = '(' + b + ' < 1 and (' + pos + ' <= ' + a + ' or ' + pos + ' >= (' + b + ' + ' + len + ')' + ')) or (' + pos + ' <= ' + a + ' and ' + pos + ' >= ' + b + ')';
break;
case '+': b = '((' + a + ' + ' + b + ') mod ( ' + len + '))';
case ':':
a += ' + 1';
b += ' + 1';
include = '(' + b + ' < ' + a + ' and (' + pos + ' >= ' + a + ' or ' + pos + ' <= ' + b + ')) or (' + pos + ' >= ' + a + ' and ' + pos + ' <= ' + b + ')';
break;
default: include = (a + ' + 1');
}
return '[' + include + ']';
},
filter: function(argument, Local){
Local.i = Local.i || 0;
Local.all = Local.all || this.parentNode.childNodes;
Local.len = Local.len || Local.all.length;
var i = Local.i;
var len = Local.len;
var all = Local.all;
var include = false;
var a = argument.a + ((argument.a < 0) ? len : 0);
var b = argument.b + ((argument.b < 0) ? len : 0);
switch (argument.special){
case '-':
b = (a - b) % len;
include = (b < 0) ? (i <= a || i >= (b + len)) : (i <= a && i >= b);
break;
case '+': b = (b + a) % len;
case ':': include = (b < a) ? (i >= a || i <= b) : (i >= a && i <= b); break;
default: include = (all[a] == this);
}
Local.i++;
return include;
}
};
/*
Script: Hash.Cookie.js
Class for creating, reading, and deleting Cookies in JSON format.
License:
MIT-style license.
*/
Hash.Cookie = new Class({
Extends: Cookie,
options: {
autoSave: true
},
initialize: function(name, options){
this.parent(name, options);
this.load();
},
save: function(){
var value = JSON.encode(this.hash);
if (value.length > 4096) return false; //cookie would be truncated!
if (value.length == 2) this.erase();
else this.write(value);
return true;
},
load: function(){
this.hash = new Hash(JSON.decode(this.read(), true));
return this;
}
});
(function(){
var methods = {};
Hash.each(Hash.prototype, function(method, name){
methods[name] = function(){
var value = method.apply(this.hash, arguments);
if (this.options.autoSave) this.save();
return value;
};
});
Hash.Cookie.implement(methods);
})();
/*
Script: Sortables.js
Class for creating a drag and drop sorting interface for lists of items.
License:
MIT-style license.
Note:
Sortables requires an XHTML doctype.
*/
var Sortables = new Class({
Implements: [Events, Options],
options: {/*
onSort: $empty,
onStart: $empty,
onComplete: $empty,*/
snap: 4,
handle: false,
revert: false,
constrain: false,
cloneOpacity: 0.7,
elementOpacity: 0.3
},
initialize: function(lists, options){
this.setOptions(options);
this.elements = [];
this.lists = [];
this.idle = true;
this.addLists($$($(lists) || lists));
if (this.options.revert) this.effect = new Fx.Morph(null, $merge({duration: 250, link: 'cancel'}, this.options.revert));
},
attach: function(){
this.addLists(this.lists);
return this;
},
detach: function(){
this.lists = this.removeLists(this.lists);
return this;
},
addItems: function(){
Array.flatten(arguments).each(function(element){
this.elements.push(element);
var start = element.retrieve('sortables:start', this.start.bindWithEvent(this, element));
var insert = element.retrieve('sortables:insert', this.insert.bind(this, element));
(this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent('mousedown', start);
element.addEvent('over', insert);
}, this);
return this;
},
addLists: function(){
Array.flatten(arguments).each(function(list){
this.lists.push(list);
this.addItems(list.getChildren());
list.addEvent('over', list.retrieve('sortables:insert', this.insert.bind(this, [list, 'inside'])));
}, this);
return this;
},
removeItems: function(){
var elements = [];
Array.flatten(arguments).each(function(element){
elements.push(element);
this.elements.remove(element);
var start = element.retrieve('sortables:start');
var insert = element.retrieve('sortables:insert');
(this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start);
element.removeEvent('over', insert);
}, this);
return elements;
},
removeLists: function(){
var lists = [];
Array.flatten(arguments).each(function(list){
lists.push(list);
this.lists.remove(list);
this.removeItems(list.getChildren());
list.removeEvent('over', list.retrieve('sortables:insert'));
}, this);
return lists;
},
getClone: function(element){
return element.clone(true).setStyles({
'margin': '0px',
'position': 'absolute',
'visibility': 'hidden'
}).inject(this.list).position(element.getRelativePosition());
},
getDroppables: function(){
var droppables = this.list.getChildren();
if (!this.options.constrain) droppables = this.lists.concat(droppables).remove(this.list);
return droppables.remove(this.clone).remove(this.element);
},
insert: function(element, where){
if (where) {
this.list = element;
this.drag.droppables = this.getDroppables();
}
where = where || (this.element.getAllPrevious().contains(element) ? 'before' : 'after');
this.element.inject(element, where);
this.fireEvent('onSort', [this.element, this.clone]);
},
start: function(event, element){
if (!this.idle) return;
this.idle = false;
this.element = element;
this.opacity = element.get('opacity');
this.list = element.getParent();
this.clone = this.getClone(element);
this.drag = this.clone.makeDraggable({
snap: this.options.snap,
container: this.options.constrain && this.clone.getParent(),
droppables: this.getDroppables(),
onStart: function(){
event.stop();
this.clone.set('opacity', this.options.cloneOpacity);
this.element.set('opacity', this.options.elementOpacity);
this.fireEvent('onStart', [this.element, this.clone]);
}.bind(this),
onCancel: this.reset.bind(this),
onComplete: this.end.bind(this)
});
this.drag.start(event);
},
end: function(){
this.element.set('opacity', this.opacity);
this.drag.detach();
if (this.effect){
var dim = this.element.getStyles('width', 'height');
var pos = this.clone.computePosition(this.element.getPosition(this.clone.offsetParent), this.clone.getParent().positioned());
this.effect.element = this.clone;
this.effect.start({
'top': pos.top,
'left': pos.left,
'width': dim.width,
'height': dim.height,
'opacity': 0.25
}).chain(this.reset.bind(this));
} else {
this.reset();
}
},
reset: function(){
this.idle = true;
this.clone.destroy();
this.fireEvent('onComplete', this.element);
},
serialize: function(index, modifier){
var serial = this.lists.map(function(list){
return list.getChildren().map(modifier || function(element, index){
return element.get('id');
}, this);
}, this);
if (this.lists.length == 1) index = 0;
return $chk(index) && index >= 0 && index < this.lists.length ? serial[index] : serial;
}
});
/*
Script: Tips.js
Class for creating nice tooltips that follow the mouse cursor when hovering over an element.
License:
MIT-style license.
Note:
Tips requires an XHTML doctype.
*/
var Tips = new Class({
Implements: [Events, Options],
options: {
onShow: function(tip){
tip.setStyle('visibility', 'visible');
},
onHide: function(tip){
tip.setStyle('visibility', 'hidden');
},
maxTitleChars: 30,
showDelay: 100,
hideDelay: 100,
className: 'tool',
offsets: {'x': 16, 'y': 16},
fixed: false
},
initialize: function(elements, options){
this.setOptions(options);
elements = $$(elements);
this.document = (elements.length) ? elements[0].ownerDocument : document;
this.toolTip = new Element('div', {
'class': this.options.className + '-tip',
'styles': {
'position': 'absolute',
'top': '0',
'left': '0',
'visibility': 'hidden'
}
}, this.document).inject(this.document.body);
this.wrapper = new Element('div').inject(this.toolTip);
elements.each(this.build, this);
},
build: function(el){
el.$attributes.myTitle = (el.href && el.get('tag') == 'a') ? el.href.replace('http://', '') : (el.rel || false);
if (el.title){
var dual = el.title.split('::');
if (dual.length > 1){
el.$attributes.myTitle = dual[0].trim();
el.$attributes.myText = dual[1].trim();
} else {
el.$attributes.myText = el.title;
}
el.removeProperty('title');
} else {
el.$attributes.myText = false;
}
if (el.$attributes.myTitle && el.$attributes.myTitle.length > this.options.maxTitleChars)
el.$attributes.myTitle = el.$attributes.myTitle.substr(0, this.options.maxTitleChars - 1) + "&hellip;";
el.addEvent('mouseenter', function(event){
this.start(el);
if (!this.options.fixed) this.locate(event);
else this.position(el);
}.bind(this));
if (!this.options.fixed) el.addEvent('mousemove', this.locate.bind(this));
var end = this.end.bind(this);
el.addEvent('mouseleave', end);
},
start: function(el){
this.wrapper.empty();
if (el.$attributes.myTitle){
this.title = new Element('span').inject(
new Element('div', {'class': this.options.className + '-title'}
).inject(this.wrapper)).set('html', el.$attributes.myTitle);
}
if (el.$attributes.myText){
this.text = new Element('span').inject(
new Element('div', {'class': this.options.className + '-text'}
).inject(this.wrapper)).set('html', el.$attributes.myText);
}
$clear(this.timer);
this.timer = this.show.delay(this.options.showDelay, this);
},
end: function(event){
$clear(this.timer);
this.timer = this.hide.delay(this.options.hideDelay, this);
},
position: function(element){
var pos = element.getPosition();
this.toolTip.setStyles({
'left': pos.x + this.options.offsets.x,
'top': pos.y + this.options.offsets.y
});
},
locate: function(event){
var doc = this.document.getSize();
var scroll = this.document.getScroll();
var tip = {'x': this.toolTip.offsetWidth, 'y': this.toolTip.offsetHeight};
var prop = {'x': 'left', 'y': 'top'};
for (var z in prop){
var pos = event.page[z] + this.options.offsets[z];
if ((pos + tip[z] - scroll[z]) > doc[z]) pos = event.page[z] - this.options.offsets[z] - tip[z];
this.toolTip.setStyle(prop[z], pos);
}
},
show: function(){
if (this.options.timeout) this.timer = this.hide.delay(this.options.timeout, this);
this.fireEvent('onShow', [this.toolTip]);
},
hide: function(){
this.fireEvent('onHide', [this.toolTip]);
}
});
/*
Script: SmoothScroll.js
Class for creating a smooth scrolling effect to all internal links on the page.
License:
MIT-style license.
Note:
SmoothScroll requires an XHTML doctype.
*/
var SmoothScroll = new Class({
Extends: Fx.Scroll,
initialize: function(options, element){
element = $(element);
var doc = element.getDocument(), win = element.getWindow();
arguments.callee.parent(doc, options);
this.links = (this.options.links) ? $$(this.options.links) : $$(doc.links);
var location = win.location.href.match(/^[^#]*/)[0] + '#';
this.links.each(function(link){
if (link.href.indexOf(location) != 0) return;
var anchor = link.href.substr(location.length);
if (anchor && $(anchor)) this.useLink(link, anchor);
}, this);
if (!Browser.Engine.webkit419) this.addEvent('onComplete', function(){
win.location.hash = this.anchor;
}, true);
},
useLink: function(link, anchor){
link.addEvent('click', function(event){
this.anchor = anchor;
this.toElement(anchor);
event.stop();
}.bind(this));
}
});
/*
Script: Slider.js
Class for creating horizontal and vertical slider controls.
License:
MIT-style license.
Note:
Slider requires an XHTML doctype.
*/
var Slider = new Class({
Implements: [Events, Options],
options: {/*
onChange: $empty,
onComplete: $empty,*/
onTick: function(position){
if(this.options.snap) position = this.toPosition(this.step);
this.knob.setStyle(this.property, position);
},
snap: false,
offset: 0,
range: false,
wheel: false,
steps: 100,
mode: 'horizontal'
},
initialize: function(element, knob, options){
this.setOptions(options);
this.element = $(element);
this.knob = $(knob);
this.previousChange = this.previousEnd = this.step = -1;
this.element.addEvent('mousedown', this.clickedElement.bind(this));
if (this.options.wheel) this.element.addEvent('mousewheel', this.scrolledElement.bindWithEvent(this));
var offset, limit = {}, modifiers = {'x': false, 'y': false};
switch (this.options.mode){
case 'vertical':
this.axis = 'y';
this.property = 'top';
offset = 'offsetHeight';
break;
case 'horizontal':
this.axis = 'x';
this.property = 'left';
offset = 'offsetWidth';
}
this.half = this.knob[offset] / 2;
this.full = this.element[offset] - this.knob[offset] + (this.options.offset * 2);
this.min = $chk(this.options.range[0]) ? this.options.range[0] : 0;
this.max = $chk(this.options.range[1]) ? this.options.range[1] : this.options.steps;
this.range = this.max - this.min;
this.steps = this.options.steps || this.full;
this.stepSize = Math.abs(this.range) / this.steps;
this.stepWidth = this.stepSize * this.full / Math.abs(this.range) ;
this.knob.setStyle('position', 'relative').setStyle(this.property, - this.options.offset);
modifiers[this.axis] = this.property;
limit[this.axis] = [- this.options.offset, this.full - this.options.offset];
this.drag = new Drag(this.knob, {
snap: 0,
limit: limit,
modifiers: modifiers,
onDrag: this.draggedKnob.bind(this),
onStart: this.draggedKnob.bind(this),
onComplete: function(){
this.draggedKnob();
this.end();
}.bind(this)
});
if (this.options.snap) {
this.drag.options.grid = Math.ceil(this.stepWidth);
this.drag.options.limit[this.axis][1] = this.full;
}
},
set: function(step){
if (!((this.range > 0) ^ (step < this.min))) step = this.min;
if (!((this.range > 0) ^ (step > this.max))) step = this.max;
this.step = Math.round(step);
this.checkStep();
this.end();
this.fireEvent('onTick', this.toPosition(this.step));
return this;
},
clickedElement: function(event){
var dir = this.range < 0 ? -1 : 1;
var position = event.page[this.axis] - this.element.getRelativePosition()[this.axis] - this.half;
position = position.limit(-this.options.offset, this.full -this.options.offset);
this.step = Math.round(this.min + dir * this.toStep(position));
this.checkStep();
this.end();
this.fireEvent('onTick', position);
},
scrolledElement: function(event){
var mode = (this.options.mode == 'horizontal') ? (event.wheel < 0) : (event.wheel > 0);
this.set(mode ? this.step - this.stepSize : this.step + this.stepSize);
event.stop();
},
draggedKnob: function(){
var dir = this.range < 0 ? -1 : 1;
var position = this.drag.value.now[this.axis];
position = position.limit(-this.options.offset, this.full -this.options.offset);
this.step = Math.round(this.min + dir * this.toStep(position));
this.checkStep();
},
checkStep: function(){
if (this.previousChange != this.step){
this.previousChange = this.step;
this.fireEvent('onChange', this.step);
}
},
end: function(){
if (this.previousEnd !== this.step){
this.previousEnd = this.step;
this.fireEvent('onComplete', this.step + '');
}
},
toStep: function(position){
var step = (position + this.options.offset) * this.stepSize / this.full * this.steps;
return this.options.steps ? Math.round(step -= step % this.stepSize) : step;
},
toPosition: function(step){
return (this.full * Math.abs(this.min - step)) / (this.steps * this.stepSize) - this.options.offset;
}
});
/*
Script: Scroller.js
Class which scrolls the contents of any Element (including the window) when the mouse reaches the Element's boundaries.
License:
MIT-style license.
Note:
Scroller requires an XHTML doctype.
*/
var Scroller = new Class({
Implements: [Events, Options],
options: {
area: 20,
velocity: 1,
onChange: function(x, y){
this.element.scrollTo(x, y);
}
},
initialize: function(element, options){
this.setOptions(options);
this.element = $(element);
this.listener = ($type(this.element) != 'element') ? $(this.element.getDocument().body) : this.element;
this.timer = null;
},
start: function(){
this.coord = this.getCoords.bind(this);
this.listener.addEvent('mousemove', this.coord);
},
stop: function(){
this.listener.removeEvent('mousemove', this.coord);
this.timer = $clear(this.timer);
},
getCoords: function(event){
this.page = (this.listener.get('tag') == 'body') ? event.client : event.page;
if (!this.timer) this.timer = this.scroll.periodical(50, this);
},
scroll: function(){
var size = this.element.getSize(), scroll = this.element.getScroll(), pos = this.element.getPosition(), change = {'x': 0, 'y': 0};
for (var z in this.page){
if (this.page[z] < (this.options.area + pos[z]) && scroll[z] != 0)
change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity;
else if (this.page[z] + this.options.area > (size[z] + pos[z]) && size[z] + size[z] != scroll[z])
change[z] = (this.page[z] - size[z] + this.options.area - pos[z]) * this.options.velocity;
}
if (change.y || change.x) this.fireEvent('onChange', [scroll.x + change.x, scroll.y + change.y]);
}
});
/*
Script: Assets.js
Provides methods to dynamically load JavaScript, CSS, and Image files into the document.
License:
MIT-style license.
*/
var Asset = new Hash({
javascript: function(source, properties){
properties = $extend({
onload: $empty,
document: document,
check: $lambda(true)
}, properties);
var script = new Element('script', {'src': source, 'type': 'text/javascript'});
var load = properties.onload.bind(script), check = properties.check, doc = properties.document;
delete properties.onload; delete properties.check; delete properties.document;
script.addEvents({
load: load,
readystatechange: function(){
if (this.readyState == 'complete') load();
}
}).setProperties(properties);
if (Browser.Engine.webkit419) var checker = (function(){
if (!$try(check)) return;
$clear(checker);
load();
}).periodical(50);
return script.inject(doc.head);
},
css: function(source, properties){
return new Element('link', $merge({
'rel': 'stylesheet', 'media': 'screen', 'type': 'text/css', 'href': source
}, properties)).inject(document.head);
},
image: function(source, properties){
properties = $merge({
'onload': $empty,
'onabort': $empty,
'onerror': $empty
}, properties);
var image = new Image();
var element = $(image) || new Element('img');
['load', 'abort', 'error'].each(function(name){
var type = 'on' + name;
var event = properties[type];
delete properties[type];
image[type] = function(){
if (!image) return;
if (!element.parentNode){
element.width = image.width;
element.height = image.height;
}
image = image.onload = image.onabort = image.onerror = null;
event.delay(1, element, element);
element.fireEvent(name, element, 1);
};
});
image.src = element.src = source;
if (image && image.complete) image.onload.delay(1);
return element.setProperties(properties);
},
images: function(sources, options){
options = $merge({
onComplete: $empty,
onProgress: $empty
}, options);
if (!sources.push) sources = [sources];
var images = [];
var counter = 0;
sources.each(function(source){
var img = new Asset.image(source, {
'onload': function(){
options.onProgress.call(this, counter, sources.indexOf(source));
counter++;
if (counter == sources.length) options.onComplete();
}
});
images.push(img);
});
return new Elements(images);
}
});
/*
Script: Fx.Elements.js
Effect to change any number of CSS properties of any number of Elements.
License:
MIT-style license.
*/
Fx.Elements = new Class({
Extends: Fx.CSS,
initialize: function(elements, options){
this.elements = this.pass = $$(elements);
arguments.callee.parent(options);
},
compute: function(from, to, delta){
var now = {};
for (var i in from){
var iFrom = from[i], iTo = to[i], iNow = now[i] = {};
for (var p in iFrom) iNow[p] = arguments.callee.parent(iFrom[p], iTo[p], delta);
}
return now;
},
set: function(now){
for (var i in now){
var iNow = now[i];
for (var p in iNow) this.render(this.elements[i], p, iNow[p]);
}
return this;
},
start: function(obj){
if (!this.check(obj)) return this;
var from = {}, to = {};
for (var i in obj){
var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {};
for (var p in iProps){
var parsed = this.prepare(this.elements[i], p, iProps[p]);
iFrom[p] = parsed.from;
iTo[p] = parsed.to;
}
}
return arguments.callee.parent(from, to);
}
});
/*
Script: Accordion.js
An Fx.Elements extension which allows you to easily create accordion type controls.
License:
MIT-style license.
Note:
Accordion requires an XHTML doctype.
*/
var Accordion = new Class({
Extends: Fx.Elements,
options: {/*
onActive: $empty,
onBackground: $empty,*/
display: 0,
show: false,
height: true,
width: false,
opacity: true,
fixedHeight: false,
fixedWidth: false,
wait: false,
alwaysHide: false
},
initialize: function(){
var params = Array.link(arguments, {'container': Element.type, 'options': Object.type, 'togglers': $defined, 'elements': $defined});
arguments.callee.parent(params.elements, params.options);
this.togglers = $$(params.togglers);
this.container = $(params.container);
this.previous = -1;
if (this.options.alwaysHide) this.options.wait = true;
if ($chk(this.options.show)){
this.options.display = false;
this.previous = this.options.show;
}
if (this.options.start){
this.options.display = false;
this.options.show = false;
}
this.effects = {};
if (this.options.opacity) this.effects.opacity = 'fullOpacity';
if (this.options.width) this.effects.width = this.options.fixedWidth ? 'fullWidth' : 'offsetWidth';
if (this.options.height) this.effects.height = this.options.fixedHeight ? 'fullHeight' : 'scrollHeight';
for (var i = 0, l = this.togglers.length; i < l; i++) this.addSection(this.togglers[i], this.elements[i]);
this.elements.each(function(el, i){
if (this.options.show === i){
this.fireEvent('onActive', [this.togglers[i], el]);
} else {
for (var fx in this.effects) el.setStyle(fx, 0);
}
}, this);
if ($chk(this.options.display)) this.display(this.options.display);
},
addSection: function(toggler, element, pos){
toggler = $(toggler);
element = $(element);
var test = this.togglers.contains(toggler);
var len = this.togglers.length;
this.togglers.include(toggler);
this.elements.include(element);
if (len && (!test || pos)){
pos = $pick(pos, len - 1);
toggler.inject(this.togglers[pos], 'before');
element.inject(toggler, 'after');
} else if (this.container && !test){
toggler.inject(this.container);
element.inject(this.container);
}
var idx = this.togglers.indexOf(toggler);
toggler.addEvent('click', this.display.bind(this, idx));
if (this.options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'});
if (this.options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'});
element.fullOpacity = 1;
if (this.options.fixedWidth) element.fullWidth = this.options.fixedWidth;
if (this.options.fixedHeight) element.fullHeight = this.options.fixedHeight;
element.setStyle('overflow', 'hidden');
if (!test){
for (var fx in this.effects) element.setStyle(fx, 0);
}
return this;
},
display: function(index){
index = ($type(index) == 'element') ? this.elements.indexOf(index) : index;
if ((this.timer && this.options.wait) || (index === this.previous && !this.options.alwaysHide)) return this;
this.previous = index;
var obj = {};
this.elements.each(function(el, i){
obj[i] = {};
var hide = (i != index) || (this.options.alwaysHide && (el.offsetHeight > 0));
this.fireEvent(hide ? 'onBackground' : 'onActive', [this.togglers[i], el]);
for (var fx in this.effects) obj[i][fx] = hide ? 0 : el[this.effects[fx]];
}, this);
return this.start(obj);
}
});
var isIE5or6, isIE6;
cxlEnv.isIE5or6 = cxlEnv.isIE6 = isIE5or6 = isIE6 = Browser.Engine.trident4;
/*
Script: dbug.js
A wrapper for Firebug console.* statements.
License:
http://clientside.cnet.com/wiki/cnet-libraries#license
*/
var dbug = {
logged: [],	
timers: {},
firebug: false, 
enabled: false, 
log: function() {
dbug.logged.push(arguments);
},
nolog: function(msg) {
dbug.logged.push(arguments);
},
time: function(name){
dbug.timers[name] = new Date().getTime();
},
timeEnd: function(name){
if (dbug.timers[name]) {
var end = new Date().getTime() - dbug.timers[name];
dbug.timers[name] = false;
dbug.log('%s: %s', name, end);
} else dbug.log('no such timer: %s', name);
},
enable: function(silent) { 
if(dbug.firebug) {
try {
dbug.enabled = true;
dbug.log = function(){
(console.debug || console.log).apply(console, arguments);
};
dbug.time = function(){
console.time.apply(console, arguments);
};
dbug.timeEnd = function(){
console.timeEnd.apply(console, arguments);
};
if(!silent) dbug.log('enabling dbug');
for(var i=0;i<dbug.logged.length;i++){ dbug.log.apply(console, dbug.logged[i]); }
dbug.logged=[];
} catch(e) {
dbug.enable.delay(400);
}
}
},
disable: function(){ 
if(dbug.firebug) dbug.enabled = false;
dbug.log = dbug.nolog;
dbug.time = function(){};
dbug.timeEnd = function(){};
},
cookie: function(set){
var value = document.cookie.match('(?:^|;)\\s*jsdebug=([^;]*)');
var debugCookie = value ? unescape(value[1]) : false;
if((debugCookie != 'true' || set) && !set) {
dbug.enable();
dbug.log('setting debugging cookie');
var date = new Date();
date.setTime(date.getTime()+(24*60*60*1000));
document.cookie = 'jsdebug=true;expires='+date.toGMTString()+';path=/;';
} else dbug.disableCookie();
},
disableCookie: function(){
dbug.log('disabling debugging cookie');
document.cookie = 'jsdebug=false;path=/;';
}
};
(function(){
var fb = typeof console != "undefined";
var debugMethods = ['debug','info','warn','error','assert','dir','dirxml'];
var otherMethods = ['trace','group','groupEnd','profile','profileEnd','count'];
function set(methodList, defaultFunction) {
for(var i = 0; i < methodList.length; i++){
dbug[methodList[i]] = (fb && console[methodList[i]])?console[methodList[i]]:defaultFunction;
}
};
set(debugMethods, dbug.log);
set(otherMethods, function(){});
})();
if (typeof console != "undefined" && console.warn){
dbug.firebug = true;
var value = document.cookie.match('(?:^|;)\\s*jsdebug=([^;]*)');
var debugCookie = value ? unescape(value[1]) : false;
if(window.location.href.indexOf("jsdebug=true")>0 || debugCookie=='true') dbug.enable();
if(debugCookie=='true')dbug.log('debugging cookie enabled');
if(window.location.href.indexOf("jsdebugCookie=true")>0){
dbug.cookie();
if(!dbug.enabled)dbug.enable();
}
if(window.location.href.indexOf("jsdebugCookie=false")>0)dbug.disableCookie();
}
/*
Script: Element.Measure.js
Extends the Element native object to include methods useful in measuring dimensions.
License:
http://clientside.cnet.com/wiki/cnet-libraries#license
*/
Element.implement({
expose: function(){
if (this.getStyle('display') != 'none') return $empty;
var before = {};
var styles = { visibility: 'hidden', display: 'block', position:'absolute' };
//use this method instead of getStyles 
$each(styles, function(value, style){
before[style] = this.style[style]||'';
}, this);
//this.getStyles('visibility', 'display', 'position');
this.setStyles(styles);
return (function(){ this.setStyles(before); }).bind(this);
},
getDimensions: function(options) {
options = $merge({computeSize: false},options);
var dim = {};
function getSize(el, options){
return (options.computeSize)?el.getComputedSize(options):el.getSize();
};
if(this.getStyle('display') == 'none'){
var restore = this.expose();
dim = getSize(this, options); //works now, because the display isn't none
restore(); //put it back where it was
} else {
try { //safari sometimes crashes here, so catch it
dim = getSize(this, options);
}catch(e){}
}
return $chk(dim.x)?$extend(dim, {width: dim.x, height: dim.y}):$extend(dim, {x: dim.width, y: dim.height});
},
getComputedSize: function(options){
options = $merge({
styles: ['padding','border'],
plains: {height: ['top','bottom'], width: ['left','right']},
mode: 'both'
}, options);
var size = {width: 0,height: 0};
switch (options.mode){
case 'vertical':
delete size.width;
delete options.plains.width;
break;
case 'horizontal':
delete size.height;
delete options.plains.height;
break;
};
var getStyles = [];
//this function might be useful in other places; perhaps it should be outside this function?
$each(options.plains, function(plain, key){
plain.each(function(edge){
options.styles.each(function(style){
getStyles.push((style=="border")?style+'-'+edge+'-'+'width':style+'-'+edge);
});
});
});
var styles = this.getStyles.apply(this, getStyles);
var subtracted = [];
$each(options.plains, function(plain, key){ //keys: width, height, plains: ['left','right'], ['top','bottom']
size['total'+key.capitalize()] = 0;
size['computed'+key.capitalize()] = 0;
plain.each(function(edge){ //top, left, right, bottom
size['computed'+edge.capitalize()] = 0;
getStyles.each(function(style,i){ //padding, border, etc.
//'padding-left'.test('left') size['totalWidth'] = size['width']+[padding-left]
if(style.test(edge)) {
styles[style] = styles[style].toInt(); //styles['padding-left'] = 5;
if(isNaN(styles[style]))styles[style]=0;
size['total'+key.capitalize()] = size['total'+key.capitalize()]+styles[style];
size['computed'+edge.capitalize()] = size['computed'+edge.capitalize()]+styles[style];
}
//if width != width (so, padding-left, for instance), then subtract that from the total
if(style.test(edge) && key!=style && 
(style.test('border') || style.test('padding')) && !subtracted.contains(style)) {
subtracted.push(style);
size['computed'+key.capitalize()] = size['computed'+key.capitalize()]-styles[style];
}
});
});
});
if($chk(size.width)) {
size.width = size.width+this.offsetWidth+size.computedWidth;
size.totalWidth = size.width + size.totalWidth;
delete size.computedWidth;
}
if($chk(size.height)) {
size.height = size.height+this.offsetHeight+size.computedHeight;
size.totalHeight = size.height + size.totalHeight;
delete size.computedHeight;
}
return $extend(styles, size);
}
});
/*
Script: Element.Shortcuts.js
Extends the Element native object to include some shortcut methods.
License:
http://clientside.cnet.com/wiki/cnet-libraries#license
*/
Element.implement({
isVisible: function() {
return this.getStyle('display') != 'none';
},
toggle: function() {
return this[this.isVisible() ? 'hide' : 'show']();
},
hide: function() {
var d;
try {
//IE fails here if the element is not in the dom
d = this.getStyle('display');
} catch(e){}
this.store('originalDisplay', d||'block'); 
this.setStyle('display','none');
return this;
},
show: function(display) {
original = this.retrieve('originalDisplay')?this.retrieve('originalDisplay'):this.get('originalDisplay');
this.setStyle('display',(display || original || 'block'));
return this;
},
swapClass: function(remove, add) {
return this.removeClass(remove).addClass(add);
},
//TODO
//DO NOT USE THIS METHOD
//it is temporary, as Mootools 1.1 will negate its requirement
fxOpacityOk: function(){
return !Browser.Engine.trident4;
}
});
/*
Script: Fx.Reveal.js
Defines Fx.Reveal, a class that shows and hides elements with a transition.
License:
http://clientside.cnet.com/wiki/cnet-libraries#license
*/
Fx.Reveal = new Class({
Extends: Fx.Morph,
options: {
styles: ['padding','border','margin'],
transitionOpacity: true,
mode:'vertical',
heightOverride: null,
widthOverride: null
},
dissolve: function(){
try {
if(!this.hiding && !this.showing) {
if(this.element.getStyle('display') != 'none'){
this.hiding = true;
this.showing = false;
this.hidden = true;
var startStyles = this.element.getComputedSize({
styles: this.options.styles,
mode: this.options.mode
});
var setToAuto = this.element.style.height === ""||this.element.style.height=="auto";
this.element.setStyle('display', 'block');
if (this.element.fxOpacityOk() && this.options.transitionOpacity) startStyles.opacity = 1;
var zero = {};
$each(startStyles, function(style, name){
zero[name] = [style, 0]; 
}, this);
var overflowBefore = this.element.getStyle('overflow');
this.element.setStyle('overflow', 'hidden');
//put the final fx method at the front of the chain
if (!this.$chain) this.$chain = [];
this.$chain.unshift(function(){
if(this.hidden) {
this.hiding = false;
$each(startStyles, function(style, name) {
startStyles[name] = style;
}, this);
this.element.setStyles($merge({display: 'none', overflow: overflowBefore}, startStyles));
if (setToAuto) this.element.setStyle('height', 'auto');
}
this.callChain();
}.bind(this));
this.start(zero);
} else {
this.callChain.delay(10, this);
this.fireEvent('onComplete', this.element);
}
}
} catch(e) {
this.hiding = false;
this.element.hide();
this.callChain.delay(10, this);
this.fireEvent('onComplete', this.element);
}
return this;
},
reveal: function(){
try {
if(!this.showing && !this.hiding) {
if(this.element.getStyle('display') == "none" || 
this.element.getStyle('visiblity') == "hidden" || 
this.element.getStyle('opacity')==0){
this.showing = true;
this.hiding = false;
this.hidden = false;
//toggle display, but hide it
var before = this.element.getStyles('visibility', 'display', 'position');
this.element.setStyles({
visibility: 'hidden',
display: 'block',
position:'absolute'
});
var setToAuto = this.element.style.height === ""||this.element.style.height=="auto";
//enable opacity effects
if(this.element.fxOpacityOk() && this.options.transitionOpacity) this.element.setStyle('opacity',0);
//create the styles for the opened/visible state
var startStyles = this.element.getComputedSize({
styles: this.options.styles,
mode: this.options.mode
});
//reset the styles back to hidden now
this.element.setStyles(before);
$each(startStyles, function(style, name) {
startStyles[name] = style;
}, this);
//if we're overridding height/width
if($chk(this.options.heightOverride)) startStyles['height'] = this.options.heightOverride.toInt();
if($chk(this.options.widthOverride)) startStyles['width'] = this.options.widthOverride.toInt();
if(this.element.fxOpacityOk() && this.options.transitionOpacity) startStyles.opacity = 1;
//create the zero state for the beginning of the transition
var zero = { 
height: 0,
display: 'block'
};
$each(startStyles, function(style, name){ zero[name] = 0 }, this);
var overflowBefore = this.element.getStyle('overflow');
//set to zero
this.element.setStyles($merge(zero, {overflow: 'hidden'}));
//start the effect
this.start(startStyles);
if (!this.$chain) this.$chain = [];
this.$chain.unshift(function(){
if (!this.options.heightOverride && setToAuto) {
if (["vertical", "both"].contains(this.options.mode)) this.element.setStyle('height', 'auto');
if (["width", "both"].contains(this.options.mode)) this.element.setStyle('width', 'auto');
}
if(!this.hidden) this.showing = false;
this.element.setStyle('overflow', overflowBefore);
this.callChain();
}.bind(this));
} else {
this.callChain();
this.fireEvent('onComplete', this.element);
}
}
} catch(e) {
this.element.setStyles({
display: 'block',
visiblity: 'visible',
opacity: 1
});
this.showing = false;
this.callChain.delay(10, this);
this.fireEvent('onComplete', this.element);
}
return this;
},
toggle: function(){
try {
if(this.element.getStyle('display') == "none" || 
this.element.getStyle('visiblity') == "hidden" || 
this.element.getStyle('opacity')==0){
this.reveal();
} else {
this.dissolve();
}
} catch(e) { this.show(); }
return this;
}
});
Element.Properties.reveal = {
set: function(options){
var reveal = this.retrieve('reveal');
if (reveal) reveal.cancel();
return this.eliminate('reveal').store('reveal:options', $extend({link: 'cancel'}, options));
},
get: function(options){
if (options || !this.retrieve('reveal')){
if (options || !this.retrieve('reveal:options')) this.set('reveal', options);
this.store('reveal', new Fx.Reveal(this, this.retrieve('reveal:options')));
}
return this.retrieve('reveal');
}
};
Element.Properties.dissolve = Element.Properties.reveal;
Element.implement({
reveal: function(options){
this.get('reveal', options).reveal();
return this;
},
dissolve: function(options){
this.get('reveal', options).dissolve();
return this;
}
});
/*
Script: MultipleOpenAccordion.js
Creates a Mootools Fx.Accordion that allows the user to open more than one element.
License:
http://clientside.cnet.com/wiki/cnet-libraries#license
*/
var MultipleOpenAccordion = new Class({
Implements: [Options, Events, Chain],
options: {
togglers: [],
elements: [],
openAll: true,
firstElementsOpen: [0],
fixedHeight: false,
fixedWidth: false,
height: true,
opacity: true,
width: false
//	onActive: $empty,
//	onBackground: $empty
},
togglers: [],
elements: [],
initialize: function(container, options){
this.setOptions(options);
this.container = $(container);
elements = $$(options.elements);
$$(options.togglers).each(function(toggler, idx){
this.addSection(toggler, elements[idx], idx);
}, this);
if (this.togglers.length) {
if (this.options.openAll) this.showAll();
else this.openSections(this.options.firstElementsOpen);
}
},
addSection: function(toggler, element, pos){
toggler = $(toggler);
element = $(element);
var test = this.togglers.contains(toggler);
var len = this.togglers.length;
this.togglers.include(toggler);
this.elements.include(element);
if (len && (!test || pos)){
pos = $pick(pos - 1, len - 1);
toggler.inject(this.elements[pos], 'after');
element.inject(toggler, 'after');
} else if (this.container && !test){
toggler.inject(this.container);
element.inject(this.container);
}
var idx = this.togglers.indexOf(toggler);
toggler.addEvent('click', this.toggleSection.bind(this, idx));
var mode;
if (this.options.height && this.options.width) mode = "both";
else mode = (this.options.height)?"vertical":"horizontal";
element.store('reveal', new Fx.Reveal(element, {
transitionOpacity: this.options.opacity,
mode: mode,
heightOverride: this.options.fixedHeight,
widthOverride: this.options.fixedWidth
}));
return this;
},
onComplete: function(idx, callChain){
this.fireEvent(this.elements[idx].isVisible()?'onActive':'onBackground', [this.togglers[idx], this.elements[idx]]);
this.callChain();
return this;
},
showSection: function(idx, useFx){
alert("showing");
this.toggleSection(idx, useFx, true);
},
hideSection: function(idx, useFx){
this.toggleSection(idx, useFx, false);
},
toggleSection: function(idx, useFx, show, callChain){
var method = show?'reveal':$defined(show)?'dissolve':'toggle';
callChain = $pick(callChain, true);
if($pick(useFx, true)) {
this.elements[idx].retrieve('reveal')[method]().chain(
this.onComplete.bind(this, [idx, callChain])
);
} else {
if (method == "toggle") el.togglek();
else el[method == "reveal"?'show':'hide']();
this.onComplete(idx, callChain);
}
return this;
},
toggleAll: function(useFx, show){
var method = show?'reveal':$chk(show)?'disolve':'toggle';
var last = this.elements.getLast();
this.elements.each(function(el, idx){
this.toggleSection(idx, useFx, show, el == last);
}, this);
return this;
},
toggleSections: function(sections, useFx, show) {
last = sections.getLast();
this.elements.each(function(el,idx){
this.toggleSection(idx, useFx, sections.contains(idx), show, idx == last);
}, this);
return this;
},
openSections: function(sections, useFx){
this.toggleSections(sections, useFx, true);
},
closeSections: function(sections, useFx){
this.toggleSections(sections, useFx, false);
},
showAll: function(useFx){
return this.toggleAll(useFx, true);
},
hideAll: function(useFx){
return this.toggleAll(useFx, false);
}
});
/*
Script: SimpleCarousel.js
Builds a carousel object that manages the basic functions of a generic carousel (a carousel	here being a collection of "slides" that play from one to the next, with a collection of "buttons" that reference each slide).
License:
http://clientside.cnet.com/wiki/cnet-libraries#license
*/
var SimpleCarousel = new Class({
Implements: [Options, Events],
options: {
//	onRotate: $empty,
//	onStop: $empty,
//	onAutoPlay: $empty,
//	onShowSlide: $empty,
slideInterval: 4000,
transitionDuration: 700,
startIndex: 0,
buttonOnClass: "selected",
buttonOffClass: "off",
rotateAction: "none",
rotateActionDuration: 100,
autoplay: true
},
initialize: function(container, slides, buttons, options){
this.container = $(container);
if(this.container.hasClass('hasCarousel')) return false;
this.setOptions(options);
this.container.addClass('hasCarousel');
this.slides = $$(slides);
this.buttons = $$(buttons);
this.createFx();
this.showSlide(this.options.startIndex);
if(this.options.autoplay) this.autoplay();
if(this.options.rotateAction != 'none') this.setupAction(this.options.rotateAction);
return this;
},
toElement: function(){
return this.container;
},
setupAction: function(action) {
this.buttons.each(function(el, idx){
$(el).addEvent(action, function() {
this.slideFx.setOptions(this.slideFx.options, {duration: this.options.rotateActionDuration});
if(this.currentSlide != idx) this.showSlide(idx);
this.stop();
}.bind(this));
}, this);
},
createFx: function(){
if (!this.slideFx) this.slideFx = new Fx.Elements(this.slides, {duration: this.options.transitionDuration});
this.slides.each(function(slide){
slide.setStyle('opacity',0);
});
},
showSlide: function(slideIndex){
var action = {};
this.slides.each(function(slide, index){
if(index == slideIndex && index != this.currentSlide){ //show
$(this.buttons[index]).swapClass(this.options.buttonOffClass, this.options.buttonOnClass);
action[index.toString()] = {
opacity: 1
};
} else {
$(this.buttons[index]).swapClass(this.options.buttonOnClass, this.options.buttonOffClass);
action[index.toString()] = {
opacity:0
};
}
}, this);
this.fireEvent('onShowSlide', slideIndex);
this.currentSlide = slideIndex;
this.slideFx.start(action);
return this;
},
autoplay: function(){
this.slideshowInt = this.rotate.periodical(this.options.slideInterval, this);
this.fireEvent('onAutoPlay');
return this;
},
stop: function(){
$clear(this.slideshowInt);
this.fireEvent('onStop');
return this;
},
rotate: function(){
current = this.currentSlide;
next = (current+1 >= this.slides.length) ? 0 : current+1;
this.showSlide(next);
this.fireEvent('onRotate', next);
return this;
}
});
/*
Script: TipsX3.js
Tooltips, BubbleTips, whatever they are, they will appear on mouseover
License:
MIT-style license.
Credits:
The idea behind Tips.js is based on Bubble Tooltips (<http://web-graphics.com/mtarchive/001717.php>) by Alessandro Fulcitiniti <http://web-graphics.com>
TipsX3.js is based on Tips.js, with slight modifications, by razvan@e-magine.ro
*/
/*
Class: TipsX3
Display a tip on any element with a title and/or href.
Note:
Tips requires an XHTML doctype.
Arguments:
elements - a collection of elements to apply the tooltips to on mouseover.
options - an object. See options Below.
Options:
maxTitleChars - the maximum number of characters to display in the title of the tip. defaults to 30.
onShow - optionally you can alter the default onShow behaviour with this option (like displaying a fade in effect);
onHide - optionally you can alter the default onHide behaviour with this option (like displaying a fade out effect);
showDelay - the delay the onShow method is called. (defaults to 100 ms)
hideDelay - the delay the onHide method is called. (defaults to 100 ms)
className - the prefix for your tooltip classNames. defaults to 'tool'.
the whole tooltip will have as classname: tool-tip
the title will have as classname: tool-title
the text will have as classname: tool-text
offsets - the distance of your tooltip from the mouse. an Object with x/y properties.
fixed - if set to true, the toolTip will not follow the mouse.
loadingText - text to display as a title while loading an AJAX tooltip.
errTitle, errText - text to display when there's a problem with the AJAX request.
Example:
(start code)
<img src="/images/i.png" title="The body of the tooltip is stored in the title" class="toolTipImg"/>
<script>
var myTips = new Tips($$('.toolTipImg'), {
maxTitleChars: 50	//I like my captions a little long
});
</script>
(end)
Note:
The title of the element will always be used as the tooltip body. If you put :: on your title, the text before :: will become the tooltip title.
If you put DOM:someElementID in your title, $('someElementID').innerHTML will be used as your tooltip contents (same syntax as above).
If you put AJAX:http://www.example.com/path/to/ajax_file.php in your title, the response text will be used as tooltip contents (same syntax as above). Either absolute or relative paths are ok.
*/
var TipsX3 = new Class({
options: { // modded for X3
onShow: function(tip){
tip.setStyle('visibility', 'visible');
},
onHide: function(tip){
tip.setStyle('visibility', 'hidden');
},
maxTitleChars: 30,
showDelay: 100,
hideDelay: 100,
className: 'tool',
offsets: {'x': 16, 'y': 16},
fixed: false,
loadingText: 'Loading...',
errTitle: 'Oops..',
errText: 'There was a problem retrieving the tooltip.'
},
initialize: function(elements, options){
this.setOptions(options);
this.toolTip = new Element('div', {
'class': this.options.className + '-tip',
'styles': {
'position': 'absolute',
'top': '0',
'left': '0',
'visibility': 'hidden'
}
}).inject(document.body);
this.wrapper = new Element('div').inject(this.toolTip);
$$(elements).each(this.build, this);
if (this.options.initialize) this.options.initialize.call(this);
},
build: function(el){ // modded for X3
el.$tmp.myTitle = (el.href && el.getTag() == 'a') ? el.href.replace('http://', '') : (el.rel || false);
if (el.title){
// check if we need to extract contents from a DOM element
if (el.title.test('^DOM:', 'i')) {
el.title = $(el.title.split(':')[1].trim()).innerHTML;	
}
// check for an URL to retrieve content from
if (el.title.test('^AJAX:', 'i')) {
el.title = this.options.loadingText + '::' + el.title;
}
var dual = el.title.split('::');
if (dual.length > 1) {
el.$tmp.myTitle = dual[0].trim();
el.$tmp.myText = dual[1].trim();
} else {
el.$tmp.myText = el.title;
}
el.removeAttribute('title');
} else {
el.$tmp.myText = false;
}
if (el.$tmp.myTitle && el.$tmp.myTitle.length > this.options.maxTitleChars) el.$tmp.myTitle = el.$tmp.myTitle.substr(0, this.options.maxTitleChars - 1) + "&hellip;";
el.addEvent('mouseenter', function(event){
this.start(el);
if (!this.options.fixed) this.locate(event);
else this.position(el);
}.bind(this));
if (!this.options.fixed) el.addEvent('mousemove', this.locate.bindWithEvent(this));
var end = this.end.bind(this);
el.addEvent('mouseleave', end);
el.addEvent('trash', end);
},
start: function(el){ // modded for X3
this.wrapper.empty();
// check if we have an AJAX request - if so, show a loading animation and launch the request	
if (el.$tmp.myText && el.$tmp.myText.test('^AJAX:', 'i')) {
//if (this.ajax) this.ajax.cancel();
this.ajax = new Ajax (el.$tmp.myText.replace(/AJAX:/i,''), {
onComplete: function (responseText, responseXML) {
el.title = responseText;
this.build(el);
this.start(el);
}.bind(this),
onFailure: function () {
el.title = this.options.errTitle + '::' + this.options.errText;
this.build(el);
this.start(el);
}.bind(this),
method: 'get'
}).request();	
el.$tmp.myText = '<div class="' + this.options.className + '-loading">&nbsp;</div>';	
}
if (el.$tmp.myTitle){
this.title = new Element('span').inject(
new Element('div', {'class': this.options.className + '-title'}).inject(this.wrapper)
).setHTML(el.$tmp.myTitle);
}
if (el.$tmp.myText){
this.text = new Element('span').inject(
new Element('div', {'class': this.options.className + '-text'}).inject(this.wrapper)
).setHTML(el.$tmp.myText);
}
$clear(this.timer);
this.timer = this.show.delay(this.options.showDelay, this);
},
end: function(event){
$clear(this.timer);
this.timer = this.hide.delay(this.options.hideDelay, this);
},
position: function(element){
var pos = element.getPosition();
this.toolTip.setStyles({
'left': pos.x + this.options.offsets.x,
'top': pos.y + this.options.offsets.y
});
},
locate: function(event){
var win = {'x': window.getWidth(), 'y': window.getHeight()};
var scroll = {'x': window.getScrollLeft(), 'y': window.getScrollTop()};
var tip = {'x': this.toolTip.offsetWidth, 'y': this.toolTip.offsetHeight};
var prop = {'x': 'left', 'y': 'top'};
for (var z in prop){
var pos = event.page[z] + this.options.offsets[z];
if ((pos + tip[z] - scroll[z]) > win[z]) pos = event.page[z] - this.options.offsets[z] - tip[z];
this.toolTip.setStyle(prop[z], pos);
};
},
show: function(){
if (this.options.timeout) this.timer = this.hide.delay(this.options.timeout, this);
this.fireEvent('onShow', [this.toolTip]);
},
hide: function(){
this.fireEvent('onHide', [this.toolTip]);
}
});
TipsX3.implement(new Events, new Options);
// =========================================================================
// Cookie functions
// =========================================================================
/* This function is used to set cookies */
function setCookie(name,value,expires,path,domain,secure) {
document.cookie = name + "=" + escape (value) +
((expires) ? "; expires=" + expires.toGMTString() : "") +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") + ((secure) ? "; secure" : "");
}
/* This function is used to get cookies */
function getCookie(name) {
var prefix = name + "=";
var start = document.cookie.indexOf(prefix);
if (start==-1) {
return null;
}
var end = document.cookie.indexOf(";", start+prefix.length);
if (end==-1) {
end=document.cookie.length;
}
var value=document.cookie.substring(start+prefix.length, end);
return unescape(value);
}
/* This function is used to delete cookies */
function deleteCookie(name,path,domain) {
if (getCookie(name)) {
document.cookie = name + "=" +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
"; expires=Thu, 01-Jan-70 00:00:01 GMT";
}
}
function setMenuCookie(id, context) {
if (cxlEnv)
cxlEnv.previousMenuCookie = getCookie("subMenu");
setCookie("subMenu", id, "", "/");
}
function revertMenuCookie()
{
if (cxlEnv.previousMenuCookie)
setMenuCookie(cxlEnv.previousMenuCookie);
}
/* (c) 2005 CaribMedia
* this module places IFRAME elements behind UL elements
* in order to prevent content to be placed
* on top of the dynamic menus
*/
/*
* @name addMenuEffects
* @description places the IFRAME
* preconditions:
* - there can be only one IFRAME
* - the menu has an id of "nav"
* - the menu is built as a nested list (UL/LI)
* - the script is run in IE
* @author Michiel van der Blonk
* @date Nov 22, 2005
*/
function addMenuEffects(obj, doShim, doHover)
{
var iframeCode = '<iframe class="menushim" src="about:blank" scrolling="no" frameborder="0"></iframe>';
var menus;
if (!obj)
return;
if (doShim)
{
// add an IFRAME to all UL's in the menu,
// this will make IE display the menu on top of all other elements
menus = obj.getElementsByTagName("ul");
for (var i=0; i<menus.length; i++)
{
submenu = menus[i];
submenu.innerHTML=(iframeCode + menus[i].innerHTML);
}
}
if (doHover)
{
// one function to show and hide the submenu
// it also resizes the iframe in the course of it
// this can not be done in the doShim part
// (see above) since natural height is calculated
// during rendering, not during loading of the page
var items = obj.getElementsByTagName("li");
for (i=0; i<items.length; i++)
{
// only act on menus that actually have a submenu
menus = items[i].getElementsByTagName("ul");
if (menus && !menus.length)
continue;
// the mouse over is quite complex
items[i].onmouseenter = function(){
var menus = this.getElementsByTagName("ul");
// apply the hover class
this.addClass('over');
// loop through all visible submenus that need to display
// the iframe, and show it
for (var i=0; i<menus.length; i++)
{
element = menus[i];
// check if there actually is something there
if (!element.firstChild)
continue;
// and of course it should be an iframe
if (!element.firstChild.tagName.toUpperCase()=='IFRAME')
continue;
iframe = element.firstChild;
// if the thing actually has a height use this for the iframe
if (parseInt(element.clientHeight)>0)
// the 1px is a quick fix, it should actually be the border size
// since IE 'forgets' to take the border height into account
iframe.style.height = (parseInt(element.clientHeight)-1) + "px";
}
};
// the mouse out removes the .over class from the list items
items[i].onmouseleave=function(){
this.removeClass(' over');
};
}
}
}
/*
* @name startList
* @description adds the menu effects for several menus
* @author Michiel van der Blonk
* @date Nov 22, 2005
*/
startList = function()
{
// check current environment
var supportsID = (document.getElementById)?true:false;
if (cxlEnv.isIE5or6 && supportsID)
{
var menus = ['dynamicMenu', 'nav', 'subMenu'];
for (n in menus)
{
var menuName = menus[n];
var menu = document.getElementById(menuName);
if (menu)
addMenuEffects(menu, true, true);
}
};
}
/*
* @name addEvent
* @description adds an event handler to an element
* this way multiple functions can be triggered by an event
* @author Michiel van der Blonk
* @date Nov 22, 2005
*/
function addEvent(obj, evType, fn)
{
var ret = false;
// MB:check if fn exists
if (!fn)
return false;
// adds an eventListener for browsers which support it
// Written by Scott Andrew: nice one, Scott
if (obj.addEventListener)
{
obj.addEventListener(evType,fn,true);
ret = true;
}
else
if (obj.attachEvent)
{
var r = obj.attachEvent("on"+evType,fn);
ret = r;
}
return ret;
}
function dragStuff()
{
// if mootools is loaded, use the short version
if (window.MooTools && $chk(Drag))
$$('.drag').makeDraggable();
else
{
if (!window.Drag || !document.getElementById)
return;
draggableItems = ['obj1', 'extra3'];
for (var i=0; i < draggableItems.length; i++) {
var dragger = document.getElementById(draggableItems[i]);
if (dragger) {
dragger.style.position = 'relative';
Drag.init(dragger, null);
}
}
}
}
addEvent(window, "load", startList);
addEvent(window, "load", dragStuff);
addEvent(window, "load", function(){setMenuCookie(-1)});
FlashObject = function(swf, id, w, h, ver, c, wm) {
this.swf = swf;
this.id = id;
this.width = w;
this.height = h;
this.version = ver || 6; // default to 6
this.align = "middle"; // default to middle
this.redirect = "";
this.sq = document.location.search.split("?")[1] || "";
this.altTxt = "Please <a href='http://www.macromedia.com/go/getflashplayer'>upgrade your Flash Player</a>.";
this.bypassTxt = "<p>Already have Flash Player? <a href='?detectflash=false&"+ this.sq +"'>Click here if you have Flash Player "+ this.version +" installed</a>.</p>";
this.params = new Object();
this.variables = new Object();
if (c) this.color = this.addParam('bgcolor', c);
if (wm) this.addParam('wmode', wm);
this.addParam('quality', 'high'); // default to high
this.doDetect = getQueryParamValue('detectflash');
}
FlashObject.prototype.addParam = function(name, value) {
this.params[name] = value;
}
FlashObject.prototype.getParams = function() {
return this.params;
}
FlashObject.prototype.getParam = function(name) {
return this.params[name];
}
FlashObject.prototype.addVariable = function(name, value) {
this.variables[name] = value;
}
FlashObject.prototype.getVariable = function(name) {
return this.variables[name];
}
FlashObject.prototype.getVariables = function() {
return this.variables;
}
FlashObject.prototype.getParamTags = function() {
var paramTags = "";
for (var param in this.getParams()) {
paramTags += '<param name="' + param + '" value="' + this.getParam(param) + '" />';
}
if (paramTags == "") {
paramTags = null;
}
return paramTags;
}
FlashObject.prototype.getHTML = function() {
var flashHTML = "";
if (window.ActiveXObject && navigator.userAgent.indexOf('Mac') == -1) { // PC IE
flashHTML += '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + this.width + '" height="' + this.height + '" id="' + this.id + '" align="' + this.align + '">';
flashHTML += '<param name="movie" value="' + this.swf + '" />';
if (this.getParamTags() != null) {
flashHTML += this.getParamTags();
}
if (this.getVariablePairs() != null) {
flashHTML += '<param name="flashVars" value="' + this.getVariablePairs() + '" />';
}
flashHTML += '</object>';
}
else { // Everyone else
flashHTML += '<embed type="application/x-shockwave-flash" src="' + this.swf + '" width="' + this.width + '" height="' + this.height + '" id="' + this.id + '" align="' + this.align + '"';
for (var param in this.getParams()) {
flashHTML += ' ' + param + '="' + this.getParam(param) + '"';
}
if (this.getVariablePairs() != null) {
flashHTML += ' flashVars="' + this.getVariablePairs() + '"';
}
flashHTML += '></embed>';
}
return flashHTML; 
}
FlashObject.prototype.getVariablePairs = function() {
var variablePairs = new Array();
for (var name in this.getVariables()) {
variablePairs.push(name + "=" + escape(this.getVariable(name)));
}
if (variablePairs.length > 0) {
return variablePairs.join("&");
}
else {
return null;
}
}
FlashObject.prototype.write = function(elementId) {
if(detectFlash(this.version) || this.doDetect=='false') {
if (elementId) {
document.getElementById(elementId).innerHTML = this.getHTML();
} else {
document.write(this.getHTML());
}
} else {
if (this.redirect != "") {
document.location.replace(this.redirect);
} else {
if (elementId) {
document.getElementById(elementId).innerHTML = this.altTxt +""+ this.bypassTxt;
} else {
document.write(this.altTxt +""+ this.bypassTxt);
}
}
} 
}
function getFlashVersion() {
var flashversion = 0;
if (navigator.plugins && navigator.plugins.length) {
var x = navigator.plugins["Shockwave Flash"];
if(x){
if (x.description) {
var y = x.description;
flashversion = y.charAt(y.indexOf('.')-1);
}
}
} else {
result = false;
for(var i = 15; i >= 3 && result != true; i--){
execScript('on error resume next: result = IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash.'+i+'"))','VBScript');
flashversion = i;
}
}
return flashversion;
}
function detectFlash(ver) { 
if (getFlashVersion() >= ver) {
return true;
} else {
return false;
}
}
// get value of querystring param
function getQueryParamValue(param) {
var q = document.location.search;
var detectIndex = q.indexOf(param);
var endIndex = (q.indexOf("&", detectIndex) != -1) ? q.indexOf("&", detectIndex) : q.length;
if(q.length > 1 && detectIndex != -1) {
return q.substring(q.indexOf("=", detectIndex)+1, endIndex);
} else {
return "";
}
}
/* add Array.push if needed */
if(Array.prototype.push == null){
Array.prototype.push = function(item){
this[this.length] = item;
return this.length;
}
}
/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo
* -----------------------------------------------------------
*
* The DHTML Calendar, version 1.0 "It is happening again"
*
* Details and latest version at:
* www.dynarch.com/projects/calendar
*
* This script is developed by Dynarch.com. Visit us at www.dynarch.com.
*
* This script is distributed under the GNU Lesser General Public License.
* Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
*/
// $Id: calendar.js,v 1.51 2005/03/07 16:44:31 mishoo Exp $
/** The Calendar object constructor. */
Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) {
// member variables
this.activeDiv = null;
this.currentDateEl = null;
this.getDateStatus = null;
this.getDateToolTip = null;
this.getDateText = null;
this.timeout = null;
this.onSelected = onSelected || null;
this.onClose = onClose || null;
this.dragging = false;
this.hidden = false;
this.minYear = 1970;
this.maxYear = 2050;
this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"];
this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"];
this.isPopup = true;
this.weekNumbers = true;
this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc.
this.showsOtherMonths = false;
this.dateStr = dateStr;
this.ar_days = null;
this.showsTime = false;
this.time24 = true;
this.yearStep = 2;
this.hiliteToday = true;
this.multiple = null;
// HTML elements
this.table = null;
this.element = null;
this.tbody = null;
this.firstdayname = null;
// Combo boxes
this.monthsCombo = null;
this.yearsCombo = null;
this.hilitedMonth = null;
this.activeMonth = null;
this.hilitedYear = null;
this.activeYear = null;
// Information
this.dateClicked = false;
// one-time initializations
if (typeof Calendar._SDN == "undefined") {
// table of short day names
if (typeof Calendar._SDN_len == "undefined")
Calendar._SDN_len = 3;
var ar = new Array();
for (var i = 8; i > 0;) {
ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len);
}
Calendar._SDN = ar;
// table of short month names
if (typeof Calendar._SMN_len == "undefined")
Calendar._SMN_len = 3;
ar = new Array();
for (var i = 12; i > 0;) {
ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len);
}
Calendar._SMN = ar;
}
};
// ** constants
/// "static", needed for event handlers.
Calendar._C = null;
/// detect a special case of "web browser"
Calendar.is_ie = ( /msie/i.test(navigator.userAgent) &&
!/opera/i.test(navigator.userAgent) );
Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) );
/// detect Opera browser
Calendar.is_opera = /opera/i.test(navigator.userAgent);
/// detect KHTML-based browsers
Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent);
// BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate
// library, at some point.
Calendar.getAbsolutePos = function(el) {
var SL = 0, ST = 0;
var is_div = /^div$/i.test(el.tagName);
if (is_div && el.scrollLeft)
SL = el.scrollLeft;
if (is_div && el.scrollTop)
ST = el.scrollTop;
var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST };
if (el.offsetParent) {
var tmp = this.getAbsolutePos(el.offsetParent);
r.x += tmp.x;
r.y += tmp.y;
}
return r;
};
Calendar.isRelated = function (el, evt) {
var related = evt.relatedTarget;
if (!related) {
var type = evt.type;
if (type == "mouseover") {
related = evt.fromElement;
} else if (type == "mouseout") {
related = evt.toElement;
}
}
while (related) {
if (related == el) {
return true;
}
related = related.parentNode;
}
return false;
};
Calendar.removeClass = function(el, className) {
if (!(el && el.className)) {
return;
}
var cls = el.className.split(" ");
var ar = new Array();
for (var i = cls.length; i > 0;) {
if (cls[--i] != className) {
ar[ar.length] = cls[i];
}
}
el.className = ar.join(" ");
};
Calendar.addClass = function(el, className) {
Calendar.removeClass(el, className);
el.className += " " + className;
};
// FIXME: the following 2 functions totally suck, are useless and should be replaced immediately.
Calendar.getElement = function(ev) {
var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget;
while (f.nodeType != 1 || /^div$/i.test(f.tagName))
f = f.parentNode;
return f;
};
Calendar.getTargetElement = function(ev) {
var f = Calendar.is_ie ? window.event.srcElement : ev.target;
while (f.nodeType != 1)
f = f.parentNode;
return f;
};
Calendar.stopEvent = function(ev) {
ev || (ev = window.event);
if (Calendar.is_ie) {
ev.cancelBubble = true;
ev.returnValue = false;
} else {
ev.preventDefault();
ev.stopPropagation();
}
return false;
};
Calendar.addEvent = function(el, evname, func) {
if (el.attachEvent) { // IE
el.attachEvent("on" + evname, func);
} else if (el.addEventListener) { // Gecko / W3C
el.addEventListener(evname, func, true);
} else {
el["on" + evname] = func;
}
};
Calendar.removeEvent = function(el, evname, func) {
if (el.detachEvent) { // IE
el.detachEvent("on" + evname, func);
} else if (el.removeEventListener) { // Gecko / W3C
el.removeEventListener(evname, func, true);
} else {
el["on" + evname] = null;
}
};
Calendar.createElement = function(type, parent) {
var el = null;
if (document.createElementNS) {
// use the XHTML namespace; IE won't normally get here unless
// _they_ "fix" the DOM2 implementation.
el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
} else {
el = document.createElement(type);
}
if (typeof parent != "undefined") {
parent.appendChild(el);
}
return el;
};
// END: UTILITY FUNCTIONS
// BEGIN: CALENDAR STATIC FUNCTIONS
/** Internal -- adds a set of events to make some element behave like a button. */
Calendar._add_evs = function(el) {
with (Calendar) {
addEvent(el, "mouseover", dayMouseOver);
addEvent(el, "mousedown", dayMouseDown);
addEvent(el, "mouseout", dayMouseOut);
if (is_ie) {
addEvent(el, "dblclick", dayMouseDblClick);
el.setAttribute("unselectable", true);
}
}
};
Calendar.findMonth = function(el) {
if (typeof el.month != "undefined") {
return el;
} else if (typeof el.parentNode.month != "undefined") {
return el.parentNode;
}
return null;
};
Calendar.findYear = function(el) {
if (typeof el.year != "undefined") {
return el;
} else if (typeof el.parentNode.year != "undefined") {
return el.parentNode;
}
return null;
};
Calendar.showMonthsCombo = function () {
var cal = Calendar._C;
if (!cal) {
return false;
}
var cal = cal;
var cd = cal.activeDiv;
var mc = cal.monthsCombo;
if (cal.hilitedMonth) {
Calendar.removeClass(cal.hilitedMonth, "hilite");
}
if (cal.activeMonth) {
Calendar.removeClass(cal.activeMonth, "active");
}
var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];
Calendar.addClass(mon, "active");
cal.activeMonth = mon;
var s = mc.style;
s.display = "block";
if (cd.navtype < 0)
s.left = cd.offsetLeft + "px";
else {
var mcw = mc.offsetWidth;
if (typeof mcw == "undefined")
// Konqueror brain-dead techniques
mcw = 50;
s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px";
}
s.top = (cd.offsetTop + cd.offsetHeight) + "px";
};
Calendar.showYearsCombo = function (fwd) {
var cal = Calendar._C;
if (!cal) {
return false;
}
var cal = cal;
var cd = cal.activeDiv;
var yc = cal.yearsCombo;
if (cal.hilitedYear) {
Calendar.removeClass(cal.hilitedYear, "hilite");
}
if (cal.activeYear) {
Calendar.removeClass(cal.activeYear, "active");
}
cal.activeYear = null;
var Y = cal.date.getFullYear() + (fwd ? 1 : -1);
var yr = yc.firstChild;
var show = false;
for (var i = 12; i > 0; --i) {
if (Y >= cal.minYear && Y <= cal.maxYear) {
yr.innerHTML = Y;
yr.year = Y;
yr.style.display = "block";
show = true;
} else {
yr.style.display = "none";
}
yr = yr.nextSibling;
Y += fwd ? cal.yearStep : -cal.yearStep;
}
if (show) {
var s = yc.style;
s.display = "block";
if (cd.navtype < 0)
s.left = cd.offsetLeft + "px";
else {
var ycw = yc.offsetWidth;
if (typeof ycw == "undefined")
// Konqueror brain-dead techniques
ycw = 50;
s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px";
}
s.top = (cd.offsetTop + cd.offsetHeight) + "px";
}
};
// event handlers
Calendar.tableMouseUp = function(ev) {
var cal = Calendar._C;
if (!cal) {
return false;
}
if (cal.timeout) {
clearTimeout(cal.timeout);
}
var el = cal.activeDiv;
if (!el) {
return false;
}
var target = Calendar.getTargetElement(ev);
ev || (ev = window.event);
Calendar.removeClass(el, "active");
if (target == el || target.parentNode == el) {
Calendar.cellClick(el, ev);
}
var mon = Calendar.findMonth(target);
var date = null;
if (mon) {
date = new Date(cal.date);
if (mon.month != date.getMonth()) {
date.setMonth(mon.month);
cal.setDate(date);
cal.dateClicked = false;
cal.callHandler();
}
} else {
var year = Calendar.findYear(target);
if (year) {
date = new Date(cal.date);
if (year.year != date.getFullYear()) {
date.setFullYear(year.year);
cal.setDate(date);
cal.dateClicked = false;
cal.callHandler();
}
}
}
with (Calendar) {
removeEvent(document, "mouseup", tableMouseUp);
removeEvent(document, "mouseover", tableMouseOver);
removeEvent(document, "mousemove", tableMouseOver);
cal._hideCombos();
_C = null;
return stopEvent(ev);
}
};
Calendar.tableMouseOver = function (ev) {
var cal = Calendar._C;
if (!cal) {
return;
}
var el = cal.activeDiv;
var target = Calendar.getTargetElement(ev);
if (target == el || target.parentNode == el) {
Calendar.addClass(el, "hilite active");
Calendar.addClass(el.parentNode, "rowhilite");
} else {
if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2)))
Calendar.removeClass(el, "active");
Calendar.removeClass(el, "hilite");
Calendar.removeClass(el.parentNode, "rowhilite");
}
ev || (ev = window.event);
if (el.navtype == 50 && target != el) {
var pos = Calendar.getAbsolutePos(el);
var w = el.offsetWidth;
var x = ev.clientX;
var dx;
var decrease = true;
if (x > pos.x + w) {
dx = x - pos.x - w;
decrease = false;
} else
dx = pos.x - x;
if (dx < 0) dx = 0;
var range = el._range;
var current = el._current;
var count = Math.floor(dx / 10) % range.length;
for (var i = range.length; --i >= 0;)
if (range[i] == current)
break;
while (count-- > 0)
if (decrease) {
if (--i < 0)
i = range.length - 1;
} else if ( ++i >= range.length )
i = 0;
var newval = range[i];
el.innerHTML = newval;
cal.onUpdateTime();
}
var mon = Calendar.findMonth(target);
if (mon) {
if (mon.month != cal.date.getMonth()) {
if (cal.hilitedMonth) {
Calendar.removeClass(cal.hilitedMonth, "hilite");
}
Calendar.addClass(mon, "hilite");
cal.hilitedMonth = mon;
} else if (cal.hilitedMonth) {
Calendar.removeClass(cal.hilitedMonth, "hilite");
}
} else {
if (cal.hilitedMonth) {
Calendar.removeClass(cal.hilitedMonth, "hilite");
}
var year = Calendar.findYear(target);
if (year) {
if (year.year != cal.date.getFullYear()) {
if (cal.hilitedYear) {
Calendar.removeClass(cal.hilitedYear, "hilite");
}
Calendar.addClass(year, "hilite");
cal.hilitedYear = year;
} else if (cal.hilitedYear) {
Calendar.removeClass(cal.hilitedYear, "hilite");
}
} else if (cal.hilitedYear) {
Calendar.removeClass(cal.hilitedYear, "hilite");
}
}
return Calendar.stopEvent(ev);
};
Calendar.tableMouseDown = function (ev) {
if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) {
return Calendar.stopEvent(ev);
}
};
Calendar.calDragIt = function (ev) {
var cal = Calendar._C;
if (!(cal && cal.dragging)) {
return false;
}
var posX;
var posY;
if (Calendar.is_ie) {
posY = window.event.clientY + document.body.scrollTop;
posX = window.event.clientX + document.body.scrollLeft;
} else {
posX = ev.pageX;
posY = ev.pageY;
}
cal.hideShowCovered();
var st = cal.element.style;
st.left = (posX - cal.xOffs) + "px";
st.top = (posY - cal.yOffs) + "px";
return Calendar.stopEvent(ev);
};
Calendar.calDragEnd = function (ev) {
var cal = Calendar._C;
if (!cal) {
return false;
}
cal.dragging = false;
with (Calendar) {
removeEvent(document, "mousemove", calDragIt);
removeEvent(document, "mouseup", calDragEnd);
tableMouseUp(ev);
}
cal.hideShowCovered();
};
Calendar.dayMouseDown = function(ev) {
var el = Calendar.getElement(ev);
if (el.disabled) {
return false;
}
var cal = el.calendar;
cal.activeDiv = el;
Calendar._C = cal;
if (el.navtype != 300) with (Calendar) {
if (el.navtype == 50) {
el._current = el.innerHTML;
addEvent(document, "mousemove", tableMouseOver);
} else
addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver);
addClass(el, "hilite active");
addEvent(document, "mouseup", tableMouseUp);
} else if (cal.isPopup) {
cal._dragStart(ev);
}
if (el.navtype == -1 || el.navtype == 1) {
if (cal.timeout) clearTimeout(cal.timeout);
cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250);
} else if (el.navtype == -2 || el.navtype == 2) {
if (cal.timeout) clearTimeout(cal.timeout);
cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250);
} else {
cal.timeout = null;
}
return Calendar.stopEvent(ev);
};
Calendar.dayMouseDblClick = function(ev) {
Calendar.cellClick(Calendar.getElement(ev), ev || window.event);
if (Calendar.is_ie) {
document.selection.empty();
}
};
Calendar.dayMouseOver = function(ev) {
var el = Calendar.getElement(ev);
if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) {
return false;
}
if (el.ttip) {
if (el.ttip.substr(0, 1) == "_") {
el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1);
}
el.calendar.tooltips.innerHTML = el.ttip;
}
if (el.navtype != 300) {
Calendar.addClass(el, "hilite");
if (el.caldate) {
Calendar.addClass(el.parentNode, "rowhilite");
}
}
return Calendar.stopEvent(ev);
};
Calendar.dayMouseOut = function(ev) {
with (Calendar) {
var el = getElement(ev);
if (isRelated(el, ev) || _C || el.disabled)
return false;
removeClass(el, "hilite");
if (el.caldate)
removeClass(el.parentNode, "rowhilite");
if (el.calendar)
el.calendar.tooltips.innerHTML = _TT["SEL_DATE"];
return stopEvent(ev);
}
};
/**
* A generic "click" handler :) handles all types of buttons defined in this
* calendar.
*/
Calendar.cellClick = function(el, ev) {
var cal = el.calendar;
var closing = false;
var newdate = false;
var date = null;
if (typeof el.navtype == "undefined") {
if (cal.currentDateEl) {
Calendar.removeClass(cal.currentDateEl, "selected");
Calendar.addClass(el, "selected");
closing = (cal.currentDateEl == el);
if (!closing) {
cal.currentDateEl = el;
}
}
cal.date.setDateOnly(el.caldate);
date = cal.date;
var other_month = !(cal.dateClicked = !el.otherMonth);
if (!other_month && !cal.currentDateEl)
cal._toggleMultipleDate(new Date(date));
else
newdate = !el.disabled;
// a date was clicked
if (other_month)
cal._init(cal.firstDayOfWeek, date);
} else {
if (el.navtype == 200) {
Calendar.removeClass(el, "hilite");
cal.callCloseHandler();
return;
}
date = new Date(cal.date);
if (el.navtype == 0)
date.setDateOnly(new Date()); // TODAY
// unless "today" was clicked, we assume no date was clicked so
// the selected handler will know not to close the calenar when
// in single-click mode.
// cal.dateClicked = (el.navtype == 0);
cal.dateClicked = false;
var year = date.getFullYear();
var mon = date.getMonth();
function setMonth(m) {
var day = date.getDate();
var max = date.getMonthDays(m);
if (day > max) {
date.setDate(max);
}
date.setMonth(m);
};
switch (el.navtype) {
case 400:
Calendar.removeClass(el, "hilite");
var text = Calendar._TT["ABOUT"];
if (typeof text != "undefined") {
text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : "";
} else {
// FIXME: this should be removed as soon as lang files get updated!
text = "Help and about box text is not translated into this language.\n" +
"If you know this language and you feel generous please update\n" +
"the corresponding file in \"lang\" subdir to match calendar-en.js\n" +
"and send it back to <mihai_bazon@yahoo.com> to get it into the distribution ;-)\n\n" +
"Thank you!\n" +
"http://dynarch.com/mishoo/calendar.epl\n";
}
alert(text);
return;
case -2:
if (year > cal.minYear) {
date.setFullYear(year - 1);
}
break;
case -1:
if (mon > 0) {
setMonth(mon - 1);
} else if (year-- > cal.minYear) {
date.setFullYear(year);
setMonth(11);
}
break;
case 1:
if (mon < 11) {
setMonth(mon + 1);
} else if (year < cal.maxYear) {
date.setFullYear(year + 1);
setMonth(0);
}
break;
case 2:
if (year < cal.maxYear) {
date.setFullYear(year + 1);
}
break;
case 100:
cal.setFirstDayOfWeek(el.fdow);
return;
case 50:
var range = el._range;
var current = el.innerHTML;
for (var i = range.length; --i >= 0;)
if (range[i] == current)
break;
if (ev && ev.shiftKey) {
if (--i < 0)
i = range.length - 1;
} else if ( ++i >= range.length )
i = 0;
var newval = range[i];
el.innerHTML = newval;
cal.onUpdateTime();
return;
case 0:
// TODAY will bring us here
if ((typeof cal.getDateStatus == "function") &&
cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) {
return false;
}
break;
}
if (!date.equalsTo(cal.date)) {
cal.setDate(date);
newdate = true;
} else if (el.navtype == 0)
newdate = closing = true;
}
if (newdate) {
ev && cal.callHandler();
}
if (closing) {
Calendar.removeClass(el, "hilite");
ev && cal.callCloseHandler();
}
};
// END: CALENDAR STATIC FUNCTIONS
// BEGIN: CALENDAR OBJECT FUNCTIONS
/**
* This function creates the calendar inside the given parent. If _par is
* null than it creates a popup calendar inside the BODY element. If _par is
* an element, be it BODY, then it creates a non-popup calendar (still
* hidden). Some properties need to be set before calling this function.
*/
Calendar.prototype.create = function (_par) {
var parent = null;
if (! _par) {
// default parent is the document body, in which case we create
// a popup calendar.
parent = document.getElementsByTagName("body")[0];
this.isPopup = true;
} else {
parent = _par;
this.isPopup = false;
}
this.date = this.dateStr ? new Date(this.dateStr) : new Date();
var table = Calendar.createElement("table");
this.table = table;
table.cellSpacing = 0;
table.cellPadding = 0;
table.calendar = this;
Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown);
var div = Calendar.createElement("div");
this.element = div;
div.className = "calendar";
if (this.isPopup) {
div.style.position = "absolute";
div.style.display = "none";
}
div.appendChild(table);
var thead = Calendar.createElement("thead", table);
var cell = null;
var row = null;
var cal = this;
var hh = function (text, cs, navtype) {
cell = Calendar.createElement("td", row);
cell.colSpan = cs;
cell.className = "button";
if (navtype != 0 && Math.abs(navtype) <= 2)
cell.className += " nav";
Calendar._add_evs(cell);
cell.calendar = cal;
cell.navtype = navtype;
cell.innerHTML = "<div unselectable='on'>" + text + "</div>";
return cell;
};
row = Calendar.createElement("tr", thead);
var title_length = 6;
(this.isPopup) && --title_length;
(this.weekNumbers) && ++title_length;
hh("?", 1, 400).ttip = Calendar._TT["INFO"];
this.title = hh("", title_length, 300);
this.title.className = "title";
if (this.isPopup) {
this.title.ttip = Calendar._TT["DRAG_TO_MOVE"];
this.title.style.cursor = "move";
hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"];
}
row = Calendar.createElement("tr", thead);
row.className = "headrow";
this._nav_py = hh("&#x00ab;", 1, -2);
this._nav_py.ttip = Calendar._TT["PREV_YEAR"];
this._nav_pm = hh("&#x2039;", 1, -1);
this._nav_pm.ttip = Calendar._TT["PREV_MONTH"];
this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0);
this._nav_now.ttip = Calendar._TT["GO_TODAY"];
this._nav_nm = hh("&#x203a;", 1, 1);
this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"];
this._nav_ny = hh("&#x00bb;", 1, 2);
this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"];
// day names
row = Calendar.createElement("tr", thead);
row.className = "daynames";
if (this.weekNumbers) {
cell = Calendar.createElement("td", row);
cell.className = "name wn";
cell.innerHTML = Calendar._TT["WK"];
}
for (var i = 7; i > 0; --i) {
cell = Calendar.createElement("td", row);
if (!i) {
cell.navtype = 100;
cell.calendar = this;
Calendar._add_evs(cell);
}
}
this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild;
this._displayWeekdays();
var tbody = Calendar.createElement("tbody", table);
this.tbody = tbody;
for (i = 6; i > 0; --i) {
row = Calendar.createElement("tr", tbody);
if (this.weekNumbers) {
cell = Calendar.createElement("td", row);
}
for (var j = 7; j > 0; --j) {
cell = Calendar.createElement("td", row);
cell.calendar = this;
Calendar._add_evs(cell);
}
}
if (this.showsTime) {
row = Calendar.createElement("tr", tbody);
row.className = "time";
cell = Calendar.createElement("td", row);
cell.className = "time";
cell.colSpan = 2;
cell.innerHTML = Calendar._TT["TIME"] || "&nbsp;";
cell = Calendar.createElement("td", row);
cell.className = "time";
cell.colSpan = this.weekNumbers ? 4 : 3;
(function(){
function makeTimePart(className, init, range_start, range_end) {
var part = Calendar.createElement("span", cell);
part.className = className;
part.innerHTML = init;
part.calendar = cal;
part.ttip = Calendar._TT["TIME_PART"];
part.navtype = 50;
part._range = [];
if (typeof range_start != "number")
part._range = range_start;
else {
for (var i = range_start; i <= range_end; ++i) {
var txt;
if (i < 10 && range_end >= 10) txt = '0' + i;
else txt = '' + i;
part._range[part._range.length] = txt;
}
}
Calendar._add_evs(part);
return part;
};
var hrs = cal.date.getHours();
var mins = cal.date.getMinutes();
var t12 = !cal.time24;
var pm = (hrs > 12);
if (t12 && pm) hrs -= 12;
var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23);
var span = Calendar.createElement("span", cell);
span.innerHTML = ":";
span.className = "colon";
var M = makeTimePart("minute", mins, 0, 59);
var AP = null;
cell = Calendar.createElement("td", row);
cell.className = "time";
cell.colSpan = 2;
if (t12)
AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]);
else
cell.innerHTML = "&nbsp;";
cal.onSetTime = function() {
var pm, hrs = this.date.getHours(),
mins = this.date.getMinutes();
if (t12) {
pm = (hrs >= 12);
if (pm) hrs -= 12;
if (hrs == 0) hrs = 12;
AP.innerHTML = pm ? "pm" : "am";
}
H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs;
M.innerHTML = (mins < 10) ? ("0" + mins) : mins;
};
cal.onUpdateTime = function() {
var date = this.date;
var h = parseInt(H.innerHTML, 10);
if (t12) {
if (/pm/i.test(AP.innerHTML) && h < 12)
h += 12;
else if (/am/i.test(AP.innerHTML) && h == 12)
h = 0;
}
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
date.setHours(h);
date.setMinutes(parseInt(M.innerHTML, 10));
date.setFullYear(y);
date.setMonth(m);
date.setDate(d);
this.dateClicked = false;
this.callHandler();
};
})();
} else {
this.onSetTime = this.onUpdateTime = function() {};
}
var tfoot = Calendar.createElement("tfoot", table);
row = Calendar.createElement("tr", tfoot);
row.className = "footrow";
cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300);
cell.className = "ttip";
if (this.isPopup) {
cell.ttip = Calendar._TT["DRAG_TO_MOVE"];
cell.style.cursor = "move";
}
this.tooltips = cell;
div = Calendar.createElement("div", this.element);
this.monthsCombo = div;
div.className = "combo";
for (i = 0; i < Calendar._MN.length; ++i) {
var mn = Calendar.createElement("div");
mn.className = Calendar.is_ie ? "label-IEfix" : "label";
mn.month = i;
mn.innerHTML = Calendar._SMN[i];
div.appendChild(mn);
}
div = Calendar.createElement("div", this.element);
this.yearsCombo = div;
div.className = "combo";
for (i = 12; i > 0; --i) {
var yr = Calendar.createElement("div");
yr.className = Calendar.is_ie ? "label-IEfix" : "label";
div.appendChild(yr);
}
this._init(this.firstDayOfWeek, this.date);
parent.appendChild(this.element);
};
/** keyboard navigation, only for popup calendars */
Calendar._keyEvent = function(ev) {
var cal = window._dynarch_popupCalendar;
if (!cal || cal.multiple)
return false;
(Calendar.is_ie) && (ev = window.event);
var act = (Calendar.is_ie || ev.type == "keypress"),
K = ev.keyCode;
if (ev.ctrlKey) {
switch (K) {
case 37: // KEY left
act && Calendar.cellClick(cal._nav_pm);
break;
case 38: // KEY up
act && Calendar.cellClick(cal._nav_py);
break;
case 39: // KEY right
act && Calendar.cellClick(cal._nav_nm);
break;
case 40: // KEY down
act && Calendar.cellClick(cal._nav_ny);
break;
default:
return false;
}
} else switch (K) {
case 32: // KEY space (now)
Calendar.cellClick(cal._nav_now);
break;
case 27: // KEY esc
act && cal.callCloseHandler();
break;
case 37: // KEY left
case 38: // KEY up
case 39: // KEY right
case 40: // KEY down
if (act) {
var prev, x, y, ne, el, step;
prev = K == 37 || K == 38;
step = (K == 37 || K == 39) ? 1 : 7;
function setVars() {
el = cal.currentDateEl;
var p = el.pos;
x = p & 15;
y = p >> 4;
ne = cal.ar_days[y][x];
};setVars();
function prevMonth() {
var date = new Date(cal.date);
date.setDate(date.getDate() - step);
cal.setDate(date);
};
function nextMonth() {
var date = new Date(cal.date);
date.setDate(date.getDate() + step);
cal.setDate(date);
};
while (1) {
switch (K) {
case 37: // KEY left
if (--x >= 0)
ne = cal.ar_days[y][x];
else {
x = 6;
K = 38;
continue;
}
break;
case 38: // KEY up
if (--y >= 0)
ne = cal.ar_days[y][x];
else {
prevMonth();
setVars();
}
break;
case 39: // KEY right
if (++x < 7)
ne = cal.ar_days[y][x];
else {
x = 0;
K = 40;
continue;
}
break;
case 40: // KEY down
if (++y < cal.ar_days.length)
ne = cal.ar_days[y][x];
else {
nextMonth();
setVars();
}
break;
}
break;
}
if (ne) {
if (!ne.disabled)
Calendar.cellClick(ne);
else if (prev)
prevMonth();
else
nextMonth();
}
}
break;
case 13: // KEY enter
if (act)
Calendar.cellClick(cal.currentDateEl, ev);
break;
default:
return false;
}
return Calendar.stopEvent(ev);
};
/**
* (RE)Initializes the calendar to the given date and firstDayOfWeek
*/
Calendar.prototype._init = function (firstDayOfWeek, date) {
var today = new Date(),
TY = today.getFullYear(),
TM = today.getMonth(),
TD = today.getDate();
this.table.style.visibility = "hidden";
var year = date.getFullYear();
if (year < this.minYear) {
year = this.minYear;
date.setFullYear(year);
} else if (year > this.maxYear) {
year = this.maxYear;
date.setFullYear(year);
}
this.firstDayOfWeek = firstDayOfWeek;
this.date = new Date(date);
var month = date.getMonth();
var mday = date.getDate();
var no_days = date.getMonthDays();
// calendar voodoo for computing the first day that would actually be
// displayed in the calendar, even if it's from the previous month.
// WARNING: this is magic. ;-)
date.setDate(1);
var day1 = (date.getDay() - this.firstDayOfWeek) % 7;
if (day1 < 0)
day1 += 7;
date.setDate(-day1);
date.setDate(date.getDate() + 1);
var row = this.tbody.firstChild;
var MN = Calendar._SMN[month];
var ar_days = this.ar_days = new Array();
var weekend = Calendar._TT["WEEKEND"];
var dates = this.multiple ? (this.datesCells = {}) : null;
for (var i = 0; i < 6; ++i, row = row.nextSibling) {
var cell = row.firstChild;
if (this.weekNumbers) {
cell.className = "day wn";
cell.innerHTML = date.getWeekNumber();
cell = cell.nextSibling;
}
row.className = "daysrow";
var hasdays = false, iday, dpos = ar_days[i] = [];
for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) {
iday = date.getDate();
var wday = date.getDay();
cell.className = "day";
cell.pos = i << 4 | j;
dpos[j] = cell;
var current_month = (date.getMonth() == month);
if (!current_month) {
if (this.showsOtherMonths) {
cell.className += " othermonth";
cell.otherMonth = true;
} else {
cell.className = "emptycell";
cell.innerHTML = "&nbsp;";
cell.disabled = true;
continue;
}
} else {
cell.otherMonth = false;
hasdays = true;
}
cell.disabled = false;
cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday;
if (dates)
dates[date.print("%Y%m%d")] = cell;
if (this.getDateStatus) {
var status = this.getDateStatus(date, year, month, iday);
if (this.getDateToolTip) {
var toolTip = this.getDateToolTip(date, year, month, iday);
if (toolTip)
cell.title = toolTip;
}
if (status === true) {
cell.className += " disabled";
cell.disabled = true;
} else {
if (/disabled/i.test(status))
cell.disabled = true;
cell.className += " " + status;
}
}
if (!cell.disabled) {
cell.caldate = new Date(date);
cell.ttip = "_";
if (!this.multiple && current_month
&& iday == mday && this.hiliteToday) {
cell.className += " selected";
this.currentDateEl = cell;
}
if (date.getFullYear() == TY &&
date.getMonth() == TM &&
iday == TD) {
cell.className += " today";
cell.ttip += Calendar._TT["PART_TODAY"];
}
if (weekend.indexOf(wday.toString()) != -1)
cell.className += cell.otherMonth ? " oweekend" : " weekend";
}
}
if (!(hasdays || this.showsOtherMonths))
row.className = "emptyrow";
}
this.title.innerHTML = Calendar._MN[month] + ", " + year;
this.onSetTime();
this.table.style.visibility = "visible";
this._initMultipleDates();
// PROFILE
// this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms";
};
Calendar.prototype._initMultipleDates = function() {
if (this.multiple) {
for (var i in this.multiple) {
var cell = this.datesCells[i];
var d = this.multiple[i];
if (!d)
continue;
if (cell)
cell.className += " selected";
}
}
};
Calendar.prototype._toggleMultipleDate = function(date) {
if (this.multiple) {
var ds = date.print("%Y%m%d");
var cell = this.datesCells[ds];
if (cell) {
var d = this.multiple[ds];
if (!d) {
Calendar.addClass(cell, "selected");
this.multiple[ds] = date;
} else {
Calendar.removeClass(cell, "selected");
delete this.multiple[ds];
}
}
}
};
Calendar.prototype.setDateToolTipHandler = function (unaryFunction) {
this.getDateToolTip = unaryFunction;
};
/**
* Calls _init function above for going to a certain date (but only if the
* date is different than the currently selected one).
*/
Calendar.prototype.setDate = function (date) {
if (!date.equalsTo(this.date)) {
this._init(this.firstDayOfWeek, date);
}
};
/**
* Refreshes the calendar. Useful if the "disabledHandler" function is
* dynamic, meaning that the list of disabled date can change at runtime.
* Just * call this function if you think that the list of disabled dates
* should * change.
*/
Calendar.prototype.refresh = function () {
this._init(this.firstDayOfWeek, this.date);
};
/** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */
Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) {
this._init(firstDayOfWeek, this.date);
this._displayWeekdays();
};
/**
* Allows customization of what dates are enabled. The "unaryFunction"
* parameter must be a function object that receives the date (as a JS Date
* object) and returns a boolean value. If the returned value is true then
* the passed date will be marked as disabled.
*/
Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) {
this.getDateStatus = unaryFunction;
};
/** Customization of allowed year range for the calendar. */
Calendar.prototype.setRange = function (a, z) {
this.minYear = a;
this.maxYear = z;
};
/** Calls the first user handler (selectedHandler). */
Calendar.prototype.callHandler = function () {
if (this.onSelected) {
this.onSelected(this, this.date.print(this.dateFormat));
}
};
/** Calls the second user handler (closeHandler). */
Calendar.prototype.callCloseHandler = function () {
if (this.onClose) {
this.onClose(this);
}
this.hideShowCovered();
};
/** Removes the calendar object from the DOM tree and destroys it. */
Calendar.prototype.destroy = function () {
var el = this.element.parentNode;
el.removeChild(this.element);
Calendar._C = null;
window._dynarch_popupCalendar = null;
};
/**
* Moves the calendar element to a different section in the DOM tree (changes
* its parent).
*/
Calendar.prototype.reparent = function (new_parent) {
var el = this.element;
el.parentNode.removeChild(el);
new_parent.appendChild(el);
};
// This gets called when the user presses a mouse button anywhere in the
// document, if the calendar is shown. If the click was outside the open
// calendar this function closes it.
Calendar._checkCalendar = function(ev) {
var calendar = window._dynarch_popupCalendar;
if (!calendar) {
return false;
}
var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev);
for (; el != null && el != calendar.element; el = el.parentNode);
if (el == null) {
// calls closeHandler which should hide the calendar.
window._dynarch_popupCalendar.callCloseHandler();
return Calendar.stopEvent(ev);
}
};
/** Shows the calendar. */
Calendar.prototype.show = function () {
var rows = this.table.getElementsByTagName("tr");
for (var i = rows.length; i > 0;) {
var row = rows[--i];
Calendar.removeClass(row, "rowhilite");
var cells = row.getElementsByTagName("td");
for (var j = cells.length; j > 0;) {
var cell = cells[--j];
Calendar.removeClass(cell, "hilite");
Calendar.removeClass(cell, "active");
}
}
this.element.style.display = "block";
this.hidden = false;
if (this.isPopup) {
window._dynarch_popupCalendar = this;
Calendar.addEvent(document, "keydown", Calendar._keyEvent);
Calendar.addEvent(document, "keypress", Calendar._keyEvent);
Calendar.addEvent(document, "mousedown", Calendar._checkCalendar);
}
this.hideShowCovered();
};
/**
* Hides the calendar. Also removes any "hilite" from the class of any TD
* element.
*/
Calendar.prototype.hide = function () {
if (this.isPopup) {
Calendar.removeEvent(document, "keydown", Calendar._keyEvent);
Calendar.removeEvent(document, "keypress", Calendar._keyEvent);
Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar);
}
this.element.style.display = "none";
this.hidden = true;
this.hideShowCovered();
};
/**
* Shows the calendar at a given absolute position (beware that, depending on
* the calendar element style -- position property -- this might be relative
* to the parent's containing rectangle).
*/
Calendar.prototype.showAt = function (x, y) {
var s = this.element.style;
s.left = x + "px";
s.top = y + "px";
this.show();
};
/** Shows the calendar near a given element. */
Calendar.prototype.showAtElement = function (el, opts) {
var self = this;
var p = Calendar.getAbsolutePos(el);
if (!opts || typeof opts != "string") {
this.showAt(p.x, p.y + el.offsetHeight);
return true;
}
function fixPosition(box) {
if (box.x < 0)
box.x = 0;
if (box.y < 0)
box.y = 0;
var cp = document.createElement("div");
var s = cp.style;
s.position = "absolute";
s.right = s.bottom = s.width = s.height = "0px";
document.body.appendChild(cp);
var br = Calendar.getAbsolutePos(cp);
document.body.removeChild(cp);
/* MB: fix ie7 calendar */
if (document.body.scrollLeft)
br.x += document.body.scrollLeft;
br.x += window.scrollX;
if (document.body.scrollTop)
br.y += document.body.scrollTop;
br.y += window.scrollY;
var tmp = box.x + box.width - br.x;
if (tmp > 0) box.x -= tmp;
tmp = box.y + box.height - br.y;
if (tmp > 0) box.y -= tmp;
};
this.element.style.display = "block";
Calendar.continuation_for_the_fucking_khtml_browser = function() {
var w = self.element.offsetWidth;
var h = self.element.offsetHeight;
self.element.style.display = "none";
var valign = opts.substr(0, 1);
var halign = "l";
if (opts.length > 1) {
halign = opts.substr(1, 1);
}
// vertical alignment
switch (valign) {
case "T": p.y -= h; break;
case "B": p.y += el.offsetHeight; break;
case "C": p.y += (el.offsetHeight - h) / 2; break;
case "t": p.y += el.offsetHeight - h; break;
case "b": break; // already there
}
// horizontal alignment
switch (halign) {
case "L": p.x -= w; break;
case "R": p.x += el.offsetWidth; break;
case "C": p.x += (el.offsetWidth - w) / 2; break;
case "l": p.x += el.offsetWidth - w; break;
case "r": break; // already there
}
p.width = w;
p.height = h + 40;
self.monthsCombo.style.display = "none";
fixPosition(p);
self.showAt(p.x, p.y);
};
if (Calendar.is_khtml)
setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10);
else
Calendar.continuation_for_the_fucking_khtml_browser();
};
/** Customizes the date format. */
Calendar.prototype.setDateFormat = function (str) {
this.dateFormat = str;
};
/** Customizes the tooltip date format. */
Calendar.prototype.setTtDateFormat = function (str) {
this.ttDateFormat = str;
};
/**
* Tries to identify the date represented in a string. If successful it also
* calls this.setDate which moves the calendar to the given date.
*/
Calendar.prototype.parseDate = function(str, fmt) {
if (!fmt)
fmt = this.dateFormat;
this.setDate(Date.parseDate(str, fmt));
};
Calendar.prototype.hideShowCovered = function () {
if (!Calendar.is_ie && !Calendar.is_opera)
return;
function getVisib(obj){
var value = obj.style.visibility;
if (!value) {
if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C
if (!Calendar.is_khtml)
value = document.defaultView.
getComputedStyle(obj, "").getPropertyValue("visibility");
else
value = '';
} else if (obj.currentStyle) { // IE
value = obj.currentStyle.visibility;
} else
value = '';
}
return value;
};
var tags = new Array("applet", "iframe", "select");
var el = this.element;
var p = Calendar.getAbsolutePos(el);
var EX1 = p.x;
var EX2 = el.offsetWidth + EX1;
var EY1 = p.y;
var EY2 = el.offsetHeight + EY1;
for (var k = tags.length; k > 0; ) {
var ar = document.getElementsByTagName(tags[--k]);
var cc = null;
for (var i = ar.length; i > 0;) {
cc = ar[--i];
p = Calendar.getAbsolutePos(cc);
var CX1 = p.x;
var CX2 = cc.offsetWidth + CX1;
var CY1 = p.y;
var CY2 = cc.offsetHeight + CY1;
if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
if (!cc.__msh_save_visibility) {
cc.__msh_save_visibility = getVisib(cc);
}
cc.style.visibility = cc.__msh_save_visibility;
} else {
if (!cc.__msh_save_visibility) {
cc.__msh_save_visibility = getVisib(cc);
}
cc.style.visibility = "hidden";
}
}
}
};
/** Internal function; it displays the bar with the names of the weekday. */
Calendar.prototype._displayWeekdays = function () {
var fdow = this.firstDayOfWeek;
var cell = this.firstdayname;
var weekend = Calendar._TT["WEEKEND"];
for (var i = 0; i < 7; ++i) {
cell.className = "day name";
var realday = (i + fdow) % 7;
if (i) {
cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]);
cell.navtype = 100;
cell.calendar = this;
cell.fdow = realday;
Calendar._add_evs(cell);
}
if (weekend.indexOf(realday.toString()) != -1) {
Calendar.addClass(cell, "weekend");
}
cell.innerHTML = Calendar._SDN[(i + fdow) % 7];
cell = cell.nextSibling;
}
};
/** Internal function. Hides all combo boxes that might be displayed. */
Calendar.prototype._hideCombos = function () {
this.monthsCombo.style.display = "none";
this.yearsCombo.style.display = "none";
};
/** Internal function. Starts dragging the element. */
Calendar.prototype._dragStart = function (ev) {
if (this.dragging) {
return;
}
this.dragging = true;
var posX;
var posY;
if (Calendar.is_ie) {
posY = window.event.clientY + document.body.scrollTop;
posX = window.event.clientX + document.body.scrollLeft;
} else {
posY = ev.clientY + window.scrollY;
posX = ev.clientX + window.scrollX;
}
var st = this.element.style;
this.xOffs = posX - parseInt(st.left);
this.yOffs = posY - parseInt(st.top);
with (Calendar) {
addEvent(document, "mousemove", calDragIt);
addEvent(document, "mouseup", calDragEnd);
}
};
// BEGIN: DATE OBJECT PATCHES
/** Adds the number of days array to the Date object. */
Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
/** Constants used for time computations */
Date.SECOND = 1000 /* milliseconds */;
Date.MINUTE = 60 * Date.SECOND;
Date.HOUR = 60 * Date.MINUTE;
Date.DAY = 24 * Date.HOUR;
Date.WEEK = 7 * Date.DAY;
Date.parseDate = function(str, fmt) {
var today = new Date();
var y = 0;
var m = -1;
var d = 0;
var a = str.split(/\W+/);
var b = fmt.match(/%./g);
var i = 0, j = 0;
var hr = 0;
var min = 0;
for (i = 0; i < a.length; ++i) {
if (!a[i])
continue;
switch (b[i]) {
case "%d":
case "%e":
d = parseInt(a[i], 10);
break;
case "%m":
m = parseInt(a[i], 10) - 1;
break;
case "%Y":
case "%y":
y = parseInt(a[i], 10);
(y < 100) && (y += (y > 29) ? 1900 : 2000);
break;
case "%b":
case "%B":
for (j = 0; j < 12; ++j) {
if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; }
}
break;
case "%H":
case "%I":
case "%k":
case "%l":
hr = parseInt(a[i], 10);
break;
case "%P":
case "%p":
if (/pm/i.test(a[i]) && hr < 12)
hr += 12;
else if (/am/i.test(a[i]) && hr >= 12)
hr -= 12;
break;
case "%M":
min = parseInt(a[i], 10);
break;
}
}
if (isNaN(y)) y = today.getFullYear();
if (isNaN(m)) m = today.getMonth();
if (isNaN(d)) d = today.getDate();
if (isNaN(hr)) hr = today.getHours();
if (isNaN(min)) min = today.getMinutes();
if (y != 0 && m != -1 && d != 0)
return new Date(y, m, d, hr, min, 0);
y = 0; m = -1; d = 0;
for (i = 0; i < a.length; ++i) {
if (a[i].search(/[a-zA-Z]+/) != -1) {
var t = -1;
for (j = 0; j < 12; ++j) {
if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; }
}
if (t != -1) {
if (m != -1) {
d = m+1;
}
m = t;
}
} else if (parseInt(a[i], 10) <= 12 && m == -1) {
m = a[i]-1;
} else if (parseInt(a[i], 10) > 31 && y == 0) {
y = parseInt(a[i], 10);
(y < 100) && (y += (y > 29) ? 1900 : 2000);
} else if (d == 0) {
d = a[i];
}
}
if (y == 0)
y = today.getFullYear();
if (m != -1 && d != 0)
return new Date(y, m, d, hr, min, 0);
return today;
};
/** Returns the number of days in the current month */
Date.prototype.getMonthDays = function(month) {
var year = this.getFullYear();
if (typeof month == "undefined") {
month = this.getMonth();
}
if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
return 29;
} else {
return Date._MD[month];
}
};
/** Returns the number of day in the year. */
Date.prototype.getDayOfYear = function() {
var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
var time = now - then;
return Math.floor(time / Date.DAY);
};
/** Returns the number of the week in year, as defined in ISO 8601. */
Date.prototype.getWeekNumber = function() {
var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
var DoW = d.getDay();
d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
var ms = d.valueOf(); // GMT
d.setMonth(0);
d.setDate(4); // Thu in Week 1
return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
};
/** Checks date and time equality */
Date.prototype.equalsTo = function(date) {
return ((this.getFullYear() == date.getFullYear()) &&
(this.getMonth() == date.getMonth()) &&
(this.getDate() == date.getDate()) &&
(this.getHours() == date.getHours()) &&
(this.getMinutes() == date.getMinutes()));
};
/** Set only the year, month, date parts (keep existing time) */
Date.prototype.setDateOnly = function(date) {
var tmp = new Date(date);
this.setDate(1);
this.setFullYear(tmp.getFullYear());
this.setMonth(tmp.getMonth());
this.setDate(tmp.getDate());
};
/** Prints the date in a string according to the given format. */
Date.prototype.print = function (str) {
var m = this.getMonth();
var d = this.getDate();
var y = this.getFullYear();
var wn = this.getWeekNumber();
var w = this.getDay();
var s = {};
var hr = this.getHours();
var pm = (hr >= 12);
var ir = (pm) ? (hr - 12) : hr;
var dy = this.getDayOfYear();
if (ir == 0)
ir = 12;
var min = this.getMinutes();
var sec = this.getSeconds();
s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N]
s["%A"] = Calendar._DN[w]; // full weekday name
s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N]
s["%B"] = Calendar._MN[m]; // full month name
// FIXME: %c : preferred date and time representation for the current locale
s["%C"] = 1 + Math.floor(y / 100); // the century number
s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
s["%e"] = d; // the day of the month (range 1 to 31)
// FIXME: %D : american date style: %m/%d/%y
// FIXME: %E, %F, %G, %g, %h (man strftime)
s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
s["%k"] = hr;	// hour, range 0 to 23 (24h format)
s["%l"] = ir;	// hour, range 1 to 12 (12h format)
s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
s["%n"] = "\n";	// a newline character
s["%p"] = pm ? "PM" : "AM";
s["%P"] = pm ? "pm" : "am";
// FIXME: %r : the time in am/pm notation %I:%M:%S %p
// FIXME: %R : the time in 24-hour notation %H:%M
s["%s"] = Math.floor(this.getTime() / 1000);
s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
s["%t"] = "\t";	// a tab character
// FIXME: %T : the time in 24-hour notation (%H:%M:%S)
s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
s["%u"] = w + 1;	// the day of the week (range 1 to 7, 1 = MON)
s["%w"] = w;	// the day of the week (range 0 to 6, 0 = SUN)
// FIXME: %x : preferred date representation for the current locale without the time
// FIXME: %X : preferred time representation for the current locale without the date
s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99)
s["%Y"] = y;	// year with the century
s["%%"] = "%";	// a literal '%' character
var re = /%./g;
if (!Calendar.is_ie5 && !Calendar.is_khtml)
return str.replace(re, function (par) { return s[par] || par; });
var a = str.match(re);
for (var i = 0; i < a.length; i++) {
var tmp = s[a[i]];
if (tmp) {
re = new RegExp(a[i], 'g');
str = str.replace(re, tmp);
}
}
return str;
};
Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear;
Date.prototype.setFullYear = function(y) {
var d = new Date(this);
d.__msh_oldSetFullYear(y);
if (d.getMonth() != this.getMonth())
this.setDate(28);
this.__msh_oldSetFullYear(y);
};
// END: DATE OBJECT PATCHES
// global object that remembers the calendar
window._dynarch_popupCalendar = null;
/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.com/mishoo/
* ---------------------------------------------------------------------------
*
* The DHTML Calendar
*
* Details and latest version at:
* http://dynarch.com/mishoo/calendar.epl
*
* This script is distributed under the GNU Lesser General Public License.
* Read the entire license text here: http://www.gnu.org/licenses/lgpl.html
*
* This file defines helper functions for setting up the calendar. They are
* intended to help non-programmers get a working calendar on their site
* quickly. This script should not be seen as part of the calendar. It just
* shows you what one can do with the calendar, while in the same time
* providing a quick and simple method for setting it up. If you need
* exhaustive customization of the calendar creation process feel free to
* modify this code to suit your needs (this is recommended and much better
* than modifying calendar.js itself).
*/
// $Id: calendar-setup.js,v 1.25 2005/03/07 09:51:33 mishoo Exp $
/**
* This function "patches" an input field (or other element) to use a calendar
* widget for date selection.
*
* The "params" is a single object that can have the following properties:
*
* prop. name | description
* -------------------------------------------------------------------------------------------------
* inputField | the ID of an input field to store the date
* displayArea | the ID of a DIV or other element to show the date
* button | ID of a button or other element that will trigger the calendar
* eventName | event that will trigger the calendar, without the "on" prefix (default: "click")
* ifFormat | date format that will be stored in the input field
* daFormat | the date format that will be used to display the date in displayArea
* singleClick | (true/false) wether the calendar is in single click mode or not (default: true)
* firstDay | numeric: 0 to 6. "0" means display Sunday first, "1" means display Monday first, etc.
* align | alignment (default: "Br"); if you don't know what's this see the calendar documentation
* range | array with 2 elements. Default: [1900, 2999] -- the range of years available
* weekNumbers | (true/false) if it's true (default) the calendar will display week numbers
* flat | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID
* flatCallback | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar)
* disableFunc | function that receives a JS Date object and should return true if that date has to be disabled in the calendar
* onSelect | function that gets called when a date is selected. You don't _have_ to supply this (the default is generally okay)
* onClose | function that gets called when the calendar is closed. [default]
* onUpdate | function that gets called after the date is updated in the input field. Receives a reference to the calendar.
* date | the date that the calendar will be initially displayed to
* showsTime | default: false; if true the calendar will include a time selector
* timeFormat | the time format; can be "12" or "24", default is "12"
* electric | if true (default) then given fields/date areas are updated for each move; otherwise they're updated only on close
* step | configures the step of the years in drop-down boxes; default: 2
* position | configures the calendar absolute position; default: null
* cache | if "true" (but default: "false") it will reuse the same calendar object, where possible
* showOthers | if "true" (but default: "false") it will show days from other months too
*
* None of them is required, they all have default values. However, if you
* pass none of "inputField", "displayArea" or "button" you'll get a warning
* saying "nothing to setup".
*/
Calendar.setup = function (params) {
function param_default(pname, def) { if (typeof params[pname] == "undefined") { params[pname] = def; } };
param_default("inputField", null);
param_default("displayArea", null);
param_default("button", null);
param_default("eventName", "click");
param_default("ifFormat", "%Y/%m/%d");
param_default("daFormat", "%Y/%m/%d");
param_default("singleClick", true);
param_default("disableFunc", null);
param_default("dateStatusFunc", params["disableFunc"]);	// takes precedence if both are defined
param_default("dateText", null);
param_default("firstDay", null);
param_default("align", "Br");
param_default("range", [1900, 2999]);
param_default("weekNumbers", true);
param_default("flat", null);
param_default("flatCallback", null);
param_default("onSelect", null);
param_default("onClose", null);
param_default("onUpdate", null);
param_default("date", null);
param_default("showsTime", false);
param_default("timeFormat", "24");
param_default("electric", true);
param_default("step", 2);
param_default("position", null);
param_default("cache", false);
param_default("showOthers", false);
param_default("multiple", null);
var tmp = ["inputField", "displayArea", "button"];
for (var i in tmp) {
if (typeof params[tmp[i]] == "string") {
params[tmp[i]] = document.getElementById(params[tmp[i]]);
}
}
if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) {
alert("Calendar.setup:\n Nothing to setup (no fields found). Please check your code");
return false;
}
function onSelect(cal) {
var p = cal.params;
var update = (cal.dateClicked || p.electric);
if (update && p.inputField) {
p.inputField.value = cal.date.print(p.ifFormat);
if (typeof p.inputField.onchange == "function")
p.inputField.onchange();
}
if (update && p.displayArea)
p.displayArea.innerHTML = cal.date.print(p.daFormat);
if (update && typeof p.onUpdate == "function")
p.onUpdate(cal);
if (update && p.flat) {
if (typeof p.flatCallback == "function")
p.flatCallback(cal);
}
if (update && p.singleClick && cal.dateClicked)
cal.callCloseHandler();
};
if (params.flat != null) {
if (typeof params.flat == "string")
params.flat = document.getElementById(params.flat);
if (!params.flat) {
alert("Calendar.setup:\n Flat specified but can't find parent.");
return false;
}
var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect);
cal.showsOtherMonths = params.showOthers;
cal.showsTime = params.showsTime;
cal.time24 = (params.timeFormat == "24");
cal.params = params;
cal.weekNumbers = params.weekNumbers;
cal.setRange(params.range[0], params.range[1]);
cal.setDateStatusHandler(params.dateStatusFunc);
cal.getDateText = params.dateText;
if (params.ifFormat) {
cal.setDateFormat(params.ifFormat);
}
if (params.inputField && typeof params.inputField.value == "string") {
cal.parseDate(params.inputField.value);
}
cal.create(params.flat);
cal.show();
return false;
}
var triggerEl = params.button || params.displayArea || params.inputField;
triggerEl["on" + params.eventName] = function() {
var dateEl = params.inputField || params.displayArea;
var dateFmt = params.inputField ? params.ifFormat : params.daFormat;
var mustCreate = false;
var cal = window.calendar;
if (dateEl)
params.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt);
if (!(cal && params.cache)) {
window.calendar = cal = new Calendar(params.firstDay,
params.date,
params.onSelect || onSelect,
params.onClose || function(cal) { cal.hide(); });
cal.showsTime = params.showsTime;
cal.time24 = (params.timeFormat == "24");
cal.weekNumbers = params.weekNumbers;
mustCreate = true;
} else {
if (params.date)
cal.setDate(params.date);
cal.hide();
}
if (params.multiple) {
cal.multiple = {};
for (var i = params.multiple.length; --i >= 0;) {
var d = params.multiple[i];
var ds = d.print("%Y%m%d");
cal.multiple[ds] = d;
}
}
cal.showsOtherMonths = params.showOthers;
cal.yearStep = params.step;
cal.setRange(params.range[0], params.range[1]);
cal.params = params;
cal.setDateStatusHandler(params.dateStatusFunc);
cal.getDateText = params.dateText;
cal.setDateFormat(dateFmt);
if (mustCreate)
cal.create();
cal.refresh();
if (!params.position)
cal.showAtElement(params.button || params.displayArea || params.inputField, params.align);
else
cal.showAt(params.position[0], params.position[1]);
return false;
};
return cal;
};
// ** I18N
// Calendar EN language
// Author: Mihai Bazon, <mihai_bazon@yahoo.com>
// Encoding: any
// Distributed under the same terms as the calendar itself.
// For translators: please use UTF-8 if possible. We strongly believe that
// Unicode is the answer to a real internationalized world. Also please
// include your contact information in the header, as can be seen above.
// full day names
Calendar._DN = new Array
("Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday");
// Please note that the following array of short day names (and the same goes
// for short month names, _SMN) isn't absolutely necessary. We give it here
// for exemplification on how one can customize the short day names, but if
// they are simply the first N letters of the full name you can simply say:
//
// Calendar._SDN_len = N; // short day name length
// Calendar._SMN_len = N; // short month name length
//
// If N = 3 then this is not needed either since we assume a value of 3 if not
// present, to be compatible with translation files that were written before
// this feature.
// short day names
Calendar._SDN = new Array
("Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun");
// First day of the week. "0" means display Sunday first, "1" means display
// Monday first, etc.
Calendar._FD = 0;
// full month names
Calendar._MN = new Array
("January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December");
// short month names
Calendar._SMN = new Array
("Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec");
// tooltips
Calendar._TT = {};
Calendar._TT["INFO"] = "About the calendar";
Calendar._TT["ABOUT"] =
"DHTML Date/Time Selector\n" +
"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
"For latest version visit: http://www.dynarch.com/projects/calendar/\n" +
"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." +
"\n\n" +
"Date selection:\n" +
"- Use the \xab, \xbb buttons to select year\n" +
"- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" +
"- Hold mouse button on any of the above buttons for faster selection.";
Calendar._TT["ABOUT_TIME"] = "\n\n" +
"Time selection:\n" +
"- Click on any of the time parts to increase it\n" +
"- or Shift-click to decrease it\n" +
"- or click and drag for faster selection.";
Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)";
Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)";
Calendar._TT["GO_TODAY"] = "Go Today";
Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)";
Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)";
Calendar._TT["SEL_DATE"] = "Select date";
Calendar._TT["DRAG_TO_MOVE"] = "Drag to move";
Calendar._TT["PART_TODAY"] = " (today)";
// the following is to inform that "%s" is to be the first day of week
// %s will be replaced with the day name.
Calendar._TT["DAY_FIRST"] = "Display %s first";
// This may be locale-dependent. It specifies the week-end days, as an array
// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1
// means Monday, etc.
Calendar._TT["WEEKEND"] = "0,6";
Calendar._TT["CLOSE"] = "Close";
Calendar._TT["TODAY"] = "Today";
Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value";
// date formats
Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e";
Calendar._TT["WK"] = "wk";
Calendar._TT["TIME"] = "Time:";
/* (c) 2005 CaribMedia */
/*
* @name isTag
* @description simply checks if an element is a tag or a text
* IE sees tags+text, FF sees only tags
* @author Michiel van der Blonk
* @date Oct 18, 2005
*/
function isTag(node)
{
return (node.nodeType == 1);
}
/*
* @name fold
* @description folds/unfolds part of a page (tile)
* @param skip - the number of elements to skip after
* - in fact, skip is the Nth child from the parent
* @author Michiel van der Blonk
* @date July 11, 2005
* @updated Oct 18, 2005
*/
function fold(el, skip)
{
// the block to hide should be the first child after
// the show-hide button
var tile, node, parent;
// find the element
parent = el.parentNode;
if (parent.hasChildNodes())
{
// init node
node = parent.childNodes[0];
size = parent.childNodes.length;
nCountElements = 0;
nCountTags = 0;
// if there are any elements, continue
if (size > 0)
{
// loop until bounds
while (nCountTags < skip && nCountElements<size)
{
node = parent.childNodes[nCountElements];
nCountElements++;
// count the tags
if (isTag(node))
nCountTags++;
}
tile = node;
}
else
alert('error: list cannot display');
}
else
alert('error: list cannot display');
// now show/hide the element
var isHidden = false;
if (tile.className)
isHidden = tile.className.match(/hide/)!==null;
if (!isHidden)
{
tile.className += " hide";
el.className += " collapsed";
}
else
{
tile.className = tile.className.replace(" hide","");
el.className = el.className.replace(" collapsed","");
// also for elements with a single class name
tile.className = tile.className.replace("hide","");
el.className = el.className.replace("collapsed","");
}
return false;
}
/*
* @name collapse
* @description collapses all elements in a list by calling fold()
* @author Michiel van der Blonk
* @date Oct 18, 2005
*/
function collapse(listId)
{
var list = document.getElementById(listId);
var foldIcons = list.getElementsByTagName("span");
for (var i=0; i<foldIcons.length; i++)
{
if ( foldIcons[i].className.match(/fold/)!==null )
fold(foldIcons[i], 3);
}
}
/*
* @name expand
* @description expands an item by walking up the tree
* @author Michiel van der Blonk
* @date Oct 18, 2005
*/
function expand(objElement)
{
// THIS IS NOT WORKING YET.
// WE NEED TO ACTUALLY _FOLD_ HERE, SINCE THE + NEEDS TO BE SHOWN
activeElement = objElement;
do
{
if (activeElement.tagName == "UL")
{
tile.className = tile.className.replace(" hide","");
el.className = el.className.replace(" collapsed","");
// also for elements with a single class name
tile.className = tile.className.replace("hide","");
el.className = el.className.replace("collapsed","");
}
activeElement = activeElement.parentNode;
} while (activeElement.tagName!="DIV" && activeElement.tagName!="BODY")
}
/*
* @name showHide
* @description hides an element effectively by adding the 'hide' class
* @precond the class named 'hide' should exist in the css
* @author Michiel van der Blonk
* @date Oct 18, 2005
*/
function showHide(id)
{
var isHidden;
tile = document.getElementById(id);
showHideObject(tile);
}
/*
* @name showHide
* @description hides an element effectively by adding the 'hide' class
* @precond the class named 'hide' should exist in the css
* @author Michiel van der Blonk
* @date Oct 18, 2005
*/
function showHideObject(objElement)
{
var isHidden;
tile = objElement;
// check for existence of tile element
if (!tile)
return;
isHidden = tile.className.match(/hide/)!==null;
if (isHidden)
{
tile.className = tile.className.replace(" hide","");
// also for elements with a single class name
tile.className = tile.className.replace("hide","");
}
else
tile.className += " hide";
}
/*
* @name debug
* @description shows debug info in a 'debug' box in html
* @precond the element named 'debug' should exist in the css
* @author Michiel van der Blonk
* @date Oct 18, 2005
*/
function debug(s)
{
debugBox = document.getElementById('debug');
if (debugBox)
debugBox.innerHTML += s + "<br>";
}
/*
* @name findOwner
* @description finds the parent DIV
* @param evt - the event
* @author PPK (www.quirksmode.org)
* @date Oct 18, 2005
*/
function findOwner(element)
{
node = element;
while (node)
{
if (isTag(node) && node.nodeName == "DIV")
return node;
node = node.parentNode;
}
return null;
}
/*
* @name autoFold
* @description sets a timer to automatically hide the list
* @param selectId - the id of the faux-select
* @param listId - the id of the UL
* @param target - the element that triggered the event
* @param delay - nr of seconds to wait before closing
* @author Michiel van der Blonk
* @date Oct 18, 2005
*/
function autoFold(selectId, listId, target, delay)
{
// prevent bubbles
if (window.event)
window.event.cancelBubble = true;
// if this is not the list return
if (target.id!=listId)
return;
var isHidden;
list = document.getElementById(listId);
selectBox = document.getElementById(selectId);
isListVisible = list.className.match(/hide/)===null;
if (isListVisible)
window.setTimeout("fold(selectBox, 2)", delay*1000);
}
/*
* @name getTarget
* @description cross browser code for finding out an event target
* @param e - the event
* @author Michiel van der Blonk
* @date Oct 18, 2005
*/
function getTarget(e)
{
// in IE the event param is null
if (!e)
var e = window.event;
// IE has srcElement attr
if (e.srcElement)
target = e.srcElement;
// FF/NN has target attr
if (e.target)
target = e.target;
return target;
}
/* this function has been integrated into
initSelectList for performance reasons
it was set to #, which has bad usability
this is a temporary fix, Kia should fix it
*/
function restoreHrefs(selectBox)
{
var links;
var link;
var curLink;
var list = document.getElementById(selectBox);
if (!list)
return false;
links = list.getElementsByTagName("a");
for (var i=0; i<links.length; i++)
{
curLink = links[i];
rel = curLink.getAttribute('rel');
if (!isNaN(rel))
{
var page = "/" + cxlEnv.context + "do/categoryId/@rel/categoryBranchId/@rel/getDocumentList.html";
curLink.href = page.replace(new RegExp('@rel','g'), rel);
}
}
return true;
}
/*
* @name initSelectList
* @param selectId - the id of the faux-select box
* @param listId - the id of the actual list (expanding div)
* @param action - either 'select' (default) or 'submit'
* @param formId - the form that contains the select box
* @param fieldId - the hidden field which is used to submit the value
* @param autoHide - hide the list after 2 seconds
* @param currentNode - display the current node as the selected item
* @param onAction - javascript function string to call in addition to
* standard select/submit actions
* @description initialises a subcategory list box
* @precond the html for the subcat should be in place
* @author Michiel van der Blonk
* @date Oct 18, 2005
*/
function initSelectList(selectId, listId, action, formId, fieldId, autoHide, currentNode, onAction)
{
// set default action
if (!action)
action = 'select';
// get elements
selectBox = document.getElementById(selectId);
list = document.getElementById(listId);
// when someone clicks anywhere on the document
// outside of the list we close it (the list)
// list.onclick = function() {event.cancelBubble = true;return false;}
document.onclick=function(e)
{
// init
t = getTarget(e);
owner = findOwner(t);
// if this element is a child of the list
// then don't close the list
if (owner && owner.id==listId)
return;
// otherwise, if the list is currently open
// then close it now
if (t.id!=listId && t.id!=selectId )
{
if (!list.className.match(/hide/))
fold(selectBox, 2);
}
};
/*
// THIS IS NOT WORKING CORRECTLY YET
// automatically hide after two seconds
if (autoHide)
list.onmouseout = function (e) {
target = getTarget(e);
autoFold(selectId, listId, target, 2);
};
list.onblur = function (e) {
target = getTarget(e);
autoFold(selectId, listId, target, 0);
};
*/
// find the list, collapse all elements
collapse(listId);
// hide the list
fold(selectBox, 2);
try
{
// create select/submit actions for all anchors in the list
var items = list.getElementsByTagName("a");
for (var i=0; i<items.length; i++)
{
var curLink = items[i];
// restore the href
// it was set to #, which has bad usability
// this is a temporary fix, Kia should fix it
rel = curLink.getAttribute('rel');
/* if (!isNaN(rel))
{
var page = "/" + cxlEnv.context + "do/categoryId/@rel/categoryBranchId/@rel/getDocumentList.html";
curLink.href = page.replace(new RegExp('@rel','g'), rel);
}
*/
// define the submitting function
fSubmit = function()
{
selectBox.innerHTML = this.innerHTML;
fold(selectBox, 2);
form = document.getElementById(formId);
field = document.getElementById(fieldId);
field.value = this.getAttribute('rel');
if (onAction !== null) eval(onAction);
form.submit();
return false;
};
// define the select-only function
fSelect = function()
{
selectBox.innerHTML = this.innerHTML;
fold(selectBox, 2);
form = document.getElementById(formId);
field = document.getElementById(fieldId);
field.value = this.getAttribute('rel');
if (onAction !== null) eval(onAction);
return false;
};
// in case of submit attach function
if (action=='submit') {
items[i].onclick= fSubmit;
if (items[i].getAttribute('rel') == currentNode)
{
selectBox.innerHTML = items[i].innerHTML;
activeElement = items[i].parentNode.parentNode;
// expand all UL's up the tree from the current node
//expand(activeElement);
}
}
// in case of select attach function
// and select current node
else
{
items[i].onclick= fSelect;
if (items[i].getAttribute('rel') == currentNode)
{
selectBox.innerHTML = items[i].innerHTML;
activeElement = items[i].parentNode.parentNode;
// expand all UL's up the tree from the current node
//expand(activeElement);
}
}
}
}
catch(e)
{
alert(e);
}
}
// This function sorts the entity lists
function sortBy(theForm, target) {
if (theForm.sortBy.value == target) {
if (theForm.sortDirection.value == 'ASC') {
theForm.sortDirection.value = 'DESC';
} else {
theForm.sortDirection.value = 'ASC';
}
} else {
theForm.sortDirection.value = 'ASC';
}
theForm.sortBy.value=target;
theForm.submit();
return false;
}
function textCounter(field, countfield, maxlimit) {
if (field.value.length > maxlimit)
{
field.value = field.value.substring(0, maxlimit);
field.blur();
field.focus();
return false;
}
else
countfield.value = maxlimit - field.value.length;
return true;
}
function getSelectedRadio(buttonGroup) {
// returns the array number of the selected radio button or -1 if no button is selected
if (buttonGroup[0]) { // if the button group is an array (one button is not an array)
for (var i=0; i<buttonGroup.length; i++) {
if (buttonGroup[i].checked) {
return i;
}
}
} else {
if (buttonGroup.checked) { return 0; } // if the one button is checked, return zero
}
// if we get to this point, no radio button is selected
return -1;
} // Ends the "getSelectedRadio" function
function getSelectedRadioValue(buttonGroup) {
// returns the value of the selected radio button or "" if no button is selected
var i = getSelectedRadio(buttonGroup);
if (i == -1) {
return "";
} else {
if (buttonGroup[i]) { // Make sure the button group is an array (not just one button)
return buttonGroup[i].value;
} else { // The button group is just the one button, and it is checked
return buttonGroup.value;
}
}
} // Ends the "getSelectedRadioValue" function
function getDate(field, format) {
var newDate = new Date();
var day, month, year;
if (format.toLowerCase() == 'yyyy-mm-dd') {
month = field.value.substring(5,7);
if (month.charAt(0) == "0") {
month = month.charAt(1);
}
day = field.value.substring(8,10);
if (day.charAt(0) == "0") {
day = day.charAt(1);
}
newDate.setMonth(parseInt(month)-1);
newDate.setDate(parseInt(day));
newDate.setYear(parseInt(field.value.substring(0,4)));
} else if (format.toLowerCase() == 'mm/dd/yyyy') {
month = field.value.substring(0,2);
if (month.charAt(0) == "0") {
month = month.charAt(1);
}
day = field.value.substring(3,5);
if (day.charAt(0) == "0") {
day = day.charAt(1);
}
newDate.setMonth(parseInt(month)-1);
newDate.setDate(parseInt(day));
newDate.setYear(parseInt(field.value.substring(6,10)));
}
return newDate;
}
// Determines the number of days between two dates.
function daysBetween(date1, date2) {
var diff;
var days;
diff = Math.abs(date1.getTime() - date2.getTime());
days = Math.floor(diff/(1000 * 60 * 60 * 24));
return days;
}
// Accepts a non-negative currency value
function isCurrency(field) {
var result;
var regexp;
result = false;
if (field.value === '' || field.value === null) {
return result;
}
//regexp = new RegExp('^[-]?([1-9]{1}[0-9]{0,}(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|\.[0-9]{1,2})$');
regexp = new RegExp('^([1-9]{1}[0-9]{0,}(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|\.[0-9]{1,2})$');
result = regexp.test(field.value);
return result;
}
function datesEqual(date1,date2) {
var result = date1.getMonth() == date2.getMonth();
result = result && date1.getDate() == date2.getDate();
result = result && date1.getYear() == date2.getYear();
return result;
}
function checkAll(field) {
for(var i = 0; i < field.length; i++)
field[i].checked = true;
}
function uncheckAll(field) {
for(var i = 0; i < field.length; i++)
field[i].checked = false;
}
function getCalBase() {
var metaTag = document.getElementsByTagName("meta");
var calendarBase = "";
for(var i=0; i<metaTag.length; i++) {
if(metaTag[i].name == "calbase") {
calendarBase = metaTag[i].content;
}
}
return calendarBase;
}
function clearFieldIfChecked(field, checkbox) {
if (checkbox.checked) field.value = '';
}
// Enable/Disable appropriate elements based on selected country
function checkCountry(myform) {
if (myform.country.value === '') {
myform.state.disabled = false;
myform.province.disabled = false;
} else if (myform.country.value == 'CA') {
myform.province.disabled = false;
myform.state.disabled = true;
myform.state.value = '';
} else if (myform.country.value == 'US') {
myform.state.disabled = false;
myform.province.disabled = true;
myform.province.value = '';
} else {
myform.state.disabled = true;
myform.state.value = '';
myform.province.disabled = true;
myform.province.value = '';
}
}
function setElementValue(element, value) {
var el = document.getElementsByName(element)[0];
el.value = value;
}
function getElementValue(element) {
var el = document.getElementsByName(element)[0];
return el.value;
}
function isChecked(element) {
var el = document.getElementsByName(element)[0];
return el.checked;
}
function setChecked(element, on) {
var el = document.getElementsByName(element)[0];
el.checked = on;
}
function setElementDisabled(element, disabled) {
var el = document.getElementsByName(element)[0];
el.disabled = disabled;
}
function setElementReadonly(element, readonly) {
var el = document.getElementsByName(element)[0];
el.readOnly = readonly;
}
function resetFirstItem(formId) {
var frm = document.getElementById(formId);
frm.firstItem.value = '0';
}
/*
function selectAllInList(listId) {
selectAllInList(listId, true);
}
*/
function selectAllInList(listId, on) {
var list = document.getElementById(listId);
var len = list.length;
for(i=0; i<len; i++) {
list.options[i].selected=on;
}
}
// Get the LI values from a UL tag and concatenate them with '|'.
// Set element 'elemId' to the concatenated value.
function getListValues(listId, prefix, elemId) {
var list = document.getElementById(listId);
var values = '';
for (var i=0; i < list.childNodes.length; i++)
{
var item = list.childNodes[i].getAttribute('value');
var id = item.substring(prefix.length,item.length);
values += id;
if (i < list.childNodes.length-1)
values += '|';
}
document.getElementById(elemId).value = values;
}
/* (c) 2009 CaribMedia
* this module defines and initiates nice effects
* preconditions:
* - MooTools available
*/
var openPopup;
(function() {
var cxlFx = new Class({
Implements: [Options],
options : {
hover : true,
popup: true,
zebra: true,
linkTracking: true,
tooltips: false,
picNav: false,
loginPopup: false,
flashClips: false,
accordion: false,
slider: false,
sifr: false,
rating:false,
nosifr: ''
},
initialize: function(options){
this.setOptions(options);
var opt = this.options;
if (opt.hover)	this.doAddHover();
if (opt.tooltips)	this.tooltips();
if (opt.zebra)	this.zebraStripes();
if (opt.picNav)	this.pictureNavigation();
if (opt.loginPopup)	this.loginPopup();
if (opt.linkTracking)	this.addLinkTracking();
if (opt.flashClips)	this.flashClips();
if (opt.accordion)	this.accordion();
if (opt.slider)	this.slider();
if (opt.popup)	this.popup();
if (opt.rating)	this.rating();
if (opt.sifr)
if (window.loadFonts)
//window.addEvent('load', function() {loadFonts(opt.nosifr)});
loadFonts(opt.nosifr);
},
/*
* @name sfHover
* @description gives all input elements an effect
* @author Michiel van der Blonk
* @date Apr 6, 2006
*/
sfHover : function(addFocusFx) {
// add :hover and :focus support to internet explorer 5 and 6
// remove this code as soon as most common browsers support this
if (cxlEnv.isIE5or6)
{
var tagNames = ['p','li','ul','input','button','select','img'];
tagNames.each( function(tagName) {
$$(tagName).each( function(tag)
{
tag.addEvent('mouseenter', function() {tag.addClass('over');});
tag.addEvent('mouseleave', function() {tag.removeClass('over');});
if (addFocusFx)
{
tag.addEvent('focus', function() {tag.addClass('focus');});
tag.addEvent('blur', function() {tag.removeClass('focus');});
}
});
});
}
return true;
},
/*
* @name tooltips
* @description initiate tooltips
* @author Michiel van der Blonk
* @date Apr 6, 2006
*/
tooltips : function()
{
if (window.hasTooltips)
domTT_replaceTitles(null,"'styleClass', 'niceTitle', 'offsetX', 25, 'offsetY', -20, 'type', 'velcro', 'source', 'tt' ");
},
/*
* @name popup
* @description initiate popup effect
* @author Michiel van der Blonk
* @date June 16, 2006
* @source http://www.openhosting.co.uk/articles/webdev/5918/
*/
popup : function()
{
// check to see that the browser supports the getElementsByTagName method
// if not, exit the loop
if (!document.getElementsByTagName) {
return false;
}
// create an array of objects of each link in the document
var popuplinks = document.getElementsByTagName("a");
// loop through each of these links (anchor tags)
for (var i=0; i < popuplinks.length; i++)
{
// if the link has a class of "popup"...
cName = popuplinks[i].getAttribute("class");
if (!cName)
cName = popuplinks[i].className;
re = new RegExp("popup","ig");
if (cName && re.test(cName)) {
options = null;
if (new RegExp("popup-fullscreen","ig").test(cName))
options = "fullscreen";
if (new RegExp("popup-tiny","ig").test(cName))
options = "tiny";
if (new RegExp("popup-medium","ig").test(cName))
options = "medium";
if (new RegExp("popup-picture","ig").test(cName))
options = "picture";
if (new RegExp("popup-large","ig").test(cName))
options = "large";
// add an onclick event on the fly to pass the href attribute
// of the link to our second function, openPopUp
popuplinks[i].onclick = function() {
return cxlFx.openPopUp(this.getAttribute("href"), options);
};
}
}
return false;
},
openPopUp : function(linkURL, options, width, height) {
// default position in options
var position = 'screenX=300, screenY=250, top=250, left=300';
var resizable = "resizable=yes";
var scrollbars = "scrollbars=1";
var defaultOptions = resizable + ',' + scrollbars + ',' + position;
// define options
var popupOptions = {
'fullscreen': '',
'tiny' : 'width=250, height=150, ' + defaultOptions,
'small' : 'width=350, height=200, ' + defaultOptions,
'medium' : 'width=450, height=225, ' + defaultOptions,
'picture' : 'width=680, height=530, ' + defaultOptions,
'large' : 'width=800, height=600, ' + resizable + ',' + scrollbars
};
// get special ops
if (!options)
{
var sOptions = '';
if (width && height)
sOptions += 'width='+width + ', height='+height + ',';
sOptions += resizable + ',' + position;
}
else
sOptions = popupOptions[options];
var handle = window.open(linkURL, 'popup', sOptions);
handle.focus();
return false;
},
doAddHover : function(){
var addFocusFx = true;
this.sfHover(addFocusFx);
},
flashClips : function()
{
var clips = {
gallerybutton : 'gallerymovie',
menubutton: 'menumovie',
guestbutton: 'guestmovie',
eventsbutton: 'eventsmovie',
barbutton: 'barmovie'
// contactbutton: 'contactmovie' not doing anything special
};
var i;
for (button in clips)
{
var oButton = $(button);
//alert(oButton.id);
if (oButton) {
oButton.addEvent("click", function() {
// first set contentPane to overflow hidden to
// fix the 'screwed up movie' bug
var contentPane = $('contentPane');
if (contentPane)
contentPane.style.overflow = 'hidden';
// now play the movie! It's.... showtime!!!!
var oMovie = $(clips[this.id]);
this.style.display="none";
cxlFx.showhide(oMovie);
});
}
}
},
showhide : function(obj)
{
if (obj.style.display == "block")
obj.style.display = "none";
else
obj.style.display = "block";
},
switchMovie : function (buttonId, movieId)
{
var clips = {
gallerybutton : 'gallerymovie',
menubutton: 'menumovie',
guestbutton: 'guestmovie',
eventsbutton: 'eventsmovie',
barbutton: 'barmovie'
// contactbutton: 'contactmovie' not doing anything special
};
cxlFx.prototype.showhide($(buttonId));
cxlFx.prototype.showhide($(movieId));
},
flashInterface : function(id, eventName)
{
var oButton = document.getElementById(button);
if (eventName == 'click')
{
if (cxlEnv.isIE)
oButton.onclick();
}
},
zebraStripes : function()
{
$$('#contentPane table tr').each(function(el, count){
if (!el.hasClass('even') && !el.hasClass('odd'))
el.className += count % 2 === 0 ? 'odd' : 'even';
});
},
/*
* @name pictureNavigation
* @description setup the previous and next buttons
* @author Michiel van der Blonk
* @date January 13, 2008
*/
pictureNavigation : function()
{
if (!window.currentThumb)
window.currentThumb = 1;
var mainPictureField = $$('.field_main_picture img');
var prev = $('previousThumb');
var next = $('nextThumb');
if (!mainPictureField || !prev || !next)
return;
if (mainPictureField.length)
{
var mainPicture = mainPictureField[0];
mainPicture.addEvent("mouseover", function() {
prev.addClass('visible');
next.addClass('visible');
});
mainPicture.addEvent("mouseout", function(evt) {
if (evt.toElement && evt.toElement.tagName=='BUTTON')
return;
if (evt.relatedTarget && evt.relatedTarget.tagName=='BUTTON')
return;
prev.removeClass('visible');
next.removeClass('visible');
});
$('previousThumb').onclick = function()	{
if (!$$('.field_picture' + (currentThumb-1) + ' img').length) return;
currentThumb--;
mainPicture.src = $$('.field_picture' + currentThumb + ' img')[0].src;
};
$('nextThumb').onclick = function() {
if (!$$('.field_picture' + (currentThumb+1) + ' img').length) return;
currentThumb++;
mainPicture.src = $$('.field_picture' + currentThumb + ' img')[0].src;
};
}
},
loginPopup : function() {
if (!$('memberInfo') || !$('login'))
return true;
if (!$('memberInfo').hasClass('layer'))
return true;
$('memberInfo').addClass('loginHide');
$('login').onclick = function() {
$('memberInfo').removeClass('loginHide');
$('memberInfo').addClass('loginShow');
return false;
};
return true;
},
addLinkTracking: function()
{
//no tracker then quit
if(!window.pageTracker) return;
//suggested by remy
var host = window.location.host;
//go thru each link
$$('a').each(function(el)
{
//if rel tag is google then track what's inside brackets
//ex: google[download/thisfile]
if(el.rel && el.rel.match(/^google/i))
{
el.addEvent('click',function()
{
var track_id = this.rel.match(/^google\[(.*)\]$/);
if(track_id)
{
//we have a match use array[1] for tracking
pageTracker._trackPageview(track_id[1]);
}
});
}
//if has http, must be external link, track as
//outbound/domainname
//else if(el.href && el.href.test(/^http:\/\//))
else if(el.host != host)
{
el.addEvent('click',function()
{
var track_id = this.href.match(/^http:\/\/([^\/]+)/);
if(track_id)
{
//we have a match use array[1] for tracking
pageTracker._trackPageview('outgoing/'+track_id[1]);
}
});
}
});
},
accordion: function() {
if (!$('sidebarNav'))
return;
if (window.MultipleOpenAccordion)
{
var sideToggle = new MultipleOpenAccordion($('sidebarNav'), {
elements: $$('#sidebarNav>div'),
togglers: $$('#sidebarNav>h2'),
openAll: false,
opacity: false,
firstElementsOpen:[5],
onActive: function(myToggler){myToggler.addClass('open');},
onBackground: function(myToggler){myToggler.removeClass('open');}
});
$('openAccordion').onclick = function() { sideToggle.showAll.call(sideToggle); };
$('closeAccordion').onclick = function() { sideToggle.hideAll.call(sideToggle); };
}
},
rating: function() {
var mySlider = new Slider('myElement', 'myKnob', {
range: [-50, 50],
wheel: true,
snap: true,
onStart: function(){
this.borderFx = this.borderFx || this.element.tween('border').start('#ccc');
},
onTick: function(pos){
this.element.setStyle('border-color', '#f00');
this.knob.setStyle(this.property, pos);
},
onComplete: function(){
this.element.tween('border').start('#000');
}
});
},
slider: function() {
var el = $('featuredArticles') || $('rotatingArticles');
if (!el) 
return;
new SimpleCarousel(
el.id,
$$('#' + el.id + ' .article'),
$$('#num_nav .button'),
{rotateAction: 'click'}
);
}
});
window.addEvent('domready', function() {
var fx = new cxlFx({accordion:false, slider:true, sifr:false, nosifr:'home'});
openPopUp = fx.openPopUp;
});
})();
/*
Author: Michiel van der Blonk
Date: Somewhere in 2006
Description:
cxlObject has generic form functions
- getForm
- imageSelect
- addCalendar
- initCalendars
- validateForm
Note: this file depends on MooTools to be loaded.
*/
var cxlObject = new Class( {
getForm: function()
{
return document.forms[this.formName];
},
imageSelect: function()
{
window.open(cxlPage.imageSelection + '?dispatch=images&id=' + cxlPage.id, 'image', 'width=750, height=400, screenX=300, screenY=100, top=100,left=300, resizable=yes');
},
addCalendar: function(fieldId, buttonId, sOptions)
{
if (!this.calendars)
this.calendars = new Array();
this.calendars[fieldId] = {field:fieldId, button:buttonId, options:sOptions};
if (sOptions=='startdate')
this.startCalendar = fieldId;
if (sOptions=='enddate')
this.endCalendar = fieldId;
},
//utility functions for the calendars
invalidDate: function(d)
{
var startDateElement = $(cxlPage.startCalendar);
var startDate = Date.parseDate(startDateElement.value, "m/%d/%Y");
return (d < startDate);
},
//utility functions for the calendars
blockRange: function(d)
{
var ret = true;
var out = '';
if (cxlPage.blockedDates)
{
if (d.getDay()===0) // block all sundays
ret = true;
else
{
var blockedDates = cxlPage.blockedDates;
ret = false;
for (i=0;i<blockedDates.length;i++)
{
startDate = new Date(blockedDates[i].start);
endDate = new Date(blockedDates[i].end);
// add one day, so end date behaves properly
endDate.setDate(endDate.getDate()+1);
options = blockedDates[i].options;
curDate = new Date(d);
if (options=='yearly')
curDate.setYear(startDate.getFullYear());
if (curDate>=startDate && curDate<=endDate)
ret = true;
}
}
return ret;
}
},
setEndDate: function (cal)
{
var startDateElement = $(cxlPage.startCalendar);
var endDateElement = $(cxlPage.endCalendar);
if (startDateElement.value !== '' && endDateElement.value === '')
endDateElement.value = startDateElement.value;
},
initCalendars: function() {
var i;
for (i in cxlPage.calendars)
{
var calendar = cxlPage.calendars[i];
if (typeof calendar == "object" && $(calendar.field))
{
switch(calendar.options)
{
case 'startdate':
cxlPage.calendars[i].object =
Calendar.setup({inputField:calendar.field, button:calendar.button, ifFormat:"%m/%d/%Y", step:1, showsTime:false, onUpdate:cxlPage.setEndDate});
break;
case 'enddate':
cxlPage.calendars[i].object =
Calendar.setup({inputField:calendar.field, button:calendar.button, ifFormat:"%m/%d/%Y", step:1, showsTime:false, disableFunc:cxlPage.invalidDate});
break;
default:
cxlPage.calendars[i].object =
Calendar.setup({inputField:calendar.field, button:calendar.button, ifFormat:"%m/%d/%Y", step:1, showsTime:false, disableFunc:cxlPage.blockRange});
break;
}
}
}
},
initSliders:	function() {
function setupSlider(id)
{
var slider = new Element('div').set(
{
'id':id+'_slider', 
'styles': 
{
'width': '72px', 
'height':'12px', 
'background': 'url(/visitaruba/styles/member/visitaruba/bg_rating_stars2.jpg) no-repeat -60px 0',
'position':'relative',	
'left':'12em',
'font-size':'10px',
'line-height':'10px'
}
}).injectAfter($(id));
new Element('div').set(
{
'id':id+'_knob', 
'class':'knob',
'styles':{
'width': '12px', 
'height': '11px',
'position' : 'absolute',
'font-size':'10px',
'line-height':'10px',
'background':'url(/visitaruba/styles/member/visitaruba/bg_bullet.gif) no-repeat center center'
}	
}).inject(slider);	
return slider;
}
$$('form .slider').each(
function(el) {
var slider = setupSlider(el.id);
// Create the new slider instance
new Slider(slider, slider.getElement('.knob'), {
steps: 5,	// There are 5 steps
wheel: true,
snap: true,
range: [0,5],	// Minimum value is 0
onChange: function(value){
if (!$defined(value) || isNaN(value))
value = 0;
// Everytime the value changes, we change the select element
el.value = value;
var knobWidth = parseInt(slider.style.width) / (this.steps+1);
var pos = (this.steps-value) * knobWidth * -1;
$('comments').innerText += pos;
slider.setStyle('background-position', "" + (knobWidth+pos) + 'px 0');
slider.set('title', $chk(value)?'no rating':value+' stars');
}
}).set('value', el.value.toInt());
//el.hide();
}
);
/*	var mySlider = new Slider('subRating_1_slider', 'subRating_1_knob', {
range: [0, 5],
wheel: true,
snap: true,
onStart: function(){
this.borderFx = this.borderFx || this.element.tween('border').start('#ccc');
},
onTick: function(pos){
this.element.setStyle('border-color', '#f00');
this.knob.setStyle(this.property, pos);
},
onComplete: function(){
this.element.tween('border').start('#000');
}
});
$$('.slider').each(function(el) {
new Slider(el, el.getElement('.knob'), {
steps: 5, // There are 5 steps
range: [1], // Minimum value is 1
onChange: function(value){
// Everytime the value changes, we change the value of the select box
this.value = value;
}
}).set(this.value);
}
*/
},
isDate: function(d, formatted) {
var ret = false;
var date = new Date(d);
// it's at least a number
if (!isNaN(date))
{
if (formatted)
{
var day = date.getDate();
var month = date.getMonth()+1;
var year = date.getFullYear();
var dateString = '' + month + '.' + day + '.' + year;
var pattern = new RegExp(dateString);
ret = pattern.test(d);
}
else
ret = true;
}
return ret;
},
/*
* @Date: Somewhere 2006
* @Description: Validate fields based on class name
* example: class="validation-date" will be
* matched against mm/dd/yy, or a valid Date object
**/
validateForm: function(frm, target)
{
var i;
var ret = true;
var field;
var out='';
var errorFields = [];
if (!target)
target = "errors";
if (!$(target))
{
console.log('setup element ' + target + ' to make errors visible');
return false;
}
// loop through all fields
// check if they have validation class name
// and do appropriate validation
// @return true, if all validation passes
for (i=0; i<frm.elements.length; i++)
{
field = frm.elements[i];
// skip disabled fields and fields without a name
if (field.disabled || field.name==undefined)
continue;
if ($('label-'+field.name))
field.label = $('label-'+field.name).innerHTML;
else
field.label = field.name;
// validate required fields
filter = /validation-required/;
if (filter.test(field.className))
{
if (field.type=='checkbox')
{
if (!field.checked)
{
out += 'Please check the ' + field.label + ' box<br />';
errorFields.push(field);
ret = false;
}
}
else
if (field.value==='')
{
out += 'Please enter a value for ' + field.label + '<br />';
errorFields.push(field);
ret = false;
}
}
// validate numeric fields
filter = /validation-number/;
if (filter.test(field.className))
{
if (field.value!=='' && isNaN(field.value))
{
out += 'Please enter a number for ' + field.label + '<br />';
errorFields.push(field);
ret = false;
}
}
// validate digit only fields
filter = /validation-digits/;
if (filter.test(field.className))
{
var filter = /^[0-9]+$/;
if (field.value!=='' && !filter.test(field.value))
{
out += 'Please enter a number for ' + field.label + '<br />';
errorFields.push(field);
ret = false;
}
}
// validate date fields
filter = /validation-date/;
if (filter.test(field.className))
{
if (field.value!=='' && !isDate(field.value, true))
{
out += 'Please enter a valid date for ' + field.label + '<br />';
errorFields.push(field);
ret = false;
}
}
// validate this date later than other field's date
filter = /validation-date-after/;
if (filter.test(field.className))
{
var otherFieldName = field.className.replace(/.*validation-date-after-/,'').replace(/ .*/,'');
if (field.value!=='' && $(otherFieldName))
{
var otherField = $(otherFieldName);
if (isDate(field.value) && isDate(otherField.value))
{
var date1	= new Date(field.value);
var date2 = new Date(otherField.value);
}
if (+date1 <= +date2) // + converts to number
{
out += 'Please enter a date for ' + field.label + ' after ' + otherField.name + '<br />';
errorFields.push(field);
ret = false;
}
}
}
// validate email addresses
filter = /format-email/;
if (filter.test(field.className))
{
filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
if (field.value!=='' && !filter.test(field.value))
{
out += 'Please enter a valid email address in ' + field.label + '<br />';
errorFields.push(field);
ret = false;
}
}
// validate credit cards
// this uses Luhn validation
// which is a numeric algorithm
filter = /format-creditcard/;
if (filter.test(field.className))
{
filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
if (field.value!=='' && !this.isValidCreditCard(field.value))
{
out += 'Please enter a valid credit card number' + '<br />';
errorFields.push(field);
ret = false;
}
}
// validate urls
filter = /format-url/;
if (filter.test(field.className))
{
filter = /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$/i;
if (field.value!=='' && !filter.test(field.value))
{
out += 'Please enter a valid url in ' + field.label + '<br />';
errorFields.push(field);
ret = false;
}
}
// validate verification fields
filter = /validation-match/;
if (filter.test(field.className))
{
var otherField = field.className.replace(/.*validation-match-/,'').replace(/ .*/,'');
if (field.value!=='' && field.value!=$(otherField).value)
{
out += 'The value in ' + field.label + ' does not match ' + otherField + '<br />';
errorFields.push(field);
ret = false;
}
}
$(field).removeClass('error');
}
$(target).innerHTML = out;
// indicate errors
for (i = 0; i < errorFields.length; i++)
$(errorFields[i]).addClass('error');
window.scroll(0,0);
return ret;
},
/*
* @Date: Feb 21, 2005
* @Description: This function strips defined chars from a string
* useful in validation routines
* example: stripChars(str, "()-") returns the string with any
* brackets and dashes removed
**/
stripChars : function(str, chars) {
var i;
var newstring = "";
for (i = 0; i < str.length; i++) {
mychar = str.charAt(i);
if (chars.indexOf(mychar) == -1)
newstring += mychar;
}
return newstring;
},
/**
* @Date: Feb 21, 2005
* @Description: This function extracts defined chars from a string
* useful in validation routines
* it is 'sort of' the reverse of stripChars
* example: extractChars(str, "0123456789") returns all digits from the string
**/
extractChar: function(str, chars) {
var i;
var newstring = "";
for (i = 0; i < str.length; i++) {
mychar = str.charAt(i);
if (chars.indexOf(mychar) != -1)
newstring += mychar;
}
return newstring;
},
/**
* @Date: Dec 1, 2004
* @Description: This function tests a credit card using the Luhn validation
* The sum of digits must be divisible by 10
* digits in odd positions are doubled, then sum of left+right digit is taken
**/
isValidCreditCard: function(sCreditCardNumber)
{
var nTotal = 0;
var nPosition = 0;
var bValid = true; // innocent until proven guilty
sCreditCardNumber = this.extractChars(sCreditCardNumber, "0123456789");
if (sCreditCardNumber.length < 13)
bValid = false;
else
{
for ( i = sCreditCardNumber.length; i > 0 ; i--)
{
var nDigit = 0;
// advance
nPosition++;
// get digit
nDigit= parseInt(sCreditCardNumber.charAt(i-1));
// odd position: add to total
if ((nPosition % 2) !== 0)
nTotal += parseInt(nDigit);
else
// even position: add sum of digits to total
{
// calc sum of left and right digit (use parseInt to cut off fractional parts
var nDoubled = nDigit * 2;
var nLeftDigit = parseInt(nDoubled / 10);
var nRightDigit = nDoubled % 10;
// get sum of left and right
nTotal += nLeftDigit + nRightDigit;
}
}
// if divisible by 10 it is valid
bValid = (nTotal % 10) === 0;
}
return (bValid);
},
// utility functions for the form
setDispatch: function(value, frm) {
// default to cxlPage.getForm()
if (typeof frm=="undefined")
{
if (window.cxlPage && window.cxlPage.getForm())
frm = cxlPage.getForm();
else
return false;
}
frm.dispatch.value = value;
return true;
},
submitForm: function(target) {
if (!window.cxlPage || !window.cxlPage.getForm())
return false;
this.setDispatch(target, window.cxlPage.getForm());
window.cxlPage.getForm().submit();
return false;
},
initNeverExpires: function() {
if (!window.cxlPage || !window.cxlPage.getForm())
return;
var frm = window.cxlPage.getForm();
if (frm.neverExpire)
frm.neverExpire.checked = (frm.expirationDate.value === '');
},
checkFeatured: function() {
if (!window.cxlPage || !window.cxlPage.getForm())
return;
var frm = cxlPage.getForm();
if (frm.pressRelease)
frm.pressRelease.checked = false;
},
checkPressRelease: function() {
if (!window.cxlPage || !window.cxlPage.getForm())
return;
var frm = window.cxlPage.getForm();
if (frm.featured)
frm.featured.checked = false;
},
deleteImage: function(image) {
if (!window.cxlPage || !window.cxlPage.getForm())
return;
var frm = window.cxlPage.getForm();
if (confirm(window.cxlPage.confirmDelete)) {
var theLink = window.cxlPage.imageSelection + '?dispatch=delete&id=' + image;
window.location.href = theLink;
}
}
}
);
/*
* @name
* @description initiate image effects
* @author Michiel van der Blonk
* @date May 13, 2008
*/
window.addEvent("load", function()
{
$$('#contentPane #thumbs img').each(function(thumb){
thumb.onclick = function(){$('mainPicture').src = thumb.src;};
});
}
);
// clear menus
if (location.pathname.match(/listing/i)==null)
setMenuCookie(-1);
if (typeof onLoadActions=='function')
if (typeof addEvent=='function')
{
if (window.MooTools)
window.addEvent("domready", onLoadActions);
else
addEvent(window, "load", onLoadActions);
}
else
window.onload = onLoadActions;
