
function $A(arrayish) {
var arr = [];
for (var i=0; i<arrayish.length; i++) {
arr.push(arrayish[i]);
};
return arr;
}


Array.prototype.each = function(callback) {
for (var i=0; i<this.length; i++) {
callback(this[i], i);
};
}
var System = new Object();
System.isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;
System.isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false;
System.isFF = function() {
return System.getBrowser() == "Firefox";
}
System.getBrowser = function() {
return this._searchString(this.dataBrowser);
}
System._searchString = function (data) {
for (var i=0; i<data.length; i++) {
var dataString = data[i].string;
var dataProp = data[i].prop;
this.versionSearchString = data[i].versionSearch || data[i].identity;
if (dataString) {
if (dataString.indexOf(data[i].subString) != -1)
return data[i].identity;
} else if (dataProp)
return data[i].identity;
}
},
System.isIE = function(v1, v2) {
var arVersion = navigator.appVersion.split("MSIE")
var version = parseFloat(arVersion[1])
return ((v1 == null || version > v1) && 
(v2 == null || version < v2) && 
document.body.filters);
}
System.needHoverHack = function() {
return System.isIE(5.5, 7.0);
}
System.needRoundedCornersHack = function() {
return System.isIE(5.5, 7.0);
}
System.hasDisplayTable = function() {
return !System.isIE(null, 8.0);
}
System.isIE = function(v1, v2) {
var arVersion = navigator.appVersion.split("MSIE")
var version = parseFloat(arVersion[1])
return ((v1 == null || version > v1) && 
(v2 == null || version < v2) && 
document.body.filters);
}
System.hasDisplayTable = function() {
return !System.isIE(null, 8.0);
}
System.dataBrowser = [
{
string: navigator.userAgent,
subString: "Chrome",
identity: "Chrome"
},
{
string: navigator.userAgent,
subString: "OmniWeb",
versionSearch: "OmniWeb/",
identity: "OmniWeb"
},
{
string: navigator.vendor,
subString: "Apple",
identity: "Safari",
versionSearch: "Version"
},
{
prop: window.opera,
identity: "Opera"
},
{
string: navigator.vendor,
subString: "iCab",
identity: "iCab"
},
{
string: navigator.vendor,
subString: "KDE",
identity: "Konqueror"
},
{
string: navigator.userAgent,
subString: "Firefox",
identity: "Firefox"
},
{
string: navigator.vendor,
subString: "Camino",
identity: "Camino"
},
{		// for newer Netscapes (6+)
string: navigator.userAgent,
subString: "Netscape",
identity: "Netscape"
},
{
string: navigator.userAgent,
subString: "MSIE",
identity: "Explorer",
versionSearch: "MSIE"
},
{
string: navigator.userAgent,
subString: "Gecko",
identity: "Mozilla",
versionSearch: "rv"
},
{ 		// for older Netscapes (4-)
string: navigator.userAgent,
subString: "Mozilla",
identity: "Netscape",
versionSearch: "Mozilla"
}
]


Evt = new Object();
Evt.extend = function(e) {
e.stop = function() {
cancelBubble(this);
cancelEvent(this);
}
return e;
}
Evt._handlers = {};
Evt.add = function(obj, type, fn) {
return addEvent(obj, type, fn);
}
Evt.remove = function(obj, type, fn) {
return removeEvent(obj, type, fn);
}
function addEvent(obj, type, fn) {
if (!obj) { return; };



if (obj instanceof Array) {
obj.each(function(item) { addEvent(item, type, function(e) { fn(e, item); }) });
return;
};

if (type instanceof Array) {
type.each(function(item) { addEvent(obj, item, fn); });
return;
};
var wrappedFn = function(e) { fn(Evt.extend(e)); };
Evt._handlers[fn] = wrappedFn;
_addEvent(obj, type, wrappedFn);
}
function _addEvent(obj, type, fn) {
if (obj.addEventListener) {
var mappings = {};
switch (obj.tagName) { 
case "body":
mappings["load"] = "DOMContentLoaded";
default:
};
if (System.isFF()) {
mappings["mousewheel"] = "DOMMouseScroll";
};
if (mappings[type]) {
type = mappings[type];
};
obj.addEventListener( type, fn, false );
} else if (obj.attachEvent) {
var eName = "e"+type+fn;
var name = type+fn;

while (obj[eName]) {
eName += "_";
name += "_";
};
obj[eName] = fn;
obj[name] = function() { obj[eName]( window.event ); }
obj.attachEvent( "on" + type, obj[name] );
}
}
function cancelBubble(e) {
if (e.stopPropagation) {
e.stopPropagation();
} else {
e.cancelBubble = true;
};
}
function cancelEvent(e) {
if (e.preventDefault) { 
e.preventDefault();
} else {
e.returnValue = false;
};
}
function getEventTarget(e) {
var target;
if (e.target) {
target = e.target;
} else if (e.srcElement) {
target = e.srcElement;
};
if (target.nodeType == 3) { // fix for Safari bug
target = target.parentNode;  
};
return target;
}
function removeEvent(obj, type, fn) {

if (type instanceof Array) {
type.each(function(item) { removeEvent(obj, item, fn); });
return;
};
var wrappedFn = Evt._handlers[fn];
if (obj.removeEventListener) {
if (type == "mousewheel") {
type = "DOMMouseScroll";
};
obj.removeEventListener( type, wrappedFn, false );
} else if (obj.detachEvent) {
obj.detachEvent( "on"+type, obj[type+wrappedFn] );
obj[type+wrappedFn] = null;
obj["e"+type+wrappedFn] = null;
}
};



function $(id) {
var el = document.getElementById(id);
return el ? window.Element.extend(el) : el;
}
function $T(id, tag) {
return $(id).getElementsByTagName(tag).map(window.Element.extend);
}
function $F(id) {
return $(id).value;
}
var page = new Object();
page.m = new Object();
page.v = new Object();
page.c = new Object();

page._forms = {};
page._inputFeatures = [];
page.addForm = function(id, form) {
page._forms[id] = form;
var target = form.getTarget();
if (target) {
Evt.add($(target), "load", function(e) {  
if (form.getSubmitting()) { form.doOnTargetLoaded(e); };
});
};
return form;
}
page.getForm = function(id) {
return page._forms[id];
}
page.addInputFeature = function(feature) {
page._inputFeatures.push(feature);
}

page._components = {};
page._componentTypes = {};
page.addComponent = function(type, name, component) {
page._components[name] = component;
if (!page._componentTypes[type]) {
page._componentTypes[type] = [];
};
page._componentTypes[type].push(component);
return component;
}
page.getComponentsByType = function(type) {
return page._componentTypes[type] || [];
}
page.getComponent = function(name) {
return page._components[name];
}






