Array.prototype.indexOf = function (value, offset) {
var len = this.length;
offset = offset || 0;
offset = offset < 0 ? Math.max(0, len + offset) : offset;
for (var i=offset; i<len; i++) {
if (this[i] === value) { return i; }
}
return -1;
}
Array.prototype.filter = function(func, scope) {
scope = scope || this;
var result = [], index = 0;
for (var i=0,l=this.lenth; i<l; l++) {
var item = this[i];
if (func.call(scope, item, i, this)) {
result[index++] = item;
}
}
return result;
};
Array.prototype.map = function(func, scope) {
scope = scope || this;
var result = [], index = 0;
for (var i=0,l=this.lenth; i<l; l++) {
result[index++] = func.call(scope, this[i], i, this);
}
return result;
};
String.prototype.trim = function() {
return this.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
};
String.prototype.toUcFirst = function() {
var str = this.toLowerCase();
return str.replace(/^([a-z])/g, function(x,l) { return l.toUpperCase() });
};
String.prototype.toUcWords = function() {
var str = this.toLowerCase();
return str.replace(/(^([a-z])|\s[a-z])/g, function(x,l) { return l.toUpperCase() });
};
String.prototype.toCamel = function() {
var str = this.toLowerCase();
return str.replace(/-([a-z])/g, function(x,l) { return l.toUpperCase() });
};
String.prototype.padLeft = function(len, chr) {
var str = this;
while (str.length < len) {
str = chr + str;
}
return str;
};
String.prototype.padRight = function(len, chr) {
var str = this;
while (str.length < len) {
str += chr;
}
return str;
};
String.prototype.truncate = function(size, noBreak) {
noBreak = !!noBreak;
var result = this, truncated = false;
if (size > 0 && this.length-1 > size) {
result = result.substring(0, size);
truncated = true;
}
noBreak && (result = result.replace(/(\r\n|\r|\n)+/g, '<br />'));
return truncated ? '<span class="caption" title="'+this+'">'+result+'<span class="dots">...</span></span>' : result;
};
Function.prototype.inherits = function(value) {
function temp() { };
temp.prototype = value.prototype;
this.prototype = new temp();
this.prototype.constructor = this;
this.parentClass = value;
};
var TDOM = {};
TDOM._onLoad = [];
TDOM.documentLoaded = false;
TDOM.UNIQUE_ID_PROPERTY = 'tdom_unique_id_property';
TDOM.UNIQUE_ID_COUNTER = 1;
TDOM.NodeType = { ELEMENT: 1, ATTRIBUTE: 2, TEXT: 3, CDATA_SECTION: 4, ENTITY_REFERENCE: 5, ENTITY: 6, PROCESSING_INSTRUCTION: 7, COMMENT: 8, DOCUMENT: 9, DOCUMENT_TYPE: 10, DOCUMENT_FRAGMENT: 11, NOTATION: 12 };
TDOM._doOnLoad = function(e) {
TDOM.documentLoaded = true;
TListener.remove(window,'load',TDOM._doOnLoad);
for (var i=0, l=TDOM._onLoad.length; i < l; i++) {
TDOM._onLoad[i].func.call(TDOM._onLoad[i].scope);
}
TDOM._onLoad = [];
}
TDOM.onLoad = function(f,scope) {
scope = scope || this;
TDOM.documentLoaded ? f.call(scope) : TDOM._onLoad.push({scope:scope, func:f});
}
TDOM.getElement = function(value,doc) {
doc = doc || document;
return typeof value == "string" ? doc.getElementById(value) : value;
};
TDOM.getDocument = function(node) {
node = TDOM.getElement(node) || document;
return node.nodeType == TDOM.NodeType.DOCUMENT ? node : node.ownerDocument || node.document || document;
};
TDOM.getRootNode = function(node) {
var doc = TDOM.getDocument(node);
return document.compatMode == 'CSS1Compat' ? doc.documentElement : doc.body;
};
TDOM.getWindow = function(node) {
if (node && typeof node.opener != 'undefined') { return node; }
var doc = TDOM.getDocument(node);
return doc.parentWindow || doc.defaultView || window;
};
TDOM.getUniqueId = function(el) {
var p = TDOM.UNIQUE_ID_PROPERTY;
if (el.hasOwnProperty && el.hasOwnProperty(p)) {
var value = el[p];
if (value) {
return value;
}
}
if (!el[p]) {
var value = TDOM.UNIQUE_ID_COUNTER++;
el[p] = value;
}
return el[p];
};
TDOM.resolveNode = function(node, property, test) {
test = test || function (n) { return n.nodeType == TDOM.NodeType.ELEMENT; }
property = property || 'nextSibling';
while (node)  {
if (test(node)) { return node; }
try {
node = node[property];
} catch(e) {
return null;
}
}
return node;
};
TDOM.nextElement = function(node) {
return TDOM.resolveNode(node.nextSibling);
};
TDOM.previousElement = function(node) {
return TDOM.resolveNode(node.previousSibling, 'previousSibling');
};
TDOM.firstChild = function(node) {
return TDOM.resolveNode(node.firstChild, 'nextSibling');
};
TDOM.lastChild = function(node) {
node = node.lastChild;
return TDOM.resolveNode(node, 'nextSibling') || TDOM.resolveNode(node, 'previousSibling');
};
TDOM.firstHiddenParent = function(node) {
return TDOM.resolveNode(node, 'parentNode', function(n) { return n.nodeType == TDOM.NodeType.ELEMENT && TStyle.get(n, "display") == "none" });
};
TDOM.insertElement = function(a, after, b) {
if (b && b.parentNode) {
c = after ? TDOM.nextElement(b) : b;
c ? b.parentNode.insertBefore(a,c) : b.parentNode.appendChild(a);
}
};
TDOM.createElement = function(name, attr) {
var el = document.createElement(name);
el && attr && TDOM.setAttributes(el,attr);
return el;
};
TDOM.setAttributes = function(el, attr) {
for (var a in attr) {
switch (a) {
case 'for': el.htmlFor = attr[a]; break;
case 'class': el.className = attr[a]; break;
case 'style': TStyle.setStyles(el, attr[a]); break;
default: el.setAttribute(a, attr[a]);
}
}
};
TDOM.setText = function(el, text) {
// #FIXME: incomplete
var node = node.nodeType == TDOM.NodeType.TEXT ? el : el.firstChild;
// Text node detected
if (node && node.nodeType == TDOM.NodeType.TEXT) {
node.data = text;
} else {
el.appendChild(document.createTextNode(text));
}
}
TDOM.getText = function(el) {
// #FIXME: incomplete
var node = node.nodeType == TDOM.NodeType.TEXT ? el : el.firstChild;
return node && node.nodeType == TDOM.NodeType.TEXT ? node.data = text : '';
}
TDOM.matchSize = function(rec, el) {
rec.width -= parseInt(TStyle.get(el,'paddingLeft'));
rec.width -= parseInt(TStyle.get(el,'paddingRight'));
rec.width -= parseInt(TStyle.get(el,'borderLeftWidth'));
rec.width -= parseInt(TStyle.get(el,'borderRightWidth'));
rec.height -= parseInt(TStyle.get(el,'paddingTop'));
rec.height -= parseInt(TStyle.get(el,'paddingBottom'));
rec.height -= parseInt(TStyle.get(el,'borderTopWidth'));
rec.height -= parseInt(TStyle.get(el,'borderBottomWidth'));
return rec;
};
TDOM.toLocalCoordinates = function(p, el) {
// Fix a given position object relative to an element
// Walk through each parent and sustract their top/left relative position if they are positioned as absolute, relative or fixed.
var parent = TDOM.getElement(el);
do {
parent = TDOM.resolveNode(parent.parentNode,'parentNode',function(n) { return n.nodeType == TDOM.NodeType.ELEMENT && TStyle.get(n,'position') != 'static'; });
if (parent) {
var point = TDOM.getPos(parent);
p.top -= point.top;
p.left -= point.left;
if (!TUserAgent.WEBKIT || TStyle.get(el,'position') != 'fixed') {
var bt = parseInt(TStyle.get(parent,'borderTopWidth'));
var bl = parseInt(TStyle.get(parent,'borderLeftWidth'));
p.top -= isNaN(bt) ? 0 : bt;
p.left -= isNaN(bl) ? 0 : bl;
}
}
} while(parent);
return p;
};
TDOM.getSize = function(el, forceVisible) {
el = TDOM.getElement(el);
// Ensure that the element is visible
forceVisible !== false && TStyle.ensureVisible(el);
// Calculate the size
var w = el.offsetWidth;
var h = el.offsetHeight;
// Restore element and parents previous states
forceVisible !== false && TStyle.restoreVisible(el);
return new TRect(0, 0, Math.round(w), Math.round(h));
};
TDOM.getPos = function(el, forceVisible, toLocalCoordinates) {
// Position of the element relative to the entire document
el = TDOM.getElement(el);
var doc = TDOM.getDocument(el), viewport = TDOM.getRootNode(doc), point = new TPoint();
if (el == viewport) { return point; }
var scroll = TDOM.getDocumentScroll(doc);
// Ensure that the element is visible
forceVisible !== false && TStyle.ensureVisible(el);
// IE, FF, Opera, etc
if (el.getBoundingClientRect) {
var box = el.getBoundingClientRect();
point.top = box.top + scroll.top;
point.left = box.left + scroll.left;
// Sustract 2 pixel offset for IE
if (TUserAgent.IE) { point.left -= 2; point.top -= 2; }
// Safari
} else {
var parent = el;
do {
point.top += parent.offsetTop;
point.left += parent.offsetLeft;
if (parent != el) {
point.top += parent.clientTop || 0;
point.left += parent.clientLeft || 0;
}
if (TStyle.get(parent,'position') == "fixed") {
point.top += scroll.top;
point.left += scroll.left;
break;
}
parent = parent.offsetParent;
} while (parent);
parent = el.parentNode;
while (parent && parent != doc.body) {
point.top -= parent.scrollTop;
point.left -= parent.scrollLeft;
parent = parent.parentNode;
}
}
toLocalCoordinates !== false && (point = TDOM.toLocalCoordinates(point,el));
// Restore element and parents previous states
forceVisible !== false && TStyle.restoreVisible(el);
return point;
};
TDOM.getBounds = function(el, forceVisible, toLocalCoordinates) {
el = TDOM.getElement(el);
// Ensure that the element is visible
forceVisible !== false && TStyle.ensureVisible(el);
var rec = TDOM.getSize(el, false), pos = TDOM.getPos(el, false, toLocalCoordinates);
rec.top = pos.top; rec.left = pos.left;
// Restore element and parents previous states
forceVisible !== false && TStyle.restoreVisible(el);
return rec;
};
TDOM.getDocumentScroll = function(node) {
var doc = TDOM.getDocument(node);
node = TDOM.getRootNode(node);
return new TPoint(Math.max(node.scrollTop,doc.body.scrollTop), Math.max(node.scrollLeft,doc.body.scrollLeft));
};
TDOM.getDocumentSize = function(node) {
var v = TDOM.getRootNode(node), s = TDOM.getViewportSize(node);
return new TRect(0,0,Math.max(v.scrollWidth, s.width), Math.max(v.scrollHeight, s.height));
};
TDOM.getViewportSize = function(node) {
var w = 0, h = 0, win = TDOM.getWindow(node);
// Safari
if (typeof win.innerWidth != 'undefined') {
w = win.innerWidth;
h = win.innerHeight;
// Others
} else {
node = TDOM.getRootNode(node);
w = node.clientWidth;
h = node.clientHeight;
}
return new TRect(0,0,w,h);
};
TDOM.getViewportBounds = function(node) {
var pos = TDOM.getDocumentScroll(node), rec = TDOM.getViewportSize(node);
rec.top = pos.top; rec.left = pos.left;
return rec;
};
TDOM.align = function(el,torec,alignment,fixposition) {
var t=0, l=0, rec1 = TDOM.getBounds(el);
switch (alignment) {
// Side alignments
case 'lt': t=torec.top; l=torec.left-rec1.width; break;
case 'lb': t=torec.top+torec.height-rec1.height; l=torec.left-rec1.width; break;
case 'lm': t=Math.round(torec.top+(torec.height/2)-(rec1.height/2)); l=torec.left-rec1.width; break;
case 'tl': t=torec.top-rec1.height; l=torec.left; break;
case 'tr': t=torec.top-rec1.height; l=torec.left+torec.width-rec1.width; break;
case 'tm': t=torec.top-rec1.height; l=Math.round(torec.left+(torec.width/2)-(rec1.width/2)); break;
case 'rt': t=torec.top; l=torec.left+torec.width; break;
case 'rb': t=torec.top+torec.height-rec1.height; l=torec.left+torec.width; break;
case 'rm': t=Math.round(torec.top+(torec.height/2)-(rec1.height/2)); l=torec.left+torec.width; break;
case 'bl': t=torec.top+torec.height; l=torec.left; break;
case 'br': t=torec.top+torec.height; l=torec.left+torec.width-rec1.width; break;
case 'bm': t=torec.top+torec.height; l=Math.round(torec.left+(torec.width/2)-(rec1.width/2)); break;
// Corners
case 'tlc': case 'ltc': t=torec.top-rec1.height; l=torec.left-rec1.width; break;
case 'blc': case 'lbc': t=torec.top+torec.height; l=torec.left-rec1.width; break;
case 'trc': case 'rtc': t=torec.top-rec1.height; l=torec.left+torec.width; break;
case 'brc': default:    t=torec.top+torec.height; l=torec.left+torec.width; break;
}
if (fixposition !== false) {
var rec2 = TDOM.getViewportBounds(el);
rec2 = TDOM.toLocalCoordinates(rec2,el);
// Fix top position if it get out of the bottom screen bound
if (t+rec1.height>rec2.top+rec2.height) { t=torec.top-rec1.height; }
// Fix top position if it get out of the top screen bound
if (t<rec2.top) { t=torec.top+torec.height; }
// Fix left position if it get out of the right screen bound
if (l+rec1.width>rec2.left+rec2.width) { l=torec.left-rec1.width; }
// Fix left position if it get out of the left screen bound
if (l<rec2.left) { l=torec.left+torec.width; }
}
var point = new TPoint(t,l);
el.style.top = point.top+'px';
el.style.left = point.left+'px';
return point;
};
TStyle= {};

