
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);
};
}

Evt = new Object();
Evt.extend = function(e) {
e.stop = function() {
cancelBubble(this);
cancelEvent(this);
}
return e;
}
Evt._handlers = {};
Evt.add = function(obj, type, fn) {
addEvent(obj, type, fn);
}
function addEvent(obj, type, fn) {
var wrappedFn = function(e) { fn(Evt.extend(e)); };
Evt._handlers[fn] = wrappedFn;
_addEvent(obj, type, wrappedFn);
}
function _addEvent(obj, type, fn) {
if (!obj) { return; };



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

if (type instanceof Array) {
type.each(function(item) { addEvent(obj, item, fn); });
return;
};
if (obj.addEventListener) {
switch (obj.tagName) { 
case "body":
var mappings = { mousewheel: "DOMMouseScroll", load: "DOMContentLoaded" };
default:
var 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) {
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) {
return document.getElementById(id);
}
function $T(id, tag) {
return $(id).getElementsByTagName(tag);
}
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) {
addEvent($(target), "load", function(e) { form.onTargetLoad(e); });
};
}
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);
}
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.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;


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


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;
});  
}
Function.prototype.bind = function(obj) {
var _fun = this;
return function() {
return _fun.apply(obj, arguments);
};
}


Cls.inherit(Transition, Object);
function Transition() {
this._frames = 10;
this._timeout = 20;
this._stepCallback = function() { };
this._completeCallbacks = [];
this._handles = [];
this._calculateFraction = function(frame) {
return frame / this._frames;
}.bind(this);
}
Transition.prototype.cancel = function() {
this._handles.each(function(handle) {
clearTimeout(handle);
});
this._handles = [];
}
Transition.prototype.getFrames = function(frames) {
return this._frames;
}
Transition.prototype.getTimeout = function(timeout) {
return this._timeout;
}
Transition.prototype.run = function() {
this.cancel();
this._stepCallback(0, this._calculateFraction(0));
this.setupTimeout();
}
Transition.prototype.setFrames = function(frames) {
this._frames = frames;
}
Transition.prototype.setTimeout = function(timeout) {
this._timeout = timeout;
}
Transition.prototype.timeoutStep = function(frame) {
this._stepCallback(frame, this._calculateFraction(frame));
if (frame >= this._frames) {
this._completeCallbacks.each(function(cb) { cb(); });
};
}
Transition.prototype.setupTimeout = function() {
for (var i = 1; i <= this._frames; i++) {
this._handles.push(setTimeout(function(i) { return function() { this.timeoutStep(i); }.bind(this) }.bind(this)(i), i * this.getTimeout()));
};
}
Transition.prototype.oncomplete = function(f) {
this._completeCallbacks.push(f);
return this;
}
/* 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 */

var Opacity = new Object();
Opacity.set = function(object, opacity) {
object.style.opacity = opacity;
var ieOpacity = Math.round(opacity*100);
object.style.filter = sprintf("progid:DXImageTransform.Microsoft.Alpha(opacity=%s)", ieOpacity);
}



Cls.inherit(TransitionOpacity, Transition);
function TransitionOpacity(object, startOpacity, stopOpacity) {
TransitionOpacity.baseConstructor.call(this);
this._stepCallback = function(frame, fraction) {
Opacity.set(object, startOpacity + (stopOpacity - startOpacity) * fraction);
};
if (stopOpacity == 1) {
this.oncomplete(function() {
object.style.filter = null;
});
};
}
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 = (document.body.offsetWidth - 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 centerWindow_y(popup) {
var windowHeight = window.innerHeight || document.documentElement.offsetHeight;
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;
}
var I18N = new Object();
I18N.strings = {};
function _(string) {
return I18N.strings[string] || string;
}
Lang = {
NOMINATIVE: 1,
getWordForm: function(word, value, wordCase) {

if (value == 1) {
return word;
};

var last = word[word.length - 1];
var suffix2 = word.substr(word.length - 2, 2);
if (suffix2 == "ay") { // e.g. day, gay
return word + "s";
};
if (suffix2[1] == "y") {
return word.substr(0, word.length - 1) + "ies";   
};
if (suffix2[1] == "h") {
return word + "es";
};
return word + "s";
}
}

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 el;
};
Cls.extend(window.Element, element || {});
function $E(tagName, className, content) {
var el = new Element(tagName);
el.className = className;
if (content) {
el.appendChild(document.createTextNode(content));
};
return el;
}
KeyBindings.prototype = new Object();
KeyBindings.prototype.add = KeyBindings_add;
KeyBindings.prototype.handle = KeyBindings_handle;
KeyBindings.prototype.handleGroup = KeyBindings_handleGroup;
KeyBindings.prototype.remove = KeyBindings_remove;
function KeyBindings() {
this._bindings = {};
this.GROUPS = ['element', 'group', 'all'];
for (var i=0; i<this.GROUPS.length; i++) {
this._bindings[this.GROUPS[i]] = {};
};
}
function KeyBindings_add(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;
}
function KeyBindings_handle(event) {
var code = event.keyCode || event.charCode;
var handled = false;
for (var i=0; i<this.GROUPS.length; i++) {
var data = this.handleGroup(code, this.GROUPS[i], event);
handled = handled || data.handled;
if (data.terminated) {
break;
};
};
if (handled) {
cancelEvent(event);
};
}
function KeyBindings_handleGroup(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 };
}
function KeyBindings_remove(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;
}
var Bind = new Object();
Bind.addElement = function(element, key, fun) {
if (!element._keyBindings) {
element._keyBindings = new KeyBindings();
addEvent(element, 'keypress', function(e) { element._keyBindings.handle(e) });
};
element._keyBindings.add(key, fun, 'element');
};
Bind.addGroup = function(element, key, fun) {
if (!element._keyBindings) {
element._keyBindings = new KeyBindings();
addEvent(element, 'keypress', function(e) { element._keyBindings.handle(e) });
};
element._keyBindings.add(key, fun, 'group');
};
Bind.removeElement = function(element, key, fun) {
if (!element._keyBindings) {
return;
};
element._keyBindings.remove(key, fun, 'element');
};
Bind.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;
}

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