page._loadHandlers = [];
page.c.onload = function(callback) {
var env = { m: {}, v: {}, c: {} };
page._loadHandlers.push({ callback: callback, env: env });
}
page.events = {
_registered: {},
getRegisteredFor: function(event) {
if (!this._registered[event]) {
this._registered[event] = [];
};
return this._registered[event];
},
bind: function(event, handler) {
this.getRegisteredFor(event).push(handler);
},
fire: function(event, params) {
this.getRegisteredFor(event).each(function(f) { f(event, params); });
}
};
page.c.onLoad = function() {

};
page.c.onUnload = function() {

};
page.getXMLRPCGateway = function() {
return "xmlrpc.php";
};
addEvent(window, "unload", page.c.onUnload );
page.init = function() {
if (page._done) return;
page._done = true;
page._loadHandlers.each(function(handler) {
handler.callback(handler.env);
});
};
/* Mozilla/Firefox/Opera 9 */
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", page.init, false);
}
/* Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
document.write("<script id=\"__ie_onload\" defer=\"defer\" src=\"javascript:void(0)\"><\/script>");
var script = document.getElementById("__ie_onload");
if (script) {
script.onreadystatechange = function() {
if (this.readyState == "complete") {
page.init(); 
}
};
};
/*@end @*/
/* Safari */
if (/WebKit/i.test(navigator.userAgent)) {
var _timer = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
clearInterval(_timer);
page.init();
}
}, 10);
}
window.onload = page.init;
/* Function printf(format_string,arguments...)
* Javascript emulation of the C printf function (modifiers and argument types 
*    "p" and "n" are not supported due to language restrictions)
*
* Copyright 2003 K&L Productions. All rights reserved
* http://www.klproductions.com 
*
* Terms of use: This function can be used free of charge IF this header is not
*               modified and remains with the function code.
* 
* Legal: Use this code at your own risk. K&L Productions assumes NO resposibility
*        for anything.
********************************************************************************/
function sprintf(fstring)
{ var pad = function(str,ch,len)
{ var ps='';
for(var i=0; i<Math.abs(len); i++) ps+=ch;
return len>0?str+ps:ps+str;
}
var processFlags = function(flags,width,rs,arg)
{ var pn = function(flags,arg,rs)
{ if(arg>=0)
{ if(flags.indexOf(' ')>=0) rs = ' ' + rs;
else if(flags.indexOf('+')>=0) rs = '+' + rs;
}
else
rs = '-' + rs;
return rs;
}
var iWidth = parseInt(width,10);
if(width.charAt(0) == '0')
{ var ec=0;
if(flags.indexOf(' ')>=0 || flags.indexOf('+')>=0) ec++;
if(rs.length<(iWidth-ec)) rs = pad(rs,'0',rs.length-(iWidth-ec));
return pn(flags,arg,rs);
}
rs = pn(flags,arg,rs);
if(rs.length<iWidth)
{ if(flags.indexOf('-')<0) rs = pad(rs,' ',rs.length-iWidth);
else rs = pad(rs,' ',iWidth - rs.length);
}    
return rs;
}
var converters = new Array();
converters['c'] = function(flags,width,precision,arg)
{ if(typeof(arg) == 'number') return String.fromCharCode(arg);
if(typeof(arg) == 'string') return arg.charAt(0);
return '';
}
converters['d'] = function(flags,width,precision,arg)
{ return converters['i'](flags,width,precision,arg); 
}
converters['u'] = function(flags,width,precision,arg)
{ return converters['i'](flags,width,precision,Math.abs(arg)); 
}
converters['i'] =  function(flags,width,precision,arg)
{ var iPrecision=parseInt(precision);
var rs = ((Math.abs(arg)).toString().split('.'))[0];
if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
return processFlags(flags,width,rs,arg); 
}
converters['E'] = function(flags,width,precision,arg) 
{ return (converters['e'](flags,width,precision,arg)).toUpperCase();
}
converters['e'] =  function(flags,width,precision,arg)
{ iPrecision = parseInt(precision);
if(isNaN(iPrecision)) iPrecision = 6;
rs = (Math.abs(arg)).toExponential(iPrecision);
if(rs.indexOf('.')<0 && flags.indexOf('#')>=0) rs = rs.replace(/^(.*)(e.*)$/,'$1.$2');
return processFlags(flags,width,rs,arg);        
}
converters['f'] = function(flags,width,precision,arg)
{ iPrecision = parseInt(precision);
if(isNaN(iPrecision)) iPrecision = 6;
rs = (Math.abs(arg)).toFixed(iPrecision);
if(rs.indexOf('.')<0 && flags.indexOf('#')>=0) rs = rs + '.';
return processFlags(flags,width,rs,arg);
}
converters['G'] = function(flags,width,precision,arg)
{ return (converters['g'](flags,width,precision,arg)).toUpperCase();
}
converters['g'] = function(flags,width,precision,arg)
{ iPrecision = parseInt(precision);
absArg = Math.abs(arg);
rse = absArg.toExponential();
rsf = absArg.toFixed(6);
if(!isNaN(iPrecision))
{ rsep = absArg.toExponential(iPrecision);
rse = rsep.length < rse.length ? rsep : rse;
rsfp = absArg.toFixed(iPrecision);
rsf = rsfp.length < rsf.length ? rsfp : rsf;
}
if(rse.indexOf('.')<0 && flags.indexOf('#')>=0) rse = rse.replace(/^(.*)(e.*)$/,'$1.$2');
if(rsf.indexOf('.')<0 && flags.indexOf('#')>=0) rsf = rsf + '.';
rs = rse.length<rsf.length ? rse : rsf;
return processFlags(flags,width,rs,arg);        
}  
converters['o'] = function(flags,width,precision,arg)
{ var iPrecision=parseInt(precision);
var rs = Math.round(Math.abs(arg)).toString(8);
if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
if(flags.indexOf('#')>=0) rs='0'+rs;
return processFlags(flags,width,rs,arg); 
}
converters['X'] = function(flags,width,precision,arg)
{ return (converters['x'](flags,width,precision,arg)).toUpperCase();
}
converters['x'] = function(flags,width,precision,arg)
{ var iPrecision=parseInt(precision);
arg = Math.abs(arg);
var rs = Math.round(arg).toString(16);
if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
if(flags.indexOf('#')>=0) rs='0x'+rs;
return processFlags(flags,width,rs,arg); 
}
converters['s'] = function(flags,width,precision,arg)
{ var iPrecision=parseInt(precision);
var rs = arg;
if(rs.length > iPrecision) rs = rs.substring(0,iPrecision);
return processFlags(flags,width,rs,0);
}
farr = fstring.split('%');
retstr = farr[0];
fpRE = /^([-+ #]*)(\d*)\.?(\d*)([cdieEfFgGosuxX])(.*)$/;
for(var i=1; i<farr.length; i++)
{ fps=fpRE.exec(farr[i]);
if(!fps) continue;
if(arguments[i]!=null) retstr+=converters[fps[4]](fps[1],fps[2],fps[3],arguments[i]);
retstr += fps[5];
}
return retstr;
}
/* Function printf() END */



Array.prototype.reduce = function(callback, seed) {
var result = seed;
this.each(function(item) {
result = callback(result, item);
});
return result;
}



Array.prototype.filter = function(predicate) {
if (!predicate) {
predicate = function(item) { return item; };
};
var filtered = this.reduce(function(result, item) {
if (predicate && predicate(item) || !predicate && item) {
result.push(item);
};
return result;
}, []);
return filtered;
}


var Links = new Object();
Links.baseUrl = window.baseUrl || window.location.href.replace(/\/[^\/]*$/i, "/");
Links.skin = window.skin || "default";
Links.action = function(action, params) {
if (!params) { params = {}; };
params.a = action;
return this.link_to(params);
}
Links.controller = function(name) {
name = name || "index";
return Links.baseUrl + name + ".php";
}
Links.image = function(name, params) {
if (!params) {
return sprintf("%spublic/skins/raw/%s/images/%s", Links.baseUrl, Links.skin, name);
};
var query_string = this.make_query_string(params);
return sprintf("%spublic/skins/raw/%s/images/%s?%s", Links.baseUrl, Links.skin, name, query_string);
}
Links.link_to = function(params) {
return Links.link_to_normal(params);
}
Links.link_to_normal = function(params) {
var query_string = this.make_query_string(params);
if (query_string.length == 0) {
return Links.baseUrl + "index.php";
};
return Links.baseUrl + "index.php?" + query_string;
}
Links.make_param_string = function(key, value) {
if (value instanceof Function) {
return "";
};
if (value instanceof Array) {
var param_strings = [];
if (value.length > 0) {
for (var i=0; i<value.length; i++) {
param_strings.push(Links.make_param_string(key + "[" + i.toString() + "]", value[i]));
};
} else {
for (var subkey in value) {
param_strings.push(Links.make_param_string(key + "[" + subkey + "]", value[subkey]));
};
};
var result = param_strings.filter().join("&");
return result;
};
return sprintf("%s=%s", encodeURIComponent(key), encodeURIComponent(value));
}
Links.make_query_string = function(params) {
var param_strings = [];
for (var param_name in params) {
param_strings.push(this.make_param_string(param_name, params[param_name]));
};
return param_strings.filter().join("&");
}
Links.update_url = function(url, param, value) {
url = url.replace(new RegExp(sprintf("([\?&])%s=[^&#]+(&|$)", param), "g"), "$1");
if (url.match(/\?/)) { 
url = url + "&" + encodeURIComponent(param) + "=" + encodeURIComponent(value);
} else {
url = url + "?" + encodeURIComponent(param) + "=" + encodeURIComponent(value);
};
return url;
}
Links.uploaded_file = function(file) {
return Links.baseUrl + "public/uploaded/" + file;
}
Links.xml = function(name, params) {
var query_string = this.make_query_string(params);
if (query_string.length == 0) {
return "xml.php?_xml=" + encodeURIComponent(name);
};
return "xml.php?_xml=" + encodeURIComponent(name) + "&" + query_string;
}
Links.xmlrpc = function() {
return Links.baseUrl + "xmlrpc2.php";
}
Links.json = function() {
return Links.baseUrl + "json.php";
}
Links.xslt = function(name, params) {
var query_string = this.make_query_string(params);
if (query_string.length == 0) {
return "xslt.php?_xslt=" + encodeURIComponent(name);
};
return "xslt.php?_xslt=" + encodeURIComponent(name) + "&" + query_string;
}



Array.prototype.map = function(callback) {
var result = [];
this.each(function(item) {
result.push(callback(item));
});
return result;
}

Array.prototype.flatten = function() {
return this.reduce(function(result, item) {
return result.concat(item);
}, []);
}
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(val, fromIndex) {
if (typeof(fromIndex) != 'number') { 
fromIndex = 0; 
}
for (var index = fromIndex,len = this.length; index < len; index++) {
if (this[index] == val) { return index; };
}
return -1;
};
}

Array.prototype.contains = function(item) {
return (this.indexOf(item) != -1);
}



Array.prototype.unique = function() {
var result = this.reduce(function(res, item) {
if (!res.values.contains(item)) {
res.values.push(item);
};
return res;
}, { values: [], found: {}});
return result.values;
}

function $A(item) {
if (item instanceof Array) {
return item;
};
if (!item) {
return [];
};
var newItem = [];
for (var i=0; i<item.length; i++) {
newItem.push(item[i]);
};
return newItem;
} 

Function.prototype.bind = function() {
var _fun = this;
var obj = arguments[0];
var boundArguments = [];
if (arguments.length > 1) {
boundArguments = $A(arguments).slice(1);
};
return function() {
return _fun.apply(obj, boundArguments.concat($A(arguments)));
};
}
function isAncestorOf(parent, child) {
if (child.parentNode == parent) {
return true;
};
if (!child.parentNode) {
return false;
};
return isAncestorOf(parent, child.parentNode);
}


Object.prototype.each = function(callback) {
for (var i in this) {
if (!Object.prototype[i] || 
Object.prototype[i] != this[i]) {
callback(this[i], i);
};
};
}

String.prototype.ucfirst = function() {
return this.substr(0, 1).toUpperCase() + this.substr(1);
}



var Cls = {};
Cls.inherit = function(subClass, baseClass, methods) {
function inheritance() {};
inheritance.prototype = baseClass.prototype;
subClass.prototype = new inheritance();
subClass.prototype.constructor = subClass;
subClass.baseConstructor = baseClass;
subClass.superClass = baseClass.prototype;
if (methods) { 
this.extend(subClass, methods);
};
}

Cls.extend = function(destination, source) {
source.each(function(value, key) {
destination.prototype[key] = value;
});  
}
Cls.extendDirect = function(destination, source) {
source.each(function(value, key) {
destination[key] = value;
});  
}
Cls.extendDumb = function(destination, source) {
for (var key in source) {
destination.prototype[key] = source[key];
};  
}
Cls.property = function(baseClass, propertyName) {
var getterName = "get" + propertyName.ucfirst();
var setterName = "set" + propertyName.ucfirst();
var memberName = "_" + propertyName;
baseClass.prototype[getterName] = function() {
return this[memberName];
};
baseClass.prototype[setterName] = function(value) {
this[memberName] = value;
return this;
};
};





var element = window.Element;
window.Element = function(tagName, attributes) {
attributes = attributes || {};
tagName = tagName.toLowerCase();
var el = document.createElement(tagName);
attributes.each(function(value, name) { el.setAttribute(name, value); });
return window.Element.extend(el);
};
window.Element.extend = function(el) {
Cls.extendDirect(el, {
css: function(properties) {
properties.each(function(value, key) {
this.style[this.propertyToName(key)] = value;
}.bind(this));
},
down: function(selector) {
return $$(selector, this);
},
up: function(selector) {
var currentNode = window.Element.extend(this.parentNode);
while (currentNode && currentNode.tagName.toUpperCase() != "HTML") {
if (Selector.match(currentNode, selector)) {
return currentNode;
};
currentNode = window.Element.extend(currentNode.parentNode);
};
return null;
},
empty: function() {
while (this.childNodes.length > 0) {
this.removeChild(this.childNodes[0]);
};
},
clear: function() {
while (this.childNodes.length > 0) {
this.removeChild(this.childNodes[0]);
};
return this;
},
remove: function() {
this.parentNode.removeChild(this);
},
propertyToName: function(property) {
var parts = property.split(/-/);
return parts[0] + parts.slice(1).map(function(part) { return part.ucfirst(); }).join("");
}
});
return el;
}


Cls.extendDumb(window.Element, element || {});
function $E(tagName, className, content, attrs, children) {
attrs = attrs || {};
children = children || [];
var el = new Element(tagName);
if (className) { 
el.className = className;
};
if (content) {
el.appendChild(document.createTextNode(content));
};

attrs.each(function(value, key) {
el[key] = value;
});
children.each(function(child) { 
el.appendChild(child); 
});
return el;
}










var Selector = {

find: function(compositeSelector, context) {
var selectorParts = compositeSelector.split(/\s*,\s*/);
var matches = selectorParts.map(function(simpleSelector) { return Selector.findSimple(simpleSelector, context); });
return matches.flatten().map(window.Element.extend);
},

findSimple: function(simpleSelector, context) {
var subselectors = simpleSelector.split(/\s+/);
var finalContext = subselectors.reduce(Selector.applySubselector.bind(Selector), { nodes: [context || document.body], mode: "normal" })
return finalContext.nodes;
},
match: function(node, simpleSelector) {
var subselectors = simpleSelector.split(/\s+/);
if (subselectors.length == 0) { 
return true; 
};
if (!this.subselectorMatch(node, subselectors[subselectors.length - 1])) { 
return false; 
};
if (subselectors.length == 1) { 
return true; 
};
return node.up(subselectors.slice(0, subselectors.length - 1).join(" ")) != null;
},
subselectorMatch: function(node, selector) {
var selectorData = this.parseSubselector(selector);
if (selectorData.tagName) {
if (node.tagName.toUpperCase() != selectorData.tagName.toUpperCase()) { return false; };
};
switch (selectorData.subselectorType) {
case ".":
if (!hasClass(node, selectorData.subselectorData)) { return false; };
break;
case "#":
if (node.id != selectorData.subselectorData) { return false; };
break;
default:
break;
};
return true;
},
traverseChildren: function(root, predicate, result) {
return $A(root.childNodes).filter(function(node) { 
return node.nodeType == 1 && predicate(node) // nodeType=1: Element node
});
},
traverseTree: function(root, predicate, result) {
if (root.nodeType != 1) { // nodeType=1: Element node
return;
};
if (predicate(root)) { 
result.push(root); 
};
$A(root.childNodes).each(function(node) { 
Selector.traverseTree(node, predicate, result); 
});
return result;
},
parseSubselector: function(subselector) {
var matches = subselector.match(/^(.*?)(?:([.#])(.*?))?$/);
return {
tagName: matches[1],
subselectorType: matches[2],
subselectorData: matches[3]
};
},
applySubselector: function(context, subselector) {
var nodes = context.nodes;
var data = this.parseSubselector(subselector);
var newContext = {
nodes: context.nodes,
state: "normal"
};
if (subselector == ">") {
newContext.state = ">";
return newContext;
};
var traverseFun = null;
switch (context.state) {
case ">":
traverseFun = Selector.traverseChildren.bind(Selector);
break;
default:
traverseFun = Selector.traverseTree.bind(Selector);
break;
};
switch (data.subselectorType) {
case ".":
var matchRegexp = new RegExp("\\b" + data.subselectorData + "\\b");
newContext.nodes = nodes.map(function(node) {
return traverseFun(node, function(n) { 
return n.className.match(matchRegexp) && (data.tagName == "" || n.tagName.toUpperCase() == data.tagName.toUpperCase());
}, []);
}).flatten().unique();
break;
case "#":
newContext.nodes = nodes.map(function(node) { 
if (node.getAttribute("id") == data.subselectorData) {
return [node];
};
var newNode = $(data.subselectorData);


if (!newNode ||
!isAncestorOf(node, newNode)) {
return [];
};
return [newNode];
}).flatten().unique();
break;
default:
if (data.tagName != "") {
newContext.nodes = nodes.map(function(node) {
return traverseFun(node, function(n) { 
return n.tagName.toUpperCase() == data.tagName.toUpperCase();
}, []);
}).flatten().unique();
};
};
return newContext;
}
}

function $$(selector, context) {
var matches = Selector.find(selector, context);
return matches.length > 0 ? matches[0] : null;
}

String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/, "");
}




function tc(element, cls) {
if (hasClass(element, cls)) {
rc(element, cls);
} else {
ac(element, cls);
};
}
function ac(element, cls) {
if (element instanceof Array) {
element.each(function(e) { ac(e, cls); });
return;
};
if (!hasClass(element, cls)) {
element.className += " " + cls;
};
}
function rc(element, cls) {
if (element instanceof Array) {
element.each(function(e) { rc(e, cls); });
return;
};
element.className = element.className.split(/\s+/).filter(function(className) {
return className != cls;
}).join(" ");
}
function hasClass(element, cls) {
return element.className.split(/\s+/).indexOf(cls) != -1;
}
function addRemoveClass(element, cls, guard) {
if (guard) {
ac(element, cls);
} else {
rc(element, cls);
};
}
function textBoxSelect(item, from, to) {
if (item.setSelectionRange) {

item.setSelectionRange(from, to);
} else if (item.createTextRange) {

var range = item.createTextRange();
range.moveStart("character", from);
range.moveEnd("character", to - item.value.length);
range.select();
};
};



function KeyBindings() {
KeyBindings.baseConstructor.call(this);
this.GROUPS = ["element", "group", "all"];
this.setBindings({});
this.GROUPS.each(function(group) {
this.getBindings()[group] = {};
}.bind(this));
}
Cls.inherit(KeyBindings, Object, {
add: function(key, fun, group) {
this.remove(key, fun, group);
if (!this._bindings[group][key]) { 
this._bindings[group][key] = { sequence: [], hash: {} };
};
this._bindings[group][key].sequence.push(fun);
this._bindings[group][key].hash[fun] = this._bindings[group][key].sequence.length - 1;
},
handle: function(e) {
var code = e.keyCode || e.charCode;
var handled = false;
for (var i=0; i<this.GROUPS.length; i++) {
var data = this.handleGroup(code, this.GROUPS[i], e);
handled = handled || data.handled;
if (data.terminated) {
break;
};
};
if (handled) {
e.stop();
};
},
handleGroup: function(code, group, event) {
var binding = this._bindings[group][code];
if (!binding || binding.sequence.length == 0) { 
return { handled: false, terminated: false };
};
for (var i = binding.sequence.length - 1; i >= 0; i--) {
if (!binding.sequence[i](event)) {
return { handled: true, terminated: true };
};
};
return { handled: true, terminated: false };
},
remove: function(key, fun, group) {
if (!this._bindings[group][key]) { 
this._bindings[group][key] = { sequence: [], hash: {} };
};
var index = this._bindings[group][key].hash[fun];
if (index == null) {
return;
};
this._bindings[group][key].sequence.splice(index, 1);
this._bindings[group][key].hash[fun] = null;
}
});
Cls.property(KeyBindings, "bindings");
var Bind = {
ESCAPE: 27,
UP: 38,
DOWN: 40,
PAGE_UP: 33,
PAGE_DOWN: 34, 
setupNode: function(element) {
if (!element._keyBindings) {
element._keyBindings = new KeyBindings();
Evt.add(element, "keydown", element._keyBindings.handle.bind(element._keyBindings));
};
},
addElement: function(element, key, fun) {
this.setupNode(element);
if (element instanceof Array) {
element.each(function(item) { this.addElement(item, key, fun) }.bind(this));
return;
};
if (key instanceof Array) {
key.each(function(item) { this.addElement(element, item, fun) }.bind(this));
return;
};
element._keyBindings.add(key, fun, "element");
},
addGroup: function(element, key, fun) {
this.setupNode(element);
element._keyBindings.add(key, fun, "group");
},
removeElement: function(element, key, fun) {
if (!element._keyBindings) {
return;
};
element._keyBindings.remove(key, fun, "element");
},
removeGroup: function(element, key, fun) {
if (!element._keyBindings) {
return;
};
element._keyBindings.remove(key, fun, "group");
}
}


var Keys = new Object();
Keys.BACKSPACE = 8;
Keys.TAB = 9;
Keys.ENTER = 13;
Keys.ESCAPE = 27;
Keys.PAGE_UP = 33;
Keys.PAGE_DOWN = 34;
Keys.ARROW_LEFT = 37;
Keys.ARROW_UP = 38;
Keys.ARROW_RIGHT = 39;
Keys.ARROW_DOWN = 40;
Keys.DELETE = 46;
Keys.isModification = function(charCode, keyCode) {
charCode = charCode || keyCode;
return charCode >= 32 || 
keyCode == Keys.BACKSPACE || 
keyCode == Keys.DELETE;
}
function getElementComputedStyle(element, property) {
if (document.defaultView && document.defaultView.getComputedStyle) {
return getElementComputedStyleMozilla(element, property);
}

if (element.currentStyle) {
return getElementComputedStyleIE(element, property);
}
return "";
}
function getElementComputedStyleIE(element, property) {
return element.currentStyle[propertyCssToPropertyDom(property)];
}
function getElementComputedStyleMozilla(element, property) {
return document.defaultView.getComputedStyle(element, "").getPropertyValue(property);
}
function propertyCssToPropertyDom(property) {
var i;
while ((i = property.indexOf("-")) != -1) {
property = property.substr(0, i) + property.substr(i+1,1).toUpperCase() + property.substr(i+2);
};
return property;
}




function FeatureTrackHover(element, options) {
options = options || {};
this._element = element;
this._className = options.className || "hover";
this.setup();
}
Cls.inherit(FeatureTrackHover, Object, {
setup: function() {
var _this = this;
addEvent(this._element, "mouseover", function(e) { _this.onHover(e) });
addEvent(this._element, "mouseout", function(e) { _this.onOut(e) });
},
onHover: function(e) {
ac(this._element, this._className);
},
onOut: function(e) {
rc(this._element, this._className);
}
});
var RPC = {
gateway: null,
uri_cb: null,  
call: function(method, params, success, fail, error) {
return this.gateway.call(this.uri_cb(), success, fail, error, method, params);
}
}
function createXMLHttpRequest() {
var xmlhttp;
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
xmlhttp = new XMLHttpRequest();
};
};
return {
xmlhttp: xmlhttp,
readyState: 0,
responseXML: null,
responseText: "",
onsuccess: null,
url: "",
sent: "",
async: 1,
onsuccesscalled: false,
error: function(text) {
alert(error);
return true;
},
onreadystatechange: function() {
},
open: function(method, url, mode) { 
var obj = this;
this.xmlhttp.onreadystatechange = function () {
obj.readyState = obj.xmlhttp.readyState;
if (obj.xmlhttp.readyState == 4) {
obj.responseXML  = obj.xmlhttp.responseXML;
obj.responseText = obj.xmlhttp.responseText;
if (obj.onsuccess) { 
obj.onsuccesscalled = true;
obj.onsuccess(); 
};
};
obj.onreadystatechange();
};
var ts = new Date;
if (url.indexOf('?') == -1) {
url = url + "?_ts=" + ts.getTime();
} else {
url = url + "&_ts=" + ts.getTime();
};
this.url = url;
this.async = mode;
this.xmlhttp.open(method, url, mode);
this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
},
send: function(data) {
this.sent = data;
this.xmlhttp.send(data);




if (!this.async && !this.onsuccesscalled && this.xmlhttp.readyState == 4) {
this.responseXML  = this.xmlhttp.responseXML;
this.responseText = this.xmlhttp.responseText;
this.onsuccesscalled = true;
if (this.onsuccess) {
this.onsuccess();
};
};
},
handleError: function(callbacks) { 




if (this.xmlhttp.responseText == "" && this.xmlhttp.responseXML == null) {
return false;
};
if (!this.xmlhttp.responseXML) {
return this.error("Error; server responded with '"+this.xmlhttp.responseText+"'");
};
if (!this.xmlhttp.responseXML.documentElement) {
return this.error("Error; server responded with '"+this.xmlhttp.responseText+"'");
};
if (this.xmlhttp.responseXML.documentElement.tagName == "parsererror") {
return this.error("Error; server responded with '"+this.xmlhttp.responseText+"'");
};
var root = this.xmlhttp.responseXML.documentElement;
if (root.tagName == 'error') {
var handler = null;
var code = root.getAttribute('code');
var text = root.text ? root.text : root.textContent;
if (callbacks != null) {
handler = callbacks[code];
};
if (handler) {
return handler(code, text);
} else {
var query_text = this.sent.replace(/&/g, "\n");
return this.error("ERROR: " + code + " " + text + "\n" + query_text);
};
};
return false;
}
} 
};
function getInnerText (node) {
if (typeof node.textContent != 'undefined') {
return node.textContent;
} else if (typeof node.innerText != 'undefined') {
return node.innerText;
} else if (typeof node.text != 'undefined') {
return node.text;
} else {
switch (node.nodeType) {
case 3:
case 4:
return node.nodeValue;
break;
case 1:
case 11:
var innerText = '';
for (var i = 0; i < node.childNodes.length; i++) {
innerText += getInnerText(node.childNodes[i]);
}
return innerText;
break;
default:
return '';
}
}
}



Array.prototype.fmap = function(data) {
var result = [];
this.each(function(item) {
result.push(item(data));
});
return result;
}








function XMLRPCPending(xmlrpc, name, params) {
this._xmlrpc = xmlrpc;
this._name = name;
this._params = params;
this._success = [];
this._error = [];
this._failure = [];
}
Cls.inherit(XMLRPCPending, Object, {
add: function(success, error, failure) {
this._success.push(success);
this._error.push(error);
this._failure.push(failure);
},
success: function(r) {
this._success.fmap(r);
this.completed(function(s, e, f) { s(r); });
},
error: function(r) {
this._error.fmap(r);
this.completed(function(s, e, f) { e(r); });
},
failure: function(r) {
this._failure.fmap(r);
this.completed(function(s, e, f) { f(r); });
},
completed: function(r) {
if (!this._xmlrpc._cached[this._name]) { this._xmlrpc._cached[this._name] = {}; };
this._xmlrpc._cached[this._name][this._params] = r;
this._xmlrpc._pending[this._name][this._params] = null;
}
});
XMLRPCResponse.prototype = new Object;
XMLRPCResponse.prototype.isError = XMLRPCResponse_isError;
function XMLRPCResponse(param) {
this.param = param;
}
function XMLRPCResponse_isError() {
return false;
}
/* ---------- */
XMLRPCError.prototype = new Object;
XMLRPCError.prototype.isError = XMLRPCError_isError;
XMLRPCError.prototype.getCode = XMLRPCError_getCode;
XMLRPCError.prototype.getMessage = XMLRPCError_getMessage;
function XMLRPCError(code, message) {
this._message = message;
this._code    = code;
}
function XMLRPCError_getMessage() {
return this._message;
}
function XMLRPCError_getCode() {
return this._code;
}
function XMLRPCError_isError() {
return true;
}
/* ---------- */
var XMLRPC = new Object;
XMLRPC._cacheEnabled = {};
XMLRPC._cached = {};
XMLRPC._pending = {};

XMLRPC.enableCache = function(methodList) {
this._cacheEnabled = {};
var _t = this;
methodList.each(function(method) {
_t._cacheEnabled[method] = true;
});
};
XMLRPC.prepare = function(name, params) {
var methodName = "<methodName>"+name+"</methodName>\n";
var paramsText = "<params>\n";
for (var i=0; i<params.length; i++) {
paramsText += this._prepareParam(params[i]);
};
paramsText += "</params>\n";
return "<methodCall>\n"+methodName+paramsText+"</methodCall>\n";
};
XMLRPC._prepareParam = function(value) {
var paramText;
paramText  = "<param>";
paramText += this._prepareValue(value);
paramText += "</param>\n";
return paramText;
}
XMLRPC._prepareValue = function(value) {
var paramText = "<value>";
switch (typeof value) {
case "object":
if (value instanceof Array) {
paramText += this._prepareArray(value);
} else {
paramText += this._prepareObject(value);
};
break;
case "boolean":
paramText += this._prepareBoolean(value);
break;
case "undefined":
throw "Undefined parameter value";
default:
paramText += this._prepareString(value);
break;
};
paramText += "</value>";
return paramText;
}
XMLRPC._prepareArray = function(value) {
var valueText = "";
for (var i=0; i<value.length; i++) {
valueText += XMLRPC._prepareValue(value[i]);
};
return "<array><data>"+valueText+"</data></array>";
}
XMLRPC._prepareBoolean = function(value) {
return "<boolean>" + (value ? 1 : 0) + "</boolean>";
}
XMLRPC._prepareObject = function(value) {
var valueText = "";
for (var key in value) {
if (!(value[key] instanceof Function)) {
valueText += "<member><name>"+key+"</name>"+this._prepareValue(value[key])+"</member>\n"
};
};
return "<struct>"+valueText+"</struct>";
}
XMLRPC._prepareString = function(value) {
return "<string>"+value.toString().replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;")+"</string>";
}
XMLRPC.parseResponse = function(responseXML) {
if (!responseXML) { 
return new XMLRPCError(null, null);
};

var faultElement = responseXML.getElementsByTagName('fault')[0];

if (faultElement) {
var code    = getInnerText(faultElement.getElementsByTagName('int')[0]);
var message = getInnerText(faultElement.getElementsByTagName('string')[0]);
var response = new XMLRPCError(code, message);
return response;
};





var paramXML = responseXML.getElementsByTagName('param')[0];
if (paramXML) {
return new XMLRPCResponse(this._parseResponseParam(paramXML));
} else {
return new XMLRPCResponse(null);
};
};
XMLRPC._parseResponseParam = function(element) {
for (var i=0; i<element.childNodes.length; i++) {
var node = element.childNodes[i];
if (node.tagName == "value") {
return this._parseValue(node);
};
};
}
XMLRPC._parseValue = function(element) {
for (var i=0; i<element.childNodes.length; i++) {
var node = element.childNodes[i];
switch (node.tagName) {
case "int":
case "i4":
return this._parseInt(node);
case "boolean":
return this._parseBoolean(node);
case "string":
return this._parseString(node);
case "double":
return this._parseDouble(node);
case "dateTime.iso8601":
return this._parseDateTime(node);
case "base64":
return this._parseBase64(node);
case "struct":
return this._parseStruct(node);
case "array":
return this._parseArray(node);
};
};  
}
XMLRPC._parseInt = function(element) {
return parseInt(getInnerText(element));
}
XMLRPC._parseBoolean = function(element) {
var text = getInnerText(element);
if (!text) { 
return false;
};
if (text == 'false') {
return false;
};
if (text == 'no') {
return false;
};
if (text == '0') {
return false;
};
return true;
}
XMLRPC._parseString = function(element) {
return getInnerText(element);
}
XMLRPC._parseDouble = function(element) {
return parseFloat(getInnerText(element));
}
XMLRPC._parseDateTime = function(element) {

return getInnerText(element);
}
XMLRPC._parseBase64 = function(element) {
return getInnerText(element);
}
XMLRPC._parseStruct = function(element) {
var struct = new Object;
for (var i=0; i<element.childNodes.length; i++) {
var node = element.childNodes[i];
if (node.tagName == "member") {
var member = this._parseMember(node);
struct[member.name] = member.value;
};
};
return struct;  
}
XMLRPC._parseMember = function(element) {
var member = new Array();
for (var i=0; i<element.childNodes.length; i++) {
var node = element.childNodes[i];
switch (node.tagName) {
case "name":
member.name = this._parseName(node);
break;
case "value":
member.value = this._parseValue(node); 
break;
};
};
return member;
}
XMLRPC._parseName = function(element) {
return getInnerText(element);
}
XMLRPC._parseArray = function(element) {
for (var i=0; i<element.childNodes.length; i++) {
var node = element.childNodes[i];
if (node.tagName == "data") {
return this._parseData(node);
};
};
}
XMLRPC._parseData = function(element) {
var data = new Array();
for (var i=0; i<element.childNodes.length; i++) {
var node = element.childNodes[i];
if (node.tagName == "value") {
data.push(this._parseValue(node));
};
};
return data;
}
XMLRPC.callSync = function(url, successCallback, errorCallback, failureCallback, name, params) {
params = [params];
var request = this.prepareRequest(url, successCallback, errorCallback, failureCallback, name, params);

request.open('POST', url, 0);
var query = this.prepare(name, params);
request.send(query);
}
XMLRPC.call = function(url, successCallback, errorCallback, failureCallback, name, params) {
params = [params];

if (this._cacheEnabled[name] && this._cached[name] && this._cached[name][params]) {
this._cached[name][params](successCallback, errorCallback, failureCallback);
return;
};

if (this._cacheEnabled[name] && this._pending[name] && this._pending[name][params]) {
this._pending[name][params].add(successCallback, errorCallback, failureCallback);
return;
};
var request;
if (this._cacheEnabled[name]) {
var callback = new XMLRPCPending(this, name, params);
callback.add(successCallback, errorCallback, failureCallback);
if (!this._pending[name]) { this._pending[name] = {}; };
this._pending[name][params] = callback;
request = this.prepareRequest(url, 
function(r) { callback.success(r); }, 
function(r) { callback.error(r); },
function(r) { callback.failure(r); }, 
name, params);
} else {
request = this.prepareRequest(url, successCallback, errorCallback, failureCallback, name, params);
};

request.open('POST',url,1);
var query = this.prepare(name, params);
request.send(query);
return request;
};
XMLRPC.prepareRequest = function(url, successCallback, errorCallback, failureCallback, name, params) {
var request = createXMLHttpRequest();
request.error = XMLRPC._ajaxErrorHandler; 
request.onsuccess = function() { 
if (request.handleError()) { 
if (failureCallback) {
failureCallback();
};
return false; 
}; 
var response = XMLRPC.parseResponse(request.xmlhttp.responseXML);
if (response.isError()) {
if (errorCallback) {
errorCallback(response); 
}; 
} else {
if (successCallback) {
successCallback(response); 
};
};
};
return request;
}
XMLRPC._ajaxErrorHandler = function(text) {
return true;
};
RPC.gateway = XMLRPC;
RPC.uri_cb = Links.xmlrpc;


Function.prototype.debounce = function(timeout, callFirst) {
var _originalFunction = this;
var debounced = function() {
if (this._timeout) {
clearTimeout(this._timeout);
};
var callArgs = $A(arguments);
var _t = this;
this._timeout = setTimeout(function() {
_t._timeout = null;
_originalFunction.apply(_originalFunction, callArgs);
}, this._timeoutValue);
};
debounced._timeoutValue = timeout;
debounced._timeout = null;
return debounced.bind(debounced);
}


Function.prototype.stopEvent = function() {
var _wrapped = this;
var wrapper = function() {
arguments[0].stop();
_wrapped.apply(_wrapped, arguments);
};
return wrapper.bind(wrapper);
}
var Geometry = {
place: function(element, point) {
element.style.left = point.x.toString() + "px";
element.style.top  = point.y.toString() + "px";
}
};
function center(popup, noreshedule) {


if (popup.clientWidth == 0 && !noreshedule) {
setTimeout(function() { center(popup, 1); }, 200);
return;
};
center_x(popup);
center_y(popup);
}
function centerWindow(popup, noreshedule) {


if (popup.clientWidth == 0 && !noreshedule) {
setTimeout(function() { center(popup, 1); }, 200);
return;
};
center_x(popup);
centerWindow_y(popup);
}
function centerIn(popup, target) {
centerIn_x(popup, target);
centerIn_y(popup, target);
}
function centerIn_x(popup, target) {
var left = getLeft(target) + (target.clientWidth - popup.clientWidth) / 2;
popup.style.left = left.toString() + "px";
}
function centerIn_y(popup, target) {
var top = getTop(target) + (target.clientHeight - popup.clientHeight) / 2;
popup.style.top = top.toString() + "px";
}
function center_x(popup) {
var left = (windowWidth() - popup.offsetWidth) / 2;
popup.style.left = left.toString() + "px";
popup.style.marginLeft = "auto";
}
function center_y(popup) {
var top = (document.documentElement.clientHeight - popup.offsetHeight) / 2;
var offset = getWindowTopOffset() + top;

if (offset < 0) {
offset = 0;
};
popup.style.top = offset.toString() + "px";
}
function windowHeight() {
return window.innerHeight || document.documentElement.offsetHeight
}
function windowWidth() {
return document.body.offsetWidth;
}
function centerWindow_y(popup) {
var windowHeight = window.windowHeight();
var top = (windowHeight - popup.offsetHeight) / 2;
var offset = getWindowTopOffset() + top;

if (offset < 0) {
offset = 0;
};
popup.style.top = offset.toString() + "px";
popup.style.marginTop = "auto";
}
function getScrollXY() {
var scrOfX = 0, scrOfY = 0;
if( typeof( window.pageYOffset ) == "number" ) {

scrOfY = window.pageYOffset;
scrOfX = window.pageXOffset;
} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {

scrOfY = document.body.scrollTop;
scrOfX = document.body.scrollLeft;
} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {

scrOfY = document.documentElement.scrollTop;
scrOfX = document.documentElement.scrollLeft;
}
return { x: scrOfX, y: scrOfY };
}
function getWindowTopOffset() {
var offsets = getScrollXY();
return offsets.y;
}
function getPositionParent(element) {
var parent = element.parentNode;
while (parent && parent.style.position == "static") {
parent = parent.parentNode;
};
if (parent == null) {
return document.body;
};
return parent;
}
function getDocumentHeight() {
return document.documentElement.scrollHeight || document.body.scrollHeight;
}
function getWindowHeight() {
return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
}
function getWindowWidth() {
return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
}
function getLeft(item) {
var parent = item.offsetParent;
var scrollDelta = (item.tagName != "HTML") ? item.scrollLeft : 0;
if (parent) {
return item.offsetLeft + getLeft(parent) - scrollDelta;
} { 
return item.offsetLeft - scrollDelta;
};
}
function getTop(item) {
var parent = item.offsetParent;
var scrollDelta = (item.tagName != "HTML") ? item.scrollTop : 0;
if (parent) {
return item.offsetTop + getTop(parent) - scrollDelta;
} { 
return item.offsetTop - scrollDelta;
};
}
function getBottom(item) {
if (item.tagName == "SELECT") {
return getTop(item) + item.offsetHeight;
} else {
return getTop(item) + item.clientHeight;
};
}
function getRight(item) {
var width = item.clientWidth || item.scrollWidth;
return getLeft(item) + width;
}
function getLeftParent(item) {
var parent = item.offsetParent;
if (parent) {
return getLeft(parent);
} { 
return 0;
};
}
function getTopParent(item) {
var parent = item.offsetParent;
if (parent) {
return getTop(parent);
} { 
return 0;
};
}
function getPosition(e) {
var cursor = {x:0, y:0};
if (e.pageX || e.pageY) {
cursor.x = e.pageX;
cursor.y = e.pageY;
} 
else {
var de = document.documentElement;
var b = document.body;
cursor.x = e.clientX + 
(de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0);
cursor.y = e.clientY + 
(de.scrollTop || b.scrollTop) - (de.clientTop || 0);
}
return cursor;
}


function Anchor(node) {
Anchor.baseConstructor.call(this);
this.setNode(node);
this.setDx(0);
this.setDy(0);
}
Cls.inherit(Anchor, Object, {
offset: function(dx, dy) {
this.setDx(this.getDx() + dx);
this.setDy(this.getDy() + dy);
return this;
},
topLeft: function(node) {
var baseX = getLeft(node.offsetParent);
var baseY = getTop(node.offsetParent);
node.css({
position: "absolute",
top: (this.getY() + this.getDy() - baseY) + "px",
left: (this.getX() + this.getDx() - baseX) + "px"
});
return this;
},
topRight: function(node) {
var baseX = getLeft(node.offsetParent);
var baseY = getTop(node.offsetParent);
node.css({
position: "absolute",
top: (this.getY() + this.getDy() - baseY) + "px",
left: (this.getX() + this.getDx() - baseX - node.offsetWidth) + "px"
});
return this;
}
});
Cls.property(Anchor, "node");
Cls.property(Anchor, "dx");
Cls.property(Anchor, "dy");


function AnchorBottomCenter(node) {
AnchorBottomCenter.baseConstructor.call(this, node);
}
Cls.inherit(AnchorBottomCenter, Anchor, {
getX: function() {
return getLeft(this.getNode()) + this.getNode().offsetWidth / 2;
},
getY: function() {
return getTop(this.getNode()) + this.getNode().offsetHeight;
}
});


function isSelectHackRequiredForPopups() {
var arVersion = navigator.appVersion.split("MSIE")
var version = parseFloat(arVersion[1])
return (version > 5.5 && version < 7.0);
}
function isAncestorOf(parent, node) {
while (node.parentNode && node.parentNode != parent) {
node = node.parentNode;
};
return node.parentNode;
}
function hideSelects(popup) {
if (!isSelectHackRequiredForPopups()) { return; };
var nodeList = $A(document.getElementsByTagName("SELECT"));
nodeList.each(function(node) {
if (!popup || !isAncestorOf(popup, node)) { 
node.style.visibility = 'hidden';
};
});   
return nodeList;
}
function showSelects(nodeList) {
if (!isSelectHackRequiredForPopups()) { return; };
nodeList.each(function(node) {
node.style.visibility = '';
}); 
}


function MulticastCallback() {
this._callbacks = [];
}
Cls.inherit(MulticastCallback, Object, {
add: function(cb) {
this._callbacks.push(cb);
},
fire: function() {
var eventArguments = arguments;
this._callbacks.each(function(cb) {
cb.apply(null, eventArguments);
});
}
});

Cls.event = function(baseClass, eventName) {
var memberName = "_" + eventName;
var addName = "on" + eventName.ucfirst();
var fireName = "doOn" + eventName.ucfirst();
baseClass.prototype[addName] = function(callback) {
this[memberName].add(callback);
return this;
};
baseClass.prototype[fireName] = function() {
this[memberName].fire.apply(this[memberName], arguments);
};
var oldBaseConstructor = baseClass.baseConstructor;
baseClass.baseConstructor = function() {
oldBaseConstructor.apply(this, arguments);
this[memberName] = new MulticastCallback();
};
};




function PopupSlice() {
PopupSlice.baseConstructor.call(this);
this._popup = null;
this._selectHackData = [];
}
Cls.inherit(PopupSlice, Object, {
getPopup: function() {
if (!this._popup) {
this._popup = document.body.appendChild($E("div", "system_gui_popup"));
this.doOnSetup(this._popup);
};
return this._popup;
},
hide: function() {
this.getPopup().css({ visibility: "hidden" });
if (isSelectHackRequiredForPopups()) {
showSelects(this._selectHackData);
this._selectHackData = [];
};
},
show: function() {
var popup = this.getPopup();
popup.css({
visibility: "visible",
left: "-100000px",
top: "-100000px"
});
if (isSelectHackRequiredForPopups()) {
this._selectHackData = hideSelects(popup);
};
setTimeout(this.doOnShow.bind(this), 100);
}
})

Cls.event(PopupSlice, "setup");
Cls.event(PopupSlice, "show");




function PopupOverlay() {
PopupOverlay.baseConstructor.call(this);
this._overlay = null;
this.onShow(function() { 
centerWindow(this.getPopup());
}.bind(this));
}
Cls.inherit(PopupOverlay, PopupSlice, {
getOverlay: function() {
if (!this._overlay) {
this._overlay = document.createElement("div");
document.body.appendChild(this._overlay);
this._overlay.id = "system_gui_popup_overlay";
};
return this._overlay;
},
hide: function() {
var overlay = this.getOverlay();
overlay.style.visibility = "hidden";  
PopupOverlay.superClass.hide.call(this);    
},
show: function() {
var overlay = this.getOverlay();
overlay.style.visibility = "visible";
PopupOverlay.superClass.show.call(this);
}
});