TStyle._visibleStack = {};

TStyle.get = function(el, attr) {
var doc = TDOM.getDocument(el);
// W3C computed style
if (doc.defaultView && doc.defaultView.getComputedStyle) {
var styles = doc.defaultView.getComputedStyle(el, "");
if (styles) {
if (attr == 'float') {
attr = 'cssFloat';
} else
if (attr == 'opacity') {
attr = "opacity" in styles ? "opacity" : ("MozOpacity" in styles ? "MozOpacity" : ("KhtmlOpacity" in styles ? "KhtmlOpacity" : attr));
}
return styles[attr];
}
} else
// IE current style
if (el.currentStyle) {
if (attr == 'opacity' && el.filters) {
var val=100;
try {
val = el.filters['DXImageTransform.Microsoft.Alpha'].opacity;
} catch(e) {
try {
val = el.filters('alpha').opacity;
} catch(e) { }
}
return val/100;
}
attr = attr == 'float' ? 'styleFloat' : attr;
return el.currentStyle[attr];
}
// Element Atribute
return el.style[attr];
};

TStyle.set = function(el, attr, value) {
if (attr == 'opacity') {
if (value < 0 || value > 1) {
return;
}
if ("opacity" in el.style) {
el.style.opacity = value;
} else
if ("MozOpacity" in el.style) {
el.style.MozOpacity = value;
} else
if ("KhtmlOpacity" in el.style) {
el.style.KhtmlOpacity = value;
} else
if ("filter" in el.style) {
el.style.filter = "alpha(opacity=" + value * 100 + ")";
}
return;
}
if (attr == 'float') {
attr = TUserAgent.IE ? 'styleFloat' : 'cssFloat';
}
el.style[attr] = value;
};

TStyle.setStyles = function(el, attrs) {
attrs = attrs.split(/\s*?;\s*?/);
for (var i=0,l=attrs.length; i<l; i++) {
attr = attrs[i];
attr = attr.split(/\s*?:\s*?/);
TStyle.set(el,attr[0].toCamel().trim(),attr[1].trim());
}
};

TStyle.setUnselectable = function(el, value, recursion) {
if (TUserAgent.GECKO) {
el.style['MozUserSelect'] = value ? 'none' : '';
} else
if (TUserAgent.WEBKIT) {
el.style['WebkitUserSelect'] = value ? 'none' : '';
} else {
value ? el.setAttribute("unselectable", "on") : el.removeAttribute("unselectable");
}
if (recursion !== false) {
el = TDOM.firstChild(el);
while (el) {
TStyle.setUnselectable(el, value, recursion);
el = TDOM.nextElement(el);
}
}
}

TStyle.isVisible = function(node) {
return TDOM.firstHiddenParent(node) == null;
};

TStyle.ensureVisible = function(el) {
var id = TDOM.getUniqueId(el);
// Make it visible once
if (id && !TStyle._visibleStack[id]) {
// Check if its not already visible
var parent = TDOM.firstHiddenParent(el);
if (parent) {
// Make it visible and store his and his parent current values
TStyle._visibleStack[id] = [];
while (parent) {
TStyle._visibleStack[id].push([parent, parent.style.display, parent.style.position, parent.style.visibility]);
parent.style.visibility = "hidden";
// #FIXME: must check this with floated elements, it could change top/left values on some browsers
parent.style.position = "absolute";
parent.style.display = "block";
parent = TDOM.firstHiddenParent(parent.parentNode);
}
}
}
}

TStyle.restoreVisible = function(el) {
var id = TDOM.getUniqueId(el);
if (id && TStyle._visibleStack[id]) {
var parent = TStyle._visibleStack[id].shift();
while (parent) {
parent[0].style.display = parent[1];
parent[0].style.position = parent[2];
parent[0].style.visibility = parent[3];
parent = TStyle._visibleStack[id].shift();
}
}
TStyle._visibleStack[id] = false;
}
TClasses = {};

TClasses.has = function(el,value) {
var re = new RegExp('(^|\\s+)' + value + '(\\s+|$)');
return re.test(el.className);
};

TClasses.add = function(el,value) {
if (TClasses.has(el,value)) return;
if (!el.className) {
el.className = value;
} else {
el.className = [el.className.trim(), value].join(' ');
}
};

TClasses.remove = function(el,value) {
var re = new RegExp('(^|\\s+)?' + value + '(\\s+|$)?','g');
el.className = el.className.replace(re,' ').trim();
};

TClasses.toggle = function(el, value) {
var set = !TClasses.has(el,value);
TClasses[set ? 'add' : 'remove'](el,value);
};

TClasses.swap = function(el, class1, class2) {
if (!TClasses.has(el, class1)) {
TClasses.add(class2);
} else {
var re = new RegExp('(^|\\s+)?' + class1 + '(\\s+|$)?','g');
el.className = el.className.replace(re,class2).trim();
}
};
var TUserAgent = {};
TUserAgent.AGENT = navigator.userAgent;
TUserAgent.PLATFORM = navigator.platform;
TUserAgent.WEBKIT = TUserAgent.AGENT.indexOf('WebKit') != -1;
TUserAgent.GECKO = TUserAgent.AGENT.indexOf('Gecko') != -1;
TUserAgent.OPERA = typeof opera != "undefined";
TUserAgent.IE = TUserAgent.AGENT.indexOf('MSIE') != -1;
TUserAgent.FIREFOX = TUserAgent.AGENT.indexOf('Firefox') != -1;
TUserAgent.CHROME = TUserAgent.AGENT.indexOf('Chrome') != -1;
TUserAgent.SAFARI = TUserAgent.AGENT.indexOf('Safari') == -1 && !TUserAgent.CHROME;
TUserAgent.KONQUEROR = TUserAgent.AGENT.indexOf('Konqueror') != -1;
TUserAgent.MAC = TUserAgent.PLATFORM.indexOf('Mac');
TUserAgent.WIN = TUserAgent.PLATFORM.indexOf('Win');
TUserAgent.LINUX = TUserAgent.PLATFORM.indexOf('Linux');
TUserAgent.VERSION = 0;

// Calculate browser version depending on user agent
var matches = TUserAgent.AGENT.match(/WebKit\/([^\s]*)/);
if (matches && matches[1]) { TUserAgent.VERSION = parseFloat(matches[1]); };
matches = TUserAgent.AGENT.match(/Opera( Mini)?[\s\/]([^\s]*)/);
if (matches && matches[2]) { TUserAgent.VERSION = parseFloat(matches[2]); };
matches = TUserAgent.AGENT.match(/MSIE\s([^;]*)/);
if (matches && matches[1]) { TUserAgent.VERSION = parseFloat(matches[1]); };
matches = TUserAgent.AGENT.match(/Gecko\/([^\s]*)/);
if (matches && matches[1]) {
TUserAgent.VERSION = parseFloat(matches[1]);
matches = TUserAgent.AGENT.match(/rv:([^\s\)]*)/);
if (matches && matches[1]) { TUserAgent.VERSION = parseFloat(matches[1]); }
};
var TPoint = function (top,left) {
this.top = top || 0;
this.left = left || 0;
}

TPoint.prototype.top = 0;
TPoint.prototype.left = 0;

TPoint.prototype.toString = function() {
return "Top: " + this.top + "\nLeft: " + this.left;
}
var TRect = function (top,left,width,height) {
this.top = top || 0;
this.left = left || 0;
this.width = width || 0;
this.height = height || 0;
}
TRect.inherits(TPoint);
TRect.prototype.width = 0;
TRect.prototype.height = 0;

TRect.prototype.toString = function() {
return "Top: " + this.top + "\nLeft: " + this.left + "\nWidth: " + this.width + "\nHeight: " + this.height;
}
var TObject = function () { };

TObject.parentClass = null;
TObject.prototype.className = 'TObject';

TObject.prototype.free = function () { };

TObject.prototype.instanceOf = function(aClass) {
return this instanceof aClass;
}
var TComponent = function (id) {
TObject.prototype.constructor.call(this);
this.id = id || this.getName();
};
TComponent.inherits(TObject);

TComponent._counters = [];
TComponent.prototype.id = null;
TComponent.prototype.className = 'TComponent';

TComponent.prototype.free = function () {
TListener.removeAll(this);
};

TComponent.prototype.getName = function() {
if (this.id === null) {
var count = TComponent._counters[this.className] || 1;
this.id = this.className+(count++);
TComponent._counters[this.className] = count;
}
return this.id;
};

TComponent.prototype.listen = function (type, callback, scope, capture) {
TListener.add(this, type, callback, scope || this, capture);
};

TComponent.prototype.unlisten = function (type, callback, scope, capture) {
TListener.remove(this, type, callback, scope || this, capture);
};

TComponent.prototype.dispatch = function (event) {
event = typeof event == 'string' ? new TEvent(event) : event;
return TListener.dispatch(this, event);
};
var TControl = function(element,listeners) {
this._parent = null;
this._inlineScript = {};
this.element = TDOM.getElement(element) || this._createElement();
TComponent.prototype.constructor.call(this);
TClasses.add(this.element, this.className);

this.focusable(true);
this._parseElement(this.element);
this._parseClasses(this.element);
this.element.setAttribute('role', this.role);
if (listeners !== false) {
this.focusable() && this._enableFocusListeners(true);
(this._controlStyles & TControl.Style.KEYEVENTS) && this._enableKeyListeners(true);
(this._controlStyles & TControl.Style.MOUSEEVENTS) && this._enableMouseListeners(true);
(this._controlStyles & TControl.Style.DOUBLECLICK) && this._enableDoubleclickListeners(true);
}
};
TControl.inherits(TComponent);

/* ------------------------------------------------------------------------------- */

TControl.Style = { FOCUSABLE: 1, KEYEVENTS: 2, MOUSEEVENTS: 4, DOUBLECLICK: 8 };
TControl.State = { DOWN: 1, HOVER: 2, HIDDEN: 4, OPENED: 8, ACTIVE: 16, CHECKED: 32, PRESSED: 64, SELECTED: 128, DISABLED: 256, READONLY: 512, DEFAULT:1024, HASPOPUP:2048 };

TControl.AutoState = { };
TControl.AutoState['down']     = function() { if (this.support(TControl.State.DOWN, true)) { this.down(true); return true; } };
TControl.AutoState['opened']   = function() { if (this.support(TControl.State.OPENED, true)) { this.opened(true); return true; } };
TControl.AutoState['hidden']   = function() { if (this.support(TControl.State.HIDDEN, true)) { this.visible(false); return true; } };
TControl.AutoState['active']   = function() { if (this.support(TControl.State.ACTIVE, true)) { this.active(true); return true; } };
TControl.AutoState['focused']  = function() { if (this.support(TControl.State.ACTIVE, true)) { this.focused(true); return true; } };
TControl.AutoState['checked']  = function() { if (this.support(TControl.State.CHECKED, true)) { this.checked(true); return true; } };
TControl.AutoState['selected'] = function() { if (this.support(TControl.State.SELECTED, true)) { this.selected(false); return true; } };
TControl.AutoState['disabled'] = function() { if (this.support(TControl.State.DISABLED, true)) { this.enabled(false); return true; } };
TControl.AutoState['readonly'] = function() { if (this.support(TControl.State.READONLY, true)) { this.readonly(true); return true; } };

TControl.StateAria = { };
TControl.StateAria[TControl.State.DOWN] = 'pressed';
TControl.StateAria[TControl.State.HIDDEN] = 'hidden';
TControl.StateAria[TControl.State.OPENED] = 'expanded';
TControl.StateAria[TControl.State.CHECKED] = 'checked';
TControl.StateAria[TControl.State.SELECTED] = 'selected';
TControl.StateAria[TControl.State.DISABLED] = 'disabled';
TControl.StateAria[TControl.State.READONLY] = 'readonly';
TControl.StateAria[TControl.State.HASPOPUP] = 'haspopup';

TControl.StateClass = { };
TControl.StateClass[TControl.State.DOWN] = 'down';
TControl.StateClass[TControl.State.HOVER] = 'hover';
TControl.StateClass[TControl.State.OPENED] = 'opened';
TControl.StateClass[TControl.State.ACTIVE] = 'active';
TControl.StateClass[TControl.State.CHECKED] = 'checked';
TControl.StateClass[TControl.State.DEFAULT] = 'default';
TControl.StateClass[TControl.State.PRESSED] = 'pressed';
TControl.StateClass[TControl.State.SELECTED] = 'selected';
TControl.StateClass[TControl.State.DISABLED] = 'disabled';
TControl.StateClass[TControl.State.READONLY] = 'readonly';
TControl.StateClass[TControl.State.HASPOPUP] = 'haspopup';

/* ------------------------------------------------------------------------------- */

TControl.prototype.role = 'widget';
TControl.prototype.popup = null;
TControl.prototype.element = null;
TControl.prototype._parent = null;
TControl.prototype.className = 'TControl';
TControl.prototype._inlineScript = {};
TControl.prototype._controlStates = 0;
TControl.prototype._controlStyles = TControl.Style.FOCUSABLE | TControl.Style.KEYEVENTS | TControl.Style.MOUSEEVENTS;
TControl.prototype._supportedStates = TControl.State.HOVER | TControl.State.DISABLED | TControl.State.HIDDEN | TControl.State.PRESSED;

/* ------------------------------------------------------------------------------- */

TControl.prototype.free = function () {
this.parent(null);
this.element = null;
TControl.prototype.free.call(this);
};