function ac(element, cls) {
if (!element.className.match(cls)) {
element.className += " " + cls;
};
}
function rc(element, cls) {
element.className = element.className.replace(new RegExp('\s*'+cls+'\s*'),"").trim();
}
function hasClass(element, cls) {
return element.className.match(cls);
}
function addRemoveClass(element, cls, guard) {
if (guard) {
ac(element, cls);
} else {
rc(element, cls);
};
}




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);
}
});



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



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

Array.prototype.flatten = function() {
return this.reduce(function(result, item) {
return result.concat(item);
}, []);
}



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

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



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;
}
function isAncestorOf(parent, child) {
if (child.parentNode == parent) {
return true;
};
if (!child.parentNode) {
return false;
};
return isAncestorOf(parent, child.parentNode);
}







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();
},

findSimple: function(simpleSelector, context) {
var subselectors = simpleSelector.split(/\s+/);
return subselectors.reduce(Selector.applySubselector, [context || document.body])
},
applySubselector: function(nodes, subselector) {
var matches = subselector.match(/^(.*?)(?:([.#])(.*?))?$/);
var tagName = matches[1];
var subselectorType = matches[2];
var subselectorData = matches[3];
if (tagName != "") {
var keptNodes = nodes.filter(function(node) { return node.tagName == tagName; });
nodes = nodes.map(function(node) { return $A(node.getElementsByTagName(tagName)); }).flatten();
nodes = nodes.concat(keptNodes);
};
switch (subselectorType) {
case ".":
var matchRegexp = new RegExp("\\b" + subselectorData + "\\b");
nodes = nodes.filter(function(node) { 
return node.className.match(matchRegexp);
});
break;
case "#":
nodes = nodes.map(function(node) { 
if (node.getAttribute("id") == subselectorData) {
return [node];
};
var newNode = $(subselectorData);


if (!newNode ||
!isAncestorOf(node, newNode)) {
return [];
};
return [newNode];
}).flatten().unique();
break;
};
return nodes;
}
}

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









function FeatureGallery(container, options) {
this._container = container;
this._images = [];
this._options = options || {};
this.setup(this._container);
}
Cls.inherit(FeatureGallery, Object, {
showLightbox: function() {
var lightbox = this.getLightbox();
lightbox.style.visibility = "visible";
centerWindow(lightbox);
new TransitionOpacity(lightbox, 0, 1).run();
},
hideLightbox: function() {
var lightbox = this.getLightbox();
new TransitionOpacity(lightbox, 1, 0).oncomplete(function() {
lightbox.style.visibility = "hidden";
}).run();
},
createLightbox: function() {
this._eLightbox = document.createElement("div");
this._eLightbox.className = "rp_lightbox";
this._eContent = this._eLightbox.appendChild(document.createElement("div"));
this._eContent.className = "rp_lightbox_content";
this._eControls = this._eLightbox.appendChild(document.createElement("div"));
this._eControls.className = "rp_lightbox_controls";
this._eClose = this._eControls.appendChild($E("div", "button", _("Click to close")));
if (!this._options.closeOnlyViaButton) {
Evt.add(this._eLightbox, "click", this.onClose.bind(this));
} else {
Evt.add(this._eClose, "click", this.onClose.bind(this));
};
this.doCreateLightbox();    
Selector.find("div.button", this._eControls).each(function(node) { new FeatureTrackHover(node); });
document.body.appendChild(this._eLightbox);
},
doOnClose: function() {
},
onClose: function(e) {
this.doOnClose();
this.hideLightbox();
},

doCreateLightbox: function() {
},
getContent: function() {
if (!this._eContent) { this.createLightbox(); }
return this._eContent;
},
getLightbox: function() {
if (!this._eContent) { this.createLightbox(); }
return this._eLightbox;
},
getFullImage: function(img) {
return img.parentNode.href;
},
doOnClick: function(e, img) {
},
onClick: function(e, img) {
e.stop();
var content = this.getContent();
while (content.childNodes.length) { content.removeChild(content.childNodes[0]); };
var image = content.appendChild(document.createElement("img"));
image.src = this.getFullImage(img);

fixWidth = function() {
this.getLightbox().style.width = image.width + "px";
}.bind(this);
if (!image.complete) {
Evt.add(image, "load", function(e) { 
setTimeout(function() {
fixWidth(); 
this.doOnClick(e, img);
this.showLightbox();
}.bind(this), 300);
}.bind(this));
} else {
fixWidth();
this.doOnClick(e, img);
this.showLightbox();
};
},
setup: function(container) {
$A(container.getElementsByTagName("img")).each(this.setupElement.bind(this));
},
setupElement: function(img) {
Evt.add(img.parentNode, "click", function(e) { this.onClick(e, img); }.bind(this));
var image = new Image();
image.src = this.getFullImage(img);
this._images.push(image);
}
});


page.c.onload(function(e) {
new FeatureGallery($("gallery"));
});