TControl.prototype.getName = function() {
return this.element.id || (this.element.id = TComponent.prototype.getName.call(this));
};

/* ------------------------------------------------------------------------------- */

TControl.prototype._parseElement = function(el) {
var child = TDOM.firstChild(el), ids=[];
while (child) {
ids = child.id.indexOf(':') != -1 ? child.id.split(':') : [child.id];
this._parseChild(child,ids[0]);
child = TDOM.nextElement(child);
}
};

TControl.prototype._parseClasses = function(el) {
var classes = el.className;
var re = new RegExp(this.className+"-(.+?)(\\s|$)",'g');
while (match = re.exec(classes)) {
match = match[1].trim();
if (!TControl.AutoState[match] || !TControl.AutoState[match].call(this)) {
this._parseCustomClass(match);
}
}
};

TControl.prototype._parseChild = function(el,token) {
return false;
};

TControl.prototype._parseCustomClass = function(value) {
return false;
};

TControl.prototype._setStateClass = function(method,value) {
TClasses[method](this.element, this.className+'-'+value);
};

TControl.prototype._createElement = function() {
return document.createElement('div');
};

TControl.prototype._parentEnabled = function() {
return !this._parent || this._parent.enabled();
};

/* ------------------------------------------------------------------------------- */

TControl.prototype.parent = function(value) {
if (typeof value != 'undefined' && value instanceof TContainer && this._parent != value) {
value ? value.appendChild(this) : (this._parent && this._parent.removeChild(this));
this._parent = value;
}
return this._parent;
};

TControl.prototype.state = function(state,value) {
if (typeof value != 'undefined') {
value = value ? true : false;
if (this.support(state, value)) {
TControl.StateAria[state] && this.element.setAttribute('aria-'+TControl.StateAria[state], value);
TControl.StateClass[state] && this._setStateClass(value ? 'add' : 'remove', TControl.StateClass[state]);
this._controlStates = value ? this._controlStates | state : this._controlStates & ~state;
}
}
return !!(this._controlStates & state);
};

TControl.prototype.support = function(state,value) {
var result = !!(this._supportedStates & state);
result = result && (typeof value != 'undefined' ? value != this.state(state) : result);
return  result;
};

/* ------------------------------------------------------------------------------- */

TControl.prototype.setPopup = function(value) {
if (value instanceof TPopupMenu) {
this.element.oncontextmenu = function() { return false; }
this.element.setAttribute('aria-haspopup',true);
this.element.setAttribute('aria-owns',value.id);
this.popup = value;
}
};

/* ------------------------------------------------------------------------------- */

TControl.prototype.active = function(value) {
typeof value != 'undefined' && this.active() != value && this.enabled() && this.visible() && this._doActive(value);
return this.state(TControl.State.ACTIVE);
};

TControl.prototype.hover = function(value) {
typeof value != 'undefined' && this.hover() != value && this._doHover(value);
return this.state(TControl.State.HOVER);
};

TControl.prototype.focused = function(value) {
typeof value != 'undefined' && this.focusable() && this.focused() != value && this._doFocused(value);
return this.state(TControl.State.ACTIVE);
};

TControl.prototype.focusable = function(value) {
typeof value != 'undefined' && this.focusable() != value && (this._controlStyles & TControl.Style.FOCUSABLE) && this._doFocusable(value);
return !!(this._supportedStates & TControl.State.ACTIVE);
};

TControl.prototype.visible = function(value) {
typeof value != 'undefined' && this.support(TControl.State.HIDDEN,!value) && this.dispatch(new TEvent(value ? 'show': 'hide')) && this._doVisible(value);
return !this.state(TControl.State.HIDDEN);
};

TControl.prototype.enabled = function(value) {
typeof value != 'undefined' && this.support(TControl.State.DISABLED,!value) && (value ? (this._parentEnabled() && this.dispatch(new TEvent('enable')) && this._doEnabled(true)) : (this.dispatch(new TEvent('disable')) && this._doEnabled(false)));
return !this.state(TControl.State.DISABLED);
};

TControl.prototype.pressed = function(value) {
typeof value != 'undefined' && this.support(TControl.State.PRESSED, value) && this.dispatch(new TEvent(value ? 'press': 'release')) && this._doPressed(value);
return this.state(TControl.State.PRESSED);
};

TControl.prototype.show = function() {
this.visible(true);
};

TControl.prototype.hide = function() {
this.visible(false);
};

/* ------------------------------------------------------------------------------- */

TControl.prototype._doActive = function(value) {
this.state(TControl.State.ACTIVE, value);
this._parent && this._parent.setActive && this._parent.setActive(this,value);
};

TControl.prototype._doHover = function(value) {
this.state(TControl.State.HOVER, value);
};

TControl.prototype._doFocused = function(value) {
value && this.element.focus();
};

TControl.prototype._doFocusable = function(value) {
//this.element.hideFocus = value;
//this.element.style.outline = value ? 'none' : '';
!value && this.focused(false);
this.element.setAttribute('tabIndex', value ? 0 : -1);
this._supportedStates = value ? (this._supportedStates | TControl.State.ACTIVE) : (this._supportedStates & ~TControl.State.ACTIVE);
}

TControl.prototype._doVisible = function(value) {
this.element.style.display = value ? '' : 'none';
this.state(TControl.State.HIDDEN, !value);
!value && this._parent && this._parent.setActive && this._parent.setActive(this,false);
}

TControl.prototype._doEnabled = function(value) {
if (!value) {
this.hover(false);
this.pressed(false);
this._parent && this._parent.setActive && this._parent.setActive(this,false);
}
this.focusable(value);
this.state(TControl.State.DISABLED, !value);
};

TControl.prototype._doPressed = function(value) {
this.state(TControl.State.PRESSED, value);
};

TControl.prototype._doPopup = function(e) {
if (this.popup && e.buttons.right) {
/*this.popup.popup(e.screenX, e.screenY);
e.preventDefault();
e.stopPropagation();
return true;*/
}
};

TControl.prototype._doInlineScript = function(e) {
var script = this._inlineScript[e.type];
if (!script && typeof this.element['on'+e.type] == 'function') {
script = this._inlineScript[e.type] = this.element['on'+e.type];
this.element['on'+e.type] = function() { return false; };
}
return !script || script.call(this.element,e) !== false;
};

/* ------------------------------------------------------------------------------- */

TControl.prototype._onFocus = function(e) {
var result = this.dispatch(e) && this._doInlineScript(e);
this.active(true);
return result;
};

TControl.prototype._onBlur = function(e) {
var result = this.dispatch(e) && this._doInlineScript(e);
this.pressed(false);
this.active(false);
return result;
};

/* ------------------------------------------------------------------------------- */

TControl.prototype._onKeydown = function(e) {
this.enabled() && this.dispatch(e) && this._doInlineScript(e);
};

TControl.prototype._onKeyup = function(e) {
this.enabled() && this.dispatch(e) && this._doInlineScript(e);
};

TControl.prototype._onKeypress = function(e) {
this.enabled() && this.dispatch(e) && this._doInlineScript(e);
};

/* ------------------------------------------------------------------------------- */

TControl.prototype._onMouseover = function(e) {
this.enabled() && this.dispatch(e) && this._doInlineScript(e) && this.hover(true);
};

TControl.prototype._onMouseout = function(e) {
this.enabled() && this.dispatch(e) && this._doInlineScript(e);
this.pressed(false);
this.hover(false);
};

TControl.prototype._onMousedown = function(e) {
this.dispatch(e) && this._doInlineScript(e);
if (this.enabled() && !e.canceled && e.buttons.left) {
this.pressed(true);
this.focused(true);
this.active(true);
}
};

TControl.prototype._onMouseup = function(e) {
this.dispatch(e) && this._doInlineScript(e);
if (!e.canceled && this.pressed()) {
this._doPopup(e);
this._onClick(e);
}
this.pressed(false);
};

/* ------------------------------------------------------------------------------- */

TControl.prototype._onClick = function(e) {
e.type = 'click';
this.enabled() && this.dispatch(e) && this._doInlineScript(e);
};

TControl.prototype._onDblclick = function(e) {
this.enabled() && this.dispatch(e) && this._doInlineScript(e);
};

/* ------------------------------------------------------------------------------- */

TControl.prototype._enableFocusListeners = function(value) {
var el = this.element, method = value ? 'add' : 'remove';
TListener[method](el, 'blur', this._onBlur, this);
TListener[method](el, 'focus', this._onFocus, this);
};

TControl.prototype._enableKeyListeners = function(value) {
var el = this.element, method = value ? 'add' : 'remove';
TListener[method](el, 'keyup', this._onKeyup, this);
TListener[method](el, 'keydown', this._onKeydown, this);
TListener[method](el, 'keypress', this._onKeypress, this);
};

TControl.prototype._enableMouseListeners = function(value) {
var el = this.element, method = value ? 'add' : 'remove';
TListener[method](el, 'mouseup', this._onMouseup, this);
TListener[method](el, 'mouseout', this._onMouseout, this);
TListener[method](el, 'mousedown', this._onMousedown, this);
TListener[method](el, 'mouseover', this._onMouseover, this);
};

TControl.prototype._enableDoubleclickListeners = function(value) {
var el = this.element, method = value ? 'add' : 'remove';
TListener[method](el, 'dblclick', this._onDblclick, this);
};
var TContainer = function (element,listeners) {
this.childs = [];
TControl.prototype.constructor.call(this,element,listeners);

if (this.body) {
this.body.id = this.id+'Body';
TClasses.add(this.body,this.className+'-body');
} else {
this.body = this.element;
}
if (this.label) {
this.label.id = this.id+'Label';
TClasses.add(this.label,this.className+'-label');
this.element.setAttribute('aria-labelledby',this.label.id);
}
};
TContainer.inherits(TControl);

/* ------------------------------------------------------------------------------- */

TContainer.ZIndexTop = 0;
TContainer.ZIndexStart = 5000;

/* ------------------------------------------------------------------------------- */

TContainer.prototype.role = 'group';
TContainer.prototype.body = null;
TContainer.prototype.label = null;
TContainer.prototype.childs = [];
TContainer.prototype.className = 'TContainer';
TContainer.prototype.activeIndex = -1;
TContainer.prototype.cancelIndex = -1;
TContainer.prototype.defaultIndex = -1;
TContainer.prototype._allowedChilds = TControl;
TContainer.prototype._controlStyles &= ~TControl.Style.FOCUSABLE;

/* ------------------------------------------------------------------------------- */

TContainer.prototype.free = function() {
for (var i=this.childs.length-1; i>=0; i--) {
var child = this.removeChild(i);
child.free();
}
this.body = null;
this.label = null;
TControl.prototype.free.call(this);
};

/* ------------------------------------------------------------------------------- */

TContainer.prototype._parseChild = function(el,token) {
switch (token) {
case 'body': this._setBody(el); break;
case 'label': this._setLabel(el); break;
default: this._setControl(el);
}
};

TContainer.prototype._setBody = function(el) {
this.body && this.body.setAttribute('role', 'presentation');
this.body = el;
this._parseElement(el);
};

TContainer.prototype._setLabel = function(el) {
this.label && this.label.setAttribute('role', 'presentation');
this.label = el;
this._parseElement(el);
};

TContainer.prototype._setControl = function(el) {
var re = new RegExp("T([a-zA-Z0-9]+?)(\\s|$)");
match = el.className && re.exec(el.className);
if (match && typeof window['T'+match[1]] == 'function') {
var ctrl = new window['T'+match[1]](el,false);
ctrl instanceof this._allowedChilds && this._insertChild(ctrl,this.childs.length);
}
};

TContainer.prototype._setStateClass = function(method,value) {
TControl.prototype._setStateClass.call(this,method,value);
this.label && TClasses[method](this.label, this.className+'-label-'+value);
this.body != this.element && TClasses[method](this.label, this.className+'-body-'+value);
};

TContainer.prototype._insertChild = function(control,index) {
var activeControl = this.childs[this.activeIndex];
control._parent = this;
this.enabled() || control.enabled(false);
this.childs.splice(index,0,control);
control.focusable() && control._enableFocusListeners(true);
activeControl && this.setActive(this.indexOf(activeControl));
};

/* ------------------------------------------------------------------------------- */

TContainer.prototype.indexOf = function(control) {
control = TDOM.getElement(control);
if (control) {
do {
if (control.id) {
for (var i=0, l=this.childs.length; i<l; i++) {
if (this.childs[i].id == control.id) { return i; }
}
}
control = control instanceof TControl ? control._parent : control.parentNode;
} while (control && control != this && control != this.body);
}
return -1;
}

TContainer.prototype.appendChild = function(control) {
return this.addChildAt(control, this.childs.length);
};

TContainer.prototype.addChildAt = function(control,index) {
if (control instanceof this._allowedChilds) {
var parent = control._parent;
index = index < 0 ? 0 : (index > this.childs.length ? this.childs.length : index);
// Remove the control from his previous container.
if (parent && parent == this) {
// If the control parent is this container then move the control to his new index and exit.
// You should not call addChild or addChildAt to move a control, use the <code>moveChild</code> method instead.
this.moveChild(control, index);
return;
}
// Insert the control
this._insertChild(control,index)
var next = this.childs[index+1];
next ? this.body.insertBefore(control.element, next.element) : this.body.appendChild(control.element);
return true;
}
return false;
};

TContainer.prototype.moveChild = function(from,to) {
from = typeof from == 'number' ? from : this.indexOf(from);
if (from != to && this.childs[from]) {
var control = this.childs[from];
this.childs.splice(from,1);
this.childs.splice(to,0,control);
var next = this.childs[to+1];
next ? this.body.insertBefore(control.element, next.element) : this.body.appendChild(control.element);
}
};

TContainer.prototype.removeChild = function(control) {
var index = typeof control == 'number' ? control : this.indexOf(control);
control = this.childs[index];
if (control) {
this.childs.splice(index,1);
this.body.removeChild(control.element);
control._parent = null;
}
return control;
};

/* ------------------------------------------------------------------------------- */

TContainer.prototype.getNextAvailable = function(index,lookbackward) {
var nextid = typeof index == 'number' ? index+1 : this.activeIndex+1;
while (this.childs[nextid]) {
var c = this.childs[nextid];
if (c.visible() && c.enabled()) { return nextid; }
nextid++;
}
return lookbackward !== false ? this.getPreviousAvailable(index,false) : -1;
};

TContainer.prototype.getPreviousAvailable = function(index,lookforward) {
var previd = typeof index == 'number' ? index-1 : this.activeIndex-1;
while (this.childs[previd]) {
var c = this.childs[previd];
if (c.visible() && c.enabled()) { return previd; }
previd--;
}
return lookforward !== false ? this.getNextAvailable(index,false) : -1;
};

/* ------------------------------------------------------------------------------- */

TContainer.prototype.setCancel = function(value) {
value = typeof value == 'number' ? value : this.indexOf(value);
this.cancelIndex = value;
};

TContainer.prototype.setDefault = function(value) {
value = typeof value == 'number' ? value : this.indexOf(value);
this.childs[this.defaultIndex] && this.childs[this.defaultIndex].state(TControl.State.DEFAULT,false);
this.childs[value] && this.childs[value].state(TControl.State.DEFAULT,true);
this.defaultIndex = value;
};

TContainer.prototype.setActive = function(index,value) {
if (!this.enabled()) { return; }
value = value !== false;
index = typeof index == 'number' ? index : this.indexOf(index);
if (!value || index == this.activeIndex) { return; }
var item = this.childs[index], active = this.childs[this.activeIndex];
if (!item || !item.enabled() || !item.visible()) {
if (this.focusable()) {
// Look forward and backward for next available item
index = index <= 0 ? 0 : (index > this.childs.length-1 ? this.childs.length-1 : index);
index = index > this.activeIndex ? this.getNextAvailable(index) : this.getPreviousAvailable(index);
} else {
index = -1;
}
}
item = index != this.activeIndex && this.childs[index];
this.activeIndex = index;
active && active.active(false);
return !!item && item.active(true);
};

/* ------------------------------------------------------------------------------- */

TContainer.prototype._doEnabled = function(value) {
TControl.prototype._doEnabled.call(this,value);
for (var i=0,l=this.childs.length; i<l; i++) {
this.childs[i].enabled(value);
}
};

TContainer.prototype._doDefaultAction = function(e,method) {
if (e.keyCode == 13 && this.childs[this.defaultIndex]) {
// Default action
this.childs[this.defaultIndex][method](e);
e.preventDefault();
return false;
} else
if (e.keyCode == 27 && this.childs[this.cancelIndex]) {
// Cancel action
e.keyCode = 13;
this.childs[this.cancelIndex][method](e);
e.preventDefault();
return false;
}
return true;
};

TContainer.prototype._doContainerMousedownSetActive = function(e,index) {
this.setActive(index);
if (this.focusable()) {
this.focused(true);
// Check if browser support focused container (Safari does not) and cancel the default focus behavior
if (this.focused()) {
e.preventDefault();
e.canceled = false;
}
// IE does not prevent default focus behavior when clicked on a link or other focusable element
// Thats why we set a timeout to restore the focus to the container
if (TUserAgent.IE) {
var This = this;
setTimeout(function() { This.focusable() && This.focused(true); },0);
}
}
};

/* ------------------------------------------------------------------------------- */

TContainer.prototype._onFocus = function(e) {
var result = TControl.prototype._onFocus.call(this,e);
if (result) {
var item = this.childs[this.activeIndex] || this.childs[0];
item && item.active(true);
}
return result;
}

TContainer.prototype._onBlur = function(e) {
var result = TControl.prototype._onBlur.call(this,e);
if (result) {
var This = this;
var item = this.childs[this.activeIndex];
setTimeout(function() { !This.focused() && item && item.active(false); }, 100);
}
return result;
}

/* ------------------------------------------------------------------------------- */

TContainer.prototype._onKeydown = function(e) {
if (this.enabled()) {
var item = this.childs[this.indexOf(e.target)], active = this.childs[this.activeIndex];
item = item || (active && active.active() ? active : null);
item ? item._onKeydown(e) : TControl.prototype._onKeydown.call(this,e);
!e.canceled && this._doDefaultAction(e,'_onKeydown');
}
};

TContainer.prototype._onKeyup = function(e) {
if (this.enabled()) {
var item = this.childs[this.indexOf(e.target)], active = this.childs[this.activeIndex];
item = item || (active && active.active() ? active : null);
item ? item._onKeyup(e) : TControl.prototype._onKeyup.call(this,e);
!e.canceled && this._doDefaultAction(e,'_onKeyup');
}
};

TContainer.prototype._onKeypress = function(e) {
/*if (this.enabled()) {
var item = this.childs[this.indexOf(e.target)], active = this.childs[this.activeIndex];
item = item || (active && active.active() ? active : null);
item ? item._onKeypress(e) : TControl.prototype._onKeypress.call(this,e);
}*/
};

/* ------------------------------------------------------------------------------- */

TContainer.prototype._onMousedown = function(e) {
var index = this.indexOf(e.target), item = this.childs[index];
this._doContainerMousedownSetActive(e,item ? index : this.activeIndex);
item ? item._onMousedown(e) : TControl.prototype._onMousedown.call(this,e);
};

TContainer.prototype._onMouseup = function(e) {
var index = this.indexOf(e.target), item = this.childs[index];
item ? item._onMouseup(e) : TControl.prototype._onMouseup.call(this,e);
};

TContainer.prototype._onMouseover = function(e) {
if (this.enabled()) {
var index = this.indexOf(e.target), item = this.childs[index];
item ? item._onMouseover(e) : TControl.prototype._onMouseover.call(this,e);
}
};

TContainer.prototype._onMouseout = function(e) {
if (this.enabled()) {
var index = this.indexOf(e.target), item = this.childs[index];
item ? item._onMouseout(e) : TControl.prototype._onMouseout.call(this,e);
}
};

TContainer.prototype._onDblclick = function(e) {
if (this.enabled()) {
var index = this.indexOf(e.target), item = this.childs[index];
item ? item._onDblclick(e) : TControl.prototype._onDblclick.call(this,e);
}
};
var TFlash = function(name, movie, width, height) {
this._vars = [];                        // Flashvars
this._eattrs = {};                      // Embed attributes
this._oattrs = {};                      // Object attributes
this._params = {};                      // Object or embed params

this.name = name;                       // ID or name of the movie object
this.movie = movie;                     // Movie file in server
this.width = width;                     // Movie width in document
this.height = height;                   // Movie height in document
this.version = '9,0,0,0';               // Set movie player version
this.transparent = false;               // Set movie transparency on
this.preventcache = false;              // Try to prevento loading cached movie

// Set some standar attributes
this.set('id', name);
this.set('src', movie);
this.set('menu', false);
this.set('quality', 'high');
this.set('allowScriptAccess','sameDomain');
this.set('type', 'application/x-shockwave-flash');
this.set('classid', 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000');
this.set('pluginspage', 'http://www.macromedia.com/go/getflashplayer');
}
TFlash.GlobalContainer = null;

TFlash.prototype.addVar = function(name, value) {
this._vars.push(name + '=' + escape(value));
}

TFlash.prototype.addVars = function(vars) {
if (vars) {
vars = vars.split('&');
for (var i=0, c=vars.length; i < c; i++) {
this._vars.push(vars[i]);
}
}
}

TFlash.draw = function(movie, width, height, transparent, vars) {
var swf = new TFlash('', movie, width, height);
swf.transparent = transparent ? true : false;
swf.addVars(vars);
swf.draw();
}

TFlash.prototype.draw = function(container) {
var html = this.toHTML();
container = typeof container != 'undefined' ? TDOM.getElement(container) : null;
container ? container.innerHTML=html : document.write(html);
}

TFlash.prototype.toHTML = function() {
// Prevent caching
if (this.preventcache) {
var src = this._params["movie"];
src += src.indexOf('?') != -1 ? '&' : '?';
src += Math.random();
this.set('src', src);
}
// Set some attributes
this.set('width', this.width);
this.set('height', this.height);
this.set('wmode', this.transparent ? 'transparent' : 'window');
this.set('codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=' + this.version);
// FlashVars
if (this._vars.length > 0) {
this.addVars(this._params['flashvars']);
this.set('flashvars', this._vars.join('&'));
}
// Create HTML code
var html = '';
if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length) {
html += '<embed ';
for (var i in this._eattrs) {
html += i + '="' + this._eattrs[i] + '" ';
}
html += '> </embed>';
} else {
html += '<object ';
for (var i in this._oattrs) {
html += i + '="' + this._oattrs[i] + '" ';
}
html += '>';
for (var i in this._params) {
html += '<param name="' + i + '" value="' + this._params[i] + '" /> ';
}
html += '</object>';
}
return html;
}

TFlash.prototype.set = function(name, value) {
switch (name){
case "classid": this._oattrs[name] = value; break;
case "pluginspage": this._eattrs[name] = value; break;
case "src":
case "movie": this._eattrs["src"] = this._params["movie"] = value; break;
case "id":
case "name": this._eattrs["id"] = this._eattrs["name"] = this._oattrs["id"] = this._oattrs["name"] = value; break;
case "width":
case "height":
case "align":
case "vspace":
case "hspace":
case "class":
case "title":
case "accesskey":
case "tabindex": this._eattrs[name] = this._oattrs[name] = value; break;
case "onafterupdate":
case "onbeforeupdate":
case "onblur":
case "oncellchange":
case "onclick":
case "ondblclick":
case "ondrag":
case "ondragend":
case "ondragenter":
case "ondragleave":
case "ondragover":
case "ondrop":
case "onfinish":
case "onfocus":
case "onhelp":
case "onmousedown":
case "onmouseup":
case "onmouseover":
case "onmousemove":
case "onmouseout":
case "onkeypress":
case "onkeydown":
case "onkeyup":
case "onload":
case "onlosecapture":
case "onpropertychange":
case "onreadystatechange":
case "onrowsdelete":
case "onrowenter":
case "onrowexit":
case "onrowsinserted":
case "onstart":
case "onscroll":
case "onbeforeeditfocus":
case "onactivate":
case "onbeforedeactivate":
case "ondeactivate":
case "codebase": this._oattrs[name] = value; break;
default: this._eattrs[name] = this._params[name] = value;
}
}
var TFlashIntf = function(movie, swf) {
this.id = movie;                            // Movie name/id in document
this.container = null;                      // Container element for connectors (if ExternalInterface not pressent)
this._isintf = false;                       // Is ExternalInterface present?
this._connector = swf;                      // Connector swf file
TFlashIntf.instances[movie] = this;         // Add instance to stack to be able to retrieve it by id later
}
TFlashIntf.inherits(TComponent);
TFlashIntf.instances = [];

TFlashIntf.QueryJSIntf = function(movie) {
var movie = TFlashIntf.instances[movie];
if (movie) {
movie._isintf = true;
return true;
} else {
return false;
}
}

TFlashIntf.FromAS = function(movie, type, args) {
var movie = TFlashIntf.instances[movie];
var argo = {};
eval("argo = "+args+";");
movie.dispatch(new TFlashEvent(type, movie, argo));
}

TFlashIntf.prototype.callAS = function(event, args) {
var movie = TUserAgent.IE ? window[this.id] : document[this.id];
if (movie != null) {
if (this._isintf) {
movie.CallAS(event, args);
} else {
args = args || {};
this.container = TDOM.getElement(this.container);
var url = this._connector + (this._connector.indexOf('?') ? '&' : '?');
var swf = new TFlash("swfconn", url + 'id=' + this.id + '&' + 'event='+event, 1, 1);
swf.preventcache = true;
swf.transparent = true;
for (var i in args) { swf.addVar(i,args[i]); }
swf.draw(this.container);
}
}
}

TFlashIntf.prototype.serialize = function(arg) {
switch (typeof arg) {
case 'number':
case 'boolean': return arg;
case 'string': return '"'+arg.replace('"','\"').replace("\n",'\n').replace("\r",'')+'"';
case 'object': return arg.length ? this.serializeArray(arg) : this.serializeObject(arg);
default: return 'null';
}
}

TFlashIntf.prototype.serializeArray = function(arr) {
var ars = [];
for (var i=0,l=arr.length; i<l; i++) {
ard.push(this.serialize(arr[i]));
ars += this.serialize(arr[i]);
}
return '['+ars.join(',')+']';
}

TFlashIntf.prototype.serializeObject = function(obj) {
var obs = [];
for (var i in obj) {
obs.push(i+':'+this.serialize(obj[i]));
}
return '{'+obs.join(',')+'}';
}
TListener = function() {};

TListener._listeners = {};

TListener._handleBrowserEvent = function(listener, e) {
e = e || window.event;
var event = new TBrowserEvent(e), result = true;
// Simulate capture phase for IE events
if (!listener.src.addEventListener && listener.capture) {
// Skip bubble phase for marked events
if (e.keyCode < 0 || e.returnValue != undefined) { return true; }
// Event has to be marked to skip bubbling phase firing listeners twice
var fail = false;
if (e.keyCode == 0) {
try { e.keyCode = -1; }
catch(error) { fail = true; }
}
if (fail || e.returnValue == undefined) { e.returnValue = true; }
// Create the target chain.
var targets = [], target = listener.src;
while (target) {
targets.push(target);
target = target.parentNode;
}
// Capture phase dispatch listeners from the root target of the target chain to the target element itself.
event.phase = 'capture';
for (var i=targets.length-1; i>=0 && !event.stopped; i--) {
event.currentTarget = targets[i];
result = TListener._fire(targets[i], event.type, true, event) && result;
}
event.free();
return result;
// If its bubbling fire the callback
} else {
event.currentTarget = listener.src;
event.phase = listener.capture ? 'capture' : (event.target == listener.src ? 'target' : 'bubble');
result = listener.callback.call(listener.scope, event) !== false;
!result && event.preventDefault();
result = result && !event.canceled;
event.free();
return result;
}
}

TListener.add = function (src, type, callback, scope, capture) {
// If type is an array setup a listener on every type in the list
if (type.length && typeof type.splice != 'undefined') {
for (var i=0, l=type.length; i<l; i++) {
TListener.add(src, type[i], callback, scope);
}
// Add listener
} else {
src = TDOM.getElement(src);
scope = scope || src;
capture = capture ? true : false;
if (!src) { return; }
var id = TDOM.getUniqueId(src);
var list = TListener._listeners;
list[id] = list[id] || {};
list[id][type] = list[id][type] || {};
list[id][type][capture] = list[id][type][capture] || [];
list = list[id][type][capture];
// Check if the listener already exist
for (var i=0, l=list.length; i<l; i++) {
if (list[i].callback == callback && list[i].scope == scope) {
return;
}
}
// Create the listener
var listener = {src:src, type:type, callback:callback, scope:scope, capture:capture};
// Setup a handler to catch Browser Events and add listener to HTML Element
var component = typeof TComponent != 'undefined' && src instanceof TComponent;
if (!component) {
listener.handler = function(e) {
return TListener._handleBrowserEvent.call(src, listener, e);
};
src.addEventListener ? src.addEventListener(type, listener.handler, capture) : src.attachEvent("on" + type, listener.handler);
}
list.push(listener);
}
};

TListener.remove = function(src, type, callback, scope, capture) {
// If type is an array call remove on every type in the list
if (type.length && typeof type.splice != 'undefined') {
for (var i=0, l=type.length; i<l; i++) {
TListener.remove(src, type[i], callback, scope, capture);
}
} else {
src = TDOM.getElement(src);
if (!src) { return; }
if (!callback && typeof capture == 'undefined') {
TListener.remove(src, type, callback, scope, true);
}
scope = scope || src;
capture = capture ? true : false;
var id = TDOM.getUniqueId(src);
var list = TListener._listeners;
list[id] = list[id] || {};
list[id][type] = list[id][type] || {};
list[id][type][capture] = list[id][type][capture] || [];
list = list[id][type][capture];
for (var i=0, l=list.length; i<l; i++) {
if (!callback || (list[i].callback == callback && list[i].scope == scope)) {
var l = list[i];
list.splice(i, 1);
var component = typeof TComponent != 'undefined' && src instanceof TComponent;
if (!component) {
src.removeEventListener ? src.removeEventListener(type, l.handler, capture) : src.detachEvent("on" + type, l.handler);
}
l = null;
}
}
}
};

TListener.removeAll = function(src) {
src = TDOM.getElement(src);
if (!src) { return; }
var id = TDOM.getUniqueId(src);
if (TListener._listeners[id]) {
for (var type in TListener._listeners[id]) {
TListener.remove(src, type);
}
}
};

TListener.dispatch = function (src, e) {
src = TDOM.getElement(src);
e.target = src;
if (!src) { return; }
var result = true;
var id = TDOM.getUniqueId(src);
var listeners = TListener._listeners;
var capture = false, bubbling = true;
if (listeners[id] && listeners[id][e.type]) {
listeners = listeners[id][e.type];
var capture = true in listeners;
var bubbling = false in listeners;
}
var targets = [];
var target = src;
// Create the dispatcher targets chain.
while (target) {
targets.push(target);
target = target._parent;
}
// Capture phase dispatch listeners from the root target of the target chain to the target element itself.
if (capture) {
e.phase = 'capture';
for (var i=targets.length-1; i>0 && !e.stopped; i--) {
e.currentTarget = targets[i];
result = TListener._fire(targets[i], e.type, true, e) && result;
}
}
// Target and bubbling phase where event is proccessed in the event target and
// then make his way back to the root targte of the targets chain.
if (bubbling) {
// Target phase
e.phase = 'target';
e.currentTarget = targets[0];
result = TListener._fire(targets[0], e.type, false, e) && result;
// Bubbling phase
if (e.bubble) {
e.phase = 'bubble';
for (var i=1, l=targets.length; i<l && !e.stopped; i++) {
e.currentTarget = targets[i];
result = TListener._fire(targets[i], e.type, false, e) && result;
}
}
}

!result && e.preventDefault();
result = result && !e.canceled;
return result;
};

TListener._fire = function(target, type, capture, event) {
var result = true;
var id = TDOM.getUniqueId(target);
var listeners = TListener._listeners;
// Fire listeners
if (listeners[id] && listeners[id][type] && listeners[id][type][capture]) {
listeners = listeners[id][type][capture];
for (var i=0, l=listeners.length; i < l && !event.killed; i++) {
result = result && listeners[i].callback.call(listeners[i].scope, event) !== false;
}
}
// Also fire inline events
var control = typeof TControl != 'undefined' && target instanceof TControl;
target = control ? target.element : target;
if (target['on'+type]) {
var res = target['on'+type](event);
result = result && res !== false;
}
return result;
};

TListener.add(window, 'load', TDOM._doOnLoad);
var TEvent = function (type, bubble) {
this.type = type;
this.bubble = bubble !== false ? true : false;
};
TEvent.inherits(TObject);

TEvent.prototype.className = 'TEvent';
TEvent.prototype.type = null;
TEvent.prototype.phase = null;
TEvent.prototype.target = null;
TEvent.prototype.currentTarget = null;
TEvent.prototype.bubble = false;
TEvent.prototype.stopped = false;
TEvent.prototype.killed = false;
TEvent.prototype.canceled = false;

TEvent.prototype.stopPropagation = function() {
this.stopped = true;
};

TEvent.prototype.stopImmediatePropagation = function() {
this.killed = true;
this.stopPropagation();
};

TEvent.prototype.preventDefault = function() {
this.canceled = true;
};

TEvent.prototype.free = function() {
this.type = null;
this.phase = null;
this.target = null;
this.currentTarget = null;
};
TFlashEvent = function (type, movie, arguments) {
TEvent.prototype.constructor.call(this, type);
this.target = movie;
this.arguments = arguments;
};
TFlashEvent.inherits(TEvent);

TFlashEvent.prototype.className = 'TFlashEvent';
TFlashEvent.prototype.arguments = {};
TBrowserEvent = function (e) {
TEvent.prototype.constructor.call(this, e.type);
this.event = e;

// Resolve event target
// Some browsers allow text nodes to dispatch events and they must be resolved to his parent element node
target = e.target || e.srcElement;
this.target = TDOM.resolveNode(target, 'parentNode');

// Resolve Related Target
this.relatedTarget = e.relatedTarget;
if (!this.relatedTarget) {
if (this.type == "mouseover") {
this.relatedTarget = e.fromElement;
} else
if (this.type == "mouseout") {
this.relatedTarget = e.toElement;
}
}

// Retrieve keyboard information
this.keyCode = e.keyCode || e.which || 0;
this.charCode = e.charCode || (this.type == "keypress" ? e.keyCode : 0);
this.altKey = e.altKey;
this.ctrlKey = e.ctrlKey;
this.shiftKey = e.shiftKey;
this.metaKey = e.metaKey;

// Retrieve mouse information
this.screenX = e.screenX || 0;
this.screenY = e.screenY || 0;
this.offsetX = typeof e.layerX  != "undefined" ? e.layerX  : e.offsetX;
this.offsetY = typeof e.layerY  != "undefined" ? e.layerY  : e.offsetY;
this.clientX = typeof e.clientX != "undefined" ? e.clientX : e.pageX;
this.clientY = typeof e.clientY != "undefined" ? e.clientY : e.pageY;
this.buttons = TUserAgent.IE ? { left: e.button & 1, middle: e.button & 4, right: e.button & 2 } : { left: e.button == 0, middle: e.button == 1, right: e.which ? e.which == 3 : e.button == 2 };
};
TBrowserEvent.inherits(TEvent);

TBrowserEvent.prototype.className = 'TBrowserEvent';
TBrowserEvent.prototype.event = null;
TBrowserEvent.prototype.relatedTarget = null;
TBrowserEvent.prototype.keyCode = null;
TBrowserEvent.prototype.charCode = null;
TBrowserEvent.prototype.altKey = false;
TBrowserEvent.prototype.ctrlKey = false;
TBrowserEvent.prototype.shiftKey = false;
TBrowserEvent.prototype.metaKey = false;
TBrowserEvent.prototype.screenX = 0;
TBrowserEvent.prototype.screenY = 0;
TBrowserEvent.prototype.offsetX = 0;
TBrowserEvent.prototype.offsetY = 0;
TBrowserEvent.prototype.clientX = 0;
TBrowserEvent.prototype.clientY = 0;
TBrowserEvent.prototype.buttons = {};
TBrowserEvent.prototype.stopPropagation = function () {
if(this.event.stopPropagation){
this.event.stopPropagation();
}else{
this.event.cancelBubble = true;
}
TEvent.prototype.stopPropagation.call(this);
};

TBrowserEvent.prototype.preventDefault = function () {
if(this.event.preventDefault){
this.event.preventDefault();
}else{
this.event.returnValue = false;
}
TEvent.prototype.preventDefault.call(this);
};

TBrowserEvent.prototype.free = function() {
this.event = null;
this.buttons = null;
this.relatedTarget = null;
TEvent.prototype.free.call(this);
}
var TPanel = function (element,listener) {
TContainer.prototype.constructor.call(this,element,listener);
};
TPanel.inherits(TContainer);

/* ------------------------------------------------------------------------------- */

TPanel.prototype.role = 'region';
TPanel.prototype.className = 'TPanel';
var TButton = function (element,listeners) {
TControl.prototype.constructor.call(this,element,listeners);
if (this.caption) {
this.caption.id = this.id+'Caption';
TClasses.add(this.caption,this.className+'-caption');
this.element.setAttribute('aria-labelledby', this.caption.id);
} else {
this.caption = this.element;
}
};
TButton.inherits(TControl);

/* ------------------------------------------------------------------------------- */

TButton.Groups = {};
TButton.prototype.role = 'button';
TButton.prototype.caption = null;
TButton.prototype.className = 'TButton';
TButton.prototype.allowAllUp = false;
TButton.prototype._supportedStates |= TControl.State.DEFAULT;

/* ------------------------------------------------------------------------------- */

TButton.prototype.free = function () {
this.caption = null;
TControl.prototype.free.call(this);
};

/* ------------------------------------------------------------------------------- */

TButton.prototype._parseChild = function(el,token) {
switch (token) {
case 'caption': this._setCaption(el); break;
default: el.setAttribute('role', 'presentation');
}
};

TButton.prototype._setCaption = function(el) {
el.nodeName == 'A' && el.setAttribute('tabIndex',-1);
this.caption && this.caption.setAttribute('role', 'presentation');
this.caption = el;
this._parseElement(el);
};

TButton.prototype._parseCustomClass = function(value) {
if (value == 'allowAllUp') {
this.allowAllUp = true;
} else {
var re = new RegExp("^group-(.*?)$");
if (match = re.exec(value)) {
this.group(match[1].trim());
}
}
};

TButton.prototype._setStateClass = function(method,value) {
TControl.prototype._setStateClass.call(this,method,value);
this.caption && this.caption != this.element && TClasses[method](this.caption, this.className+'-caption-'+value);
};

/* ------------------------------------------------------------------------------- */

TButton.prototype.down = function(value) {
if (typeof value != 'undefined' && this.support(TControl.State.DOWN, value) && this.dispatch(new TEvent(value ? 'candown': 'canup'))) {
if (value ? this._doDown() : this._doUp()) {
this.state(TControl.State.DOWN, value);
this.dispatch(new TEvent(value ? 'down': 'up'));
}
}
return this.state(TControl.State.DOWN);
};

TButton.prototype.group = function(group) {
if (typeof group != 'undefined') {
if (!group) {
if (TButton.Groups[this.group] && TButton.Groups[this.group][this.id]) {
delete TButton.Groups[this.group][this.id];
}
this._supportedStates = this._supportedStates & ~TControl.State.DOWN;
this.group = null;
} else {
this._supportedStates = this._supportedStates | TControl.State.DOWN;
TButton.Groups[group] = TButton.Groups[group] || {};
TButton.Groups[group][this.id] = this;
this.group = group;
}
}
return this.group;
};

/* ------------------------------------------------------------------------------- */

TButton.prototype._doUp = function() {
if (TButton.Groups[this.group]) {
for (var id in TButton.Groups[this.group]) {
var btn = TButton.Groups[this.group][id];
if (btn.allowAllUp || (btn.id != this.id && btn.down())) {
return true;
}
}
return false;
}
};

TButton.prototype._doDown = function() {
if (TButton.Groups[this.group]) {
this.state(TControl.State.DOWN, true);
for (var id in TButton.Groups[this.group]) {
if (id != this.id) {
if (TButton.Groups[this.group][id].down(false)) {
this.state(TControl.State.DOWN, false);
return false;
}
}
}
}
return true;
};

/* ------------------------------------------------------------------------------- */

TButton.prototype._onKeydown = function(e) {
TControl.prototype._onKeydown.call(this,e);
this.enabled() && !e.canceled && (e.keyCode == 32 || e.keyCode == 13) && this.pressed(true);
};

TButton.prototype._onKeyup = function(e) {
TControl.prototype._onKeyup.call(this,e);
if (!e.canceled && this.pressed() && (e.keyCode == 32 || e.keyCode == 13)) {
this.pressed(false);
this.down(!this.down());
this._onClick(e);
}
};

/* ------------------------------------------------------------------------------- */

TButton.prototype._onMouseup = function(e) {
this.pressed() && this.down(!this.down());
TControl.prototype._onMouseup.call(this,e);
};
var TMenuItem = function (element) {
TButton.prototype.constructor.call(this,element,false);
this._supportedStates |= TControl.State.ACTIVE;
};
TMenuItem.inherits(TButton);

/* ------------------------------------------------------------------------------- */

TMenuItem.prototype.role = 'menuitem';
TMenuItem.prototype.className = 'TMenuItem';
TMenuItem.prototype._controlStyles = 0;
TMenuItem.prototype._supportedStates |= TControl.State.HASPOPUP | TControl.State.OPENED;

/* ------------------------------------------------------------------------------- */

TMenuItem.prototype.free = function () {
this.popup && this.popup.free();
this.popup = null;
TControl.prototype.free.call(this);
};

/* ------------------------------------------------------------------------------- */

TMenuItem.prototype._parseChild = function(el,token) {
switch (token) {
case 'popup': this._setPopup(el); break;
case 'caption': this._setCaption(el); break;
default: el.setAttribute('role', 'presentation');
}
};

TMenuItem.prototype._setPopup = function(el) {
if (this.popup) { return; }
var re = new RegExp("T([a-zA-Z0-9]+?)(\\s|$)");
match = el.className && re.exec(el.className);
var type = match && window['T'+match[1]];
type && typeof type == 'function' && TMenu.prototype.isPrototypeOf(type.prototype) && this.setPopup(new type(el,false));
};

TMenuItem.prototype._createElement = function() {
return document.createElement('li');
};

TMenuItem.prototype._setStateClass = function(method,value) {
TButton.prototype._setStateClass.call(this,method,value);
this.popup && TClasses[method](this.popup, this.className+'-popup-'+value);
};

/* ------------------------------------------------------------------------------- */

TMenuItem.prototype.open = function() {
if (this.popup && !this.opened()) {
var menu = this._parent instanceof TMenu ? this._parent : null;
var refrec = TDOM.getBounds(this.element);
var position = menu ? menu._onPopupPositionQuery() : 'bl';
TDOM.align(this.popup.element,refrec,position);
this.popup.visible(true);
this.state(TControl.State.OPENED,true);
}
};

TMenuItem.prototype.close = function() {
if (this.popup) {
var item = this.popup.childs[this.popup.activeIndex];
if (item) {
item.close();
item.active(false);
}
}
this.opened() && this.popup.visible(false);
this.state(TControl.State.OPENED,false);
};

TMenuItem.prototype.opened = function(value) {
typeof value != 'undefined' && (value ? this.open() : this.close());
return this.state(TControl.State.OPENED);
};

TMenuItem.prototype.setPopup = function(value) {
if (value instanceof TMenu) {
this.state(TControl.State.HASPOPUP,true);
this.element.appendChild(value.element);
this.element.setAttribute('aria-haspopup',true);
value._parent = this;
this.popup = value;
}
};

/* ------------------------------------------------------------------------------- */

TMenuItem.prototype._doActive = function(value) {
TButton.prototype._doActive.call(this,value);
!value && this.pressed(false);
var This = this;
setTimeout(function() { !This.active() && This.close(); },200);
};

/* ------------------------------------------------------------------------------- */

TMenuItem.prototype._onKeydown = function(e) {
this.popup && this.opened() && this.popup._onKeydown(e);
!e.canceled && TButton.prototype._onKeydown.call(this,e);
if (!e.canceled) {
var menu = this._parent instanceof TMenu ? this._parent : null;
if (menu && this.popup) {
if (!this.opened()) {
if (menu._onKeydownOpenQuery(e)) {
this.open();
this.popup.childs[0] && this.popup.childs[0].active(true);
e.preventDefault();
}
} else {
if (menu._onKeydownCloseQuery(e)) {
this.close();
e.preventDefault();
}
}
}
}
(e.keyCode == 32 || e.keyCode == 13) && e.preventDefault();
};

TMenuItem.prototype._onKeyup = function(e) {
this.popup && this.opened() && this.popup._onKeyup(e);
!e.canceled && this.active() && TButton.prototype._onKeyup.call(this,e);
};

TMenuItem.prototype._onKeypress = function(e) {
/*this.popup && this.opened() && this.popup._onKeypress(e);
!e.canceled && TButton.prototype._onKeypress.call(this,e);*/
};

/* ------------------------------------------------------------------------------- */

TMenuItem.prototype._onMouseup = function(e) {
this.popup && this.opened() && this.popup._onMouseup(e);
!e.canceled && this.active() && TButton.prototype._onMouseup.call(this,e);
e.preventDefault();
//e.stopPropagation();        // <---- !!!!!
};

TMenuItem.prototype._onMousedown = function(e) {
this.popup && this.opened() && this.popup._onMousedown(e);
!e.canceled && TButton.prototype._onMousedown.call(this,e);
!e.canceled && this.popup && !this.opened() && this.open();
e.preventDefault();
};

TMenuItem.prototype._onMouseover = function(e) {
this.popup && this.opened() && this.popup._onMouseover(e);
!e.canceled && TButton.prototype._onMouseover.call(this,e);
if (this.enabled() && !e.canceled ) {
this.active(true);
var menu = this._parent instanceof TMenu ? this._parent : null;
if (menu && menu.autoOpen) {
var This = this;
setTimeout(function() { This.active() && This.open(); },300);
}
}
};

TMenuItem.prototype._onMouseout = function(e) {
this.popup && this.opened() && this.popup._onMouseout(e);
!e.canceled && TButton.prototype._onMouseout.call(this,e);
this.active(false);
};

TMenuItem.prototype._onDblclick = function(e) {
this.popup && this.opened() && this.popup._onDblclick(e);
!e.canceled && TButton.prototype._onDblclick.call(this,e);
};

TMenuItem.prototype._onClick = function(e) {
this.popup && this.opened() && this.popup._onClick(e);
!e.canceled && TButton.prototype._onClick.call(this,e);
if (!this.popup && !e.canceled && this.enabled()) {
e.preventDefault();
var item = this, menu = null;
do {
menu = item._parent instanceof TMenu ? item._parent : null;
item = menu._parent instanceof TMenuItem ? menu._parent : null;
item && item.close();
} while (item);
}
};
var TMenuItemSeparator = function (element) {
TControl.prototype.constructor.call(this,element,false);
this.element.setAttribute('tabIndex',-1);
};
TMenuItemSeparator.inherits(TControl);
TMenuItemSeparator.prototype.role = 'separator';
TMenuItemSeparator.prototype.className = 'TMenuItemSeparator';
TMenuItemSeparator.prototype.controlStyles = 0;
TMenuItemSeparator.prototype.supportedStates = 0;

/* ------------------------------------------------------------------------------- */

TMenuItemSeparator.prototype._onMousedown = function(e) {
e.stopPropagation();
e.preventDefault();
return false;
};
var TMenu = function (element,listeners) {
TContainer.prototype.constructor.call(this,element,listeners);
TStyle.get(this.element, 'display') == 'none' && (this._controlStates |= TControl.State.HIDDEN);
this.element.style.outline = 'none';
this.element.hideFocus = true;
};
TMenu.inherits(TContainer);

/* ------------------------------------------------------------------------------- */

TMenu.Alignment = { TOP:0, LEFT:1, BOTTOM:2, RIGHT:3 };

/* ------------------------------------------------------------------------------- */

TMenu.prototype.role = 'menu';
TMenu.prototype.autoOpen = false;
TMenu.prototype.className = 'TMenu';
TMenu.prototype.alignment = TMenu.Alignment.TOP;
TMenu.prototype._allowedChilds = TMenuItem;

/* ------------------------------------------------------------------------------- */

TMenu.prototype._setControl = function(el) {
var ctrl = null, re = new RegExp("T([a-zA-Z0-9]+?)(\\s|$)");
match = el.className && re.exec(el.className);
if (match && typeof window['T'+match[1]] == 'function') {
ctrl = new window['T'+match[1]](el,false);
if (ctrl instanceof this._allowedChilds) {
this._insertChild(ctrl,this.childs.length);
// Dettected control that is not TMenu or TMenuItem descendants
// is created and skipped (not added to the child list).
} else {
(ctrl._controlStyles & TControl.Style.KEYEVENTS) && ctrl._enableKeyListeners(true);
(ctrl._controlStyles & TControl.Style.MOUSEEVENTS) && ctrl._enableMouseListeners(true);
(ctrl._controlStyles & TControl.Style.DOUBLECLICK) && ctrl._enableDoubleclickListeners(true);
ctrl.focusable() && ctrl._enableFocusListeners(true);
}
} else {
// No control dettected, create a TMenuItem around the child element
ctrl = new this._allowedChilds(el);
this._insertChild(ctrl,this.childs.length);
}
};

TMenu.prototype._createElement = function() {
return document.createElement('ul');
};

/* ------------------------------------------------------------------------------- */

TMenu.prototype.setActive = function(index,value) {
TContainer.prototype.setActive.call(this,index,value);
var item = this.childs[this.activeIndex];
this.element.setAttribute('aria-activedescendant',item ? item.id : '');
return !!item;
};

TMenu.prototype.setActiveNext = function() {
var index = this.getNextAvailable(null,false);
index = index != -1 ? index : this.getNextAvailable(-1);
index != -1 && this.setActive(index);
var item = this.childs[this.activeIndex];
return !!item;
};

TMenu.prototype.setActivePrev = function(pop) {
var index = this.getPreviousAvailable(null,false);
index = index != -1 ? index : this.getPreviousAvailable(this.childs.length);
index != -1 && this.setActive(index);
var item = this.childs[this.activeIndex];
return !!item;
};

/* ------------------------------------------------------------------------------- */

TMenu.prototype.visible = function(value) {
typeof value != 'undefined' && this.support(TControl.State.HIDDEN) && this.dispatch(new TEvent(value ? 'show': 'hide')) && this._doVisible(value);
return !this.state(TControl.State.HIDDEN);
};

TMenu.prototype._doVisible = function(value) {
// #TODO: setup animation
this.element.style.display = value ? 'block' : 'none';
this.state(TControl.State.HIDDEN, !value);
!value && this._parent && this._parent.setActive && this._parent.setActive(this,false);
};

/* ------------------------------------------------------------------------------- */

TMenu.prototype._onKeydown = function(e) {
TContainer.prototype._onKeydown.call(this,e);
this.enabled() && !e.canceled && this._onKeydownNavigate(e) && e.preventDefault();
};

/* ------------------------------------------------------------------------------- */

TMenu.prototype._onKeydownNavigate = function(e) {
var horz = this.alignment == TMenu.Alignment.TOP || this.alignment == TMenu.Alignment.BOTTOM;
var vert = this.alignment == TMenu.Alignment.LEFT || this.alignment == TMenu.Alignment.RIGHT;
switch (e.keyCode) {
case 36: this.setActive(0); return true;                            // HOME
case 35: this.setActive(this.childs.length-1); return true;         // END
case 37: return horz && this.setActivePrev();                       // LEFT
case 39: return horz && this.setActiveNext();                       // RIGHT
case 38: return vert && this.setActivePrev();                       // UP
case 40: return vert && this.setActiveNext();                       // DOWN
}
};

TMenu.prototype._onKeydownOpenQuery = function(e) {
if (e.keyCode == 13 || e.keyCode == 32) { return true; }              // ENTER / SPACEBAR)
switch (this.alignment) {
case TMenu.Alignment.TOP: return e.keyCode == 40;                   // DOWN
case TMenu.Alignment.LEFT: return e.keyCode == 39;                  // RIGHT
case TMenu.Alignment.RIGHT: return e.keyCode == 37;                 // LEFT
case TMenu.Alignment.BOTTOM: return e.keyCode == 38;                // UP
}
};

TMenu.prototype._onKeydownCloseQuery = function(e) {
switch (this.alignment) {
case TMenu.Alignment.TOP: return e.keyCode == 38;                   // UP
case TMenu.Alignment.LEFT: return e.keyCode == 37;                  // LEFT
case TMenu.Alignment.RIGHT: return e.keyCode == 39;                 // RIGHT
case TMenu.Alignment.BOTTOM: return e.keyCode == 40;                // DOWN
}
};

TMenu.prototype._onPopupPositionQuery = function() {
switch (this.alignment) {
case TMenu.Alignment.LEFT: return 'rt';                             // RIGHT  / TOP
case TMenu.Alignment.RIGHT: return 'lt';                            // LEFT   / TOP
case TMenu.Alignment.BOTTOM: return 'tl';                           // TOP    / LEFT
default: return 'bl';                                               // BOTTOM / LEFT
}
};
var TMenuBar = function (element,listeners,menuitem) {
TMenu.prototype.constructor.call(this,element,listeners,menuitem);
};
TMenuBar.inherits(TMenu);
TMenuBar.prototype.role = 'menubar';
TMenuBar.prototype.className = 'TMenuBar';
TMenuBar.prototype.alignment = TMenu.Alignment.TOP;
TMenuBar.prototype._controlStyles |= TControl.Style.FOCUSABLE;

/* ------------------------------------------------------------------------------- */

TMenuBar.prototype._onMousedown = function(e) {
var target = e.target;
TMenu.prototype._onMousedown.call(this,e);
if (!e.canceled) {
var item = this.childs[this.indexOf(target)];
item && item.popup && item.opened() && item.popup.indexOf(target) == -1 && item.close();
}
};

/* ------------------------------------------------------------------------------- */

TMenuBar.prototype._onKeydownOpenQuery = function(e) {
if (e.keyCode == 13 || e.keyCode == 32) { return true; }                  // ENTER / SPACEBAR)
switch (this.alignment) {
case TMenu.Alignment.TOP:
case TMenu.Alignment.BOTTOM: return e.keyCode == 38 || e.keyCode == 40; // Vertical layout opens with UP/DOWN keys
case TMenu.Alignment.LEFT:
case TMenu.Alignment.RIGHT: return e.keyCode == 37 || e.keyCode == 39;  // Horizontal layout opens with LEFT/RIGHT keys
}
};

TMenuBar.prototype._onKeydownCloseQuery = function(e) {
return false;
};
var TPopupMenu = function (element,listeners,menuitem) {
TMenu.prototype.constructor.call(this,element,listeners,menuitem);
this.element.setAttribute('aria-expanded',false);
};
TPopupMenu.inherits(TMenu);
TPopupMenu.prototype.autoOpen = true;
TPopupMenu.prototype.className = 'TPopupMenu';
TPopupMenu.prototype.alignment = TMenu.Alignment.LEFT;
TPopupMenu.prototype._ie6iframe = null;
TPopupMenu.prototype._shadow = null;

/* ------------------------------------------------------------------------------- */

TPopupMenu.prototype.free = function() {
if (this._ie6iframe) {
this.element.parentNode.removeChild(this._ie6iframe);
this._ie6iframe = null;
}
TMenu.prototype.free.call(this);
};

TPopupMenu.prototype.popup = function(x,y) {
this.visible(false);
var rec = new TRect(y,x,0,0);
TDOM.align(this.element,rec,align);
this.visible(true);
};

/* ------------------------------------------------------------------------------- */

TPopupMenu.prototype._doVisible = function(value) {
// #TODO: setup animation
var sdw = this._shadow;
var ifr = this._ie6iframe;
if (value) {
var rec = TDOM.getBounds(this.element);
if (TUserAgent.IE && TUserAgent.VERSION < 7) {
// IE6 cutting edges fix
this.element.style.width = (rec.width-parseInt(TStyle.get(this.element,'borderLeftWidth'))-parseInt(TStyle.get(this.element,'borderRightWidth'))-parseInt(TStyle.get(this.element,'paddingLeft'))-parseInt(TStyle.get(this.element,'paddingRight')))+'px';
if (!ifr) {
var ifr = document.createElement('iframe');
ifr.style.zIndex = TStyle.get(this.element, 'zIndex')-2;
ifr.style.position = 'absolute';
TStyle.set(ifr,'opacity',0);
this.element.parentNode.appendChild(ifr);
this._ie6iframe = ifr;
}
}
if (!sdw) {
var sdw = document.createElement('div');
sdw.style.zIndex = TStyle.get(this.element, 'zIndex')-1;
sdw.style.background = '#000';
sdw.style.position = 'absolute';
TStyle.set(sdw,'opacity',0.3);
this.element.parentNode.appendChild(sdw);
this._shadow = sdw;
}
sdw.style.top = (rec.top+2)+'px';
sdw.style.left = (rec.left+2)+'px';
sdw.style.width = rec.width+'px';
sdw.style.height = rec.height+'px';
sdw.style.display = 'block';
if (ifr) {
ifr.style.top = rec.top+'px';
ifr.style.left = rec.left+'px';
ifr.style.width = rec.width+'px';
ifr.style.height = rec.height+'px';
ifr.style.display = 'block';
}
} else {
sdw && (sdw.style.display = 'none');
ifr && (ifr.style.display = 'none');
this.element.style.width = '';
}
TMenu.prototype._doVisible.call(this,value);
};
var TModalWin = function(element,listeners,fixOffset) {
TControl.prototype.constructor.call(this,element,listeners);
this._setupElements();
this.visible(false);
this.fixOffset = !!fixOffset;
};
TModalWin.inherits(TControl);

TModalWin.prototype.body = null;
TModalWin.prototype.back = null;
TModalWin.prototype.opacity = 0.8;
TModalWin.prototype.role = 'alertdialog';
TModalWin.prototype.fixOffset = false;
TModalWin.prototype.className = 'TModalWin';
TModalWin.prototype._ie6iframe = null;
TModalWin.prototype._controlStyles = 0;
TModalWin.prototype.supportedStates = TControl.State.HIDDEN;

/* ------------------------------------------------------------------------------- */

TModalWin.OpenedWin = [];
TModalWin._resizeTimer = null;

TModalWin.HandleResize = function(e) {
if (TModalWin._resizeTimer != null) {
clearTimeout(TModalWin._resizeTimer);
TModalWin._resizeTimer = null;
}
TModalWin._resizeTimer = setTimeout( function() {
if (TModalWin.OpenedWin.length == 0) { return; }
for (var i=0,l=TModalWin.OpenedWin.length; i<l; i++) {
TModalWin.OpenedWin[i]._resizeContent();
}
TModalWin._resizeTimer = null;
},100);
};

TModalWin.HandleScroll = function(e) {
if (TModalWin.OpenedWin.length == 0) { return; }
for (var i=0,l=TModalWin.OpenedWin.length; i<l; i++) {
TModalWin.OpenedWin[i]._centerBody();
}
};

/* ------------------------------------------------------------------------------- */

TModalWin.prototype.free = function () {
this.body = null;
this.back = null;
if (this._ie6iframe) {
this.element.parentNode.removeChild(this._ie6iframe);
this._ie6iframe = null;
}
TControl.prototype.free.call(this);
};

/* ------------------------------------------------------------------------------- */

TModalWin.prototype._parseChild = function(el,token) {
switch (token) {
case 'body': this._setBody(el); break;
case 'back': this._setBackground(el); break;
default: el.setAttribute('role', 'presentation');
}
};

TModalWin.prototype._setBody = function(el) {
this.body && this.body.setAttribute('role', 'presentation');
this.body = el;
this._parseElement(el);
};

TModalWin.prototype._setBackground = function(el) {
this.back && this.back.setAttribute('role', 'presentation');
this.back = el;
};

TModalWin.prototype._setStateClass = function(method,value) {
TControl.prototype._setStateClass.call(this,method,value);
this.body && TClasses[method](this.body, this.className+'-body-'+value);
this.back && TClasses[method](this.back, this.className+'-back-'+value);
};

TModalWin.prototype._setupElements = function() {
if (!this.body) {
this.body = document.createElement('div');
this.body.innerHTML = this.element.innerHTML;
this.element.innerHTML = '';
this.element.appendChild(this.body);
}
if (!this.back) {
this.back = document.createElement('div');
this.element.appendChild(this.back);
}
if (TUserAgent.IE && TUserAgent.VERSION < 7 && !this._ie6iframe) {
var iframe = document.createElement('iframe');
iframe.style.zIndex = TStyle.get(this.back, 'zIndex')-1;
iframe.style.position = 'absolute';
TStyle.set(iframe,'opacity',0);
this.element.appendChild(iframe);
this._ie6iframe = iframe;
}
TClasses.add(this.back,this.className+'-back');
TClasses.add(this.body,this.className+'-body');
};

/* ------------------------------------------------------------------------------- */

TModalWin.prototype.open = function() {
this.visible(true);
this._centerBody();
};

TModalWin.prototype.close = function() {
this.visible(false);
};

/* ------------------------------------------------------------------------------- */

TModalWin.prototype._doVisible = function(value) {
if (value) {
this._resizeContent();
// Agregar al stack para incluirlo en el listener
TModalWin.OpenedWin.push(this);
// Establecer listener solo una vez para todos los win
TListener.add(window, 'scroll', TModalWin.HandleScroll);
TListener.add(window, 'resize', TModalWin.HandleResize);
} else {
// Sacarlo del stack
for (var i=0,l=TModalWin.OpenedWin.length;i<l;i++) {
if (TModalWin.OpenedWin[i] == this) {
TModalWin.OpenedWin.splice(i,1);
break;
}
}
}
TControl.prototype._doVisible.call(this,value);
this.element.style.display = value ? 'block' : 'none';
};

/* ------------------------------------------------------------------------------- */

TModalWin.prototype._centerBody = function() {
var bodyrec = TDOM.getBounds(this.body);
var viewportrec = TDOM.getViewportBounds();
this.body.style.top = (viewportrec.top + ((viewportrec.height-bodyrec.height) / 2)) + 'px';
this.body.style.left = (viewportrec.left + ((viewportrec.width-bodyrec.width) / 2)) + 'px';
};

TModalWin.prototype._resizeContent = function() {
//var back = this.element.style.display;
this.element.style.display = 'none';
var modalrec = TDOM.getDocumentSize(this.element);

var ot = 0, ol = 0;
if (this.fixOffset)
var parent = this.element.parentNode;
if (parent) {
var r = TDOM.getBounds(parent);
ot = r.top*-1;
ol = r.left*-1;
}
// Modal
this.element.style.top = ot+'px';
this.element.style.left = ol+'px';
this.element.style.width = modalrec.width+'px';
this.element.style.height = modalrec.height+'px';
// Background
this.back.style.top = '0px';
this.back.style.left = '0px';
this.back.style.width = modalrec.width+'px';
this.back.style.height = modalrec.height+'px';
TStyle.set(this.back,'opacity',this.opacity);
// Iframe
if (this._ie6iframe) {
var ifr = this._ie6iframe;
ifr.style.top = modalrec.top+'px';
ifr.style.left = modalrec.left+'px';
ifr.style.width = modalrec.width+'px';
ifr.style.height = modalrec.height+'px';
}
// Body
this._centerBody();
this.element.style.display = 'block';
};
var TGrid = function(el) {
TComponent.prototype.constructor.call(this,el);
this.data = TDOM.getElement(el);
this.params = {};
}
TGrid.inherits(TComponent);

/* ------------------------------------------------------------------------------- */

TGrid.prototype.url = '';
TGrid.prototype.data = null;
TGrid.prototype.modal = null;
TGrid.prototype.params = {};
TGrid.prototype.changed = false;
TGrid.prototype.updating = false;
TGrid.prototype.rowstart = 0;
TGrid.prototype.rowcount = 0;
TGrid.prototype.rowtotal = 0;
TGrid.prototype.sortcol  = 0;
TGrid.prototype.sortmode = 0;
TGrid.prototype.searchcol = 0;
TGrid.prototype.searchmode = 0;
TGrid.prototype.searchstring = '';

/* ------------------------------------------------------------------------------- */

TGrid.prototype.nextPage = function() {
if (this.rowstart + this.rowcount < this.rowtotal ) {
this.rowstart = this.rowstart + this.rowcount;
this.send();
}
}

TGrid.prototype.prevPage = function() {
if (this.rowstart > 0) {
this.rowstart = this.rowstart - this.rowcount;
if (this.rowstart < 0) {
this.rowstart = 0;
}
this.send();
}
}

TGrid.prototype.setRowStart = function(value) {
value = parseInt(value);
if (!isNaN(value) && value >= 0) {
if (this.rowstart != value && value < this.rowtotal) {
this.rowstart = value;
this.changed = true;
}
}
}

TGrid.prototype.setRowCount = function(value) {
value = parseInt(value);
if (!isNaN(value) && value >= 5) {
if (this.rowcount != value) {
this.rowcount = value;
this.changed = true;
}
}
}

TGrid.prototype.setSearchCol = function(value) {
value = parseInt(value);
if (!isNaN(value) && value >= 0) {
if (this.searchcol != value) {
this.searchcol = value;
this.changed = true;
}
}
}

TGrid.prototype.setSearchMode = function(value) {
value = parseInt(value);
if (!isNaN(value) && value >= 0) {
if (this.searchmode != value) {
this.searchmode = value;
this.changed = true;
}
}
}

TGrid.prototype.setSearchString = function(value) {
if (this.searchstring != value) {
this.searchstring = value;
this.changed = true;
}
}

TGrid.prototype.sort = function(col) {
col = parseInt(col);
if (!isNaN(col) && col >= 0) {
if (col == this.sortcol) {
this.sortmode = this.sortmode == 1 ? 0 : 1;
} else {
this.sortcol = col;
this.sortmode = 0;
}
this.send();
}
return false;
}

TGrid.prototype.handleSubmit = function(e, reset) {
e = e || window.event;
if (e && e.keyCode == 13) {
if (this.changed) {
if (reset) {
this.rowstart = 0;
}
this.changed = false;
this.send();
}
}
}

TGrid.prototype.httpComplete = function(e) {
this.modal && this.modal.close();
var http = e.target;
if (http.error) {
this.dispatch("error", this.http.lastError);
} else {
var html = http.toString();
var regex = new RegExp(/<grid:data>([\s\S]*)<\/grid:data>/);
if (regex.test(html)) {
this.data.innerHTML = RegExp.$1;
} else {
regex = new RegExp(/<(grid:)?error>([\s\S]*)<\/(grid:)?error>/);
if (regex.test(html)) {
this.dispatch("error", RegExp.$1, '');
} else {
//var txt = html.replace('<','&lt;').replace('>','&gt;');
this.dispatch("error", 'Unknown server response<div style="margin-top:5px;padding:3px;height:75px;border:1px solid #aaa;background:#fff;overflow:auto">'+html+'</div>', html);
}
}
regex = new RegExp(/<grid:rows>([\s\S]*)<\/grid:rows>/);
if (regex.test(html)) {
var rowtotal = parseInt(RegExp.$1);
if (!isNaN(rowtotal) && rowtotal >= 0) {
this.rowtotal = rowtotal;
}
}
}
this.dispatch("rowchange", this.rowstart, this.rowcount, this.rowtotal);
}

TGrid.prototype.send = function() {
var params = [];
this.modal && this.modal.open(this.modal);
params.push('rowstart='+this.rowstart);
params.push('rowcount='+this.rowcount);
params.push('sortcol='+this.sortcol);
params.push('sortmode='+this.sortmode);
params.push('searchcol='+this.searchcol);
params.push('searchmode='+this.searchmode);
params.push('searchstring='+this.searchstring);
for (var p in this.params) { params.push(p+'='+this.params[p]); }
THttpRequest.send(this.url, this.httpComplete, 'POST', params.join('&'), this);
}
var TTabSet = function (tabset) {
this.id       = tabset;
this.count    = 0;
this.tabset   = TDOM.getElement(tabset);
this.selected = -1;

// Initialize Tabset
if (this.tabset) {
var tab = TDOM.firstChild(this.tabset);
while (tab) {
this.setupTab(tab);
tab = TDOM.nextElement(tab);
}
this.selected = this.selected > this.count-1 ? -1 : this.selected;
}
}

TTabSet.inherits(TComponent);
TTabSet.ownAttr = "tabset_tab_unique_id";

TTabSet.prototype.doOut = function (e) {
TClasses.remove(e.currentTarget, 'over');
}

TTabSet.prototype.doOver = function (e) {
TClasses.add(e.currentTarget, 'over');
}

TTabSet.prototype.doClick = function (e) {
this.dispatch("click", e.currentTarget);
this.select(e.currentTarget);
this.dispatch("change", e.currentTarget);
}

TTabSet.prototype.getTabById = function (id) {
var tab = TDOM.firstChild(this.tabset);
while (tab) {
if (tab[TTabSet.ownAttr] == id) {
return tab;
}
tab = TDOM.nextElement(tab);
}
return null;
}

TTabSet.prototype.setupTab = function(tab) {
var id = this.count++;
tab[TTabSet.ownAttr] = id;
if (TClasses.has(tab, 'selected')) {
if (this.selected != -1) {
var tab2 = this.getTabById(this.selected);
TClasses.remove(tab2,'selected');
}
this.selected = id;
}
TListener.add(tab, 'click', this.doClick, this);
TListener.add(tab, 'mouseout', this.doOut, this);
TListener.add(tab, 'mouseover', this.doOver, this);
return id;
}

TTabSet.prototype.select = function (tab) {
if (typeof tab == 'number') {
var id = tab;
tab = this.getTabById(tab);
} else {
var id = tab[TTabSet.ownAttr];
}
if (id == this.selected) { return; }
id = id > this.count-1 || id < 0 ? -1 : id;
var old = this.getTabById(this.selected);
var canchange = this.dispatch("canchange", old, tab, id) !== false;
if (canchange) {
if (old) {
TClasses.remove(old, 'selected');
}
if (tab) {
TClasses.add(tab, 'selected');
}
this.selected = id;
this.dispatch("change", tab, id);
}
}
var THint = function() { }
THint.count = 0;
THint.cache = [];
THint.current = -1;
THint.currentElement = null;
THint.inner = null;
THint.iframe = null;
THint.container = null;
THint.timer = 0;
THint.over = false;

THint.setup = function() {
THint.container = document.createElement('div');
THint.container.className = 'THint';
THint.container.style.position = 'absolute';
THint.container.style.display = 'none';
THint.container.style.zIndex = 99899;
THint.inner = document.createElement('div');
THint.inner.className = 'inner';
TListener.add(THint.container,'mouseout',THint.hide);
TListener.add(THint.container,'mouseover',function() { clearTimeout(THint.timer); });

// If IE 6 or lower create a div inside container and set an iframe
// at the bottom of it to prevent selects and lists to pop up in front of the calendar
if (TUserAgent.IE && TUserAgent.VERSION < 7) {
THint.iframe = document.createElement("iframe");
THint.iframe.src = "javascript:false;";
THint.iframe.style.position = 'absolute';
THint.iframe.style.display = 'none';
THint.iframe.style.zIndex = 99898;
TDOM.setStyle(THint.iframe, "opacity", "0");
TListener.add(THint.iframe,'mouseout',THint.hide);
TListener.add(THint.iframe,'mouseover',function() { clearTimeout(THint.timer); });
document.body.appendChild(THint.iframe);
}
THint.container.appendChild(THint.inner);
document.body.appendChild(THint.container);
}
TDOM.onLoad(THint.setup);

THint.hide = function() {
if (THint.timer) {
clearTimeout(THint.timer);
THint.timer = null;
}
THint.over = false;
if (!THint.container) { return; }
THint.current = -1;
THint.currentElement = null;
THint.iframe && (THint.iframe.style.display = 'none');
THint.timer = setTimeout(function() { THint.container.style.display = 'none'; },100);
}

THint.show = function(el,html,pos) {
THint.over = true;
if (!THint.container) { return; }
if (THint.timer) {
clearTimeout(THint.timer);
THint.timer = null;
}
if (!el['thint_unique_identifier']) {
el['thint_unique_identifier'] = THint.count++;
}
THint.current = el['thint_unique_identifier'];
THint.currentElement = el;
THint.inner.innerHTML = html;
var rec = TDOM.getBounds(THint.container);
TDOM.align(THint.container,TDOM.getBounds(el,true,false),pos);
if (THint.iframe) {
rec = TDOM.getBounds(THint.container);
THint.iframe.style.width = rec.width + 6 + 'px';
THint.iframe.style.height = rec.height + 6 + 'px';
THint.iframe.style.top = rec.top - 4 + 'px';
THint.iframe.style.left = rec.left - 4 + 'px';
THint.iframe.style.display = 'block';
}
var This = this;
THint.timer = setTimeout(function() {
THint.over && (THint.container.style.display = 'block');
}, 250);
}

THint.showURL = function(url,el,pos,wm,cache) {
THint.over = true;
clearTimeout(THint.timer);
cache = typeof cache == 'undefined' ? 1 : cache;
if (!el['thint_unique_identifier']) {
el['thint_unique_identifier'] = THint.count++;
}
if (THint.current == el['thint_unique_identifier']) {
return;
}
if (cache && THint.cache[el['thint_unique_identifier']]) {
THint.show(el,THint.cache[el['thint_unique_identifier']],pos);
} else {
el.id = el.id ? el.id : 'THintID'+el['thint_unique_identifier'];
wm = wm ? wm : 'Obteniendo información<br />Por favor espere...';
THint.show(el,wm,pos);
THttp.send(url,THint.showURLCallback,null,'THintPos='+pos+'&THintElement='+el.id);
}
}

THint.showURLCallback = function(e) {
var values = {};
var params = e.target.params;
for (var i=0,l=params.length; i<l; i++) {
var p = params[i].split('=');
values[p[0]] = p[1];
}
var el = TDOM.getElement(values['THintElement']);
if (!el) { return; }
var html = e.target.toString();
if (html.match(/<hint>([\s\S]*?)<\/hint>/ig)) {
THint.cache[el['thint_unique_identifier']] = RegExp.$1;
if (el['thint_unique_identifier'] == THint.current) {
THint.over && THint.show(el,RegExp.$1,values['THintPos']);
}
} else {
THint.over && THint.show(el,'<h1>Error:</h1><p>Unknown response from server</p>',values['THintPos']);
}
}
TPopup = function(name, width, height, top, left) {

this.id        = name;
this.top       = !top ? -1 : top;
this.left      = !left ? -1 : left;
this.width     = !width ? 200 : width;
this.height    = !height ? 200 : height;
this.scrolls   = false;
this.toolbar   = false;
this.statusbar = false;
this.resizable = false;
this.opened    = false;

this.handler   = null;

this.open = function(url) {
this.top  = this.top < 0 ? (screen.height - this.height - 40) / 2 : this.top;
this.left = this.left < 0 ? (screen.width - this.width - 25) / 2 : this.left;
var settings  ='width='+this.width+',';
settings +='height='+this.height+',';
settings +='top='+this.top+',';
settings +='left='+this.left+',';
settings +='status='+(this.statusbar ? 1 : 0)+',';
settings +='toolbar='+(this.toolbar ? 1 : 0)+',';
settings +='resizable='+(this.resizable ? 1 : 0)+',';
settings +='scrollbars='+(this.scrolls ? 1 : 0);
this.handler = window.open(url,this.id,settings);
if (this.handler) {
this.handler.focus();
}
this.opened = true;
}

this.close = function() {
if (this.opened) {
this.handler.close();
this.opened = false;
}
}

this.showModal = function(url) {
this.open(url);
TEvents.listen(this.handler.opener,'focus',this._keepModal,this);
}

this._keepModal = function(win,e) {
// this.handler.focus();
try {
TEvents.unlisten(this.handler.opener,'focus',this._keepModal);
this.handler.close();
} catch (e) { }
}

this.minimize = function minimize(){
this.win.blur();
}
}

TPopup.New = function(name,width,height,src,scrolls,resizable,modal) {
var popup = new TPopup(name);
popup.scrolls = scrolls;
popup.resizable = resizable;
if (screen.height - 150 < height) {
height = screen.height - 150;
popup.scrolls = true;
}
if (screen.width - 150 < width) {
width = screen.width - 150;
popup.scrolls = true;
}
popup.width = width;
popup.height = height;
if (modal) {
popup.showModal(src);
} else {
popup.open(src);
}
return popup;
}
var THttp = function () {
this.xhr = null;
this.open = false;
this.error = false;
this.params = [];
this.lastError = '';
TComponent.prototype.constructor.call(this);
};
THttp.inherits(TComponent);

THttp.timeout = 15;
THttp.MSXML = ["MSXML2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
THttp.NULLFunction = null;
THttp.prototype.className = 'THttp';


THttp.prototype.free = function () {
if (this.open) {
this.abort();
}
TComponent.prototype.free.call(this);
};

THttp.prototype.clear = function() {
this.params = [];
}

THttp.prototype.getParams = function() {
return this.params.join('&');
}

THttp.prototype.addParam = function(name,value) {
this.params.push(name+'='+value);
}

THttp.prototype.addParams = function(params) {
if (params) {
params = params.split('&');
for (var i=0, c=params.length; i < c; i++) {
this.params.push(params[i]);
}
}
}

THttp.prototype.toString = function() {
return this.xhr ? this.xhr.responseText : '';
}

THttp.prototype.toXML = function() {
return this.xhr ? this.xhr.responseXML : null;
}

THttp.prototype.toScript = function() {
//try {
//  return this.xhr ? eval("(" + this.xhr.responseXML + ")") : null;
//} catch (e) { }
}

THttp.prototype.getResponseHeader = function(hdr) {
if (this.xhr && this.xhr.readyState == 4) {
return this.xhr.getResponseHeader(hdr);
}
}

THttp.prototype.getXhr = function() {
if (this.xhr) { return this.xhr; }
if (typeof XMLHttpRequest != 'undefined') {    // XHR
return new XMLHttpRequest;
} else {                                       // MSXML
if (typeof THttp.MSXML == "string") {
return new ActiveXObject(THttp.MSXML);
} else {
for(var i=0; i < THttp.MSXML.length; i++){
try {
var xhr = new ActiveXObject(THttp.MSXML[i]);
THttp.MSXML = THttp.MSXML[i];
THttp.NULLFunction = function() { };
return xhr;
} catch(e){}
}
}
}
// No XHR available
this.error = true;
}

THttp.prototype.readyStateChange = function() {
if (!this.open || !this.xhr) { return; }
this.dispatch("readystatechange");
if (this.xhr.readyState == 4) {
this.open = false;
var code = this.xhr.status;
if (code == 200) {
this.dispatch("success");
this.dispatch("complete");
} else {
this.error = true;
this.lastError = "[" + code + "] " + this.xhr.statusText;
this.dispatch("error", this.xhr.status, this.xhr.statusText);
this.dispatch("complete");
}
this.setReady();
}
}

THttp.prototype.abort = function() {
if (this.open) {
this.open = false;
this.xhr.abort();
this.dispatch("abort");
this.dispatch("complete");
this.setReady();
}
}

THttp.prototype.setReady = function() {
this.xhr.onreadystatechange = THttp.NULLFunction;
this.xhr = null;
this.dispatch("ready");
}

THttp.prototype.get = function (url) {
this.send(url, 'GET');
}

THttp.prototype.post = function (url, params) {
this.send(url, 'POST', params);
}

THttp.prototype.send = function (url, method, params) {
this.abort();
var This = this;
this.open = true;
this.error = false;
this.addParams(params);
this.xhr = this.getXhr();
if (this.error) {
this.open = false;
this.error = true;
this.lastError = "Could not create XML HTTP Request Object.\nUpdate your browser";
this.dispatch("error", 0, this.lastError);
this.dispatch("complete");
this.setReady();
} else {
params = this.getParams();
method = method && method.toUpperCase() == 'POST' ? 'POST' : 'GET';
if (method == 'GET' && params != '') {
url += url.indexOf('?') ? '&'+params : '?'+params;
params = '';
}
this.dispatch("open");
try {
this.xhr.onreadystatechange = function() {
This.readyStateChange.call(This);
}
this.xhr.open(method,url,true);
this.xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=iso-8859-1");
if (method == 'POST') {
this.xhr.setRequestHeader("Content-Length", params.length);
}
this.xhr.send(params);
} catch (e) {
this.open = false;
this.error = true;
this.lastError = "Error while opening connection";
this.dispatch("error", 0, this.lastError);
this.dispatch("complete");
this.setReady();
}
}
}
THttpRequest = {};
THttpRequest._ready = [];
THttpRequest._opened = [];
THttpRequest._callbacks = {};
THttpRequest.MAX_OPENED_CONNECTION = 5;

THttpRequest.getHttp = function () {
if (THttpRequest._opened.length >= THttpRequest.MAX_OPENED_CONNECTION) {
alert("Too many open conections!.\nPlase wait until pending requests are done\nand try again.");
return false;
}
var http = null;
if (THttpRequest._ready.length) {
http = THttpRequest._ready.pop();
} else {
http = new THttp();
http.listen('ready',THttpRequest.doHttpReady);
http.listen('complete',THttpRequest.doHttpComplete);
}
return http;
};

THttpRequest.doHttpReady = function(e) {
var http = e.target;
http.clear();
THttpRequest._ready.push(http);
};

THttpRequest.doHttpComplete = function(e,code,text) {
var http = e.target;
var callback = THttpRequest._callbacks[http.id];
if (callback) {
var func = callback['complete'];
func && func.call(callback['scope'],e,code,text);
}
};

THttpRequest.send = function (url, callback, method, params, scope) {
var http = THttpRequest.getHttp();
THttpRequest._callbacks[http.id] = {complete:callback, scope:scope || this};
http.send(url, method, params);
};
