/**
 * javascript by Miracle 3.1
 * copyright (c) eWorld - 2004-2011
 */

/* ######### "prototype" ######### */
/* Prototype JavaScript framework, version 1.6.1
 * (c) 2005-2009 Sam Stephenson
 *
 * Prototype is freely distributable under the terms of an MIT-style license.
 * For details, see the Prototype web site: http://www.prototypejs.org/
 *
 *--------------------------------------------------------------------------*/

var Prototype ={
 Version: '1.6.1',

 Browser: (function(){
 var ua = navigator.userAgent;
 var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
 return{
 IE: !!window.attachEvent && !isOpera,
 Opera: isOpera,
 WebKit: ua.indexOf('AppleWebKit/') > -1,
 Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
 MobileSafari: /Apple.*Mobile.*Safari/.test(ua)
}
})(),

 BrowserFeatures:{
 XPath: !!document.evaluate,
 SelectorsAPI: !!document.querySelector,
 ElementExtensions: (function(){
 var constructor = window.Element || window.HTMLElement;
 return !!(constructor && constructor.prototype);
})(),
 SpecificElementExtensions: (function(){
 if (typeof window.HTMLDivElement !== 'undefined')
 return true;

 var div = document.createElement('div');
 var form = document.createElement('form');
 var isSupported = false;

 if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])){
 isSupported = true;
}

 div = form = null;

 return isSupported;
})()
},

 ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
 JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,

 emptyFunction: function(){},
 K: function(x){return x}
};

if (Prototype.Browser.MobileSafari)
 Prototype.BrowserFeatures.SpecificElementExtensions = false;


var Abstract ={};


var Try ={
 these: function(){
 var returnValue;

 for (var i = 0, length = arguments.length; i < length; i++){
 var lambda = arguments[i];
 try{
 returnValue = lambda();
 break;
}catch (e){}
}

 return returnValue;
}
};

/* Based on Alex Arnell's inheritance implementation. */

var Class = (function(){
 function subclass(){};
 function create(){
 var parent = null, properties = $A(arguments);
 if (Object.isFunction(properties[0]))
 parent = properties.shift();

 function klass(){
 this.initialize.apply(this, arguments);
}

 Object.extend(klass, Class.Methods);
 klass.superclass = parent;
 klass.subclasses = [];

 if (parent){
 subclass.prototype = parent.prototype;
 klass.prototype = new subclass;
 parent.subclasses.push(klass);
}

 for (var i = 0; i < properties.length; i++)
 klass.addMethods(properties[i]);

 if (!klass.prototype.initialize)
 klass.prototype.initialize = Prototype.emptyFunction;

 klass.prototype.constructor = klass;
 return klass;
}

 function addMethods(source){
 var ancestor = this.superclass && this.superclass.prototype;
 var properties = Object.keys(source);

 if (!Object.keys({toString: true}).length){
 if (source.toString != Object.prototype.toString)
 properties.push("toString");
 if (source.valueOf != Object.prototype.valueOf)
 properties.push("valueOf");
}

 for (var i = 0, length = properties.length; i < length; i++){
 var property = properties[i], value = source[property];
 if (ancestor && Object.isFunction(value) &&
 value.argumentNames().first() == "$super"){
 var method = value;
 value = (function(m){
 return function(){return ancestor[m].apply(this, arguments);};
})(property).wrap(method);

 value.valueOf = method.valueOf.bind(method);
 value.toString = method.toString.bind(method);
}
 this.prototype[property] = value;
}

 return this;
}

 return{
 create: create,
 Methods:{
 addMethods: addMethods
}
};
})();
(function(){

 var _toString = Object.prototype.toString;

 function extend(destination, source){
 for (var property in source)
 destination[property] = source[property];
 return destination;
}

 function inspect(object){
 try{
 if (isUndefined(object)) return 'undefined';
 if (object === null) return 'null';
 return object.inspect ? object.inspect() : String(object);
}catch (e){
 if (e instanceof RangeError) return '...';
 throw e;
}
}

 function toJSON(object){
 var type = typeof object;
 switch (type){
 case 'undefined':
 case 'function':
 case 'unknown': return;
 case 'boolean': return object.toString();
}

 if (object === null) return 'null';
 if (object.toJSON) return object.toJSON();
 if (isElement(object)) return;

 var results = [];
 for (var property in object){
 var value = toJSON(object[property]);
 if (!isUndefined(value))
 results.push(property.toJSON() + ': ' + value);
}

 return '{' + results.join(', ') + '}';
}

 function toQueryString(object){
 return $H(object).toQueryString();
}

 function toHTML(object){
 return object && object.toHTML ? object.toHTML() : String.interpret(object);
}

 function keys(object){
 var results = [];
 for (var property in object)
 results.push(property);
 return results;
}

 function values(object){
 var results = [];
 for (var property in object)
 results.push(object[property]);
 return results;
}

 function clone(object){
 return extend({}, object);
}

 function isElement(object){
 return !!(object && object.nodeType == 1);
}

 function isArray(object){
 return _toString.call(object) == "[object Array]";
}


 function isHash(object){
 return object instanceof Hash;
}

 function isFunction(object){
 return typeof object === "function";
}

 function isString(object){
 return _toString.call(object) == "[object String]";
}

 function isNumber(object){
 return _toString.call(object) == "[object Number]";
}

 function isUndefined(object){
 return typeof object === "undefined";
}

 extend(Object,{
 extend: extend,
 inspect: inspect,
 toJSON: toJSON,
 toQueryString: toQueryString,
 toHTML: toHTML,
 keys: keys,
 values: values,
 clone: clone,
 isElement: isElement,
 isArray: isArray,
 isHash: isHash,
 isFunction: isFunction,
 isString: isString,
 isNumber: isNumber,
 isUndefined: isUndefined
});
})();
Object.extend(Function.prototype, (function(){
 var slice = Array.prototype.slice;

 function update(array, args){
 var arrayLength = array.length, length = args.length;
 while (length--) array[arrayLength + length] = args[length];
 return array;
}

 function merge(array, args){
 array = slice.call(array, 0);
 return update(array, args);
}

 function argumentNames(){
 var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
 .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
 .replace(/\s+/g, '').split(',');
 return names.length == 1 && !names[0] ? [] : names;
}

 function bind(context){
 if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
 var __method = this, args = slice.call(arguments, 1);
 return function(){
 var a = merge(args, arguments);
 return __method.apply(context, a);
}
}

 function bindAsEventListener(context){
 var __method = this, args = slice.call(arguments, 1);
 return function(event){
 var a = update([event || window.event], args);
 return __method.apply(context, a);
}
}

 function curry(){
 if (!arguments.length) return this;
 var __method = this, args = slice.call(arguments, 0);
 return function(){
 var a = merge(args, arguments);
 return __method.apply(this, a);
}
}

 function delay(timeout){
 var __method = this, args = slice.call(arguments, 1);
 timeout = timeout * 1000
 return window.setTimeout(function(){
 return __method.apply(__method, args);
}, timeout);
}

 function defer(){
 var args = update([0.01], arguments);
 return this.delay.apply(this, args);
}

 function wrap(wrapper){
 var __method = this;
 return function(){
 var a = update([__method.bind(this)], arguments);
 return wrapper.apply(this, a);
}
}

 function methodize(){
 if (this._methodized) return this._methodized;
 var __method = this;
 return this._methodized = function(){
 var a = update([this], arguments);
 return __method.apply(null, a);
};
}

 return{
 argumentNames: argumentNames,
 bind: bind,
 bindAsEventListener: bindAsEventListener,
 curry: curry,
 delay: delay,
 defer: defer,
 wrap: wrap,
 methodize: methodize
}
})());


Date.prototype.toJSON = function(){
 return '"' + this.getUTCFullYear() + '-' +
 (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
 this.getUTCDate().toPaddedString(2) + 'T' +
 this.getUTCHours().toPaddedString(2) + ':' +
 this.getUTCMinutes().toPaddedString(2) + ':' +
 this.getUTCSeconds().toPaddedString(2) + 'Z"';
};


RegExp.prototype.match = RegExp.prototype.test;

RegExp.escape = function(str){
 return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
};
var PeriodicalExecuter = Class.create({
 initialize: function(callback, frequency){
 this.callback = callback;
 this.frequency = frequency;
 this.currentlyExecuting = false;

 this.registerCallback();
},

 registerCallback: function(){
 this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},

 execute: function(){
 this.callback(this);
},

 stop: function(){
 if (!this.timer) return;
 clearInterval(this.timer);
 this.timer = null;
},

 onTimerEvent: function(){
 if (!this.currentlyExecuting){
 try{
 this.currentlyExecuting = true;
 this.execute();
 this.currentlyExecuting = false;
}catch(e){
 this.currentlyExecuting = false;
 throw e;
}
}
}
});
Object.extend(String,{
 interpret: function(value){
 return value == null ? '' : String(value);
},
 specialChar:{
 '\b': '\\b',
 '\t': '\\t',
 '\n': '\\n',
 '\f': '\\f',
 '\r': '\\r',
 '\\': '\\\\'
}
});

Object.extend(String.prototype, (function(){

 function prepareReplacement(replacement){
 if (Object.isFunction(replacement)) return replacement;
 var template = new Template(replacement);
 return function(match){return template.evaluate(match)};
}

 function gsub(pattern, replacement){
 var result = '', source = this, match;
 replacement = prepareReplacement(replacement);

 if (Object.isString(pattern))
 pattern = RegExp.escape(pattern);

 if (!(pattern.length || pattern.source)){
 replacement = replacement('');
 return replacement + source.split('').join(replacement) + replacement;
}

 while (source.length > 0){
 if (match = source.match(pattern)){
 result += source.slice(0, match.index);
 result += String.interpret(replacement(match));
 source = source.slice(match.index + match[0].length);
}else{
 result += source, source = '';
}
}
 return result;
}

 function sub(pattern, replacement, count){
 replacement = prepareReplacement(replacement);
 count = Object.isUndefined(count) ? 1 : count;

 return this.gsub(pattern, function(match){
 if (--count < 0) return match[0];
 return replacement(match);
});
}

 function scan(pattern, iterator){
 this.gsub(pattern, iterator);
 return String(this);
}

 function truncate(length, truncation){
 length = length || 30;
 truncation = Object.isUndefined(truncation) ? '...' : truncation;
 return this.length > length ?
 this.slice(0, length - truncation.length) + truncation : String(this);
}

 function strip(){
 return this.replace(/^\s+/, '').replace(/\s+$/, '');
}

 function stripTags(){
 return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, '');
}

 function stripScripts(){
 return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
}

 function extractScripts(){
 var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
 var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
 return (this.match(matchAll) || []).map(function(scriptTag){
 return (scriptTag.match(matchOne) || ['', ''])[1];
});
}

 function evalScripts(){
 return this.extractScripts().map(function(script){return eval(script)});
}

 function escapeHTML(){
 return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}

 function unescapeHTML(){
 return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&');
}


 function toQueryParams(separator){
 var match = this.strip().match(/([^?#]*)(#.*)?$/);
 if (!match) return{};

 return match[1].split(separator || '&').inject({}, function(hash, pair){
 if ((pair = pair.split('='))[0]){
 var key = decodeURIComponent(pair.shift());
 var value = pair.length > 1 ? pair.join('=') : pair[0];
 if (value != undefined) value = decodeURIComponent(value);

 if (key in hash){
 if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
 hash[key].push(value);
}
 else hash[key] = value;
}
 return hash;
});
}

 function toArray(){
 return this.split('');
}

 function succ(){
 return this.slice(0, this.length - 1) +
 String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
}

 function times(count){
 return count < 1 ? '' : new Array(count + 1).join(this);
}

 function camelize(){
 var parts = this.split('-'), len = parts.length;
 if (len == 1) return parts[0];

 var camelized = this.charAt(0) == '-'
 ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
 : parts[0];

 for (var i = 1; i < len; i++)
 camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

 return camelized;
}

 function capitalize(){
 return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
}

 function underscore(){
 return this.replace(/::/g, '/')
 .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')
 .replace(/([a-z\d])([A-Z])/g, '$1_$2')
 .replace(/-/g, '_')
 .toLowerCase();
}

 function dasherize(){
 return this.replace(/_/g, '-');
}

 function inspect(useDoubleQuotes){
 var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character){
 if (character in String.specialChar){
 return String.specialChar[character];
}
 return '\\u00' + character.charCodeAt().toPaddedString(2, 16);
});
 if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
 return "'" + escapedString.replace(/'/g, '\\\'') + "'";
}

 function toJSON(){
 return this.inspect(true);
}

 function unfilterJSON(filter){
 return this.replace(filter || Prototype.JSONFilter, '$1');
}

 function isJSON(){
 var str = this;
 if (str.blank()) return false;
 str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
 return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
}

 function evalJSON(sanitize){
 var json = this.unfilterJSON();
 try{
 if (!sanitize || json.isJSON()) return eval('(' + json + ')');
}catch (e){}
 throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
}

 function include(pattern){
 return this.indexOf(pattern) > -1;
}

 function startsWith(pattern){
 return this.indexOf(pattern) === 0;
}

 function endsWith(pattern){
 var d = this.length - pattern.length;
 return d >= 0 && this.lastIndexOf(pattern) === d;
}

 function empty(){
 return this == '';
}

 function blank(){
 return /^\s*$/.test(this);
}

 function interpolate(object, pattern){
 return new Template(this, pattern).evaluate(object);
}

 return{
 gsub: gsub,
 sub: sub,
 scan: scan,
 truncate: truncate,
 strip: String.prototype.trim ? String.prototype.trim : strip,
 stripTags: stripTags,
 stripScripts: stripScripts,
 extractScripts: extractScripts,
 evalScripts: evalScripts,
 escapeHTML: escapeHTML,
 unescapeHTML: unescapeHTML,
 toQueryParams: toQueryParams,
 parseQuery: toQueryParams,
 toArray: toArray,
 succ: succ,
 times: times,
 camelize: camelize,
 capitalize: capitalize,
 underscore: underscore,
 dasherize: dasherize,
 inspect: inspect,
 toJSON: toJSON,
 unfilterJSON: unfilterJSON,
 isJSON: isJSON,
 evalJSON: evalJSON,
 include: include,
 startsWith: startsWith,
 endsWith: endsWith,
 empty: empty,
 blank: blank,
 interpolate: interpolate
};
})());

var Template = Class.create({
 initialize: function(template, pattern){
 this.template = template.toString();
 this.pattern = pattern || Template.Pattern;
},

 evaluate: function(object){
 if (object && Object.isFunction(object.toTemplateReplacements))
 object = object.toTemplateReplacements();

 return this.template.gsub(this.pattern, function(match){
 if (object == null) return (match[1] + '');

 var before = match[1] || '';
 if (before == '\\') return match[2];

 var ctx = object, expr = match[3];
 var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
 match = pattern.exec(expr);
 if (match == null) return before;

 while (match != null){
 var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1];
 ctx = ctx[comp];
 if (null == ctx || '' == match[3]) break;
 expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
 match = pattern.exec(expr);
}

 return before + String.interpret(ctx);
});
}
});
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;

var $break ={};

var Enumerable = (function(){
 function each(iterator, context){
 var index = 0;
 try{
 this._each(function(value){
 iterator.call(context, value, index++);
});
}catch (e){
 if (e != $break) throw e;
}
 return this;
}

 function eachSlice(number, iterator, context){
 var index = -number, slices = [], array = this.toArray();
 if (number < 1) return array;
 while ((index += number) < array.length)
 slices.push(array.slice(index, index+number));
 return slices.collect(iterator, context);
}

 function all(iterator, context){
 iterator = iterator || Prototype.K;
 var result = true;
 this.each(function(value, index){
 result = result && !!iterator.call(context, value, index);
 if (!result) throw $break;
});
 return result;
}

 function any(iterator, context){
 iterator = iterator || Prototype.K;
 var result = false;
 this.each(function(value, index){
 if (result = !!iterator.call(context, value, index))
 throw $break;
});
 return result;
}

 function collect(iterator, context){
 iterator = iterator || Prototype.K;
 var results = [];
 this.each(function(value, index){
 results.push(iterator.call(context, value, index));
});
 return results;
}

 function detect(iterator, context){
 var result;
 this.each(function(value, index){
 if (iterator.call(context, value, index)){
 result = value;
 throw $break;
}
});
 return result;
}

 function findAll(iterator, context){
 var results = [];
 this.each(function(value, index){
 if (iterator.call(context, value, index))
 results.push(value);
});
 return results;
}

 function grep(filter, iterator, context){
 iterator = iterator || Prototype.K;
 var results = [];

 if (Object.isString(filter))
 filter = new RegExp(RegExp.escape(filter));

 this.each(function(value, index){
 if (filter.match(value))
 results.push(iterator.call(context, value, index));
});
 return results;
}

 function include(object){
 if (Object.isFunction(this.indexOf))
 if (this.indexOf(object) != -1) return true;

 var found = false;
 this.each(function(value){
 if (value == object){
 found = true;
 throw $break;
}
});
 return found;
}

 function inGroupsOf(number, fillWith){
 fillWith = Object.isUndefined(fillWith) ? null : fillWith;
 return this.eachSlice(number, function(slice){
 while(slice.length < number) slice.push(fillWith);
 return slice;
});
}

 function inject(memo, iterator, context){
 this.each(function(value, index){
 memo = iterator.call(context, memo, value, index);
});
 return memo;
}

 function invoke(method){
 var args = $A(arguments).slice(1);
 return this.map(function(value){
 return value[method].apply(value, args);
});
}

 function max(iterator, context){
 iterator = iterator || Prototype.K;
 var result;
 this.each(function(value, index){
 value = iterator.call(context, value, index);
 if (result == null || value >= result)
 result = value;
});
 return result;
}

 function min(iterator, context){
 iterator = iterator || Prototype.K;
 var result;
 this.each(function(value, index){
 value = iterator.call(context, value, index);
 if (result == null || value < result)
 result = value;
});
 return result;
}

 function partition(iterator, context){
 iterator = iterator || Prototype.K;
 var trues = [], falses = [];
 this.each(function(value, index){
 (iterator.call(context, value, index) ?
 trues : falses).push(value);
});
 return [trues, falses];
}

 function pluck(property){
 var results = [];
 this.each(function(value){
 results.push(value[property]);
});
 return results;
}

 function reject(iterator, context){
 var results = [];
 this.each(function(value, index){
 if (!iterator.call(context, value, index))
 results.push(value);
});
 return results;
}

 function sortBy(iterator, context){
 return this.map(function(value, index){
 return{
 value: value,
 criteria: iterator.call(context, value, index)
};
}).sort(function(left, right){
 var a = left.criteria, b = right.criteria;
 return a < b ? -1 : a > b ? 1 : 0;
}).pluck('value');
}

 function toArray(){
 return this.map();
}

 function zip(){
 var iterator = Prototype.K, args = $A(arguments);
 if (Object.isFunction(args.last()))
 iterator = args.pop();

 var collections = [this].concat(args).map($A);
 return this.map(function(value, index){
 return iterator(collections.pluck(index));
});
}

 function size(){
 return this.toArray().length;
}

 function inspect(){
 return '#<Enumerable:' + this.toArray().inspect() + '>';
}









 return{
 each: each,
 eachSlice: eachSlice,
 all: all,
 every: all,
 any: any,
 some: any,
 collect: collect,
 map: collect,
 detect: detect,
 findAll: findAll,
 select: findAll,
 filter: findAll,
 grep: grep,
 include: include,
 member: include,
 inGroupsOf: inGroupsOf,
 inject: inject,
 invoke: invoke,
 max: max,
 min: min,
 partition: partition,
 pluck: pluck,
 reject: reject,
 sortBy: sortBy,
 toArray: toArray,
 entries: toArray,
 zip: zip,
 size: size,
 inspect: inspect,
 find: detect
};
})();
function $A(iterable){
 if (!iterable) return [];
 if ('toArray' in Object(iterable)) return iterable.toArray();
 var length = iterable.length || 0, results = new Array(length);
 while (length--) results[length] = iterable[length];
 return results;
}

function $w(string){
 if (!Object.isString(string)) return [];
 string = string.strip();
 return string ? string.split(/\s+/) : [];
}

Array.from = $A;


(function(){
 var arrayProto = Array.prototype,
 slice = arrayProto.slice,
 _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available

 function each(iterator){
 for (var i = 0, length = this.length; i < length; i++)
 iterator(this[i]);
}
 if (!_each) _each = each;

 function clear(){
 this.length = 0;
 return this;
}

 function first(){
 return this[0];
}

 function last(){
 return this[this.length - 1];
}

 function compact(){
 return this.select(function(value){
 return value != null;
});
}

 function flatten(){
 return this.inject([], function(array, value){
 if (Object.isArray(value))
 return array.concat(value.flatten());
 array.push(value);
 return array;
});
}

 function without(){
 var values = slice.call(arguments, 0);
 return this.select(function(value){
 return !values.include(value);
});
}

 function reverse(inline){
 return (inline !== false ? this : this.toArray())._reverse();
}

 function uniq(sorted){
 return this.inject([], function(array, value, index){
 if (0 == index || (sorted ? array.last() != value : !array.include(value)))
 array.push(value);
 return array;
});
}

 function intersect(array){
 return this.uniq().findAll(function(item){
 return array.detect(function(value){return item === value});
});
}


 function clone(){
 return slice.call(this, 0);
}

 function size(){
 return this.length;
}

 function inspect(){
 return '[' + this.map(Object.inspect).join(', ') + ']';
}

 function toJSON(){
 var results = [];
 this.each(function(object){
 var value = Object.toJSON(object);
 if (!Object.isUndefined(value)) results.push(value);
});
 return '[' + results.join(', ') + ']';
}

 function indexOf(item, i){
 i || (i = 0);
 var length = this.length;
 if (i < 0) i = length + i;
 for (; i < length; i++)
 if (this[i] === item) return i;
 return -1;
}

 function lastIndexOf(item, i){
 i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
 var n = this.slice(0, i).reverse().indexOf(item);
 return (n < 0) ? n : i - n - 1;
}

 function concat(){
 var array = slice.call(this, 0), item;
 for (var i = 0, length = arguments.length; i < length; i++){
 item = arguments[i];
 if (Object.isArray(item) && !('callee' in item)){
 for (var j = 0, arrayLength = item.length; j < arrayLength; j++)
 array.push(item[j]);
}else{
 array.push(item);
}
}
 return array;
}

 Object.extend(arrayProto, Enumerable);

 if (!arrayProto._reverse)
 arrayProto._reverse = arrayProto.reverse;

 Object.extend(arrayProto,{
 _each: _each,
 clear: clear,
 first: first,
 last: last,
 compact: compact,
 flatten: flatten,
 without: without,
 reverse: reverse,
 uniq: uniq,
 intersect: intersect,
 clone: clone,
 toArray: clone,
 size: size,
 inspect: inspect,
 toJSON: toJSON
});

 var CONCAT_ARGUMENTS_BUGGY = (function(){
 return [].concat(arguments)[0][0] !== 1;
})(1,2)

 if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat;

 if (!arrayProto.indexOf) arrayProto.indexOf = indexOf;
 if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf;
})();
function $H(object){
 return new Hash(object);
};

var Hash = Class.create(Enumerable, (function(){
 function initialize(object){
 this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
}

 function _each(iterator){
 for (var key in this._object){
 var value = this._object[key], pair = [key, value];
 pair.key = key;
 pair.value = value;
 iterator(pair);
}
}

 function set(key, value){
 return this._object[key] = value;
}

 function get(key){
 if (this._object[key] !== Object.prototype[key])
 return this._object[key];
}

 function unset(key){
 var value = this._object[key];
 delete this._object[key];
 return value;
}

 function toObject(){
 return Object.clone(this._object);
}

 function keys(){
 return this.pluck('key');
}

 function values(){
 return this.pluck('value');
}

 function index(value){
 var match = this.detect(function(pair){
 return pair.value === value;
});
 return match && match.key;
}

 function merge(object){
 return this.clone().update(object);
}

 function update(object){
 return new Hash(object).inject(this, function(result, pair){
 result.set(pair.key, pair.value);
 return result;
});
}

 function toQueryPair(key, value){
 if (Object.isUndefined(value)) return key;
 return key + '=' + encodeURIComponent(String.interpret(value));
}

 function toQueryString(){
 return this.inject([], function(results, pair){
 var key = encodeURIComponent(pair.key), values = pair.value;

 if (values && typeof values == 'object'){
 if (Object.isArray(values))
 return results.concat(values.map(toQueryPair.curry(key)));
}else results.push(toQueryPair(key, values));
 return results;
}).join('&');
}

 function inspect(){
 return '#<Hash:{' + this.map(function(pair){
 return pair.map(Object.inspect).join(': ');
}).join(', ') + '}>';
}

 function toJSON(){
 return Object.toJSON(this.toObject());
}

 function clone(){
 return new Hash(this);
}

 return{
 initialize: initialize,
 _each: _each,
 set: set,
 get: get,
 unset: unset,
 toObject: toObject,
 toTemplateReplacements: toObject,
 keys: keys,
 values: values,
 index: index,
 merge: merge,
 update: update,
 toQueryString: toQueryString,
 inspect: inspect,
 toJSON: toJSON,
 clone: clone
};
})());

Hash.from = $H;
Object.extend(Number.prototype, (function(){
 function toColorPart(){
 return this.toPaddedString(2, 16);
}

 function succ(){
 return this + 1;
}

 function times(iterator, context){
 $R(0, this, true).each(iterator, context);
 return this;
}

 function toPaddedString(length, radix){
 var string = this.toString(radix || 10);
 return '0'.times(length - string.length) + string;
}

 function toJSON(){
 return isFinite(this) ? this.toString() : 'null';
}

 function abs(){
 return Math.abs(this);
}

 function round(){
 return Math.round(this);
}

 function ceil(){
 return Math.ceil(this);
}

 function floor(){
 return Math.floor(this);
}

 return{
 toColorPart: toColorPart,
 succ: succ,
 times: times,
 toPaddedString: toPaddedString,
 toJSON: toJSON,
 abs: abs,
 round: round,
 ceil: ceil,
 floor: floor
};
})());

function $R(start, end, exclusive){
 return new ObjectRange(start, end, exclusive);
}

var ObjectRange = Class.create(Enumerable, (function(){
 function initialize(start, end, exclusive){
 this.start = start;
 this.end = end;
 this.exclusive = exclusive;
}

 function _each(iterator){
 var value = this.start;
 while (this.include(value)){
 iterator(value);
 value = value.succ();
}
}

 function include(value){
 if (value < this.start)
 return false;
 if (this.exclusive)
 return value < this.end;
 return value <= this.end;
}

 return{
 initialize: initialize,
 _each: _each,
 include: include
};
})());



var Ajax ={
 getTransport: function(){
 return Try.these(
 function(){return new XMLHttpRequest()},
 function(){return new ActiveXObject('Msxml2.XMLHTTP')},
 function(){return new ActiveXObject('Microsoft.XMLHTTP')}
 ) || false;
},

 activeRequestCount: 0
};

Ajax.Responders ={
 responders: [],

 _each: function(iterator){
 this.responders._each(iterator);
},

 register: function(responder){
 if (!this.include(responder))
 this.responders.push(responder);
},

 unregister: function(responder){
 this.responders = this.responders.without(responder);
},

 dispatch: function(callback, request, transport, json){
 this.each(function(responder){
 if (Object.isFunction(responder[callback])){
 try{
 responder[callback].apply(responder, [request, transport, json]);
}catch (e){}
}
});
}
};

Object.extend(Ajax.Responders, Enumerable);

Ajax.Responders.register({
 onCreate: function(){Ajax.activeRequestCount++},
 onComplete: function(){Ajax.activeRequestCount--}
});
Ajax.Base = Class.create({
 initialize: function(options){
 this.options ={
 method: 'post',
 asynchronous: true,
 contentType: 'application/x-www-form-urlencoded',
 encoding: 'UTF-8',
 parameters: '',
 evalJSON: true,
 evalJS: true
};
 Object.extend(this.options, options ||{});

 this.options.method = this.options.method.toLowerCase();

 if (Object.isString(this.options.parameters))
 this.options.parameters = this.options.parameters.toQueryParams();
 else if (Object.isHash(this.options.parameters))
 this.options.parameters = this.options.parameters.toObject();
}
});
Ajax.Request = Class.create(Ajax.Base,{
 _complete: false,

 initialize: function($super, url, options){
 $super(options);
 this.transport = Ajax.getTransport();
 this.request(url);
},

 request: function(url){
 this.url = url;
 this.method = this.options.method;
 var params = Object.clone(this.options.parameters);

 if (!['get', 'post'].include(this.method)){
 params['_method'] = this.method;
 this.method = 'post';
}

 this.parameters = params;

 if (params = Object.toQueryString(params)){
 if (this.method == 'get')
 this.url += (this.url.include('?') ? '&' : '?') + params;
 else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
 params += '&_=';
}

 try{
 var response = new Ajax.Response(this);
 if (this.options.onCreate) this.options.onCreate(response);
 Ajax.Responders.dispatch('onCreate', this, response);

 this.transport.open(this.method.toUpperCase(), this.url,
 this.options.asynchronous);

 if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);

 this.transport.onreadystatechange = this.onStateChange.bind(this);
 this.setRequestHeaders();

 this.body = this.method == 'post' ? (this.options.postBody || params) : null;
 this.transport.send(this.body);

 /* Force Firefox to handle ready state 4 for synchronous requests */
 if (!this.options.asynchronous && this.transport.overrideMimeType)
 this.onStateChange();

}
 catch (e){
 this.dispatchException(e);
}
},

 onStateChange: function(){
 var readyState = this.transport.readyState;
 if (readyState > 1 && !((readyState == 4) && this._complete))
 this.respondToReadyState(this.transport.readyState);
},

 setRequestHeaders: function(){
 var headers ={
 'X-Requested-With': 'XMLHttpRequest',
 'X-Prototype-Version': Prototype.Version,
 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
};

 if (this.method == 'post'){
 headers['Content-type'] = this.options.contentType +
 (this.options.encoding ? '; charset=' + this.options.encoding : '');

 /* Force "Connection: close" for older Mozilla browsers to work
 * around a bug where XMLHttpRequest sends an incorrect
 * Content-length header. See Mozilla Bugzilla #246651.
 */
 if (this.transport.overrideMimeType &&
 (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
 headers['Connection'] = 'close';
}

 if (typeof this.options.requestHeaders == 'object'){
 var extras = this.options.requestHeaders;

 if (Object.isFunction(extras.push))
 for (var i = 0, length = extras.length; i < length; i += 2)
 headers[extras[i]] = extras[i+1];
 else
 $H(extras).each(function(pair){headers[pair.key] = pair.value});
}

 for (var name in headers)
 this.transport.setRequestHeader(name, headers[name]);
},

 success: function(){
 var status = this.getStatus();
 return !status || (status >= 200 && status < 300);
},

 getStatus: function(){
 try{
 return this.transport.status || 0;
}catch (e){return 0}
},

 respondToReadyState: function(readyState){
 var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);

 if (state == 'Complete'){
 try{
 this._complete = true;
 (this.options['on' + response.status]
 || this.options['on' + (this.success() ? 'Success' : 'Failure')]
 || Prototype.emptyFunction)(response, response.headerJSON);
}catch (e){
 this.dispatchException(e);
}

 var contentType = response.getHeader('Content-type');
 if (this.options.evalJS == 'force'
 || (this.options.evalJS && this.isSameOrigin() && contentType
 && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
 this.evalResponse();
}

 try{
 (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
 Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
}catch (e){
 this.dispatchException(e);
}

 if (state == 'Complete'){
 this.transport.onreadystatechange = Prototype.emptyFunction;
}
},

 isSameOrigin: function(){
 var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
 return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
 protocol: location.protocol,
 domain: document.domain,
 port: location.port ? ':' + location.port : ''
}));
},

 getHeader: function(name){
 try{
 return this.transport.getResponseHeader(name) || null;
}catch (e){return null;}
},

 evalResponse: function(){
 try{
 return eval((this.transport.responseText || '').unfilterJSON());
}catch (e){
 this.dispatchException(e);
}
},

 dispatchException: function(exception){
 (this.options.onException || Prototype.emptyFunction)(this, exception);
 Ajax.Responders.dispatch('onException', this, exception);
}
});

Ajax.Request.Events =
 ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];








Ajax.Response = Class.create({
 initialize: function(request){
 this.request = request;
 var transport = this.transport = request.transport,
 readyState = this.readyState = transport.readyState;

 if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4){
 this.status = this.getStatus();
 this.statusText = this.getStatusText();
 this.responseText = String.interpret(transport.responseText);
 this.headerJSON = this._getHeaderJSON();
}

 if(readyState == 4){
 var xml = transport.responseXML;
 this.responseXML = Object.isUndefined(xml) ? null : xml;
 this.responseJSON = this._getResponseJSON();
}
},

 status: 0,

 statusText: '',

 getStatus: Ajax.Request.prototype.getStatus,

 getStatusText: function(){
 try{
 return this.transport.statusText || '';
}catch (e){return ''}
},

 getHeader: Ajax.Request.prototype.getHeader,

 getAllHeaders: function(){
 try{
 return this.getAllResponseHeaders();
}catch (e){return null}
},

 getResponseHeader: function(name){
 return this.transport.getResponseHeader(name);
},

 getAllResponseHeaders: function(){
 return this.transport.getAllResponseHeaders();
},

 _getHeaderJSON: function(){
 var json = this.getHeader('X-JSON');
 if (!json) return null;
 json = decodeURIComponent(escape(json));
 try{
 return json.evalJSON(this.request.options.sanitizeJSON ||
 !this.request.isSameOrigin());
}catch (e){
 this.request.dispatchException(e);
}
},

 _getResponseJSON: function(){
 var options = this.request.options;
 if (!options.evalJSON || (options.evalJSON != 'force' &&
 !(this.getHeader('Content-type') || '').include('application/json')) ||
 this.responseText.blank())
 return null;
 try{
 return this.responseText.evalJSON(options.sanitizeJSON ||
 !this.request.isSameOrigin());
}catch (e){
 this.request.dispatchException(e);
}
}
});

Ajax.Updater = Class.create(Ajax.Request,{
 initialize: function($super, container, url, options){
 this.container ={
 success: (container.success || container),
 failure: (container.failure || (container.success ? null : container))
};

 options = Object.clone(options);
 var onComplete = options.onComplete;
 options.onComplete = (function(response, json){
 this.updateContent(response.responseText);
 if (Object.isFunction(onComplete)) onComplete(response, json);
}).bind(this);

 $super(url, options);
},

 updateContent: function(responseText){
 var receiver = this.container[this.success() ? 'success' : 'failure'],
 options = this.options;

 if (!options.evalScripts) responseText = responseText.stripScripts();

 if (receiver = $(receiver)){
 if (options.insertion){
 if (Object.isString(options.insertion)){
 var insertion ={}; insertion[options.insertion] = responseText;
 receiver.insert(insertion);
}
 else options.insertion(receiver, responseText);
}
 else receiver.update(responseText);
}
}
});

Ajax.PeriodicalUpdater = Class.create(Ajax.Base,{
 initialize: function($super, container, url, options){
 $super(options);
 this.onComplete = this.options.onComplete;

 this.frequency = (this.options.frequency || 2);
 this.decay = (this.options.decay || 1);

 this.updater ={};
 this.container = container;
 this.url = url;

 this.start();
},

 start: function(){
 this.options.onComplete = this.updateComplete.bind(this);
 this.onTimerEvent();
},

 stop: function(){
 this.updater.options.onComplete = undefined;
 clearTimeout(this.timer);
 (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
},

 updateComplete: function(response){
 if (this.options.decay){
 this.decay = (response.responseText == this.lastText ?
 this.decay * this.options.decay : 1);

 this.lastText = response.responseText;
}
 this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
},

 onTimerEvent: function(){
 this.updater = new Ajax.Updater(this.container, this.url, this.options);
}
});



function $(element){
 if (arguments.length > 1){
 for (var i = 0, elements = [], length = arguments.length; i < length; i++)
 elements.push($(arguments[i]));
 return elements;
}
 if (Object.isString(element))
 element = document.getElementById(element);
 return Element.extend(element);
}

if (Prototype.BrowserFeatures.XPath){
 document._getElementsByXPath = function(expression, parentElement){
 var results = [];
 var query = document.evaluate(expression, $(parentElement) || document,
 null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
 for (var i = 0, length = query.snapshotLength; i < length; i++)
 results.push(Element.extend(query.snapshotItem(i)));
 return results;
};
}

/*--------------------------------------------------------------------------*/

if (!window.Node) var Node ={};

if (!Node.ELEMENT_NODE){
 Object.extend(Node,{
 ELEMENT_NODE: 1,
 ATTRIBUTE_NODE: 2,
 TEXT_NODE: 3,
 CDATA_SECTION_NODE: 4,
 ENTITY_REFERENCE_NODE: 5,
 ENTITY_NODE: 6,
 PROCESSING_INSTRUCTION_NODE: 7,
 COMMENT_NODE: 8,
 DOCUMENT_NODE: 9,
 DOCUMENT_TYPE_NODE: 10,
 DOCUMENT_FRAGMENT_NODE: 11,
 NOTATION_NODE: 12
});
}


(function(global){

 var SETATTRIBUTE_IGNORES_NAME = (function(){
 var elForm = document.createElement("form");
 var elInput = document.createElement("input");
 var root = document.documentElement;
 elInput.setAttribute("name", "test");
 elForm.appendChild(elInput);
 root.appendChild(elForm);
 var isBuggy = elForm.elements
 ? (typeof elForm.elements.test == "undefined")
 : null;
 root.removeChild(elForm);
 elForm = elInput = null;
 return isBuggy;
})();

 var element = global.Element;
 global.Element = function(tagName, attributes){
 attributes = attributes ||{};
 tagName = tagName.toLowerCase();
 var cache = Element.cache;
 if (SETATTRIBUTE_IGNORES_NAME && attributes.name){
 tagName = '<' + tagName + ' name="' + attributes.name + '">';
 delete attributes.name;
 return Element.writeAttribute(document.createElement(tagName), attributes);
}
 if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
 return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
};
 Object.extend(global.Element, element ||{});
 if (element) global.Element.prototype = element.prototype;
})(this);

Element.cache ={};
Element.idCounter = 1;

Element.Methods ={
 visible: function(element){
 return $(element).style.display != 'none';
},

 toggle: function(element){
 element = $(element);
 Element[Element.visible(element) ? 'hide' : 'show'](element);
 return element;
},


 hide: function(element){
 element = $(element);
 element.style.display = 'none';
 return element;
},

 show: function(element){
 element = $(element);
 element.style.display = '';
 return element;
},

 remove: function(element){
 element = $(element);
 element.parentNode.removeChild(element);
 return element;
},

 update: (function(){

 var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
 var el = document.createElement("select"),
 isBuggy = true;
 el.innerHTML = "<option value=\"test\">test</option>";
 if (el.options && el.options[0]){
 isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
}
 el = null;
 return isBuggy;
})();

 var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){
 try{
 var el = document.createElement("table");
 if (el && el.tBodies){
 el.innerHTML = "<tbody><tr><td>test</td></tr></tbody>";
 var isBuggy = typeof el.tBodies[0] == "undefined";
 el = null;
 return isBuggy;
}
}catch (e){
 return true;
}
})();

 var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function (){
 var s = document.createElement("script"),
 isBuggy = false;
 try{
 s.appendChild(document.createTextNode(""));
 isBuggy = !s.firstChild ||
 s.firstChild && s.firstChild.nodeType !== 3;
}catch (e){
 isBuggy = true;
}
 s = null;
 return isBuggy;
})();

 function update(element, content){
 element = $(element);

 if (content && content.toElement)
 content = content.toElement();

 if (Object.isElement(content))
 return element.update().insert(content);

 content = Object.toHTML(content);

 var tagName = element.tagName.toUpperCase();

 if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING){
 element.text = content;
 return element;
}

 if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY){
 if (tagName in Element._insertionTranslations.tags){
 while (element.firstChild){
 element.removeChild(element.firstChild);
}
 Element._getContentFromAnonymousElement(tagName, content.stripScripts())
 .each(function(node){
 element.appendChild(node)
});
}
 else{
 element.innerHTML = content.stripScripts();
}
}
 else{
 element.innerHTML = content.stripScripts();
}

 content.evalScripts.bind(content).defer();
 return element;
}

 return update;
})(),

 replace: function(element, content){
 element = $(element);
 if (content && content.toElement) content = content.toElement();
 else if (!Object.isElement(content)){
 content = Object.toHTML(content);
 var range = element.ownerDocument.createRange();
 range.selectNode(element);
 content.evalScripts.bind(content).defer();
 content = range.createContextualFragment(content.stripScripts());
}
 element.parentNode.replaceChild(content, element);
 return element;
},

 insert: function(element, insertions){
 element = $(element);

 if (Object.isString(insertions) || Object.isNumber(insertions) ||
 Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
 insertions ={bottom:insertions};

 var content, insert, tagName, childNodes;

 for (var position in insertions){
 content = insertions[position];
 position = position.toLowerCase();
 insert = Element._insertionTranslations[position];

 if (content && content.toElement) content = content.toElement();
 if (Object.isElement(content)){
 insert(element, content);
 continue;
}

 content = Object.toHTML(content);

 tagName = ((position == 'before' || position == 'after')
 ? element.parentNode : element).tagName.toUpperCase();

 childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());

 if (position == 'top' || position == 'after') childNodes.reverse();
 childNodes.each(insert.curry(element));

 content.evalScripts.bind(content).defer();
}

 return element;
},

 wrap: function(element, wrapper, attributes){
 element = $(element);
 if (Object.isElement(wrapper))
 $(wrapper).writeAttribute(attributes ||{});
 else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
 else wrapper = new Element('div', wrapper);
 if (element.parentNode)
 element.parentNode.replaceChild(wrapper, element);
 wrapper.appendChild(element);
 return wrapper;
},

 inspect: function(element){
 element = $(element);
 var result = '<' + element.tagName.toLowerCase();
 $H({'id': 'id', 'className': 'class'}).each(function(pair){
 var property = pair.first(), attribute = pair.last();
 var value = (element[property] || '').toString();
 if (value) result += ' ' + attribute + '=' + value.inspect(true);
});
 return result + '>';
},

 recursivelyCollect: function(element, property){
 element = $(element);
 var elements = [];
 while (element = element[property])
 if (element.nodeType == 1)
 elements.push(Element.extend(element));
 return elements;
},

 ancestors: function(element){
 return Element.recursivelyCollect(element, 'parentNode');
},

 descendants: function(element){
 return Element.select(element, "*");
},

 firstDescendant: function(element){
 element = $(element).firstChild;
 while (element && element.nodeType != 1) element = element.nextSibling;
 return $(element);
},

 immediateDescendants: function(element){
 if (!(element = $(element).firstChild)) return [];
 while (element && element.nodeType != 1) element = element.nextSibling;
 if (element) return [element].concat($(element).nextSiblings());
 return [];
},

 previousSiblings: function(element){
 return Element.recursivelyCollect(element, 'previousSibling');
},

 nextSiblings: function(element){
 return Element.recursivelyCollect(element, 'nextSibling');
},

 siblings: function(element){
 element = $(element);
 return Element.previousSiblings(element).reverse()
 .concat(Element.nextSiblings(element));
},

 match: function(element, selector){
 if (Object.isString(selector))
 selector = new Selector(selector);
 return selector.match($(element));
},

 up: function(element, expression, index){
 element = $(element);
 if (arguments.length == 1) return $(element.parentNode);
 var ancestors = Element.ancestors(element);
 return Object.isNumber(expression) ? ancestors[expression] :
 Selector.findElement(ancestors, expression, index);
},

 down: function(element, expression, index){
 element = $(element);
 if (arguments.length == 1) return Element.firstDescendant(element);
 return Object.isNumber(expression) ? Element.descendants(element)[expression] :
 Element.select(element, expression)[index || 0];
},

 previous: function(element, expression, index){
 element = $(element);
 if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
 var previousSiblings = Element.previousSiblings(element);
 return Object.isNumber(expression) ? previousSiblings[expression] :
 Selector.findElement(previousSiblings, expression, index);
},

 next: function(element, expression, index){
 element = $(element);
 if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
 var nextSiblings = Element.nextSiblings(element);
 return Object.isNumber(expression) ? nextSiblings[expression] :
 Selector.findElement(nextSiblings, expression, index);
},


 select: function(element){
 var args = Array.prototype.slice.call(arguments, 1);
 return Selector.findChildElements(element, args);
},

 adjacent: function(element){
 var args = Array.prototype.slice.call(arguments, 1);
 return Selector.findChildElements(element.parentNode, args).without(element);
},

 identify: function(element){
 element = $(element);
 var id = Element.readAttribute(element, 'id');
 if (id) return id;
 do{id = 'anonymous_element_' + Element.idCounter++}while ($(id));
 Element.writeAttribute(element, 'id', id);
 return id;
},

 readAttribute: function(element, name){
 element = $(element);
 if (Prototype.Browser.IE){
 var t = Element._attributeTranslations.read;
 if (t.values[name]) return t.values[name](element, name);
 if (t.names[name]) name = t.names[name];
 if (name.include(':')){
 return (!element.attributes || !element.attributes[name]) ? null :
 element.attributes[name].value;
}
}
 return element.getAttribute(name);
},

 writeAttribute: function(element, name, value){
 element = $(element);
 var attributes ={}, t = Element._attributeTranslations.write;

 if (typeof name == 'object') attributes = name;
 else attributes[name] = Object.isUndefined(value) ? true : value;

 for (var attr in attributes){
 name = t.names[attr] || attr;
 value = attributes[attr];
 if (t.values[attr]) name = t.values[attr](element, value);
 if (value === false || value === null)
 element.removeAttribute(name);
 else if (value === true)
 element.setAttribute(name, name);
 else element.setAttribute(name, value);
}
 return element;
},

 getHeight: function(element){
 return Element.getDimensions(element).height;
},

 getWidth: function(element){
 return Element.getDimensions(element).width;
},

 classNames: function(element){
 return new Element.ClassNames(element);
},

 hasClassName: function(element, className){
 if (!(element = $(element))) return;
 var elementClassName = element.className;
 return (elementClassName.length > 0 && (elementClassName == className ||
 new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
},

 addClassName: function(element, className){
 if (!(element = $(element))) return;
 if (!Element.hasClassName(element, className))
 element.className += (element.className ? ' ' : '') + className;
 return element;
},

 removeClassName: function(element, className){
 if (!(element = $(element))) return;
 element.className = element.className.replace(
 new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
 return element;
},

 toggleClassName: function(element, className){
 if (!(element = $(element))) return;
 return Element[Element.hasClassName(element, className) ?
 'removeClassName' : 'addClassName'](element, className);
},

 cleanWhitespace: function(element){
 element = $(element);
 var node = element.firstChild;
 while (node){
 var nextNode = node.nextSibling;
 if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
 element.removeChild(node);
 node = nextNode;
}
 return element;
},

 empty: function(element){
 return $(element).innerHTML.blank();
},

 descendantOf: function(element, ancestor){
 element = $(element), ancestor = $(ancestor);

 if (element.compareDocumentPosition)
 return (element.compareDocumentPosition(ancestor) & 8) === 8;

 if (ancestor.contains)
 return ancestor.contains(element) && ancestor !== element;

 while (element = element.parentNode)
 if (element == ancestor) return true;

 return false;
},

 scrollTo: function(element){
 element = $(element);
 var pos = Element.cumulativeOffset(element);
 window.scrollTo(pos[0], pos[1]);
 return element;
},

 getStyle: function(element, style){
 element = $(element);
 style = style == 'float' ? 'cssFloat' : style.camelize();
 var value = element.style[style];
 if (!value || value == 'auto'){
 var css = document.defaultView.getComputedStyle(element, null);
 value = css ? css[style] : null;
}
 if (style == 'opacity') return value ? parseFloat(value) : 1.0;
 return value == 'auto' ? null : value;
},

 getOpacity: function(element){
 return $(element).getStyle('opacity');
},

 setStyle: function(element, styles){
 element = $(element);
 var elementStyle = element.style, match;
 if (Object.isString(styles)){
 element.style.cssText += ';' + styles;
 return styles.include('opacity') ?
 element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
}
 for (var property in styles)
 if (property == 'opacity') element.setOpacity(styles[property]);
 else
 elementStyle[(property == 'float' || property == 'cssFloat') ?
 (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
 property] = styles[property];

 return element;
},

 setOpacity: function(element, value){
 element = $(element);
 element.style.opacity = (value == 1 || value === '') ? '' :
 (value < 0.00001) ? 0 : value;
 return element;
},

 getDimensions: function(element){
 element = $(element);
 var display = Element.getStyle(element, 'display');
 if (display != 'none' && display != null) // Safari bug
 return{width: element.offsetWidth, height: element.offsetHeight};

 var els = element.style;
 var originalVisibility = els.visibility;
 var originalPosition = els.position;
 var originalDisplay = els.display;
 els.visibility = 'hidden';
 if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari
 els.position = 'absolute';
 els.display = 'block';
 var originalWidth = element.clientWidth;
 var originalHeight = element.clientHeight;
 els.display = originalDisplay;
 els.position = originalPosition;
 els.visibility = originalVisibility;
 return{width: originalWidth, height: originalHeight};
},

 makePositioned: function(element){
 element = $(element);
 var pos = Element.getStyle(element, 'position');
 if (pos == 'static' || !pos){
 element._madePositioned = true;
 element.style.position = 'relative';
 if (Prototype.Browser.Opera){
 element.style.top = 0;
 element.style.left = 0;
}
}
 return element;
},

 undoPositioned: function(element){
 element = $(element);
 if (element._madePositioned){
 element._madePositioned = undefined;
 element.style.position =
 element.style.top =
 element.style.left =
 element.style.bottom =
 element.style.right = '';
}
 return element;
},

 makeClipping: function(element){
 element = $(element);
 if (element._overflow) return element;
 element._overflow = Element.getStyle(element, 'overflow') || 'auto';
 if (element._overflow !== 'hidden')
 element.style.overflow = 'hidden';
 return element;
},

 undoClipping: function(element){
 element = $(element);
 if (!element._overflow) return element;
 element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
 element._overflow = null;
 return element;
},

 cumulativeOffset: function(element){
 var valueT = 0, valueL = 0;
 do{
 valueT += element.offsetTop || 0;
 valueL += element.offsetLeft || 0;
 element = element.offsetParent;
}while (element);
 return Element._returnOffset(valueL, valueT);
},

 positionedOffset: function(element){
 var valueT = 0, valueL = 0;
 do{
 valueT += element.offsetTop || 0;
 valueL += element.offsetLeft || 0;
 element = element.offsetParent;
 if (element){
 if (element.tagName.toUpperCase() == 'BODY') break;
 var p = Element.getStyle(element, 'position');
 if (p !== 'static') break;
}
}while (element);
 return Element._returnOffset(valueL, valueT);
},

 absolutize: function(element){
 element = $(element);
 if (Element.getStyle(element, 'position') == 'absolute') return element;

 var offsets = Element.positionedOffset(element);
 var top = offsets[1];
 var left = offsets[0];
 var width = element.clientWidth;
 var height = element.clientHeight;

 element._originalLeft = left - parseFloat(element.style.left || 0);
 element._originalTop = top - parseFloat(element.style.top || 0);
 element._originalWidth = element.style.width;
 element._originalHeight = element.style.height;

 element.style.position = 'absolute';
 element.style.top = top + 'px';
 element.style.left = left + 'px';
 element.style.width = width + 'px';
 element.style.height = height + 'px';
 return element;
},

 relativize: function(element){
 element = $(element);
 if (Element.getStyle(element, 'position') == 'relative') return element;

 element.style.position = 'relative';
 var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
 var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

 element.style.top = top + 'px';
 element.style.left = left + 'px';
 element.style.height = element._originalHeight;
 element.style.width = element._originalWidth;
 return element;
},

 cumulativeScrollOffset: function(element){
 var valueT = 0, valueL = 0;
 do{
 valueT += element.scrollTop || 0;
 valueL += element.scrollLeft || 0;
 element = element.parentNode;
}while (element);
 return Element._returnOffset(valueL, valueT);
},

 getOffsetParent: function(element){
 if (element.offsetParent) return $(element.offsetParent);
 if (element == document.body) return $(element);

 while ((element = element.parentNode) && element != document.body)
 if (Element.getStyle(element, 'position') != 'static')
 return $(element);

 return $(document.body);
},

 viewportOffset: function(forElement){
 var valueT = 0, valueL = 0;

 var element = forElement;
 do{
 valueT += element.offsetTop || 0;
 valueL += element.offsetLeft || 0;

 if (element.offsetParent == document.body &&
 Element.getStyle(element, 'position') == 'absolute') break;

}while (element = element.offsetParent);

 element = forElement;
 do{
 if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))){
 valueT -= element.scrollTop || 0;
 valueL -= element.scrollLeft || 0;
}
}while (element = element.parentNode);

 return Element._returnOffset(valueL, valueT);
},

 clonePosition: function(element, source){
 var options = Object.extend({
 setLeft: true,
 setTop: true,
 setWidth: true,
 setHeight: true,
 offsetTop: 0,
 offsetLeft: 0
}, arguments[2] ||{});

 source = $(source);
 var p = Element.viewportOffset(source);

 element = $(element);
 var delta = [0, 0];
 var parent = null;
 if (Element.getStyle(element, 'position') == 'absolute'){
 parent = Element.getOffsetParent(element);
 delta = Element.viewportOffset(parent);
}

 if (parent == document.body){
 delta[0] -= document.body.offsetLeft;
 delta[1] -= document.body.offsetTop;
}

 if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
 if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
 if (options.setWidth) element.style.width = source.offsetWidth + 'px';
 if (options.setHeight) element.style.height = source.offsetHeight + 'px';
 return element;
}
};

Object.extend(Element.Methods,{
 getElementsBySelector: Element.Methods.select,

 childElements: Element.Methods.immediateDescendants
});

Element._attributeTranslations ={
 write:{
 names:{
 className: 'class',
 htmlFor: 'for'
},
 values:{}
}
};

if (Prototype.Browser.Opera){
 Element.Methods.getStyle = Element.Methods.getStyle.wrap(
 function(proceed, element, style){
 switch (style){
 case 'left': case 'top': case 'right': case 'bottom':
 if (proceed(element, 'position') === 'static') return null;
 case 'height': case 'width':
 if (!Element.visible(element)) return null;

 var dim = parseInt(proceed(element, style), 10);

 if (dim !== element['offset' + style.capitalize()])
 return dim + 'px';

 var properties;
 if (style === 'height'){
 properties = ['border-top-width', 'padding-top',
 'padding-bottom', 'border-bottom-width'];
}
 else{
 properties = ['border-left-width', 'padding-left',
 'padding-right', 'border-right-width'];
}
 return properties.inject(dim, function(memo, property){
 var val = proceed(element, property);
 return val === null ? memo : memo - parseInt(val, 10);
}) + 'px';
 default: return proceed(element, style);
}
}
 );

 Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
 function(proceed, element, attribute){
 if (attribute === 'title') return element.title;
 return proceed(element, attribute);
}
 );
}

else if (Prototype.Browser.IE){
 Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
 function(proceed, element){
 element = $(element);
 try{element.offsetParent}
 catch(e){return $(document.body)}
 var position = element.getStyle('position');
 if (position !== 'static') return proceed(element);
 element.setStyle({position: 'relative'});
 var value = proceed(element);
 element.setStyle({position: position});
 return value;
}
 );

 $w('positionedOffset viewportOffset').each(function(method){
 Element.Methods[method] = Element.Methods[method].wrap(
 function(proceed, element){
 element = $(element);
 try{element.offsetParent}
 catch(e){return Element._returnOffset(0,0)}
 var position = element.getStyle('position');
 if (position !== 'static') return proceed(element);
 var offsetParent = element.getOffsetParent();
 if (offsetParent && offsetParent.getStyle('position') === 'fixed')
 offsetParent.setStyle({zoom: 1});
 element.setStyle({position: 'relative'});
 var value = proceed(element);
 element.setStyle({position: position});
 return value;
}
 );
});

 Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
 function(proceed, element){
 try{element.offsetParent}
 catch(e){return Element._returnOffset(0,0)}
 return proceed(element);
}
 );

 Element.Methods.getStyle = function(element, style){
 element = $(element);
 style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
 var value = element.style[style];
 if (!value && element.currentStyle) value = element.currentStyle[style];

 if (style == 'opacity'){
 if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
 if (value[1]) return parseFloat(value[1]) / 100;
 return 1.0;
}

 if (value == 'auto'){
 if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
 return element['offset' + style.capitalize()] + 'px';
 return null;
}
 return value;
};

 Element.Methods.setOpacity = function(element, value){
 function stripAlpha(filter){
 return filter.replace(/alpha\([^\)]*\)/gi,'');
}
 element = $(element);
 var currentStyle = element.currentStyle;
 if ((currentStyle && !currentStyle.hasLayout) ||
 (!currentStyle && element.style.zoom == 'normal'))
 element.style.zoom = 1;

 var filter = element.getStyle('filter'), style = element.style;
 if (value == 1 || value === ''){
 (filter = stripAlpha(filter)) ?
 style.filter = filter : style.removeAttribute('filter');
 return element;
}else if (value < 0.00001) value = 0;
 style.filter = stripAlpha(filter) +
 'alpha(opacity=' + (value * 100) + ')';
 return element;
};

 Element._attributeTranslations = (function(){

 var classProp = 'className';
 var forProp = 'for';

 var el = document.createElement('div');

 el.setAttribute(classProp, 'x');

 if (el.className !== 'x'){
 el.setAttribute('class', 'x');
 if (el.className === 'x'){
 classProp = 'class';
}
}
 el = null;

 el = document.createElement('label');
 el.setAttribute(forProp, 'x');
 if (el.htmlFor !== 'x'){
 el.setAttribute('htmlFor', 'x');
 if (el.htmlFor === 'x'){
 forProp = 'htmlFor';
}
}
 el = null;

 return{
 read:{
 names:{
 'class': classProp,
 'className': classProp,
 'for': forProp,
 'htmlFor': forProp
},
 values:{
 _getAttr: function(element, attribute){
 return element.getAttribute(attribute);
},
 _getAttr2: function(element, attribute){
 return element.getAttribute(attribute, 2);
},
 _getAttrNode: function(element, attribute){
 var node = element.getAttributeNode(attribute);
 return node ? node.value : "";
},
 _getEv: (function(){

 var el = document.createElement('div');
 el.onclick = Prototype.emptyFunction;
 var value = el.getAttribute('onclick');
 var f;

 if (String(value).indexOf('{') > -1){
 f = function(element, attribute){
 attribute = element.getAttribute(attribute);
 if (!attribute) return null;
 attribute = attribute.toString();
 attribute = attribute.split('{')[1];
 attribute = attribute.split('}')[0];
 return attribute.strip();
};
}
 else if (value === ''){
 f = function(element, attribute){
 attribute = element.getAttribute(attribute);
 if (!attribute) return null;
 return attribute.strip();
};
}
 el = null;
 return f;
})(),
 _flag: function(element, attribute){
 return $(element).hasAttribute(attribute) ? attribute : null;
},
 style: function(element){
 return element.style.cssText.toLowerCase();
},
 title: function(element){
 return element.title;
}
}
}
}
})();

 Element._attributeTranslations.write ={
 names: Object.extend({
 cellpadding: 'cellPadding',
 cellspacing: 'cellSpacing'
}, Element._attributeTranslations.read.names),
 values:{
 checked: function(element, value){
 element.checked = !!value;
},

 style: function(element, value){
 element.style.cssText = value ? value : '';
}
}
};

 Element._attributeTranslations.has ={};

 $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
 'encType maxLength readOnly longDesc frameBorder').each(function(attr){
 Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
 Element._attributeTranslations.has[attr.toLowerCase()] = attr;
});

 (function(v){
 Object.extend(v,{
 href: v._getAttr2,
 src: v._getAttr2,
 type: v._getAttr,
 action: v._getAttrNode,
 disabled: v._flag,
 checked: v._flag,
 readonly: v._flag,
 multiple: v._flag,
 onload: v._getEv,
 onunload: v._getEv,
 onclick: v._getEv,
 ondblclick: v._getEv,
 onmousedown: v._getEv,
 onmouseup: v._getEv,
 onmouseover: v._getEv,
 onmousemove: v._getEv,
 onmouseout: v._getEv,
 onfocus: v._getEv,
 onblur: v._getEv,
 onkeypress: v._getEv,
 onkeydown: v._getEv,
 onkeyup: v._getEv,
 onsubmit: v._getEv,
 onreset: v._getEv,
 onselect: v._getEv,
 onchange: v._getEv
});
})(Element._attributeTranslations.read.values);

 if (Prototype.BrowserFeatures.ElementExtensions){
 (function(){
 function _descendants(element){
 var nodes = element.getElementsByTagName('*'), results = [];
 for (var i = 0, node; node = nodes[i]; i++)
 if (node.tagName !== "!") // Filter out comment nodes.
 results.push(node);
 return results;
}

 Element.Methods.down = function(element, expression, index){
 element = $(element);
 if (arguments.length == 1) return element.firstDescendant();
 return Object.isNumber(expression) ? _descendants(element)[expression] :
 Element.select(element, expression)[index || 0];
}
})();
}

}

else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)){
 Element.Methods.setOpacity = function(element, value){
 element = $(element);
 element.style.opacity = (value == 1) ? 0.999999 :
 (value === '') ? '' : (value < 0.00001) ? 0 : value;
 return element;
};
}

else if (Prototype.Browser.WebKit){
 Element.Methods.setOpacity = function(element, value){
 element = $(element);
 element.style.opacity = (value == 1 || value === '') ? '' :
 (value < 0.00001) ? 0 : value;

 if (value == 1)
 if(element.tagName.toUpperCase() == 'IMG' && element.width){
 element.width++; element.width--;
}else try{
 var n = document.createTextNode(' ');
 element.appendChild(n);
 element.removeChild(n);
}catch (e){}

 return element;
};

 Element.Methods.cumulativeOffset = function(element){
 var valueT = 0, valueL = 0;
 do{
 valueT += element.offsetTop || 0;
 valueL += element.offsetLeft || 0;
 if (element.offsetParent == document.body)
 if (Element.getStyle(element, 'position') == 'absolute') break;

 element = element.offsetParent;
}while (element);

 return Element._returnOffset(valueL, valueT);
};
}

if ('outerHTML' in document.documentElement){
 Element.Methods.replace = function(element, content){
 element = $(element);

 if (content && content.toElement) content = content.toElement();
 if (Object.isElement(content)){
 element.parentNode.replaceChild(content, element);
 return element;
}

 content = Object.toHTML(content);
 var parent = element.parentNode, tagName = parent.tagName.toUpperCase();

 if (Element._insertionTranslations.tags[tagName]){
 var nextSibling = element.next();
 var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
 parent.removeChild(element);
 if (nextSibling)
 fragments.each(function(node){parent.insertBefore(node, nextSibling)});
 else
 fragments.each(function(node){parent.appendChild(node)});
}
 else element.outerHTML = content.stripScripts();

 content.evalScripts.bind(content).defer();
 return element;
};
}

Element._returnOffset = function(l, t){
 var result = [l, t];
 result.left = l;
 result.top = t;
 return result;
};

Element._getContentFromAnonymousElement = function(tagName, html){
 var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
 if (t){
 div.innerHTML = t[0] + html + t[1];
 t[2].times(function(){div = div.firstChild});
}else div.innerHTML = html;
 return $A(div.childNodes);
};

Element._insertionTranslations ={
 before: function(element, node){
 element.parentNode.insertBefore(node, element);
},
 top: function(element, node){
 element.insertBefore(node, element.firstChild);
},
 bottom: function(element, node){
 element.appendChild(node);
},
 after: function(element, node){
 element.parentNode.insertBefore(node, element.nextSibling);
},
 tags:{
 TABLE: ['<table>', '</table>', 1],
 TBODY: ['<table><tbody>', '</tbody></table>', 2],
 TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
 TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
 SELECT: ['<select>', '</select>', 1]
}
};

(function(){
 var tags = Element._insertionTranslations.tags;
 Object.extend(tags,{
 THEAD: tags.TBODY,
 TFOOT: tags.TBODY,
 TH: tags.TD
});
})();

Element.Methods.Simulated ={
 hasAttribute: function(element, attribute){
 attribute = Element._attributeTranslations.has[attribute] || attribute;
 var node = $(element).getAttributeNode(attribute);
 return !!(node && node.specified);
}
};

Element.Methods.ByTag ={};

Object.extend(Element, Element.Methods);

(function(div){

 if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']){
 window.HTMLElement ={};
 window.HTMLElement.prototype = div['__proto__'];
 Prototype.BrowserFeatures.ElementExtensions = true;
}

 div = null;

})(document.createElement('div'))

Element.extend = (function(){

 function checkDeficiency(tagName){
 if (typeof window.Element != 'undefined'){
 var proto = window.Element.prototype;
 if (proto){
 var id = '_' + (Math.random()+'').slice(2);
 var el = document.createElement(tagName);
 proto[id] = 'x';
 var isBuggy = (el[id] !== 'x');
 delete proto[id];
 el = null;
 return isBuggy;
}
}
 return false;
}

 function extendElementWith(element, methods){
 for (var property in methods){
 var value = methods[property];
 if (Object.isFunction(value) && !(property in element))
 element[property] = value.methodize();
}
}

 var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object');

 if (Prototype.BrowserFeatures.SpecificElementExtensions){
 if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY){
 return function(element){
 if (element && typeof element._extendedByPrototype == 'undefined'){
 var t = element.tagName;
 if (t && (/^(?:object|applet|embed)$/i.test(t))){
 extendElementWith(element, Element.Methods);
 extendElementWith(element, Element.Methods.Simulated);
 extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]);
}
}
 return element;
}
}
 return Prototype.K;
}

 var Methods ={}, ByTag = Element.Methods.ByTag;

 var extend = Object.extend(function(element){
 if (!element || typeof element._extendedByPrototype != 'undefined' ||
 element.nodeType != 1 || element == window) return element;

 var methods = Object.clone(Methods),
 tagName = element.tagName.toUpperCase();

 if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);

 extendElementWith(element, methods);

 element._extendedByPrototype = Prototype.emptyFunction;
 return element;

},{
 refresh: function(){
 if (!Prototype.BrowserFeatures.ElementExtensions){
 Object.extend(Methods, Element.Methods);
 Object.extend(Methods, Element.Methods.Simulated);
}
}
});

 extend.refresh();
 return extend;
})();

Element.hasAttribute = function(element, attribute){
 if (element.hasAttribute) return element.hasAttribute(attribute);
 return Element.Methods.Simulated.hasAttribute(element, attribute);
};

Element.addMethods = function(methods){
 var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;

 if (!methods){
 Object.extend(Form, Form.Methods);
 Object.extend(Form.Element, Form.Element.Methods);
 Object.extend(Element.Methods.ByTag,{
 "FORM": Object.clone(Form.Methods),
 "INPUT": Object.clone(Form.Element.Methods),
 "SELECT": Object.clone(Form.Element.Methods),
 "TEXTAREA": Object.clone(Form.Element.Methods)
});
}

 if (arguments.length == 2){
 var tagName = methods;
 methods = arguments[1];
}

 if (!tagName) Object.extend(Element.Methods, methods ||{});
 else{
 if (Object.isArray(tagName)) tagName.each(extend);
 else extend(tagName);
}

 function extend(tagName){
 tagName = tagName.toUpperCase();
 if (!Element.Methods.ByTag[tagName])
 Element.Methods.ByTag[tagName] ={};
 Object.extend(Element.Methods.ByTag[tagName], methods);
}

 function copy(methods, destination, onlyIfAbsent){
 onlyIfAbsent = onlyIfAbsent || false;
 for (var property in methods){
 var value = methods[property];
 if (!Object.isFunction(value)) continue;
 if (!onlyIfAbsent || !(property in destination))
 destination[property] = value.methodize();
}
}

 function findDOMClass(tagName){
 var klass;
 var trans ={
 "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
 "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
 "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
 "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
 "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
 "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
 "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
 "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
 "FrameSet", "IFRAME": "IFrame"
};
 if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
 if (window[klass]) return window[klass];
 klass = 'HTML' + tagName + 'Element';
 if (window[klass]) return window[klass];
 klass = 'HTML' + tagName.capitalize() + 'Element';
 if (window[klass]) return window[klass];

 var element = document.createElement(tagName);
 var proto = element['__proto__'] || element.constructor.prototype;
 element = null;
 return proto;
}

 var elementPrototype = window.HTMLElement ? HTMLElement.prototype :
 Element.prototype;

 if (F.ElementExtensions){
 copy(Element.Methods, elementPrototype);
 copy(Element.Methods.Simulated, elementPrototype, true);
}

 if (F.SpecificElementExtensions){
 for (var tag in Element.Methods.ByTag){
 var klass = findDOMClass(tag);
 if (Object.isUndefined(klass)) continue;
 copy(T[tag], klass.prototype);
}
}

 Object.extend(Element, Element.Methods);
 delete Element.ByTag;

 if (Element.extend.refresh) Element.extend.refresh();
 Element.cache ={};
};


document.viewport ={

 getDimensions: function(){
 return{width: this.getWidth(), height: this.getHeight()};
},

 getScrollOffsets: function(){
 return Element._returnOffset(
 window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
 window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
}
};

(function(viewport){
 var B = Prototype.Browser, doc = document, element, property ={};

 function getRootElement(){
 if (B.WebKit && !doc.evaluate)
 return document;

 if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
 return document.body;

 return document.documentElement;
}

 function define(D){
 if (!element) element = getRootElement();

 property[D] = 'client' + D;

 viewport['get' + D] = function(){return element[property[D]]};
 return viewport['get' + D]();
}

 viewport.getWidth = define.curry('Width');

 viewport.getHeight = define.curry('Height');
})(document.viewport);


Element.Storage ={
 UID: 1
};

Element.addMethods({
 getStorage: function(element){
 if (!(element = $(element))) return;

 var uid;
 if (element === window){
 uid = 0;
}else{
 if (typeof element._prototypeUID === "undefined")
 element._prototypeUID = [Element.Storage.UID++];
 uid = element._prototypeUID[0];
}

 if (!Element.Storage[uid])
 Element.Storage[uid] = $H();

 return Element.Storage[uid];
},

 store: function(element, key, value){
 if (!(element = $(element))) return;

 if (arguments.length === 2){
 Element.getStorage(element).update(key);
}else{
 Element.getStorage(element).set(key, value);
}

 return element;
},

 retrieve: function(element, key, defaultValue){
 if (!(element = $(element))) return;
 var hash = Element.getStorage(element), value = hash.get(key);

 if (Object.isUndefined(value)){
 hash.set(key, defaultValue);
 value = defaultValue;
}

 return value;
},

 clone: function(element, deep){
 if (!(element = $(element))) return;
 var clone = element.cloneNode(deep);
 clone._prototypeUID = void 0;
 if (deep){
 var descendants = Element.select(clone, '*'),
 i = descendants.length;
 while (i--){
 descendants[i]._prototypeUID = void 0;
}
}
 return Element.extend(clone);
}
});
/* Portions of the Selector class are derived from Jack Slocum's DomQuery,
 * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
 * license. Please see http://www.yui-ext.com/ for more information. */

var Selector = Class.create({
 initialize: function(expression){
 this.expression = expression.strip();

 if (this.shouldUseSelectorsAPI()){
 this.mode = 'selectorsAPI';
}else if (this.shouldUseXPath()){
 this.mode = 'xpath';
 this.compileXPathMatcher();
}else{
 this.mode = "normal";
 this.compileMatcher();
}

},

 shouldUseXPath: (function(){

 var IS_DESCENDANT_SELECTOR_BUGGY = (function(){
 var isBuggy = false;
 if (document.evaluate && window.XPathResult){
 var el = document.createElement('div');
 el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></div>';

 var xpath = ".//*[local-name()='ul' or local-name()='UL']" +
 "//*[local-name()='li' or local-name()='LI']";

 var result = document.evaluate(xpath, el, null,
 XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

 isBuggy = (result.snapshotLength !== 2);
 el = null;
}
 return isBuggy;
})();

 return function(){
 if (!Prototype.BrowserFeatures.XPath) return false;

 var e = this.expression;

 if (Prototype.Browser.WebKit &&
 (e.include("-of-type") || e.include(":empty")))
 return false;

 if ((/(\[[\w-]*?:|:checked)/).test(e))
 return false;

 if (IS_DESCENDANT_SELECTOR_BUGGY) return false;

 return true;
}

})(),

 shouldUseSelectorsAPI: function(){
 if (!Prototype.BrowserFeatures.SelectorsAPI) return false;

 if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false;

 if (!Selector._div) Selector._div = new Element('div');

 try{
 Selector._div.querySelector(this.expression);
}catch(e){
 return false;
}

 return true;
},

 compileMatcher: function(){
 var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
 c = Selector.criteria, le, p, m, len = ps.length, name;

 if (Selector._cache[e]){
 this.matcher = Selector._cache[e];
 return;
}

 this.matcher = ["this.matcher = function(root){",
 "var r = root, h = Selector.handlers, c = false, n;"];

 while (e && le != e && (/\S/).test(e)){
 le = e;
 for (var i = 0; i<len; i++){
 p = ps[i].re;
 name = ps[i].name;
 if (m = e.match(p)){
 this.matcher.push(Object.isFunction(c[name]) ? c[name](m) :
 new Template(c[name]).evaluate(m));
 e = e.replace(m[0], '');
 break;
}
}
}

 this.matcher.push("return h.unique(n);\n}");
 eval(this.matcher.join('\n'));
 Selector._cache[this.expression] = this.matcher;
},

 compileXPathMatcher: function(){
 var e = this.expression, ps = Selector.patterns,
 x = Selector.xpath, le, m, len = ps.length, name;

 if (Selector._cache[e]){
 this.xpath = Selector._cache[e]; return;
}

 this.matcher = ['.//*'];
 while (e && le != e && (/\S/).test(e)){
 le = e;
 for (var i = 0; i<len; i++){
 name = ps[i].name;
 if (m = e.match(ps[i].re)){
 this.matcher.push(Object.isFunction(x[name]) ? x[name](m) :
 new Template(x[name]).evaluate(m));
 e = e.replace(m[0], '');
 break;
}
}
}

 this.xpath = this.matcher.join('');
 Selector._cache[this.expression] = this.xpath;
},

 findElements: function(root){
 root = root || document;
 var e = this.expression, results;

 switch (this.mode){
 case 'selectorsAPI':
 if (root !== document){
 var oldId = root.id, id = $(root).identify();
 id = id.replace(/([\.:])/g, "\\$1");
 e = "#" + id + " " + e;
}

 results = $A(root.querySelectorAll(e)).map(Element.extend);
 root.id = oldId;

 return results;
 case 'xpath':
 return document._getElementsByXPath(this.xpath, root);
 default:
 return this.matcher(root);
}
},

 match: function(element){
 this.tokens = [];

 var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
 var le, p, m, len = ps.length, name;

 while (e && le !== e && (/\S/).test(e)){
 le = e;
 for (var i = 0; i<len; i++){
 p = ps[i].re;
 name = ps[i].name;
 if (m = e.match(p)){
 if (as[name]){
 this.tokens.push([name, Object.clone(m)]);
 e = e.replace(m[0], '');
}else{
 return this.findElements(document).include(element);
}
}
}
}

 var match = true, name, matches;
 for (var i = 0, token; token = this.tokens[i]; i++){
 name = token[0], matches = token[1];
 if (!Selector.assertions[name](element, matches)){
 match = false; break;
}
}

 return match;
},

 toString: function(){
 return this.expression;
},

 inspect: function(){
 return "#<Selector:" + this.expression.inspect() + ">";
}
});

if (Prototype.BrowserFeatures.SelectorsAPI &&
 document.compatMode === 'BackCompat'){
 Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){
 var div = document.createElement('div'),
 span = document.createElement('span');

 div.id = "prototype_test_id";
 span.className = 'Test';
 div.appendChild(span);
 var isIgnored = (div.querySelector('#prototype_test_id .test') !== null);
 div = span = null;
 return isIgnored;
})();
}

Object.extend(Selector,{
 _cache:{},

 xpath:{
 descendant: "//*",
 child: "/*",
 adjacent: "/following-sibling::*[1]",
 laterSibling: '/following-sibling::*',
 tagName: function(m){
 if (m[1] == '*') return '';
 return "[local-name()='" + m[1].toLowerCase() +
 "' or local-name()='" + m[1].toUpperCase() + "']";
},
 className: "[contains(concat(' ', @class, ' '), ' #{1}')]",
 id: "[@id='#{1}']",
 attrPresence: function(m){
 m[1] = m[1].toLowerCase();
 return new Template("[@#{1}]").evaluate(m);
},
 attr: function(m){
 m[1] = m[1].toLowerCase();
 m[3] = m[5] || m[6];
 return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
},
 pseudo: function(m){
 var h = Selector.xpath.pseudos[m[1]];
 if (!h) return '';
 if (Object.isFunction(h)) return h(m);
 return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
},
 operators:{
 '=': "[@#{1}='#{3}']",
 '!=': "[@#{1}!='#{3}']",
 '^=': "[starts-with(@#{1}, '#{3}')]",
 '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
 '*=': "[contains(@#{1}, '#{3}')]",
 '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3}')]",
 '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
},
 pseudos:{
 'first-child': '[not(preceding-sibling::*)]',
 'last-child': '[not(following-sibling::*)]',
 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
 'empty': "[count(*) = 0 and (count(text()) = 0)]",
 'checked': "[@checked]",
 'disabled': "[(@disabled) and (@type!='hidden')]",
 'enabled': "[not(@disabled) and (@type!='hidden')]",
 'not': function(m){
 var e = m[6], p = Selector.patterns,
 x = Selector.xpath, le, v, len = p.length, name;

 var exclusion = [];
 while (e && le != e && (/\S/).test(e)){
 le = e;
 for (var i = 0; i<len; i++){
 name = p[i].name
 if (m = e.match(p[i].re)){
 v = Object.isFunction(x[name]) ? x[name](m) : new Template(x[name]).evaluate(m);
 exclusion.push("(" + v.substring(1, v.length - 1) + ")");
 e = e.replace(m[0], '');
 break;
}
}
}
 return "[not(" + exclusion.join(" and ") + ")]";
},
 'nth-child': function(m){
 return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
},
 'nth-last-child': function(m){
 return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
},
 'nth-of-type': function(m){
 return Selector.xpath.pseudos.nth("position() ", m);
},
 'nth-last-of-type': function(m){
 return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
},
 'first-of-type': function(m){
 m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
},
 'last-of-type': function(m){
 m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
},
 'only-of-type': function(m){
 var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
},
 nth: function(fragment, m){
 var mm, formula = m[6], predicate;
 if (formula == 'even') formula = '2n+0';
 if (formula == 'odd') formula = '2n+1';
 if (mm = formula.match(/^(\d+)$/)) // digit only
 return '[' + fragment + "= " + mm[1] + ']';
 if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)){// an+b
 if (mm[1] == "-") mm[1] = -1;
 var a = mm[1] ? Number(mm[1]) : 1;
 var b = mm[2] ? Number(mm[2]) : 0;
 predicate = "[((#{fragment}- #{b}) mod #{a}= 0) and " +
 "((#{fragment}- #{b}) div #{a}>= 0)]";
 return new Template(predicate).evaluate({
 fragment: fragment, a: a, b: b});
}
}
}
},

 criteria:{
 tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
 className: 'n = h.className(n, r, "#{1}", c); c = false;',
 id: 'n = h.id(n, r, "#{1}", c); c = false;',
 attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
 attr: function(m){
 m[3] = (m[5] || m[6]);
 return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
},
 pseudo: function(m){
 if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
 return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
},
 descendant: 'c = "descendant";',
 child: 'c = "child";',
 adjacent: 'c = "adjacent";',
 laterSibling: 'c = "laterSibling";'
},

 patterns: [
{name: 'laterSibling', re: /^\s*~\s*/},
{name: 'child', re: /^\s*>\s*/},
{name: 'adjacent', re: /^\s*\+\s*/},
{name: 'descendant', re: /^\s/},

{name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/},
{name: 'id', re: /^#([\w\-\*]+)(\b|$)/},
{name: 'className', re: /^\.([\w\-\*]+)(\b|$)/},
{name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/},
{name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/},
{name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/}
 ],

 assertions:{
 tagName: function(element, matches){
 return matches[1].toUpperCase() == element.tagName.toUpperCase();
},

 className: function(element, matches){
 return Element.hasClassName(element, matches[1]);
},

 id: function(element, matches){
 return element.id === matches[1];
},

 attrPresence: function(element, matches){
 return Element.hasAttribute(element, matches[1]);
},

 attr: function(element, matches){
 var nodeValue = Element.readAttribute(element, matches[1]);
 return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
}
},

 handlers:{
 concat: function(a, b){
 for (var i = 0, node; node = b[i]; i++)
 a.push(node);
 return a;
},

 mark: function(nodes){
 var _true = Prototype.emptyFunction;
 for (var i = 0, node; node = nodes[i]; i++)
 node._countedByPrototype = _true;
 return nodes;
},

 unmark: (function(){

 var PROPERTIES_ATTRIBUTES_MAP = (function(){
 var el = document.createElement('div'),
 isBuggy = false,
 propName = '_countedByPrototype',
 value = 'x'
 el[propName] = value;
 isBuggy = (el.getAttribute(propName) === value);
 el = null;
 return isBuggy;
})();

 return PROPERTIES_ATTRIBUTES_MAP ?
 function(nodes){
 for (var i = 0, node; node = nodes[i]; i++)
 node.removeAttribute('_countedByPrototype');
 return nodes;
}:
 function(nodes){
 for (var i = 0, node; node = nodes[i]; i++)
 node._countedByPrototype = void 0;
 return nodes;
}
})(),

 index: function(parentNode, reverse, ofType){
 parentNode._countedByPrototype = Prototype.emptyFunction;
 if (reverse){
 for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--){
 var node = nodes[i];
 if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
}
}else{
 for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
 if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
}
},

 unique: function(nodes){
 if (nodes.length == 0) return nodes;
 var results = [], n;
 for (var i = 0, l = nodes.length; i < l; i++)
 if (typeof (n = nodes[i])._countedByPrototype == 'undefined'){
 n._countedByPrototype = Prototype.emptyFunction;
 results.push(Element.extend(n));
}
 return Selector.handlers.unmark(results);
},

 descendant: function(nodes){
 var h = Selector.handlers;
 for (var i = 0, results = [], node; node = nodes[i]; i++)
 h.concat(results, node.getElementsByTagName('*'));
 return results;
},

 child: function(nodes){
 var h = Selector.handlers;
 for (var i = 0, results = [], node; node = nodes[i]; i++){
 for (var j = 0, child; child = node.childNodes[j]; j++)
 if (child.nodeType == 1 && child.tagName != '!') results.push(child);
}
 return results;
},

 adjacent: function(nodes){
 for (var i = 0, results = [], node; node = nodes[i]; i++){
 var next = this.nextElementSibling(node);
 if (next) results.push(next);
}
 return results;
},

 laterSibling: function(nodes){
 var h = Selector.handlers;
 for (var i = 0, results = [], node; node = nodes[i]; i++)
 h.concat(results, Element.nextSiblings(node));
 return results;
},

 nextElementSibling: function(node){
 while (node = node.nextSibling)
 if (node.nodeType == 1) return node;
 return null;
},

 previousElementSibling: function(node){
 while (node = node.previousSibling)
 if (node.nodeType == 1) return node;
 return null;
},

 tagName: function(nodes, root, tagName, combinator){
 var uTagName = tagName.toUpperCase();
 var results = [], h = Selector.handlers;
 if (nodes){
 if (combinator){
 if (combinator == "descendant"){
 for (var i = 0, node; node = nodes[i]; i++)
 h.concat(results, node.getElementsByTagName(tagName));
 return results;
}else nodes = this[combinator](nodes);
 if (tagName == "*") return nodes;
}
 for (var i = 0, node; node = nodes[i]; i++)
 if (node.tagName.toUpperCase() === uTagName) results.push(node);
 return results;
}else return root.getElementsByTagName(tagName);
},

 id: function(nodes, root, id, combinator){
 var targetNode = $(id), h = Selector.handlers;

 if (root == document){
 if (!targetNode) return [];
 if (!nodes) return [targetNode];
}else{
 if (!root.sourceIndex || root.sourceIndex < 1){
 var nodes = root.getElementsByTagName('*');
 for (var j = 0, node; node = nodes[j]; j++){
 if (node.id === id) return [node];
}
}
}

 if (nodes){
 if (combinator){
 if (combinator == 'child'){
 for (var i = 0, node; node = nodes[i]; i++)
 if (targetNode.parentNode == node) return [targetNode];
}else if (combinator == 'descendant'){
 for (var i = 0, node; node = nodes[i]; i++)
 if (Element.descendantOf(targetNode, node)) return [targetNode];
}else if (combinator == 'adjacent'){
 for (var i = 0, node; node = nodes[i]; i++)
 if (Selector.handlers.previousElementSibling(targetNode) == node)
 return [targetNode];
}else nodes = h[combinator](nodes);
}
 for (var i = 0, node; node = nodes[i]; i++)
 if (node == targetNode) return [targetNode];
 return [];
}
 return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
},

 className: function(nodes, root, className, combinator){
 if (nodes && combinator) nodes = this[combinator](nodes);
 return Selector.handlers.byClassName(nodes, root, className);
},

 byClassName: function(nodes, root, className){
 if (!nodes) nodes = Selector.handlers.descendant([root]);
 var needle = ' ' + className + ' ';
 for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++){
 nodeClassName = node.className;
 if (nodeClassName.length == 0) continue;
 if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
 results.push(node);
}
 return results;
},

 attrPresence: function(nodes, root, attr, combinator){
 if (!nodes) nodes = root.getElementsByTagName("*");
 if (nodes && combinator) nodes = this[combinator](nodes);
 var results = [];
 for (var i = 0, node; node = nodes[i]; i++)
 if (Element.hasAttribute(node, attr)) results.push(node);
 return results;
},

 attr: function(nodes, root, attr, value, operator, combinator){
 if (!nodes) nodes = root.getElementsByTagName("*");
 if (nodes && combinator) nodes = this[combinator](nodes);
 var handler = Selector.operators[operator], results = [];
 for (var i = 0, node; node = nodes[i]; i++){
 var nodeValue = Element.readAttribute(node, attr);
 if (nodeValue === null) continue;
 if (handler(nodeValue, value)) results.push(node);
}
 return results;
},

 pseudo: function(nodes, name, value, root, combinator){
 if (nodes && combinator) nodes = this[combinator](nodes);
 if (!nodes) nodes = root.getElementsByTagName("*");
 return Selector.pseudos[name](nodes, value, root);
}
},

 pseudos:{
 'first-child': function(nodes, value, root){
 for (var i = 0, results = [], node; node = nodes[i]; i++){
 if (Selector.handlers.previousElementSibling(node)) continue;
 results.push(node);
}
 return results;
},
 'last-child': function(nodes, value, root){
 for (var i = 0, results = [], node; node = nodes[i]; i++){
 if (Selector.handlers.nextElementSibling(node)) continue;
 results.push(node);
}
 return results;
},
 'only-child': function(nodes, value, root){
 var h = Selector.handlers;
 for (var i = 0, results = [], node; node = nodes[i]; i++)
 if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
 results.push(node);
 return results;
},
 'nth-child': function(nodes, formula, root){
 return Selector.pseudos.nth(nodes, formula, root);
},
 'nth-last-child': function(nodes, formula, root){
 return Selector.pseudos.nth(nodes, formula, root, true);
},
 'nth-of-type': function(nodes, formula, root){
 return Selector.pseudos.nth(nodes, formula, root, false, true);
},
 'nth-last-of-type': function(nodes, formula, root){
 return Selector.pseudos.nth(nodes, formula, root, true, true);
},
 'first-of-type': function(nodes, formula, root){
 return Selector.pseudos.nth(nodes, "1", root, false, true);
},
 'last-of-type': function(nodes, formula, root){
 return Selector.pseudos.nth(nodes, "1", root, true, true);
},
 'only-of-type': function(nodes, formula, root){
 var p = Selector.pseudos;
 return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
},

 getIndices: function(a, b, total){
 if (a == 0) return b > 0 ? [b] : [];
 return $R(1, total).inject([], function(memo, i){
 if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
 return memo;
});
},

 nth: function(nodes, formula, root, reverse, ofType){
 if (nodes.length == 0) return [];
 if (formula == 'even') formula = '2n+0';
 if (formula == 'odd') formula = '2n+1';
 var h = Selector.handlers, results = [], indexed = [], m;
 h.mark(nodes);
 for (var i = 0, node; node = nodes[i]; i++){
 if (!node.parentNode._countedByPrototype){
 h.index(node.parentNode, reverse, ofType);
 indexed.push(node.parentNode);
}
}
 if (formula.match(/^\d+$/)){// just a number
 formula = Number(formula);
 for (var i = 0, node; node = nodes[i]; i++)
 if (node.nodeIndex == formula) results.push(node);
}else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)){// an+b
 if (m[1] == "-") m[1] = -1;
 var a = m[1] ? Number(m[1]) : 1;
 var b = m[2] ? Number(m[2]) : 0;
 var indices = Selector.pseudos.getIndices(a, b, nodes.length);
 for (var i = 0, node, l = indices.length; node = nodes[i]; i++){
 for (var j = 0; j < l; j++)
 if (node.nodeIndex == indices[j]) results.push(node);
}
}
 h.unmark(nodes);
 h.unmark(indexed);
 return results;
},

 'empty': function(nodes, value, root){
 for (var i = 0, results = [], node; node = nodes[i]; i++){
 if (node.tagName == '!' || node.firstChild) continue;
 results.push(node);
}
 return results;
},

 'not': function(nodes, selector, root){
 var h = Selector.handlers, selectorType, m;
 var exclusions = new Selector(selector).findElements(root);
 h.mark(exclusions);
 for (var i = 0, results = [], node; node = nodes[i]; i++)
 if (!node._countedByPrototype) results.push(node);
 h.unmark(exclusions);
 return results;
},

 'enabled': function(nodes, value, root){
 for (var i = 0, results = [], node; node = nodes[i]; i++)
 if (!node.disabled && (!node.type || node.type !== 'hidden'))
 results.push(node);
 return results;
},

 'disabled': function(nodes, value, root){
 for (var i = 0, results = [], node; node = nodes[i]; i++)
 if (node.disabled) results.push(node);
 return results;
},

 'checked': function(nodes, value, root){
 for (var i = 0, results = [], node; node = nodes[i]; i++)
 if (node.checked) results.push(node);
 return results;
}
},

 operators:{
 '=': function(nv, v){return nv == v;},
 '!=': function(nv, v){return nv != v;},
 '^=': function(nv, v){return nv == v || nv && nv.startsWith(v);},
 '$=': function(nv, v){return nv == v || nv && nv.endsWith(v);},
 '*=': function(nv, v){return nv == v || nv && nv.include(v);},
 '~=': function(nv, v){return (' ' + nv + ' ').include(' ' + v + ' ');},
 '|=': function(nv, v){return ('-' + (nv || "").toUpperCase() +
 '-').include('-' + (v || "").toUpperCase() + '-');}
},

 split: function(expression){
 var expressions = [];
 expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m){
 expressions.push(m[1].strip());
});
 return expressions;
},

 matchElements: function(elements, expression){
 var matches = $$(expression), h = Selector.handlers;
 h.mark(matches);
 for (var i = 0, results = [], element; element = elements[i]; i++)
 if (element._countedByPrototype) results.push(element);
 h.unmark(matches);
 return results;
},

 findElement: function(elements, expression, index){
 if (Object.isNumber(expression)){
 index = expression; expression = false;
}
 return Selector.matchElements(elements, expression || '*')[index || 0];
},

 findChildElements: function(element, expressions){
 expressions = Selector.split(expressions.join(','));
 var results = [], h = Selector.handlers;
 for (var i = 0, l = expressions.length, selector; i < l; i++){
 selector = new Selector(expressions[i].strip());
 h.concat(results, selector.findElements(element));
}
 return (l > 1) ? h.unique(results) : results;
}
});

if (Prototype.Browser.IE){
 Object.extend(Selector.handlers,{
 concat: function(a, b){
 for (var i = 0, node; node = b[i]; i++)
 if (node.tagName !== "!") a.push(node);
 return a;
}
});
}

function $$(){
 return Selector.findChildElements(document, $A(arguments));
}

var Form ={
 reset: function(form){
 form = $(form);
 form.reset();
 return form;
},

 serializeElements: function(elements, options){
 if (typeof options != 'object') options ={hash: !!options};
 else if (Object.isUndefined(options.hash)) options.hash = true;
 var key, value, submitted = false, submit = options.submit;

 var data = elements.inject({}, function(result, element){
 if (!element.disabled && element.name){
 key = element.name; value = $(element).getValue();
 if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
 submit !== false && (!submit || key == submit) && (submitted = true)))){
 if (key in result){
 if (!Object.isArray(result[key])) result[key] = [result[key]];
 result[key].push(value);
}
 else result[key] = value;
}
}
 return result;
});

 return options.hash ? data : Object.toQueryString(data);
}
};

Form.Methods ={
 serialize: function(form, options){
 return Form.serializeElements(Form.getElements(form), options);
},

 getElements: function(form){
 var elements = $(form).getElementsByTagName('*'),
 element,
 arr = [ ],
 serializers = Form.Element.Serializers;
 for (var i = 0; element = elements[i]; i++){
 arr.push(element);
}
 return arr.inject([], function(elements, child){
 if (serializers[child.tagName.toLowerCase()])
 elements.push(Element.extend(child));
 return elements;
})
},

 getInputs: function(form, typeName, name){
 form = $(form);
 var inputs = form.getElementsByTagName('input');

 if (!typeName && !name) return $A(inputs).map(Element.extend);

 for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++){
 var input = inputs[i];
 if ((typeName && input.type != typeName) || (name && input.name != name))
 continue;
 matchingInputs.push(Element.extend(input));
}

 return matchingInputs;
},

 disable: function(form){
 form = $(form);
 Form.getElements(form).invoke('disable');
 return form;
},

 enable: function(form){
 form = $(form);
 Form.getElements(form).invoke('enable');
 return form;
},

 findFirstElement: function(form){
 var elements = $(form).getElements().findAll(function(element){
 return 'hidden' != element.type && !element.disabled;
});
 var firstByIndex = elements.findAll(function(element){
 return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
}).sortBy(function(element){return element.tabIndex}).first();

 return firstByIndex ? firstByIndex : elements.find(function(element){
 return /^(?:input|select|textarea)$/i.test(element.tagName);
});
},

 focusFirstElement: function(form){
 form = $(form);
 form.findFirstElement().activate();
 return form;
},

 request: function(form, options){
 form = $(form), options = Object.clone(options ||{});

 var params = options.parameters, action = form.readAttribute('action') || '';
 if (action.blank()) action = window.location.href;
 options.parameters = form.serialize(true);

 if (params){
 if (Object.isString(params)) params = params.toQueryParams();
 Object.extend(options.parameters, params);
}

 if (form.hasAttribute('method') && !options.method)
 options.method = form.method;

 return new Ajax.Request(action, options);
}
};

/*--------------------------------------------------------------------------*/


Form.Element ={
 focus: function(element){
 $(element).focus();
 return element;
},

 select: function(element){
 $(element).select();
 return element;
}
};

Form.Element.Methods ={

 serialize: function(element){
 element = $(element);
 if (!element.disabled && element.name){
 var value = element.getValue();
 if (value != undefined){
 var pair ={};
 pair[element.name] = value;
 return Object.toQueryString(pair);
}
}
 return '';
},

 getValue: function(element){
 element = $(element);
 var method = element.tagName.toLowerCase();
 return Form.Element.Serializers[method](element);
},

 setValue: function(element, value){
 element = $(element);
 var method = element.tagName.toLowerCase();
 Form.Element.Serializers[method](element, value);
 return element;
},

 clear: function(element){
 $(element).value = '';
 return element;
},

 present: function(element){
 return $(element).value != '';
},

 activate: function(element){
 element = $(element);
 try{
 element.focus();
 if (element.select && (element.tagName.toLowerCase() != 'input' ||
 !(/^(?:button|reset|submit)$/i.test(element.type))))
 element.select();
}catch (e){}
 return element;
},

 disable: function(element){
 element = $(element);
 element.disabled = true;
 return element;
},

 enable: function(element){
 element = $(element);
 element.disabled = false;
 return element;
}
};

/*--------------------------------------------------------------------------*/

var Field = Form.Element;

var $F = Form.Element.Methods.getValue;

/*--------------------------------------------------------------------------*/

Form.Element.Serializers ={
 input: function(element, value){
 switch (element.type.toLowerCase()){
 case 'checkbox':
 case 'radio':
 return Form.Element.Serializers.inputSelector(element, value);
 default:
 return Form.Element.Serializers.textarea(element, value);
}
},

 inputSelector: function(element, value){
 if (Object.isUndefined(value)) return element.checked ? element.value : null;
 else element.checked = !!value;
},

 textarea: function(element, value){
 if (Object.isUndefined(value)) return element.value;
 else element.value = value;
},

 select: function(element, value){
 if (Object.isUndefined(value))
 return this[element.type == 'select-one' ?
 'selectOne' : 'selectMany'](element);
 else{
 var opt, currentValue, single = !Object.isArray(value);
 for (var i = 0, length = element.length; i < length; i++){
 opt = element.options[i];
 currentValue = this.optionValue(opt);
 if (single){
 if (currentValue == value){
 opt.selected = true;
 return;
}
}
 else opt.selected = value.include(currentValue);
}
}
},

 selectOne: function(element){
 var index = element.selectedIndex;
 return index >= 0 ? this.optionValue(element.options[index]) : null;
},

 selectMany: function(element){
 var values, length = element.length;
 if (!length) return null;

 for (var i = 0, values = []; i < length; i++){
 var opt = element.options[i];
 if (opt.selected) values.push(this.optionValue(opt));
}
 return values;
},

 optionValue: function(opt){
 return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
}
};

/*--------------------------------------------------------------------------*/


Abstract.TimedObserver = Class.create(PeriodicalExecuter,{
 initialize: function($super, element, frequency, callback){
 $super(callback, frequency);
 this.element = $(element);
 this.lastValue = this.getValue();
},

 execute: function(){
 var value = this.getValue();
 if (Object.isString(this.lastValue) && Object.isString(value) ?
 this.lastValue != value : String(this.lastValue) != String(value)){
 this.callback(this.element, value);
 this.lastValue = value;
}
}
});

Form.Element.Observer = Class.create(Abstract.TimedObserver,{
 getValue: function(){
 return Form.Element.getValue(this.element);
}
});

Form.Observer = Class.create(Abstract.TimedObserver,{
 getValue: function(){
 return Form.serialize(this.element);
}
});

/*--------------------------------------------------------------------------*/

Abstract.EventObserver = Class.create({
 initialize: function(element, callback){
 this.element = $(element);
 this.callback = callback;

 this.lastValue = this.getValue();
 if (this.element.tagName.toLowerCase() == 'form')
 this.registerFormCallbacks();
 else
 this.registerCallback(this.element);
},

 onElementEvent: function(){
 var value = this.getValue();
 if (this.lastValue != value){
 this.callback(this.element, value);
 this.lastValue = value;
}
},

 registerFormCallbacks: function(){
 Form.getElements(this.element).each(this.registerCallback, this);
},

 registerCallback: function(element){
 if (element.type){
 switch (element.type.toLowerCase()){
 case 'checkbox':
 case 'radio':
 Event.observe(element, 'click', this.onElementEvent.bind(this));
 break;
 default:
 Event.observe(element, 'change', this.onElementEvent.bind(this));
 break;
}
}
}
});

Form.Element.EventObserver = Class.create(Abstract.EventObserver,{
 getValue: function(){
 return Form.Element.getValue(this.element);
}
});

Form.EventObserver = Class.create(Abstract.EventObserver,{
 getValue: function(){
 return Form.serialize(this.element);
}
});
(function(){

 var Event ={
 KEY_BACKSPACE: 8,
 KEY_TAB: 9,
 KEY_RETURN: 13,
 KEY_ESC: 27,
 KEY_LEFT: 37,
 KEY_UP: 38,
 KEY_RIGHT: 39,
 KEY_DOWN: 40,
 KEY_DELETE: 46,
 KEY_HOME: 36,
 KEY_END: 35,
 KEY_PAGEUP: 33,
 KEY_PAGEDOWN: 34,
 KEY_INSERT: 45,

 cache:{}
};

 var docEl = document.documentElement;
 var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
 && 'onmouseleave' in docEl;

 var _isButton;
 if (Prototype.Browser.IE){
 var buttonMap ={0: 1, 1: 4, 2: 2};
 _isButton = function(event, code){
 return event.button === buttonMap[code];
};
}else if (Prototype.Browser.WebKit){
 _isButton = function(event, code){
 switch (code){
 case 0: return event.which == 1 && !event.metaKey;
 case 1: return event.which == 1 && event.metaKey;
 default: return false;
}
};
}else{
 _isButton = function(event, code){
 return event.which ? (event.which === code + 1) : (event.button === code);
};
}

 function isLeftClick(event){return _isButton(event, 0)}

 function isMiddleClick(event){return _isButton(event, 1)}

 function isRightClick(event){return _isButton(event, 2)}

 function element(event){
 event = Event.extend(event);

 var node = event.target, type = event.type,
 currentTarget = event.currentTarget;

 if (currentTarget && currentTarget.tagName){
 if (type === 'load' || type === 'error' ||
 (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
 && currentTarget.type === 'radio'))
 node = currentTarget;
}

 if (node.nodeType == Node.TEXT_NODE)
 node = node.parentNode;

 return Element.extend(node);
}

 function findElement(event, expression){
 var element = Event.element(event);
 if (!expression) return element;
 var elements = [element].concat(element.ancestors());
 return Selector.findElement(elements, expression, 0);
}

 function pointer(event){
 return{x: pointerX(event), y: pointerY(event)};
}

 function pointerX(event){
 var docElement = document.documentElement,
 body = document.body ||{scrollLeft: 0};

 return event.pageX || (event.clientX +
 (docElement.scrollLeft || body.scrollLeft) -
 (docElement.clientLeft || 0));
}

 function pointerY(event){
 var docElement = document.documentElement,
 body = document.body ||{scrollTop: 0};

 return event.pageY || (event.clientY +
 (docElement.scrollTop || body.scrollTop) -
 (docElement.clientTop || 0));
}


 function stop(event){
 Event.extend(event);
 event.preventDefault();
 event.stopPropagation();

 event.stopped = true;
}

 Event.Methods ={
 isLeftClick: isLeftClick,
 isMiddleClick: isMiddleClick,
 isRightClick: isRightClick,

 element: element,
 findElement: findElement,

 pointer: pointer,
 pointerX: pointerX,
 pointerY: pointerY,

 stop: stop
};


 var methods = Object.keys(Event.Methods).inject({}, function(m, name){
 m[name] = Event.Methods[name].methodize();
 return m;
});

 if (Prototype.Browser.IE){
 function _relatedTarget(event){
 var element;
 switch (event.type){
 case 'mouseover': element = event.fromElement; break;
 case 'mouseout': element = event.toElement; break;
 default: return null;
}
 return Element.extend(element);
}

 Object.extend(methods,{
 stopPropagation: function(){this.cancelBubble = true},
 preventDefault: function(){this.returnValue = false},
 inspect: function(){return '[object Event]'}
});

 Event.extend = function(event, element){
 if (!event) return false;
 if (event._extendedByPrototype) return event;

 event._extendedByPrototype = Prototype.emptyFunction;
 var pointer = Event.pointer(event);

 Object.extend(event,{
 target: event.srcElement || element,
 relatedTarget: _relatedTarget(event),
 pageX: pointer.x,
 pageY: pointer.y
});

 return Object.extend(event, methods);
};
}else{
 Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
 Object.extend(Event.prototype, methods);
 Event.extend = Prototype.K;
}

 function _createResponder(element, eventName, handler){
 var registry = Element.retrieve(element, 'prototype_event_registry');

 if (Object.isUndefined(registry)){
 CACHE.push(element);
 registry = Element.retrieve(element, 'prototype_event_registry', $H());
}

 var respondersForEvent = registry.get(eventName);
 if (Object.isUndefined(respondersForEvent)){
 respondersForEvent = [];
 registry.set(eventName, respondersForEvent);
}

 if (respondersForEvent.pluck('handler').include(handler)) return false;

 var responder;
 if (eventName.include(":")){
 responder = function(event){
 if (Object.isUndefined(event.eventName))
 return false;

 if (event.eventName !== eventName)
 return false;

 Event.extend(event, element);
 handler.call(element, event);
};
}else{
 if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED &&
 (eventName === "mouseenter" || eventName === "mouseleave")){
 if (eventName === "mouseenter" || eventName === "mouseleave"){
 responder = function(event){
 Event.extend(event, element);

 var parent = event.relatedTarget;
 while (parent && parent !== element){
 try{parent = parent.parentNode;}
 catch(e){parent = element;}
}

 if (parent === element) return;

 handler.call(element, event);
};
}
}else{
 responder = function(event){
 Event.extend(event, element);
 handler.call(element, event);
};
}
}

 responder.handler = handler;
 respondersForEvent.push(responder);
 return responder;
}

 function _destroyCache(){
 for (var i = 0, length = CACHE.length; i < length; i++){
 Event.stopObserving(CACHE[i]);
 CACHE[i] = null;
}
}

 var CACHE = [];

 if (Prototype.Browser.IE)
 window.attachEvent('onunload', _destroyCache);

 if (Prototype.Browser.WebKit)
 window.addEventListener('unload', Prototype.emptyFunction, false);


 var _getDOMEventName = Prototype.K;

 if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED){
 _getDOMEventName = function(eventName){
 var translations ={mouseenter: "mouseover", mouseleave: "mouseout"};
 return eventName in translations ? translations[eventName] : eventName;
};
}

 function observe(element, eventName, handler){
 element = $(element);

 var responder = _createResponder(element, eventName, handler);

 if (!responder) return element;

 if (eventName.include(':')){
 if (element.addEventListener)
 element.addEventListener("dataavailable", responder, false);
 else{
 element.attachEvent("ondataavailable", responder);
 element.attachEvent("onfilterchange", responder);
}
}else{
 var actualEventName = _getDOMEventName(eventName);

 if (element.addEventListener)
 element.addEventListener(actualEventName, responder, false);
 else
 element.attachEvent("on" + actualEventName, responder);
}

 return element;
}

 function stopObserving(element, eventName, handler){
 element = $(element);

 var registry = Element.retrieve(element, 'prototype_event_registry');

 if (Object.isUndefined(registry)) return element;

 if (eventName && !handler){
 var responders = registry.get(eventName);

 if (Object.isUndefined(responders)) return element;

 responders.each( function(r){
 Element.stopObserving(element, eventName, r.handler);
});
 return element;
}else if (!eventName){
 registry.each( function(pair){
 var eventName = pair.key, responders = pair.value;

 responders.each( function(r){
 Element.stopObserving(element, eventName, r.handler);
});
});
 return element;
}

 var responders = registry.get(eventName);

 if (!responders) return;

 var responder = responders.find( function(r){return r.handler === handler;});
 if (!responder) return element;

 var actualEventName = _getDOMEventName(eventName);

 if (eventName.include(':')){
 if (element.removeEventListener)
 element.removeEventListener("dataavailable", responder, false);
 else{
 element.detachEvent("ondataavailable", responder);
 element.detachEvent("onfilterchange", responder);
}
}else{
 if (element.removeEventListener)
 element.removeEventListener(actualEventName, responder, false);
 else
 element.detachEvent('on' + actualEventName, responder);
}

 registry.set(eventName, responders.without(responder));

 return element;
}

 function fire(element, eventName, memo, bubble){
 element = $(element);

 if (Object.isUndefined(bubble))
 bubble = true;

 if (element == document && document.createEvent && !element.dispatchEvent)
 element = document.documentElement;

 var event;
 if (document.createEvent){
 event = document.createEvent('HTMLEvents');
 event.initEvent('dataavailable', true, true);
}else{
 event = document.createEventObject();
 event.eventType = bubble ? 'ondataavailable' : 'onfilterchange';
}

 event.eventName = eventName;
 event.memo = memo ||{};

 if (document.createEvent)
 element.dispatchEvent(event);
 else
 element.fireEvent(event.eventType, event);

 return Event.extend(event);
}


 Object.extend(Event, Event.Methods);

 Object.extend(Event,{
 fire: fire,
 observe: observe,
 stopObserving: stopObserving
});

 Element.addMethods({
 fire: fire,

 observe: observe,

 stopObserving: stopObserving
});

 Object.extend(document,{
 fire: fire.methodize(),

 observe: observe.methodize(),

 stopObserving: stopObserving.methodize(),

 loaded: false
});

 if (window.Event) Object.extend(window.Event, Event);
 else window.Event = Event;
})();

(function(){
 /* Support for the DOMContentLoaded event is based on work by Dan Webb,
 Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */

 var timer;

 function fireContentLoadedEvent(){
 if (document.loaded) return;
 if (timer) window.clearTimeout(timer);
 document.loaded = true;
 document.fire('dom:loaded');
}

 function checkReadyState(){
 if (document.readyState === 'complete'){
 document.stopObserving('readystatechange', checkReadyState);
 fireContentLoadedEvent();
}
}

 function pollDoScroll(){
 try{document.documentElement.doScroll('left');}
 catch(e){
 timer = pollDoScroll.defer();
 return;
}
 fireContentLoadedEvent();
}

 if (document.addEventListener){
 document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);
}else{
 document.observe('readystatechange', checkReadyState);
 if (window == top)
 timer = pollDoScroll.defer();
}

 Event.observe(window, 'load', fireContentLoadedEvent);
})();

Element.addMethods();

/*------------------------------- DEPRECATED -------------------------------*/

Hash.toQueryString = Object.toQueryString;

var Toggle ={display: Element.toggle};

Element.Methods.childOf = Element.Methods.descendantOf;

var Insertion ={
 Before: function(element, content){
 return Element.insert(element,{before:content});
},

 Top: function(element, content){
 return Element.insert(element,{top:content});
},

 Bottom: function(element, content){
 return Element.insert(element,{bottom:content});
},

 After: function(element, content){
 return Element.insert(element,{after:content});
}
};

var $continue = new Error('"throw $continue" is deprecated, use "return" instead');

var Position ={
 includeScrollOffsets: false,

 prepare: function(){
 this.deltaX = window.pageXOffset
 || document.documentElement.scrollLeft
 || document.body.scrollLeft
 || 0;
 this.deltaY = window.pageYOffset
 || document.documentElement.scrollTop
 || document.body.scrollTop
 || 0;
},

 within: function(element, x, y){
 if (this.includeScrollOffsets)
 return this.withinIncludingScrolloffsets(element, x, y);
 this.xcomp = x;
 this.ycomp = y;
 this.offset = Element.cumulativeOffset(element);

 return (y >= this.offset[1] &&
 y < this.offset[1] + element.offsetHeight &&
 x >= this.offset[0] &&
 x < this.offset[0] + element.offsetWidth);
},

 withinIncludingScrolloffsets: function(element, x, y){
 var offsetcache = Element.cumulativeScrollOffset(element);

 this.xcomp = x + offsetcache[0] - this.deltaX;
 this.ycomp = y + offsetcache[1] - this.deltaY;
 this.offset = Element.cumulativeOffset(element);

 return (this.ycomp >= this.offset[1] &&
 this.ycomp < this.offset[1] + element.offsetHeight &&
 this.xcomp >= this.offset[0] &&
 this.xcomp < this.offset[0] + element.offsetWidth);
},

 overlap: function(mode, element){
 if (!mode) return 0;
 if (mode == 'vertical')
 return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
 element.offsetHeight;
 if (mode == 'horizontal')
 return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
 element.offsetWidth;
},


 cumulativeOffset: Element.Methods.cumulativeOffset,

 positionedOffset: Element.Methods.positionedOffset,

 absolutize: function(element){
 Position.prepare();
 return Element.absolutize(element);
},

 relativize: function(element){
 Position.prepare();
 return Element.relativize(element);
},

 realOffset: Element.Methods.cumulativeScrollOffset,

 offsetParent: Element.Methods.getOffsetParent,

 page: Element.Methods.viewportOffset,

 clone: function(source, target, options){
 options = options ||{};
 return Element.clonePosition(target, source, options);
}
};

/*--------------------------------------------------------------------------*/

if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
 function iter(name){
 return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
}

 instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
 function(element, className){
 className = className.toString().strip();
 var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
 return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
}: function(element, className){
 className = className.toString().strip();
 var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
 if (!classNames && !className) return elements;

 var nodes = $(element).getElementsByTagName('*');
 className = ' ' + className + ' ';

 for (var i = 0, child, cn; child = nodes[i]; i++){
 if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
 (classNames && classNames.all(function(name){
 return !name.toString().blank() && cn.include(' ' + name + ' ');
}))))
 elements.push(Element.extend(child));
}
 return elements;
};

 return function(className, parentElement){
 return $(parentElement || document.body).getElementsByClassName(className);
};
}(Element.Methods);

/*--------------------------------------------------------------------------*/

Element.ClassNames = Class.create();
Element.ClassNames.prototype ={
 initialize: function(element){
 this.element = $(element);
},

 _each: function(iterator){
 this.element.className.split(/\s+/).select(function(name){
 return name.length > 0;
})._each(iterator);
},

 set: function(className){
 this.element.className = className;
},

 add: function(classNameToAdd){
 if (this.include(classNameToAdd)) return;
 this.set($A(this).concat(classNameToAdd).join(' '));
},

 remove: function(classNameToRemove){
 if (!this.include(classNameToRemove)) return;
 this.set($A(this).without(classNameToRemove).join(' '));
},

 toString: function(){
 return $A(this).join(' ');
}
};

Object.extend(Element.ClassNames.prototype, Enumerable);

/*--------------------------------------------------------------------------*//* ######### "event-selectors" ######### */
































var EventSelectors ={
 version: '1.0_pre',
 cache: [],
 
 start: function(rules){
 this.rules = rules ||{};
 this.timer = new Array();
 this._extendRules();
 this.assign(this.rules);
},
 
 assign: function(rules){
 var observer = null;
 this._unloadCache();
 rules._each(function(rule){
 var selectors = $A(rule.key.split(','));
 selectors.each(function(selector){
 var pair = selector.split(':');
 var event = pair[1];
 $$(pair[0]).each(function(element){
 if(pair[1] == '' || pair.length == 1) return rule.value(element);
 if(event.toLowerCase() == 'loaded'){
 this.timer[pair[0]] = setInterval(this._checkLoaded.bind(this, element, pair[0], rule), 15);
}else{
 observer = function(event){
 var element = Event.element(event);
 if (element.nodeType == 3) // Safari Bug (Fixed in Webkit)
 element = element.parentNode;
 rule.value($(element), event);
}
 this.cache.push([element, event, observer]);
 Event.observe(element, event, observer);
}
}.bind(this));
}.bind(this));
}.bind(this));
},

 _unloadCache: function(){
 if (!this.cache) return;
 for (var i = 0; i < this.cache.length; i++){
 Event.stopObserving.apply(this, this.cache[i]);
 this.cache[i][0] = null;
}
 this.cache = [];
},
 
 _checkLoaded: function(element, timer, rule){
 var node = $(element);
 if(element.tagName != 'undefined'){
 clearInterval(this.timer[timer]);
 rule.value(node);
}
},
 
 _extendRules: function(){
 Object.extend(this.rules,{
 _each: function(iterator){
 for (key in this){
 if(key == '_each') continue; 
 var value = this[key];
 var pair = [key, value];
 pair.key = key;
 pair.value = value;
 iterator(pair);
}
}
});
}
}






























var Scriptaculous ={
 Version: '1.8.2',
 require: function(libraryName){

 document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
},
 REQUIRED_PROTOTYPE: '1.6.0.3',
 load: function(){
 function convertVersionString(versionString){
 var v = versionString.replace(/_.*|\./g, '');
 v = parseInt(v + '0'.times(4-v.length));
 return versionString.indexOf('_') > -1 ? v-1 : v;
}

 if((typeof Prototype=='undefined') ||
 (typeof Element == 'undefined') ||
 (typeof Element.Methods=='undefined') ||
 (convertVersionString(Prototype.Version) <
 convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
 throw("script.aculo.us requires the Prototype JavaScript framework >= " +
 Scriptaculous.REQUIRED_PROTOTYPE);

 var js = /scriptaculous\.js(\?.*)?$/;
 $$('head script[src]').findAll(function(s){
 return s.src.match(js);
}).each(function(s){
 var path = s.src.replace(js, ''),
 includes = s.src.match(/\?.*load=([a-z,]*)/);
 (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
 function(include){Scriptaculous.require(path+include+'.js')});
});
}
};

Scriptaculous.load();/* ######### "effects" ######### */











String.prototype.parseColor = function(){
 var color = '#';
 if (this.slice(0,4) == 'rgb('){
 var cols = this.slice(4,this.length-1).split(',');
 var i=0; do{color += parseInt(cols[i]).toColorPart()}while (++i<3);
}else{
 if (this.slice(0,1) == '#'){
 if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
 if (this.length==7) color = this.toLowerCase();
}
}
 return (color.length==7 ? color : (arguments[0] || this));
};

/*--------------------------------------------------------------------------*/

Element.collectTextNodes = function(element){
 return $A($(element).childNodes).collect( function(node){
 return (node.nodeType==3 ? node.nodeValue :
 (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
}).flatten().join('');
};

Element.collectTextNodesIgnoreClass = function(element, className){
 return $A($(element).childNodes).collect( function(node){
 return (node.nodeType==3 ? node.nodeValue :
 ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
 Element.collectTextNodesIgnoreClass(node, className) : ''));
}).flatten().join('');
};

Element.setContentZoom = function(element, percent){
 element = $(element);
 element.setStyle({fontSize: (percent/100) + 'em'});
 if (Prototype.Browser.WebKit) window.scrollBy(0,0);
 return element;
};

Element.getInlineOpacity = function(element){
 return $(element).style.opacity || '';
};

Element.forceRerendering = function(element){
 try{
 element = $(element);
 var n = document.createTextNode(' ');
 element.appendChild(n);
 element.removeChild(n);
}catch(e){}
};

/*--------------------------------------------------------------------------*/

var Effect ={
 _elementDoesNotExistError:{
 name: 'ElementDoesNotExistError',
 message: 'The specified DOM element does not exist, but is required for this effect to operate'
},
 Transitions:{
 linear: Prototype.K,
 sinoidal: function(pos){
 return (-Math.cos(pos*Math.PI)/2) + .5;
},
 reverse: function(pos){
 return 1-pos;
},
 flicker: function(pos){
 var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
 return pos > 1 ? 1 : pos;
},
 wobble: function(pos){
 return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5;
},
 pulse: function(pos, pulses){
 return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
},
 spring: function(pos){
 return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
},
 none: function(pos){
 return 0;
},
 full: function(pos){
 return 1;
}
},
 DefaultOptions:{
 duration: 1.0, // seconds
 fps: 100, // 100= assume 66fps max.
 sync: false, // true for combining
 from: 0.0,
 to: 1.0,
 delay: 0.0,
 queue: 'parallel'
},
 tagifyText: function(element){
 var tagifyStyle = 'position:relative';
 if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';

 element = $(element);
 $A(element.childNodes).each( function(child){
 if (child.nodeType==3){
 child.nodeValue.toArray().each( function(character){
 element.insertBefore(
 new Element('span',{style: tagifyStyle}).update(
 character == ' ' ? String.fromCharCode(160) : character),
 child);
});
 Element.remove(child);
}
});
},
 multiple: function(element, effect){
 var elements;
 if (((typeof element == 'object') ||
 Object.isFunction(element)) &&
 (element.length))
 elements = element;
 else
 elements = $(element).childNodes;

 var options = Object.extend({
 speed: 0.1,
 delay: 0.0
}, arguments[2] ||{});
 var masterDelay = options.delay;

 $A(elements).each( function(element, index){
 new effect(element, Object.extend(options,{delay: index * options.speed + masterDelay}));
});
},
 PAIRS:{
 'slide': ['SlideDown','SlideUp'],
 'blind': ['BlindDown','BlindUp'],
 'appear': ['Appear','Fade']
},
 toggle: function(element, effect){
 element = $(element);
 effect = (effect || 'appear').toLowerCase();
 var options = Object.extend({
 queue:{position:'end', scope:(element.id || 'global'), limit: 1}
}, arguments[2] ||{});
 Effect[element.visible() ?
 Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
}
};

Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;

/* ------------- core effects ------------- */

Effect.ScopedQueue = Class.create(Enumerable,{
 initialize: function(){
 this.effects = [];
 this.interval = null;
},
 _each: function(iterator){
 this.effects._each(iterator);
},
 add: function(effect){
 var timestamp = new Date().getTime();

 var position = Object.isString(effect.options.queue) ?
 effect.options.queue : effect.options.queue.position;

 switch(position){
 case 'front':

 this.effects.findAll(function(e){return e.state=='idle'}).each( function(e){
 e.startOn += effect.finishOn;
 e.finishOn += effect.finishOn;
});
 break;
 case 'with-last':
 timestamp = this.effects.pluck('startOn').max() || timestamp;
 break;
 case 'end':

 timestamp = this.effects.pluck('finishOn').max() || timestamp;
 break;
}

 effect.startOn += timestamp;
 effect.finishOn += timestamp;

 if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
 this.effects.push(effect);

 if (!this.interval)
 this.interval = setInterval(this.loop.bind(this), 15);
},
 remove: function(effect){
 this.effects = this.effects.reject(function(e){return e==effect});
 if (this.effects.length == 0){
 clearInterval(this.interval);
 this.interval = null;
}
},
 loop: function(){
 var timePos = new Date().getTime();
 for(var i=0, len=this.effects.length;i<len;i++)
 this.effects[i] && this.effects[i].loop(timePos);
}
});

Effect.Queues ={
 instances: $H(),
 get: function(queueName){
 if (!Object.isString(queueName)) return queueName;

 return this.instances.get(queueName) ||
 this.instances.set(queueName, new Effect.ScopedQueue());
}
};
Effect.Queue = Effect.Queues.get('global');

Effect.Base = Class.create({
 position: null,
 start: function(options){
 function codeForEvent(options,eventName){
 return (
 (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
 (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
 );
}
 if (options && options.transition === false) options.transition = Effect.Transitions.linear;
 this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options ||{});
 this.currentFrame = 0;
 this.state = 'idle';
 this.startOn = this.options.delay*1000;
 this.finishOn = this.startOn+(this.options.duration*1000);
 this.fromToDelta = this.options.to-this.options.from;
 this.totalTime = this.finishOn-this.startOn;
 this.totalFrames = this.options.fps*this.options.duration;

 this.render = (function(){
 function dispatch(effect, eventName){
 if (effect.options[eventName + 'Internal'])
 effect.options[eventName + 'Internal'](effect);
 if (effect.options[eventName])
 effect.options[eventName](effect);
}

 return function(pos){
 if (this.state === "idle"){
 this.state = "running";
 dispatch(this, 'beforeSetup');
 if (this.setup) this.setup();
 dispatch(this, 'afterSetup');
}
 if (this.state === "running"){
 pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
 this.position = pos;
 dispatch(this, 'beforeUpdate');
 if (this.update) this.update(pos);
 dispatch(this, 'afterUpdate');
}
};
})();

 this.event('beforeStart');
 if (!this.options.sync)
 Effect.Queues.get(Object.isString(this.options.queue) ?
 'global' : this.options.queue.scope).add(this);
},
 loop: function(timePos){
 if (timePos >= this.startOn){
 if (timePos >= this.finishOn){
 this.render(1.0);
 this.cancel();
 this.event('beforeFinish');
 if (this.finish) this.finish();
 this.event('afterFinish');
 return;
}
 var pos = (timePos - this.startOn) / this.totalTime,
 frame = (pos * this.totalFrames).round();
 if (frame > this.currentFrame){
 this.render(pos);
 this.currentFrame = frame;
}
}
},
 cancel: function(){
 if (!this.options.sync)
 Effect.Queues.get(Object.isString(this.options.queue) ?
 'global' : this.options.queue.scope).remove(this);
 this.state = 'finished';
},
 event: function(eventName){
 if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
 if (this.options[eventName]) this.options[eventName](this);
},
 inspect: function(){
 var data = $H();
 for(property in this)
 if (!Object.isFunction(this[property])) data.set(property, this[property]);
 return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
}
});

Effect.Parallel = Class.create(Effect.Base,{
 initialize: function(effects){
 this.effects = effects || [];
 this.start(arguments[1]);
},
 update: function(position){
 this.effects.invoke('render', position);
},
 finish: function(position){
 this.effects.each( function(effect){
 effect.render(1.0);
 effect.cancel();
 effect.event('beforeFinish');
 if (effect.finish) effect.finish(position);
 effect.event('afterFinish');
});
}
});

Effect.Tween = Class.create(Effect.Base,{
 initialize: function(object, from, to){
 object = Object.isString(object) ? $(object) : object;
 var args = $A(arguments), method = args.last(),
 options = args.length == 5 ? args[3] : null;
 this.method = Object.isFunction(method) ? method.bind(object) :
 Object.isFunction(object[method]) ? object[method].bind(object) :
 function(value){object[method] = value};
 this.start(Object.extend({from: from, to: to}, options ||{}));
},
 update: function(position){
 this.method(position);
}
});

Effect.Event = Class.create(Effect.Base,{
 initialize: function(){
 this.start(Object.extend({duration: 0}, arguments[0] ||{}));
},
 update: Prototype.emptyFunction
});

Effect.Opacity = Class.create(Effect.Base,{
 initialize: function(element){
 this.element = $(element);
 if (!this.element) throw(Effect._elementDoesNotExistError);

 if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
 this.element.setStyle({zoom: 1});
 var options = Object.extend({
 from: this.element.getOpacity() || 0.0,
 to: 1.0
}, arguments[1] ||{});
 this.start(options);
},
 update: function(position){
 this.element.setOpacity(position);
}
});

Effect.Move = Class.create(Effect.Base,{
 initialize: function(element){
 this.element = $(element);
 if (!this.element) throw(Effect._elementDoesNotExistError);
 var options = Object.extend({
 x: 0,
 y: 0,
 mode: 'relative'
}, arguments[1] ||{});
 this.start(options);
},
 setup: function(){
 this.element.makePositioned();
 this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
 this.originalTop = parseFloat(this.element.getStyle('top') || '0');
 if (this.options.mode == 'absolute'){
 this.options.x = this.options.x - this.originalLeft;
 this.options.y = this.options.y - this.originalTop;
}
},
 update: function(position){
 this.element.setStyle({
 left: (this.options.x * position + this.originalLeft).round() + 'px',
 top: (this.options.y * position + this.originalTop).round() + 'px'
});
}
});

Effect.MoveBy = function(element, toTop, toLeft){
 return new Effect.Move(element,
 Object.extend({x: toLeft, y: toTop}, arguments[3] ||{}));
};

Effect.Scale = Class.create(Effect.Base,{
 initialize: function(element, percent){
 this.element = $(element);
 if (!this.element) throw(Effect._elementDoesNotExistError);
 var options = Object.extend({
 scaleX: true,
 scaleY: true,
 scaleContent: true,
 scaleFromCenter: false,
 scaleMode: 'box', // 'box' or 'contents' or{}with provided values
 scaleFrom: 100.0,
 scaleTo: percent
}, arguments[2] ||{});
 this.start(options);
},
 setup: function(){
 this.restoreAfterFinish = this.options.restoreAfterFinish || false;
 this.elementPositioning = this.element.getStyle('position');

 this.originalStyle ={};
 ['top','left','width','height','fontSize'].each( function(k){
 this.originalStyle[k] = this.element.style[k];
}.bind(this));

 this.originalTop = this.element.offsetTop;
 this.originalLeft = this.element.offsetLeft;

 var fontSize = this.element.getStyle('font-size') || '100%';
 ['em','px','%','pt'].each( function(fontSizeType){
 if (fontSize.indexOf(fontSizeType)>0){
 this.fontSize = parseFloat(fontSize);
 this.fontSizeType = fontSizeType;
}
}.bind(this));

 this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;

 this.dims = null;
 if (this.options.scaleMode=='box')
 this.dims = [this.element.offsetHeight, this.element.offsetWidth];
 if (/^content/.test(this.options.scaleMode))
 this.dims = [this.element.scrollHeight, this.element.scrollWidth];
 if (!this.dims)
 this.dims = [this.options.scaleMode.originalHeight,
 this.options.scaleMode.originalWidth];
},
 update: function(position){
 var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
 if (this.options.scaleContent && this.fontSize)
 this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType});
 this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
},
 finish: function(position){
 if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
},
 setDimensions: function(height, width){
 var d ={};
 if (this.options.scaleX) d.width = width.round() + 'px';
 if (this.options.scaleY) d.height = height.round() + 'px';
 if (this.options.scaleFromCenter){
 var topd = (height - this.dims[0])/2;
 var leftd = (width - this.dims[1])/2;
 if (this.elementPositioning == 'absolute'){
 if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
 if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
}else{
 if (this.options.scaleY) d.top = -topd + 'px';
 if (this.options.scaleX) d.left = -leftd + 'px';
}
}
 this.element.setStyle(d);
}
});

Effect.Highlight = Class.create(Effect.Base,{
 initialize: function(element){
 this.element = $(element);
 if (!this.element) throw(Effect._elementDoesNotExistError);
 var options = Object.extend({startcolor: '#ffff99'}, arguments[1] ||{});
 this.start(options);
},
 setup: function(){

 if (this.element.getStyle('display')=='none'){this.cancel(); return;}

 this.oldStyle ={};
 if (!this.options.keepBackgroundImage){
 this.oldStyle.backgroundImage = this.element.getStyle('background-image');
 this.element.setStyle({backgroundImage: 'none'});
}
 if (!this.options.endcolor)
 this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
 if (!this.options.restorecolor)
 this.options.restorecolor = this.element.getStyle('background-color');

 this._base = $R(0,2).map(function(i){return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16)}.bind(this));
 this._delta = $R(0,2).map(function(i){return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i]}.bind(this));
},
 update: function(position){
 this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
 return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart());}.bind(this))});
},
 finish: function(){
 this.element.setStyle(Object.extend(this.oldStyle,{
 backgroundColor: this.options.restorecolor
}));
}
});

Effect.ScrollTo = function(element){
 var options = arguments[1] ||{},
 scrollOffsets = document.viewport.getScrollOffsets(),
 elementOffsets = $(element).cumulativeOffset();

 if (options.offset) elementOffsets[1] += options.offset;

 return new Effect.Tween(null,
 scrollOffsets.top,
 elementOffsets[1],
 options,
 function(p){scrollTo(scrollOffsets.left, p.round());}
 );
};

/* ------------- combination effects ------------- */

Effect.Fade = function(element){
 element = $(element);
 var oldOpacity = element.getInlineOpacity();
 var options = Object.extend({
 from: element.getOpacity() || 1.0,
 to: 0.0,
 afterFinishInternal: function(effect){
 if (effect.options.to!=0) return;
 effect.element.hide().setStyle({opacity: oldOpacity});
}
}, arguments[1] ||{});
 return new Effect.Opacity(element,options);
};

Effect.Appear = function(element){
 element = $(element);
 var options = Object.extend({
 from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
 to: 1.0,

 afterFinishInternal: function(effect){
 effect.element.forceRerendering();
},
 beforeSetup: function(effect){
 effect.element.setOpacity(effect.options.from).show();
}}, arguments[1] ||{});
 return new Effect.Opacity(element,options);
};

Effect.Puff = function(element){
 element = $(element);
 var oldStyle ={
 opacity: element.getInlineOpacity(),
 position: element.getStyle('position'),
 top: element.style.top,
 left: element.style.left,
 width: element.style.width,
 height: element.style.height
};
 return new Effect.Parallel(
 [ new Effect.Scale(element, 200,
{sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true}),
 new Effect.Opacity(element,{sync: true, to: 0.0}) ],
 Object.extend({duration: 1.0,
 beforeSetupInternal: function(effect){
 Position.absolutize(effect.effects[0].element);
},
 afterFinishInternal: function(effect){
 effect.effects[0].element.hide().setStyle(oldStyle);}
}, arguments[1] ||{})
 );
};

Effect.BlindUp = function(element){
 element = $(element);
 element.makeClipping();
 return new Effect.Scale(element, 0,
 Object.extend({scaleContent: false,
 scaleX: false,
 restoreAfterFinish: true,
 afterFinishInternal: function(effect){
 effect.element.hide().undoClipping();
}
}, arguments[1] ||{})
 );
};

Effect.BlindDown = function(element){
 element = $(element);
 var elementDimensions = element.getDimensions();
 return new Effect.Scale(element, 100, Object.extend({
 scaleContent: false,
 scaleX: false,
 scaleFrom: 0,
 scaleMode:{originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
 restoreAfterFinish: true,
 afterSetup: function(effect){
 effect.element.makeClipping().setStyle({height: '0px'}).show();
},
 afterFinishInternal: function(effect){
 effect.element.undoClipping();
}
}, arguments[1] ||{}));
};

Effect.SwitchOff = function(element){
 element = $(element);
 var oldOpacity = element.getInlineOpacity();
 return new Effect.Appear(element, Object.extend({
 duration: 0.4,
 from: 0,
 transition: Effect.Transitions.flicker,
 afterFinishInternal: function(effect){
 new Effect.Scale(effect.element, 1,{
 duration: 0.3, scaleFromCenter: true,
 scaleX: false, scaleContent: false, restoreAfterFinish: true,
 beforeSetup: function(effect){
 effect.element.makePositioned().makeClipping();
},
 afterFinishInternal: function(effect){
 effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
}
});
}
}, arguments[1] ||{}));
};

Effect.DropOut = function(element){
 element = $(element);
 var oldStyle ={
 top: element.getStyle('top'),
 left: element.getStyle('left'),
 opacity: element.getInlineOpacity()};
 return new Effect.Parallel(
 [ new Effect.Move(element,{x: 0, y: 100, sync: true}),
 new Effect.Opacity(element,{sync: true, to: 0.0}) ],
 Object.extend(
{duration: 0.5,
 beforeSetup: function(effect){
 effect.effects[0].element.makePositioned();
},
 afterFinishInternal: function(effect){
 effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
}
}, arguments[1] ||{}));
};

Effect.Shake = function(element){
 element = $(element);
 var options = Object.extend({
 distance: 20,
 duration: 0.5
}, arguments[1] ||{});
 var distance = parseFloat(options.distance);
 var split = parseFloat(options.duration) / 10.0;
 var oldStyle ={
 top: element.getStyle('top'),
 left: element.getStyle('left')};
 return new Effect.Move(element,
{x: distance, y: 0, duration: split, afterFinishInternal: function(effect){
 new Effect.Move(effect.element,
{x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect){
 new Effect.Move(effect.element,
{x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect){
 new Effect.Move(effect.element,
{x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect){
 new Effect.Move(effect.element,
{x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect){
 new Effect.Move(effect.element,
{x: -distance, y: 0, duration: split, afterFinishInternal: function(effect){
 effect.element.undoPositioned().setStyle(oldStyle);
}});}});}});}});}});}});
};

Effect.SlideDown = function(element){
 element = $(element).cleanWhitespace();

 var oldInnerBottom = element.down().getStyle('bottom');
 var elementDimensions = element.getDimensions();
 return new Effect.Scale(element, 100, Object.extend({
 scaleContent: false,
 scaleX: false,
 scaleFrom: window.opera ? 0 : 1,
 scaleMode:{originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
 restoreAfterFinish: true,
 afterSetup: function(effect){
 effect.element.makePositioned();
 effect.element.down().makePositioned();
 if (window.opera) effect.element.setStyle({top: ''});
 effect.element.makeClipping().setStyle({height: '0px'}).show();
},
 afterUpdateInternal: function(effect){
 effect.element.down().setStyle({bottom:
 (effect.dims[0] - effect.element.clientHeight) + 'px'});
},
 afterFinishInternal: function(effect){
 effect.element.undoClipping().undoPositioned();
 effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});}
}, arguments[1] ||{})
 );
};

Effect.SlideUp = function(element){
 element = $(element).cleanWhitespace();
 var oldInnerBottom = element.down().getStyle('bottom');
 var elementDimensions = element.getDimensions();
 return new Effect.Scale(element, window.opera ? 0 : 1,
 Object.extend({scaleContent: false,
 scaleX: false,
 scaleMode: 'box',
 scaleFrom: 100,
 scaleMode:{originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
 restoreAfterFinish: true,
 afterSetup: function(effect){
 effect.element.makePositioned();
 effect.element.down().makePositioned();
 if (window.opera) effect.element.setStyle({top: ''});
 effect.element.makeClipping().show();
},
 afterUpdateInternal: function(effect){
 effect.element.down().setStyle({bottom:
 (effect.dims[0] - effect.element.clientHeight) + 'px'});
},
 afterFinishInternal: function(effect){
 effect.element.hide().undoClipping().undoPositioned();
 effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
}
}, arguments[1] ||{})
 );
};

Effect.Squish = function(element){
 return new Effect.Scale(element, window.opera ? 1 : 0,{
 restoreAfterFinish: true,
 beforeSetup: function(effect){
 effect.element.makeClipping();
},
 afterFinishInternal: function(effect){
 effect.element.hide().undoClipping();
}
});
};

Effect.Grow = function(element){
 element = $(element);
 var options = Object.extend({
 direction: 'center',
 moveTransition: Effect.Transitions.sinoidal,
 scaleTransition: Effect.Transitions.sinoidal,
 opacityTransition: Effect.Transitions.full
}, arguments[1] ||{});
 var oldStyle ={
 top: element.style.top,
 left: element.style.left,
 height: element.style.height,
 width: element.style.width,
 opacity: element.getInlineOpacity()};

 var dims = element.getDimensions();
 var initialMoveX, initialMoveY;
 var moveX, moveY;

 switch (options.direction){
 case 'top-left':
 initialMoveX = initialMoveY = moveX = moveY = 0;
 break;
 case 'top-right':
 initialMoveX = dims.width;
 initialMoveY = moveY = 0;
 moveX = -dims.width;
 break;
 case 'bottom-left':
 initialMoveX = moveX = 0;
 initialMoveY = dims.height;
 moveY = -dims.height;
 break;
 case 'bottom-right':
 initialMoveX = dims.width;
 initialMoveY = dims.height;
 moveX = -dims.width;
 moveY = -dims.height;
 break;
 case 'center':
 initialMoveX = dims.width / 2;
 initialMoveY = dims.height / 2;
 moveX = -dims.width / 2;
 moveY = -dims.height / 2;
 break;
}

 return new Effect.Move(element,{
 x: initialMoveX,
 y: initialMoveY,
 duration: 0.01,
 beforeSetup: function(effect){
 effect.element.hide().makeClipping().makePositioned();
},
 afterFinishInternal: function(effect){
 new Effect.Parallel(
 [ new Effect.Opacity(effect.element,{sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition}),
 new Effect.Move(effect.element,{x: moveX, y: moveY, sync: true, transition: options.moveTransition}),
 new Effect.Scale(effect.element, 100,{
 scaleMode:{originalHeight: dims.height, originalWidth: dims.width},
 sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
 ], Object.extend({
 beforeSetup: function(effect){
 effect.effects[0].element.setStyle({height: '0px'}).show();
},
 afterFinishInternal: function(effect){
 effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
}
}, options)
 );
}
});
};

Effect.Shrink = function(element){
 element = $(element);
 var options = Object.extend({
 direction: 'center',
 moveTransition: Effect.Transitions.sinoidal,
 scaleTransition: Effect.Transitions.sinoidal,
 opacityTransition: Effect.Transitions.none
}, arguments[1] ||{});
 var oldStyle ={
 top: element.style.top,
 left: element.style.left,
 height: element.style.height,
 width: element.style.width,
 opacity: element.getInlineOpacity()};

 var dims = element.getDimensions();
 var moveX, moveY;

 switch (options.direction){
 case 'top-left':
 moveX = moveY = 0;
 break;
 case 'top-right':
 moveX = dims.width;
 moveY = 0;
 break;
 case 'bottom-left':
 moveX = 0;
 moveY = dims.height;
 break;
 case 'bottom-right':
 moveX = dims.width;
 moveY = dims.height;
 break;
 case 'center':
 moveX = dims.width / 2;
 moveY = dims.height / 2;
 break;
}

 return new Effect.Parallel(
 [ new Effect.Opacity(element,{sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition}),
 new Effect.Scale(element, window.opera ? 1 : 0,{sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
 new Effect.Move(element,{x: moveX, y: moveY, sync: true, transition: options.moveTransition})
 ], Object.extend({
 beforeStartInternal: function(effect){
 effect.effects[0].element.makePositioned().makeClipping();
},
 afterFinishInternal: function(effect){
 effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle);}
}, options)
 );
};

Effect.Pulsate = function(element){
 element = $(element);
 var options = arguments[1] ||{},
 oldOpacity = element.getInlineOpacity(),
 transition = options.transition || Effect.Transitions.linear,
 reverser = function(pos){
 return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5);
};

 return new Effect.Opacity(element,
 Object.extend(Object.extend({duration: 2.0, from: 0,
 afterFinishInternal: function(effect){effect.element.setStyle({opacity: oldOpacity});}
}, options),{transition: reverser}));
};

Effect.Fold = function(element){
 element = $(element);
 var oldStyle ={
 top: element.style.top,
 left: element.style.left,
 width: element.style.width,
 height: element.style.height};
 element.makeClipping();
 return new Effect.Scale(element, 5, Object.extend({
 scaleContent: false,
 scaleX: false,
 afterFinishInternal: function(effect){
 new Effect.Scale(element, 1,{
 scaleContent: false,
 scaleY: false,
 afterFinishInternal: function(effect){
 effect.element.hide().undoClipping().setStyle(oldStyle);
}});
}}, arguments[1] ||{}));
};

Effect.Morph = Class.create(Effect.Base,{
 initialize: function(element){
 this.element = $(element);
 if (!this.element) throw(Effect._elementDoesNotExistError);
 var options = Object.extend({
 style:{}
}, arguments[1] ||{});

 if (!Object.isString(options.style)) this.style = $H(options.style);
 else{
 if (options.style.include(':'))
 this.style = options.style.parseStyle();
 else{
 this.element.addClassName(options.style);
 this.style = $H(this.element.getStyles());
 this.element.removeClassName(options.style);
 var css = this.element.getStyles();
 this.style = this.style.reject(function(style){
 return style.value == css[style.key];
});
 options.afterFinishInternal = function(effect){
 effect.element.addClassName(effect.options.style);
 effect.transforms.each(function(transform){
 effect.element.style[transform.style] = '';
});
};
}
}
 this.start(options);
},

 setup: function(){
 function parseColor(color){
 if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
 color = color.parseColor();
 return $R(0,2).map(function(i){
 return parseInt( color.slice(i*2+1,i*2+3), 16 );
});
}
 this.transforms = this.style.map(function(pair){
 var property = pair[0], value = pair[1], unit = null;

 if (value.parseColor('#zzzzzz') != '#zzzzzz'){
 value = value.parseColor();
 unit = 'color';
}else if (property == 'opacity'){
 value = parseFloat(value);
 if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
 this.element.setStyle({zoom: 1});
}else if (Element.CSS_LENGTH.test(value)){
 var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
 value = parseFloat(components[1]);
 unit = (components.length == 3) ? components[2] : null;
}

 var originalValue = this.element.getStyle(property);
 return{
 style: property.camelize(),
 originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
 targetValue: unit=='color' ? parseColor(value) : value,
 unit: unit
};
}.bind(this)).reject(function(transform){
 return (
 (transform.originalValue == transform.targetValue) ||
 (
 transform.unit != 'color' &&
 (isNaN(transform.originalValue) || isNaN(transform.targetValue))
 )
 );
});
},
 update: function(position){
 var style ={}, transform, i = this.transforms.length;
 while(i--)
 style[(transform = this.transforms[i]).style] =
 transform.unit=='color' ? '#'+
 (Math.round(transform.originalValue[0]+
 (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
 (Math.round(transform.originalValue[1]+
 (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
 (Math.round(transform.originalValue[2]+
 (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
 (transform.originalValue +
 (transform.targetValue - transform.originalValue) * position).toFixed(3) +
 (transform.unit === null ? '' : transform.unit);
 this.element.setStyle(style, true);
}
});

Effect.Transform = Class.create({
 initialize: function(tracks){
 this.tracks = [];
 this.options = arguments[1] ||{};
 this.addTracks(tracks);
},
 addTracks: function(tracks){
 tracks.each(function(track){
 track = $H(track);
 var data = track.values().first();
 this.tracks.push($H({
 ids: track.keys().first(),
 effect: Effect.Morph,
 options:{style: data}
}));
}.bind(this));
 return this;
},
 play: function(){
 return new Effect.Parallel(
 this.tracks.map(function(track){
 var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
 var elements = [$(ids) || $$(ids)].flatten();
 return elements.map(function(e){return new effect(e, Object.extend({sync:true}, options))});
}).flatten(),
 this.options
 );
}
});

Element.CSS_PROPERTIES = $w(
 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
 'fontSize fontWeight height left letterSpacing lineHeight ' +
 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
 'right textIndent top width wordSpacing zIndex');

Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;

String.__parseStyleElement = document.createElement('div');
String.prototype.parseStyle = function(){
 var style, styleRules = $H();
 if (Prototype.Browser.WebKit)
 style = new Element('div',{style:this}).style;
 else{
 String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
 style = String.__parseStyleElement.childNodes[0].style;
}

 Element.CSS_PROPERTIES.each(function(property){
 if (style[property]) styleRules.set(property, style[property]);
});

 if (Prototype.Browser.IE && this.include('opacity'))
 styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);

 return styleRules;
};

if (document.defaultView && document.defaultView.getComputedStyle){
 Element.getStyles = function(element){
 var css = document.defaultView.getComputedStyle($(element), null);
 return Element.CSS_PROPERTIES.inject({}, function(styles, property){
 styles[property] = css[property];
 return styles;
});
};
}else{
 Element.getStyles = function(element){
 element = $(element);
 var css = element.currentStyle, styles;
 styles = Element.CSS_PROPERTIES.inject({}, function(results, property){
 results[property] = css[property];
 return results;
});
 if (!styles.opacity) styles.opacity = element.getOpacity();
 return styles;
};
}

Effect.Methods ={
 morph: function(element, style){
 element = $(element);
 new Effect.Morph(element, Object.extend({style: style}, arguments[2] ||{}));
 return element;
},
 visualEffect: function(element, effect, options){
 element = $(element);
 var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
 new Effect[klass](element, options);
 return element;
},
 highlight: function(element, options){
 element = $(element);
 new Effect.Highlight(element, options);
 return element;
}
};

$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
 'pulsate shake puff squish switchOff dropOut').each(
 function(effect){
 Effect.Methods[effect] = function(element, options){
 element = $(element);
 Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
 return element;
};
}
);

$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
 function(f){Effect.Methods[f] = Element[f];}
);

Element.addMethods(Effect.Methods);/* ######### controls ######### */




































if(typeof Effect == 'undefined')
 throw("controls.js requires including script.aculo.us' effects.js library");

var Autocompleter ={};
Autocompleter.Base = Class.create({
 baseInitialize: function(element, update, options){
 element = $(element);
 this.element = element;
 this.update = $(update);
 this.hasFocus = false;
 this.changed = false;
 this.active = false;
 this.index = 0;
 this.entryCount = 0;
 this.oldElementValue = this.element.value;

 if(this.setOptions)
 this.setOptions(options);
 else
 this.options = options ||{};

 this.options.paramName = this.options.paramName || this.element.name;
 this.options.tokens = this.options.tokens || [];
 this.options.frequency = this.options.frequency || 0.4;
 this.options.minChars = this.options.minChars || 1;
 this.options.onShow = this.options.onShow ||
 function(element, update){
 if(!update.style.position || update.style.position=='absolute'){
 update.style.position = 'absolute';
 Position.clone(element, update,{
 setHeight: false,
 offsetTop: element.offsetHeight
});
}
 Effect.Appear(update,{duration:0.15});
};
 this.options.onHide = this.options.onHide ||
 function(element, update){new Effect.Fade(update,{duration:0.15})};

 if(typeof(this.options.tokens) == 'string')
 this.options.tokens = new Array(this.options.tokens);

 if (!this.options.tokens.include('\n'))
 this.options.tokens.push('\n');

 this.observer = null;

 this.element.setAttribute('autocomplete','off');

 Element.hide(this.update);

 Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
 Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
},

 show: function(){
 if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
 if(!this.iefix &&
 (Prototype.Browser.IE) &&
 (Element.getStyle(this.update, 'position')=='absolute')){
 new Insertion.After(this.update,
 '<iframe id="' + this.update.id + '_iefix" '+
 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
 this.iefix = $(this.update.id+'_iefix');
}
 if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
},

 fixIEOverlapping: function(){
 Position.clone(this.update, this.iefix,{setTop:(!this.update.style.height)});
 this.iefix.style.zIndex = 1;
 this.update.style.zIndex = 2;
 Element.show(this.iefix);
},

 hide: function(){
 this.stopIndicator();
 if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
 if(this.iefix) Element.hide(this.iefix);
},

 startIndicator: function(){
 if(this.options.indicator) Element.show(this.options.indicator);
},

 stopIndicator: function(){
 if(this.options.indicator) Element.hide(this.options.indicator);
},

 onKeyPress: function(event){
 if(this.active)
 switch(event.keyCode){
 case Event.KEY_TAB:
 case Event.KEY_RETURN:
 this.selectEntry();
 Event.stop(event);
 case Event.KEY_ESC:
 this.hide();
 this.active = false;
 Event.stop(event);
 return;
 case Event.KEY_LEFT:
 case Event.KEY_RIGHT:
 return;
 case Event.KEY_UP:
 this.markPrevious();
 this.render();
 Event.stop(event);
 return;
 case Event.KEY_DOWN:
 this.markNext();
 this.render();
 Event.stop(event);
 return;
}
 else
 if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
 (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;

 this.changed = true;
 this.hasFocus = true;

 if(this.observer) clearTimeout(this.observer);
 this.observer =
 setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
},

 activate: function(){
 this.changed = false;
 this.hasFocus = true;
 this.getUpdatedChoices();
},

 onHover: function(event){
 var element = Event.findElement(event, 'LI');
 if(this.index != element.autocompleteIndex)
{
 this.index = element.autocompleteIndex;
 this.render();
}
 Event.stop(event);
},

 onClick: function(event){
 var element = Event.findElement(event, 'LI');
 this.index = element.autocompleteIndex;
 this.selectEntry();
 this.hide();
},

 onBlur: function(event){

 setTimeout(this.hide.bind(this), 250);
 this.hasFocus = false;
 this.active = false;
},

 render: function(){
 if(this.entryCount > 0){
 for (var i = 0; i < this.entryCount; i++)
 this.index==i ?
 Element.addClassName(this.getEntry(i),"selected") :
 Element.removeClassName(this.getEntry(i),"selected");
 if(this.hasFocus){
 this.show();
 this.active = true;
}
}else{
 this.active = false;
 this.hide();
}
},

 markPrevious: function(){
 if(this.index > 0) this.index--;
 else this.index = this.entryCount-1;
 this.getEntry(this.index).scrollIntoView(true);
},

 markNext: function(){
 if(this.index < this.entryCount-1) this.index++;
 else this.index = 0;
 this.getEntry(this.index).scrollIntoView(false);
},

 getEntry: function(index){
 return this.update.firstChild.childNodes[index];
},

 getCurrentEntry: function(){
 return this.getEntry(this.index);
},

 selectEntry: function(){
 this.active = false;
 this.updateElement(this.getCurrentEntry());
},

 updateElement: function(selectedElement){
 if (this.options.updateElement){
 this.options.updateElement(selectedElement);
 return;
}
 var value = '';
 if (this.options.select){
 var nodes = $(selectedElement).select('.' + this.options.select) || [];
 if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
}else
 value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');

 var bounds = this.getTokenBounds();
 if (bounds[0] != -1){
 var newValue = this.element.value.substr(0, bounds[0]);
 var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
 if (whitespace)
 newValue += whitespace[0];
 this.element.value = newValue + value + this.element.value.substr(bounds[1]);
}else{
 this.element.value = value;
}
 this.oldElementValue = this.element.value;
 this.element.focus();

 if (this.options.afterUpdateElement)
 this.options.afterUpdateElement(this.element, selectedElement);
},

 updateChoices: function(choices){
 if(!this.changed && this.hasFocus){
 this.update.innerHTML = choices;
 Element.cleanWhitespace(this.update);
 Element.cleanWhitespace(this.update.down());

 if(this.update.firstChild && this.update.down().childNodes){
 this.entryCount =
 this.update.down().childNodes.length;
 for (var i = 0; i < this.entryCount; i++){
 var entry = this.getEntry(i);
 entry.autocompleteIndex = i;
 this.addObservers(entry);
}
}else{
 this.entryCount = 0;
}

 this.stopIndicator();
 this.index = 0;

 if(this.entryCount==1 && this.options.autoSelect){
 this.selectEntry();
 this.hide();
}else{
 this.render();
}
}
},

 addObservers: function(element){
 Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
 Event.observe(element, "click", this.onClick.bindAsEventListener(this));
},

 onObserverEvent: function(){
 this.changed = false;
 this.tokenBounds = null;
 if(this.getToken().length>=this.options.minChars){
 this.getUpdatedChoices();
}else{
 this.active = false;
 this.hide();
}
 this.oldElementValue = this.element.value;
},

 getToken: function(){
 var bounds = this.getTokenBounds();
 return this.element.value.substring(bounds[0], bounds[1]).strip();
},

 getTokenBounds: function(){
 if (null != this.tokenBounds) return this.tokenBounds;
 var value = this.element.value;
 if (value.strip().empty()) return [-1, 0];
 var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
 var offset = (diff == this.oldElementValue.length ? 1 : 0);
 var prevTokenPos = -1, nextTokenPos = value.length;
 var tp;
 for (var index = 0, l = this.options.tokens.length; index < l; ++index){
 tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
 if (tp > prevTokenPos) prevTokenPos = tp;
 tp = value.indexOf(this.options.tokens[index], diff + offset);
 if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
}
 return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
}
});

Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS){
 var boundary = Math.min(newS.length, oldS.length);
 for (var index = 0; index < boundary; ++index)
 if (newS[index] != oldS[index])
 return index;
 return boundary;
};

Ajax.Autocompleter = Class.create(Autocompleter.Base,{
 initialize: function(element, update, url, options){
 this.baseInitialize(element, update, options);
 this.options.asynchronous = true;
 this.options.onComplete = this.onComplete.bind(this);
 this.options.defaultParams = this.options.parameters || null;
 this.url = url;
},

 getUpdatedChoices: function(){
 this.startIndicator();

 var entry = encodeURIComponent(this.options.paramName) + '=' +
 encodeURIComponent(this.getToken());

 this.options.parameters = this.options.callback ?
 this.options.callback(this.element, entry) : entry;

 if(this.options.defaultParams)
 this.options.parameters += '&' + this.options.defaultParams;

 new Ajax.Request(this.url, this.options);
},

 onComplete: function(request){
 this.updateChoices(request.responseText);
}
});



































Autocompleter.Local = Class.create(Autocompleter.Base,{
 initialize: function(element, update, array, options){
 this.baseInitialize(element, update, options);
 this.options.array = array;
},

 getUpdatedChoices: function(){
 this.updateChoices(this.options.selector(this));
},

 setOptions: function(options){
 this.options = Object.extend({
 choices: 10,
 partialSearch: true,
 partialChars: 2,
 ignoreCase: true,
 fullSearch: false,
 selector: function(instance){
 var ret = []; // Beginning matches
 var partial = []; // Inside matches
 var entry = instance.getToken();
 var count = 0;

 for (var i = 0; i < instance.options.array.length &&
 ret.length < instance.options.choices ; i++){

 var elem = instance.options.array[i];
 var foundPos = instance.options.ignoreCase ?
 elem.toLowerCase().indexOf(entry.toLowerCase()) :
 elem.indexOf(entry);

 while (foundPos != -1){
 if (foundPos == 0 && elem.length != entry.length){
 ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
 elem.substr(entry.length) + "</li>");
 break;
}else if (entry.length >= instance.options.partialChars &&
 instance.options.partialSearch && foundPos != -1){
 if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))){
 partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
 elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
 foundPos + entry.length) + "</li>");
 break;
}
}

 foundPos = instance.options.ignoreCase ?
 elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
 elem.indexOf(entry, foundPos + 1);

}
}
 if (partial.length)
 ret = ret.concat(partial.slice(0, instance.options.choices - ret.length));
 return "<ul>" + ret.join('') + "</ul>";
}
}, options ||{});
}
});





Field.scrollFreeActivate = function(field){
 setTimeout(function(){
 Field.activate(field);
}, 1);
};

Ajax.InPlaceEditor = Class.create({
 initialize: function(element, url, options){
 this.url = url;
 this.element = element = $(element);
 this.prepareOptions();
 this._controls ={};
 arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
 Object.extend(this.options, options ||{});
 if (!this.options.formId && this.element.id){
 this.options.formId = this.element.id + '-inplaceeditor';
 if ($(this.options.formId))
 this.options.formId = '';
}
 if (this.options.externalControl)
 this.options.externalControl = $(this.options.externalControl);
 if (!this.options.externalControl)
 this.options.externalControlOnly = false;
 this._originalBackground = this.element.getStyle('background-color') || 'transparent';
 this.element.title = this.options.clickToEditText;
 this._boundCancelHandler = this.handleFormCancellation.bind(this);
 this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
 this._boundFailureHandler = this.handleAJAXFailure.bind(this);
 this._boundSubmitHandler = this.handleFormSubmission.bind(this);
 this._boundWrapperHandler = this.wrapUp.bind(this);
 this.registerListeners();
},
 checkForEscapeOrReturn: function(e){
 if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
 if (Event.KEY_ESC == e.keyCode)
 this.handleFormCancellation(e);
 else if (Event.KEY_RETURN == e.keyCode)
 this.handleFormSubmission(e);
},
 createControl: function(mode, handler, extraClasses){
 var control = this.options[mode + 'Control'];
 var text = this.options[mode + 'Text'];
 if ('button' == control){
 var btn = document.createElement('input');
 btn.type = 'submit';
 btn.value = text;
 btn.className = 'editor_' + mode + '_button';
 if ('cancel' == mode)
 btn.onclick = this._boundCancelHandler;
 this._form.appendChild(btn);
 this._controls[mode] = btn;
}else if ('link' == control){
 var link = document.createElement('a');
 link.href = '#';
 link.appendChild(document.createTextNode(text));
 link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
 link.className = 'editor_' + mode + '_link';
 if (extraClasses)
 link.className += ' ' + extraClasses;
 this._form.appendChild(link);
 this._controls[mode] = link;
}
},
 createEditField: function(){
 var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
 var fld;
 if (1 >= this.options.rows && !/\r|\n/.test(this.getText())){
 fld = document.createElement('input');
 fld.type = 'text';
 var size = this.options.size || this.options.cols || 0;
 if (0 < size) fld.size = size;
}else{
 fld = document.createElement('textarea');
 fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
 fld.cols = this.options.cols || 40;
}
 fld.name = this.options.paramName;
 fld.value = text; // No HTML breaks conversion anymore
 fld.className = 'editor_field';
 if (this.options.submitOnBlur)
 fld.onblur = this._boundSubmitHandler;
 this._controls.editor = fld;
 if (this.options.loadTextURL)
 this.loadExternalText();
 this._form.appendChild(this._controls.editor);
},
 createForm: function(){
 var ipe = this;
 function addText(mode, condition){
 var text = ipe.options['text' + mode + 'Controls'];
 if (!text || condition === false) return;
 ipe._form.appendChild(document.createTextNode(text));
};
 this._form = $(document.createElement('form'));
 this._form.id = this.options.formId;
 this._form.addClassName(this.options.formClassName);
 this._form.onsubmit = this._boundSubmitHandler;
 this.createEditField();
 if ('textarea' == this._controls.editor.tagName.toLowerCase())
 this._form.appendChild(document.createElement('br'));
 if (this.options.onFormCustomization)
 this.options.onFormCustomization(this, this._form);
 addText('Before', this.options.okControl || this.options.cancelControl);
 this.createControl('ok', this._boundSubmitHandler);
 addText('Between', this.options.okControl && this.options.cancelControl);
 this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
 addText('After', this.options.okControl || this.options.cancelControl);
},
 destroy: function(){
 if (this._oldInnerHTML)
 this.element.innerHTML = this._oldInnerHTML;
 this.leaveEditMode();
 this.unregisterListeners();
},
 enterEditMode: function(e){
 if (this._saving || this._editing) return;
 this._editing = true;
 this.triggerCallback('onEnterEditMode');
 if (this.options.externalControl)
 this.options.externalControl.hide();
 this.element.hide();
 this.createForm();
 this.element.parentNode.insertBefore(this._form, this.element);
 if (!this.options.loadTextURL)
 this.postProcessEditField();
 if (e) Event.stop(e);
},
 enterHover: function(e){
 if (this.options.hoverClassName)
 this.element.addClassName(this.options.hoverClassName);
 if (this._saving) return;
 this.triggerCallback('onEnterHover');
},
 getText: function(){
 return this.element.innerHTML.unescapeHTML();
},
 handleAJAXFailure: function(transport){
 this.triggerCallback('onFailure', transport);
 if (this._oldInnerHTML){
 this.element.innerHTML = this._oldInnerHTML;
 this._oldInnerHTML = null;
}
},
 handleFormCancellation: function(e){
 this.wrapUp();
 if (e) Event.stop(e);
},
 handleFormSubmission: function(e){
 var form = this._form;
 var value = $F(this._controls.editor);
 this.prepareSubmission();
 var params = this.options.callback(form, value) || '';
 if (Object.isString(params))
 params = params.toQueryParams();
 params.editorId = this.element.id;
 if (this.options.htmlResponse){
 var options = Object.extend({evalScripts: true}, this.options.ajaxOptions);
 Object.extend(options,{
 parameters: params,
 onComplete: this._boundWrapperHandler,
 onFailure: this._boundFailureHandler
});
 new Ajax.Updater({success: this.element}, this.url, options);
}else{
 var options = Object.extend({method: 'get'}, this.options.ajaxOptions);
 Object.extend(options,{
 parameters: params,
 onComplete: this._boundWrapperHandler,
 onFailure: this._boundFailureHandler
});
 new Ajax.Request(this.url, options);
}
 if (e) Event.stop(e);
},
 leaveEditMode: function(){
 this.element.removeClassName(this.options.savingClassName);
 this.removeForm();
 this.leaveHover();
 this.element.style.backgroundColor = this._originalBackground;
 this.element.show();
 if (this.options.externalControl)
 this.options.externalControl.show();
 this._saving = false;
 this._editing = false;
 this._oldInnerHTML = null;
 this.triggerCallback('onLeaveEditMode');
},
 leaveHover: function(e){
 if (this.options.hoverClassName)
 this.element.removeClassName(this.options.hoverClassName);
 if (this._saving) return;
 this.triggerCallback('onLeaveHover');
},
 loadExternalText: function(){
 this._form.addClassName(this.options.loadingClassName);
 this._controls.editor.disabled = true;
 var options = Object.extend({method: 'get'}, this.options.ajaxOptions);
 Object.extend(options,{
 parameters: 'editorId=' + encodeURIComponent(this.element.id),
 onComplete: Prototype.emptyFunction,
 onSuccess: function(transport){
 this._form.removeClassName(this.options.loadingClassName);
 var text = transport.responseText;
 if (this.options.stripLoadedTextTags)
 text = text.stripTags();
 this._controls.editor.value = text;
 this._controls.editor.disabled = false;
 this.postProcessEditField();
}.bind(this),
 onFailure: this._boundFailureHandler
});
 new Ajax.Request(this.options.loadTextURL, options);
},
 postProcessEditField: function(){
 var fpc = this.options.fieldPostCreation;
 if (fpc)
 $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
},
 prepareOptions: function(){
 this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
 Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
 [this._extraDefaultOptions].flatten().compact().each(function(defs){
 Object.extend(this.options, defs);
}.bind(this));
},
 prepareSubmission: function(){
 this._saving = true;
 this.removeForm();
 this.leaveHover();
 this.showSaving();
},
 registerListeners: function(){
 this._listeners ={};
 var listener;
 $H(Ajax.InPlaceEditor.Listeners).each(function(pair){
 listener = this[pair.value].bind(this);
 this._listeners[pair.key] = listener;
 if (!this.options.externalControlOnly)
 this.element.observe(pair.key, listener);
 if (this.options.externalControl)
 this.options.externalControl.observe(pair.key, listener);
}.bind(this));
},
 removeForm: function(){
 if (!this._form) return;
 this._form.remove();
 this._form = null;
 this._controls ={};
},
 showSaving: function(){
 this._oldInnerHTML = this.element.innerHTML;
 this.element.innerHTML = this.options.savingText;
 this.element.addClassName(this.options.savingClassName);
 this.element.style.backgroundColor = this._originalBackground;
 this.element.show();
},
 triggerCallback: function(cbName, arg){
 if ('function' == typeof this.options[cbName]){
 this.options[cbName](this, arg);
}
},
 unregisterListeners: function(){
 $H(this._listeners).each(function(pair){
 if (!this.options.externalControlOnly)
 this.element.stopObserving(pair.key, pair.value);
 if (this.options.externalControl)
 this.options.externalControl.stopObserving(pair.key, pair.value);
}.bind(this));
},
 wrapUp: function(transport){
 this.leaveEditMode();


 this._boundComplete(transport, this.element);
}
});

Object.extend(Ajax.InPlaceEditor.prototype,{
 dispose: Ajax.InPlaceEditor.prototype.destroy
});

Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor,{
 initialize: function($super, element, url, options){
 this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
 $super(element, url, options);
},

 createEditField: function(){
 var list = document.createElement('select');
 list.name = this.options.paramName;
 list.size = 1;
 this._controls.editor = list;
 this._collection = this.options.collection || [];
 if (this.options.loadCollectionURL)
 this.loadCollection();
 else
 this.checkForExternalText();
 this._form.appendChild(this._controls.editor);
},

 loadCollection: function(){
 this._form.addClassName(this.options.loadingClassName);
 this.showLoadingText(this.options.loadingCollectionText);
 var options = Object.extend({method: 'get'}, this.options.ajaxOptions);
 Object.extend(options,{
 parameters: 'editorId=' + encodeURIComponent(this.element.id),
 onComplete: Prototype.emptyFunction,
 onSuccess: function(transport){
 var js = transport.responseText.strip();
 if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
 throw('Server returned an invalid collection representation.');
 this._collection = eval(js);
 this.checkForExternalText();
}.bind(this),
 onFailure: this.onFailure
});
 new Ajax.Request(this.options.loadCollectionURL, options);
},

 showLoadingText: function(text){
 this._controls.editor.disabled = true;
 var tempOption = this._controls.editor.firstChild;
 if (!tempOption){
 tempOption = document.createElement('option');
 tempOption.value = '';
 this._controls.editor.appendChild(tempOption);
 tempOption.selected = true;
}
 tempOption.update((text || '').stripScripts().stripTags());
},

 checkForExternalText: function(){
 this._text = this.getText();
 if (this.options.loadTextURL)
 this.loadExternalText();
 else
 this.buildOptionList();
},

 loadExternalText: function(){
 this.showLoadingText(this.options.loadingText);
 var options = Object.extend({method: 'get'}, this.options.ajaxOptions);
 Object.extend(options,{
 parameters: 'editorId=' + encodeURIComponent(this.element.id),
 onComplete: Prototype.emptyFunction,
 onSuccess: function(transport){
 this._text = transport.responseText.strip();
 this.buildOptionList();
}.bind(this),
 onFailure: this.onFailure
});
 new Ajax.Request(this.options.loadTextURL, options);
},

 buildOptionList: function(){
 this._form.removeClassName(this.options.loadingClassName);
 this._collection = this._collection.map(function(entry){
 return 2 === entry.length ? entry : [entry, entry].flatten();
});
 var marker = ('value' in this.options) ? this.options.value : this._text;
 var textFound = this._collection.any(function(entry){
 return entry[0] == marker;
}.bind(this));
 this._controls.editor.update('');
 var option;
 this._collection.each(function(entry, index){
 option = document.createElement('option');
 option.value = entry[0];
 option.selected = textFound ? entry[0] == marker : 0 == index;
 option.appendChild(document.createTextNode(entry[1]));
 this._controls.editor.appendChild(option);
}.bind(this));
 this._controls.editor.disabled = false;
 Field.scrollFreeActivate(this._controls.editor);
}
});





Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options){
 if (!options) return;
 function fallback(name, expr){
 if (name in options || expr === undefined) return;
 options[name] = expr;
};
 fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
 options.cancelLink == options.cancelButton == false ? false : undefined)));
 fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
 options.okLink == options.okButton == false ? false : undefined)));
 fallback('highlightColor', options.highlightcolor);
 fallback('highlightEndColor', options.highlightendcolor);
};

Object.extend(Ajax.InPlaceEditor,{
 DefaultOptions:{
 ajaxOptions:{},
 autoRows: 3, // Use when multi-line w/ rows == 1
 cancelControl: 'link', // 'link'|'button'|false
 cancelText: 'cancel',
 clickToEditText: 'Click to edit',
 externalControl: null, // id|elt
 externalControlOnly: false,
 fieldPostCreation: 'activate', // 'activate'|'focus'|false
 formClassName: 'inplaceeditor-form',
 formId: null, // id|elt
 highlightColor: '#ffff99',
 highlightEndColor: '#ffffff',
 hoverClassName: '',
 htmlResponse: true,
 loadingClassName: 'inplaceeditor-loading',
 loadingText: 'Loading...',
 okControl: 'button', // 'link'|'button'|false
 okText: 'ok',
 paramName: 'value',
 rows: 1, // If 1 and multi-line, uses autoRows
 savingClassName: 'inplaceeditor-saving',
 savingText: 'Saving...',
 size: 0,
 stripLoadedTextTags: false,
 submitOnBlur: false,
 textAfterControls: '',
 textBeforeControls: '',
 textBetweenControls: ''
},
 DefaultCallbacks:{
 callback: function(form){
 return Form.serialize(form);
},
 onComplete: function(transport, element){


 new Effect.Highlight(element,{
 startcolor: this.options.highlightColor, keepBackgroundImage: true});
},
 onEnterEditMode: null,
 onEnterHover: function(ipe){
 ipe.element.style.backgroundColor = ipe.options.highlightColor;
 if (ipe._effect)
 ipe._effect.cancel();
},
 onFailure: function(transport, ipe){
 alert('Error communication with the server: ' + transport.responseText.stripTags());
},
 onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
 onLeaveEditMode: null,
 onLeaveHover: function(ipe){
 ipe._effect = new Effect.Highlight(ipe.element,{
 startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
 restorecolor: ipe._originalBackground, keepBackgroundImage: true
});
}
},
 Listeners:{
 click: 'enterEditMode',
 keydown: 'checkForEscapeOrReturn',
 mouseover: 'enterHover',
 mouseout: 'leaveHover'
}
});

Ajax.InPlaceCollectionEditor.DefaultOptions ={
 loadingCollectionText: 'Loading options...'
};




Form.Element.DelayedObserver = Class.create({
 initialize: function(element, delay, callback){
 this.delay = delay || 0.5;
 this.element = $(element);
 this.callback = callback;
 this.timer = null;
 this.lastValue = $F(this.element);
 Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
},
 delayedListener: function(event){
 if(this.lastValue == $F(this.element)) return;
 if(this.timer) clearTimeout(this.timer);
 this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
 this.lastValue = $F(this.element);
},
 onTimerEvent: function(){
 this.timer = null;
 this.callback(this.element, $F(this.element));
}
});/* ######### builder ######### */






var Builder ={
 NODEMAP:{
 AREA: 'map',
 CAPTION: 'table',
 COL: 'table',
 COLGROUP: 'table',
 LEGEND: 'fieldset',
 OPTGROUP: 'select',
 OPTION: 'select',
 PARAM: 'object',
 TBODY: 'table',
 TD: 'table',
 TFOOT: 'table',
 TH: 'table',
 THEAD: 'table',
 TR: 'table'
},


 node: function(elementName){
 elementName = elementName.toUpperCase();

 var parentTag = this.NODEMAP[elementName] || 'div';
 var parentElement = document.createElement(parentTag);
 try{// prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
 parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
}catch(e){}
 var element = parentElement.firstChild || null;

 if(element && (element.tagName.toUpperCase() != elementName))
 element = element.getElementsByTagName(elementName)[0];

 if(!element) element = document.createElement(elementName);

 if(!element) return;

 if(arguments[1])
 if(this._isStringOrNumber(arguments[1]) ||
 (arguments[1] instanceof Array) ||
 arguments[1].tagName){
 this._children(element, arguments[1]);
}else{
 var attrs = this._attributes(arguments[1]);
 if(attrs.length){
 try{// prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
 parentElement.innerHTML = "<" +elementName + " " +
 attrs + "></" + elementName + ">";
}catch(e){}
 element = parentElement.firstChild || null;

 if(!element){
 element = document.createElement(elementName);
 for(attr in arguments[1])
 element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
}
 if(element.tagName.toUpperCase() != elementName)
 element = parentElement.getElementsByTagName(elementName)[0];
}
}

 if(arguments[2])
 this._children(element, arguments[2]);

 return $(element);
},
 _text: function(text){
 return document.createTextNode(text);
},

 ATTR_MAP:{
 'className': 'class',
 'htmlFor': 'for'
},

 _attributes: function(attributes){
 var attrs = [];
 for(attribute in attributes)
 attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
 '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
 return attrs.join(" ");
},
 _children: function(element, children){
 if(children.tagName){
 element.appendChild(children);
 return;
}
 if(typeof children=='object'){// array can hold nodes and text
 children.flatten().each( function(e){
 if(typeof e=='object')
 element.appendChild(e);
 else
 if(Builder._isStringOrNumber(e))
 element.appendChild(Builder._text(e));
});
}else
 if(Builder._isStringOrNumber(children))
 element.appendChild(Builder._text(children));
},
 _isStringOrNumber: function(param){
 return(typeof param=='string' || typeof param=='number');
},
 build: function(html){
 var element = this.node('div');
 $(element).update(html.strip());
 return element.down();
},
 dump: function(scope){
 if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope

 var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
 "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
 "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
 "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
 "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
 "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);

 tags.each( function(tag){
 scope[tag] = function(){
 return Builder.node.apply(Builder, [tag].concat($A(arguments)));
};
});
}
};/* ######### dragdrop ######### */







if(Object.isUndefined(Effect))
 throw("dragdrop.js requires including script.aculo.us' effects.js library");

var Droppables ={
 drops: [],

 remove: function(element){
 this.drops = this.drops.reject(function(d){return d.element==$(element)});
},

 add: function(element){
 element = $(element);
 var options = Object.extend({
 greedy: true,
 hoverclass: null,
 tree: false
}, arguments[1] ||{});

 if(options.containment){
 options._containers = [];
 var containment = options.containment;
 if(Object.isArray(containment)){
 containment.each( function(c){options._containers.push($(c))});
}else{
 options._containers.push($(containment));
}
}

 if(options.accept) options.accept = [options.accept].flatten();

 Element.makePositioned(element); // fix IE
 options.element = element;

 this.drops.push(options);
},

 findDeepestChild: function(drops){
 deepest = drops[0];

 for (i = 1; i < drops.length; ++i)
 if (Element.isParent(drops[i].element, deepest.element))
 deepest = drops[i];

 return deepest;
},

 isContained: function(element, drop){
 var containmentNode;
 if(drop.tree){
 containmentNode = element.treeNode;
}else{
 containmentNode = element.parentNode;
}
 return drop._containers.detect(function(c){return containmentNode == c});
},

 isAffected: function(point, element, drop){
 return (
 (drop.element!=element) &&
 ((!drop._containers) ||
 this.isContained(element, drop)) &&
 ((!drop.accept) ||
 (Element.classNames(element).detect(
 function(v){return drop.accept.include(v)}) )) &&
 Position.within(drop.element, point[0], point[1]) );
},

 deactivate: function(drop){
 if(drop.hoverclass)
 Element.removeClassName(drop.element, drop.hoverclass);
 this.last_active = null;
},

 activate: function(drop){
 if(drop.hoverclass)
 Element.addClassName(drop.element, drop.hoverclass);
 this.last_active = drop;
},

 show: function(point, element){
 if(!this.drops.length) return;
 var drop, affected = [];

 this.drops.each( function(drop){
 if(Droppables.isAffected(point, element, drop))
 affected.push(drop);
});

 if(affected.length>0)
 drop = Droppables.findDeepestChild(affected);

 if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
 if (drop){
 Position.within(drop.element, point[0], point[1]);
 if(drop.onHover)
 drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));

 if (drop != this.last_active) Droppables.activate(drop);
}
},

 fire: function(event, element){
 if(!this.last_active) return;
 Position.prepare();

 if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
 if (this.last_active.onDrop){
 this.last_active.onDrop(element, this.last_active.element, event);
 return true;
}
},

 reset: function(){
 if(this.last_active)
 this.deactivate(this.last_active);
}
};

var Draggables ={
 drags: [],
 observers: [],

 register: function(draggable){
 if(this.drags.length == 0){
 this.eventMouseUp = this.endDrag.bindAsEventListener(this);
 this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
 this.eventKeypress = this.keyPress.bindAsEventListener(this);

 Event.observe(document, "mouseup", this.eventMouseUp);
 Event.observe(document, "mousemove", this.eventMouseMove);
 Event.observe(document, "keypress", this.eventKeypress);
}
 this.drags.push(draggable);
},

 unregister: function(draggable){
 this.drags = this.drags.reject(function(d){return d==draggable});
 if(this.drags.length == 0){
 Event.stopObserving(document, "mouseup", this.eventMouseUp);
 Event.stopObserving(document, "mousemove", this.eventMouseMove);
 Event.stopObserving(document, "keypress", this.eventKeypress);
}
},

 activate: function(draggable){
 if(draggable.options.delay){
 this._timeout = setTimeout(function(){
 Draggables._timeout = null;
 window.focus();
 Draggables.activeDraggable = draggable;
}.bind(this), draggable.options.delay);
}else{
 window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
 this.activeDraggable = draggable;
}
},

 deactivate: function(){
 this.activeDraggable = null;
},

 updateDrag: function(event){
 if(!this.activeDraggable) return;
 var pointer = [Event.pointerX(event), Event.pointerY(event)];


 if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
 this._lastPointer = pointer;

 this.activeDraggable.updateDrag(event, pointer);
},

 endDrag: function(event){
 if(this._timeout){
 clearTimeout(this._timeout);
 this._timeout = null;
}
 if(!this.activeDraggable) return;
 this._lastPointer = null;
 this.activeDraggable.endDrag(event);
 this.activeDraggable = null;
},

 keyPress: function(event){
 if(this.activeDraggable)
 this.activeDraggable.keyPress(event);
},

 addObserver: function(observer){
 this.observers.push(observer);
 this._cacheObserverCallbacks();
},

 removeObserver: function(element){// element instead of observer fixes mem leaks
 this.observers = this.observers.reject( function(o){return o.element==element});
 this._cacheObserverCallbacks();
},

 notify: function(eventName, draggable, event){// 'onStart', 'onEnd', 'onDrag'
 if(this[eventName+'Count'] > 0)
 this.observers.each( function(o){
 if(o[eventName]) o[eventName](eventName, draggable, event);
});
 if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
},

 _cacheObserverCallbacks: function(){
 ['onStart','onEnd','onDrag'].each( function(eventName){
 Draggables[eventName+'Count'] = Draggables.observers.select(
 function(o){return o[eventName];}
 ).length;
});
}
};

/*--------------------------------------------------------------------------*/

var Draggable = Class.create({
 initialize: function(element){
 var defaults ={
 handle: false,
 reverteffect: function(element, top_offset, left_offset){
 var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
 new Effect.Move(element,{x: -left_offset, y: -top_offset, duration: dur,
 queue:{scope:'_draggable', position:'end'}
});
},
 endeffect: function(element){
 var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
 new Effect.Opacity(element,{duration:0.2, from:0.7, to:toOpacity,
 queue:{scope:'_draggable', position:'end'},
 afterFinish: function(){
 Draggable._dragging[element] = false
}
});
},
 zindex: 1000,
 revert: false,
 quiet: false,
 scroll: false,
 scrollSensitivity: 20,
 scrollSpeed: 15,
 snap: false, // false, or xy or [x,y] or function(x,y){return [x,y]}
 delay: 0
};

 if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
 Object.extend(defaults,{
 starteffect: function(element){
 element._opacity = Element.getOpacity(element);
 Draggable._dragging[element] = true;
 new Effect.Opacity(element,{duration:0.2, from:element._opacity, to:0.7});
}
});

 var options = Object.extend(defaults, arguments[1] ||{});

 this.element = $(element);

 if(options.handle && Object.isString(options.handle))
 this.handle = this.element.down('.'+options.handle, 0);

 if(!this.handle) this.handle = $(options.handle);
 if(!this.handle) this.handle = this.element;

 if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML){
 options.scroll = $(options.scroll);
 this._isScrollChild = Element.childOf(this.element, options.scroll);
}

 Element.makePositioned(this.element); // fix IE

 this.options = options;
 this.dragging = false;

 this.eventMouseDown = this.initDrag.bindAsEventListener(this);
 Event.observe(this.handle, "mousedown", this.eventMouseDown);

 Draggables.register(this);
},

 destroy: function(){
 Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
 Draggables.unregister(this);
},

 currentDelta: function(){
 return([
 parseInt(Element.getStyle(this.element,'left') || '0'),
 parseInt(Element.getStyle(this.element,'top') || '0')]);
},

 initDrag: function(event){
 if(!Object.isUndefined(Draggable._dragging[this.element]) &&
 Draggable._dragging[this.element]) return;
 if(Event.isLeftClick(event)){

 var src = Event.element(event);
 if((tag_name = src.tagName.toUpperCase()) && (
 tag_name=='INPUT' ||
 tag_name=='SELECT' ||
 tag_name=='OPTION' ||
 tag_name=='BUTTON' ||
 tag_name=='TEXTAREA')) return;

 var pointer = [Event.pointerX(event), Event.pointerY(event)];
 var pos = Position.cumulativeOffset(this.element);
 this.offset = [0,1].map( function(i){return (pointer[i] - pos[i])});

 Draggables.activate(this);
 Event.stop(event);
}
},

 startDrag: function(event){
 this.dragging = true;
 if(!this.delta)
 this.delta = this.currentDelta();

 if(this.options.zindex){
 this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
 this.element.style.zIndex = this.options.zindex;
}

 if(this.options.ghosting){
 this._clone = this.element.cloneNode(true);
 this._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
 if (!this._originallyAbsolute)
 Position.absolutize(this.element);
 this.element.parentNode.insertBefore(this._clone, this.element);
}

 if(this.options.scroll){
 if (this.options.scroll == window){
 var where = this._getWindowScroll(this.options.scroll);
 this.originalScrollLeft = where.left;
 this.originalScrollTop = where.top;
}else{
 this.originalScrollLeft = this.options.scroll.scrollLeft;
 this.originalScrollTop = this.options.scroll.scrollTop;
}
}

 Draggables.notify('onStart', this, event);

 if(this.options.starteffect) this.options.starteffect(this.element);
},

 updateDrag: function(event, pointer){
 if(!this.dragging) this.startDrag(event);

 if(!this.options.quiet){
 Position.prepare();
 Droppables.show(pointer, this.element);
}

 Draggables.notify('onDrag', this, event);

 this.draw(pointer);
 if(this.options.change) this.options.change(this);

 if(this.options.scroll){
 this.stopScrolling();

 var p;
 if (this.options.scroll == window){
 with(this._getWindowScroll(this.options.scroll)){p = [ left, top, left+width, top+height ];}
}else{
 p = Position.page(this.options.scroll);
 p[0] += this.options.scroll.scrollLeft + Position.deltaX;
 p[1] += this.options.scroll.scrollTop + Position.deltaY;
 p.push(p[0]+this.options.scroll.offsetWidth);
 p.push(p[1]+this.options.scroll.offsetHeight);
}
 var speed = [0,0];
 if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
 if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
 if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
 if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
 this.startScrolling(speed);
}

 if(Prototype.Browser.WebKit) window.scrollBy(0,0);

 Event.stop(event);
},

 finishDrag: function(event, success){
 this.dragging = false;

 if(this.options.quiet){
 Position.prepare();
 var pointer = [Event.pointerX(event), Event.pointerY(event)];
 Droppables.show(pointer, this.element);
}

 if(this.options.ghosting){
 if (!this._originallyAbsolute)
 Position.relativize(this.element);
 delete this._originallyAbsolute;
 Element.remove(this._clone);
 this._clone = null;
}

 var dropped = false;
 if(success){
 dropped = Droppables.fire(event, this.element);
 if (!dropped) dropped = false;
}
 if(dropped && this.options.onDropped) this.options.onDropped(this.element);
 Draggables.notify('onEnd', this, event);

 var revert = this.options.revert;
 if(revert && Object.isFunction(revert)) revert = revert(this.element);

 var d = this.currentDelta();
 if(revert && this.options.reverteffect){
 if (dropped == 0 || revert != 'failure')
 this.options.reverteffect(this.element,
 d[1]-this.delta[1], d[0]-this.delta[0]);
}else{
 this.delta = d;
}

 if(this.options.zindex)
 this.element.style.zIndex = this.originalZ;

 if(this.options.endeffect)
 this.options.endeffect(this.element);

 Draggables.deactivate(this);
 Droppables.reset();
},

 keyPress: function(event){
 if(event.keyCode!=Event.KEY_ESC) return;
 this.finishDrag(event, false);
 Event.stop(event);
},

 endDrag: function(event){
 if(!this.dragging) return;
 this.stopScrolling();
 this.finishDrag(event, true);
 Event.stop(event);
},

 draw: function(point){
 var pos = Position.cumulativeOffset(this.element);
 if(this.options.ghosting){
 var r = Position.realOffset(this.element);
 pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
}

 var d = this.currentDelta();
 pos[0] -= d[0]; pos[1] -= d[1];

 if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)){
 pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
 pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
}

 var p = [0,1].map(function(i){
 return (point[i]-pos[i]-this.offset[i])
}.bind(this));

 if(this.options.snap){
 if(Object.isFunction(this.options.snap)){
 p = this.options.snap(p[0],p[1],this);
}else{
 if(Object.isArray(this.options.snap)){
 p = p.map( function(v, i){
 return (v/this.options.snap[i]).round()*this.options.snap[i]}.bind(this));
}else{
 p = p.map( function(v){
 return (v/this.options.snap).round()*this.options.snap}.bind(this));
}
}}

 var style = this.element.style;
 if((!this.options.constraint) || (this.options.constraint=='horizontal'))
 style.left = p[0] + "px";
 if((!this.options.constraint) || (this.options.constraint=='vertical'))
 style.top = p[1] + "px";

 if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
},

 stopScrolling: function(){
 if(this.scrollInterval){
 clearInterval(this.scrollInterval);
 this.scrollInterval = null;
 Draggables._lastScrollPointer = null;
}
},

 startScrolling: function(speed){
 if(!(speed[0] || speed[1])) return;
 this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
 this.lastScrolled = new Date();
 this.scrollInterval = setInterval(this.scroll.bind(this), 10);
},

 scroll: function(){
 var current = new Date();
 var delta = current - this.lastScrolled;
 this.lastScrolled = current;
 if(this.options.scroll == window){
 with (this._getWindowScroll(this.options.scroll)){
 if (this.scrollSpeed[0] || this.scrollSpeed[1]){
 var d = delta / 1000;
 this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
}
}
}else{
 this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
 this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
}

 Position.prepare();
 Droppables.show(Draggables._lastPointer, this.element);
 Draggables.notify('onDrag', this);
 if (this._isScrollChild){
 Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
 Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
 Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
 if (Draggables._lastScrollPointer[0] < 0)
 Draggables._lastScrollPointer[0] = 0;
 if (Draggables._lastScrollPointer[1] < 0)
 Draggables._lastScrollPointer[1] = 0;
 this.draw(Draggables._lastScrollPointer);
}

 if(this.options.change) this.options.change(this);
},

 _getWindowScroll: function(w){
 var T, L, W, H;
 with (w.document){
 if (w.document.documentElement && documentElement.scrollTop){
 T = documentElement.scrollTop;
 L = documentElement.scrollLeft;
}else if (w.document.body){
 T = body.scrollTop;
 L = body.scrollLeft;
}
 if (w.innerWidth){
 W = w.innerWidth;
 H = w.innerHeight;
}else if (w.document.documentElement && documentElement.clientWidth){
 W = documentElement.clientWidth;
 H = documentElement.clientHeight;
}else{
 W = body.offsetWidth;
 H = body.offsetHeight;
}
}
 return{top: T, left: L, width: W, height: H};
}
});

Draggable._dragging ={};

/*--------------------------------------------------------------------------*/

var SortableObserver = Class.create({
 initialize: function(element, observer){
 this.element = $(element);
 this.observer = observer;
 this.lastValue = Sortable.serialize(this.element);
},

 onStart: function(){
 this.lastValue = Sortable.serialize(this.element);
},

 onEnd: function(){
 Sortable.unmark();
 if(this.lastValue != Sortable.serialize(this.element))
 this.observer(this.element)
}
});

var Sortable ={
 SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,

 sortables:{},

 _findRootElement: function(element){
 while (element.tagName.toUpperCase() != "BODY"){
 if(element.id && Sortable.sortables[element.id]) return element;
 element = element.parentNode;
}
},

 options: function(element){
 element = Sortable._findRootElement($(element));
 if(!element) return;
 return Sortable.sortables[element.id];
},

 destroy: function(element){
 element = $(element);
 var s = Sortable.sortables[element.id];

 if(s){
 Draggables.removeObserver(s.element);
 s.droppables.each(function(d){Droppables.remove(d)});
 s.draggables.invoke('destroy');

 delete Sortable.sortables[s.element.id];
}
},

 create: function(element){
 element = $(element);
 var options = Object.extend({
 element: element,
 tag: 'li', // assumes li children, override with tag: 'tagname'
 dropOnEmpty: false,
 tree: false,
 treeTag: 'ul',
 overlap: 'vertical', // one of 'vertical', 'horizontal'
 constraint: 'vertical', // one of 'vertical', 'horizontal', false
 containment: element, // also takes array of elements (or id's); or false
 handle: false, // or a CSS class
 only: false,
 delay: 0,
 hoverclass: null,
 ghosting: false,
 quiet: false,
 scroll: false,
 scrollSensitivity: 20,
 scrollSpeed: 15,
 format: this.SERIALIZE_RULE,


 elements: false,
 handles: false,

 onChange: Prototype.emptyFunction,
 onUpdate: Prototype.emptyFunction
}, arguments[1] ||{});

 this.destroy(element);

 var options_for_draggable ={
 revert: true,
 quiet: options.quiet,
 scroll: options.scroll,
 scrollSpeed: options.scrollSpeed,
 scrollSensitivity: options.scrollSensitivity,
 delay: options.delay,
 ghosting: options.ghosting,
 constraint: options.constraint,
 handle: options.handle};

 if(options.starteffect)
 options_for_draggable.starteffect = options.starteffect;

 if(options.reverteffect)
 options_for_draggable.reverteffect = options.reverteffect;
 else
 if(options.ghosting) options_for_draggable.reverteffect = function(element){
 element.style.top = 0;
 element.style.left = 0;
};

 if(options.endeffect)
 options_for_draggable.endeffect = options.endeffect;

 if(options.zindex)
 options_for_draggable.zindex = options.zindex;

 var options_for_droppable ={
 overlap: options.overlap,
 containment: options.containment,
 tree: options.tree,
 hoverclass: options.hoverclass,
 onHover: Sortable.onHover
};

 var options_for_tree ={
 onHover: Sortable.onEmptyHover,
 overlap: options.overlap,
 containment: options.containment,
 hoverclass: options.hoverclass
};

 Element.cleanWhitespace(element);

 options.draggables = [];
 options.droppables = [];

 if(options.dropOnEmpty || options.tree){
 Droppables.add(element, options_for_tree);
 options.droppables.push(element);
}

 (options.elements || this.findElements(element, options) || []).each( function(e,i){
 var handle = options.handles ? $(options.handles[i]) :
 (options.handle ? $(e).select('.' + options.handle)[0] : e);
 options.draggables.push(
 new Draggable(e, Object.extend(options_for_draggable,{handle: handle})));
 Droppables.add(e, options_for_droppable);
 if(options.tree) e.treeNode = element;
 options.droppables.push(e);
});

 if(options.tree){
 (Sortable.findTreeElements(element, options) || []).each( function(e){
 Droppables.add(e, options_for_tree);
 e.treeNode = element;
 options.droppables.push(e);
});
}

 this.sortables[element.id] = options;

 Draggables.addObserver(new SortableObserver(element, options.onUpdate));

},

 findElements: function(element, options){
 return Element.findChildren(
 element, options.only, options.tree ? true : false, options.tag);
},

 findTreeElements: function(element, options){
 return Element.findChildren(
 element, options.only, options.tree ? true : false, options.treeTag);
},

 onHover: function(element, dropon, overlap){
 if(Element.isParent(dropon, element)) return;

 if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree){
 return;
}else if(overlap>0.5){
 Sortable.mark(dropon, 'before');
 if(dropon.previousSibling != element){
 var oldParentNode = element.parentNode;
 element.style.visibility = "hidden"; // fix gecko rendering
 dropon.parentNode.insertBefore(element, dropon);
 if(dropon.parentNode!=oldParentNode)
 Sortable.options(oldParentNode).onChange(element);
 Sortable.options(dropon.parentNode).onChange(element);
}
}else{
 Sortable.mark(dropon, 'after');
 var nextElement = dropon.nextSibling || null;
 if(nextElement != element){
 var oldParentNode = element.parentNode;
 element.style.visibility = "hidden"; // fix gecko rendering
 dropon.parentNode.insertBefore(element, nextElement);
 if(dropon.parentNode!=oldParentNode)
 Sortable.options(oldParentNode).onChange(element);
 Sortable.options(dropon.parentNode).onChange(element);
}
}
},

 onEmptyHover: function(element, dropon, overlap){
 var oldParentNode = element.parentNode;
 var droponOptions = Sortable.options(dropon);

 if(!Element.isParent(dropon, element)){
 var index;

 var children = Sortable.findElements(dropon,{tag: droponOptions.tag, only: droponOptions.only});
 var child = null;

 if(children){
 var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);

 for (index = 0; index < children.length; index += 1){
 if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0){
 offset -= Element.offsetSize (children[index], droponOptions.overlap);
}else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0){
 child = index + 1 < children.length ? children[index + 1] : null;
 break;
}else{
 child = children[index];
 break;
}
}
}

 dropon.insertBefore(element, child);

 Sortable.options(oldParentNode).onChange(element);
 droponOptions.onChange(element);
}
},

 unmark: function(){
 if(Sortable._marker) Sortable._marker.hide();
},

 mark: function(dropon, position){

 var sortable = Sortable.options(dropon.parentNode);
 if(sortable && !sortable.ghosting) return;

 if(!Sortable._marker){
 Sortable._marker =
 ($('dropmarker') || Element.extend(document.createElement('DIV'))).
 hide().addClassName('dropmarker').setStyle({position:'absolute'});
 document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
}
 var offsets = Position.cumulativeOffset(dropon);
 Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});

 if(position=='after')
 if(sortable.overlap == 'horizontal')
 Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
 else
 Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});

 Sortable._marker.show();
},

 _tree: function(element, options, parent){
 var children = Sortable.findElements(element, options) || [];

 for (var i = 0; i < children.length; ++i){
 var match = children[i].id.match(options.format);

 if (!match) continue;

 var child ={
 id: encodeURIComponent(match ? match[1] : null),
 element: element,
 parent: parent,
 children: [],
 position: parent.children.length,
 container: $(children[i]).down(options.treeTag)
};

 /* Get the element containing the children and recurse over it */
 if (child.container)
 this._tree(child.container, options, child);

 parent.children.push (child);
}

 return parent;
},

 tree: function(element){
 element = $(element);
 var sortableOptions = this.options(element);
 var options = Object.extend({
 tag: sortableOptions.tag,
 treeTag: sortableOptions.treeTag,
 only: sortableOptions.only,
 name: element.id,
 format: sortableOptions.format
}, arguments[1] ||{});

 var root ={
 id: null,
 parent: null,
 children: [],
 container: element,
 position: 0
};

 return Sortable._tree(element, options, root);
},

 /* Construct a [i] index for a particular node */
 _constructIndex: function(node){
 var index = '';
 do{
 if (node.id) index = '[' + node.position + ']' + index;
}while ((node = node.parent) != null);
 return index;
},

 sequence: function(element){
 element = $(element);
 var options = Object.extend(this.options(element), arguments[1] ||{});

 return $(this.findElements(element, options) || []).map( function(item){
 return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
});
},

 setSequence: function(element, new_sequence){
 element = $(element);
 var options = Object.extend(this.options(element), arguments[2] ||{});

 var nodeMap ={};
 this.findElements(element, options).each( function(n){
 if (n.id.match(options.format))
 nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
 n.parentNode.removeChild(n);
});

 new_sequence.each(function(ident){
 var n = nodeMap[ident];
 if (n){
 n[1].appendChild(n[0]);
 delete nodeMap[ident];
}
});
},

 serialize: function(element){
 element = $(element);
 var options = Object.extend(Sortable.options(element), arguments[1] ||{});
 var name = encodeURIComponent(
 (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);

 if (options.tree){
 return Sortable.tree(element, arguments[1]).children.map( function (item){
 return [name + Sortable._constructIndex(item) + "[id]=" +
 encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
}).flatten().join('&');
}else{
 return Sortable.sequence(element, arguments[1]).map( function(item){
 return name + "[]=" + encodeURIComponent(item);
}).join('&');
}
}
};

Element.isParent = function(child, element){
 if (!child.parentNode || child == element) return false;
 if (child.parentNode == element) return true;
 return Element.isParent(child.parentNode, element);
};

Element.findChildren = function(element, only, recursive, tagName){
 if(!element.hasChildNodes()) return null;
 tagName = tagName.toUpperCase();
 if(only) only = [only].flatten();
 var elements = [];
 $A(element.childNodes).each( function(e){
 if(e.tagName && e.tagName.toUpperCase()==tagName &&
 (!only || (Element.classNames(e).detect(function(v){return only.include(v)}))))
 elements.push(e);
 if(recursive){
 var grandchildren = Element.findChildren(e, only, recursive, tagName);
 if(grandchildren) elements.push(grandchildren);
}
});

 return (elements.length>0 ? elements.flatten() : []);
};

Element.offsetSize = function (element, type){
 return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
};
/* ######### json ######### */
/*
Copyright (c) 2005 JSON.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The Software shall be used for Good, not Evil.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

/*
 The global object JSON contains two methods.

 JSON.stringify(value) takes a JavaScript value and produces a JSON text.
 The value must not be cyclical.

 JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
 throw a 'JSONError' exception if there is an error.
*/
var JSON ={
 copyright: '(c)2005 JSON.org',
 license: 'http://www.crockford.com/JSON/license.html',
/*
 Stringify a JavaScript value, producing a JSON text.
*/
 stringify: function (v){
 var a = [];

/*
 Emit a string.
*/
 function e(s){
 a[a.length] = s;
}

/*
 Convert a value.
*/
 function g(x){
 var c, i, l, v;

 switch (typeof x){
 case 'object':
 if (x){
 if (x instanceof Array){
 e('[');
 l = a.length;
 for (i = 0; i < x.length; i += 1){
 v = x[i];
 if (typeof v != 'undefined' &&
 typeof v != 'function'){
 if (l < a.length){
 e(',');
}
 g(v);
}
}
 e(']');
 return;
}else if (typeof x.valueOf == 'function'){
 e('{');
 l = a.length;
 for (i in x){
 v = x[i];
 if (typeof v != 'undefined' &&
 typeof v != 'function' &&
 (!v || typeof v != 'object' ||
 typeof v.valueOf == 'function')){
 if (l < a.length){
 e(',');
}
 g(i);
 e(':');
 g(v);
}
}
 return e('}');
}
}
 e('null');
 return;
 case 'number':
 e(isFinite(x) ? +x : 'null');
 return;
 case 'string':
 l = x.length;
 e('"');
 for (i = 0; i < l; i += 1){
 c = x.charAt(i);
 if (c >= ' '){
 if (c == '\\' || c == '"'){
 e('\\');
}
 e(c);
}else{
 switch (c){
 case '\b':
 e('\\b');
 break;
 case '\f':
 e('\\f');
 break;
 case '\n':
 e('\\n');
 break;
 case '\r':
 e('\\r');
 break;
 case '\t':
 e('\\t');
 break;
 default:
 c = c.charCodeAt();
 e('\\u00' + Math.floor(c / 16).toString(16) +
 (c % 16).toString(16));
}
}
}
 e('"');
 return;
 case 'boolean':
 e(String(x));
 return;
 default:
 e('null');
 return;
}
}
 g(v);
 return a.join('');
},
/*
 Parse a JSON text, producing a JavaScript value.
*/
 parse: function (text){
 return (/^(\s+|[,:{}\[\]]|"(\\["\\\/bfnrtu]|[^\x00-\x1f"\\]+)*"|-?\d+(\.\d*)?([eE][+-]?\d+)?|true|false|null)+$/.test(text)) &&
 eval('(' + text + ')');
}
};
/* ######### eventmanager ######### */
/*
 unFocus.Utilities.EventManager, version 1.0b (beta) (2005/12/16)
 Copyright: 2005, Kevin Newman (http://www.unfocus.com/Projects/)
 License: http://creativecommons.org/licenses/LGPL/2.1/
*/

if (typeof unFocus == "undefined") var unFocus ={};
if (!unFocus.Utilities) unFocus.Utilities ={};

/* Class EventManager
 Provides the interface and functionality to a Subscriber/Subscriber Pattern interface for
 classes to easily inherit or use. Event types are passed in during instantiation. I'm not
 sure that's the best way to do it, but that's how it is for now (comments are welcome). */
unFocus.Utilities.EventManager = function(arg){
 this._listeners ={};
 for (var i = arguments.length; -1 < --i;){
 this._listeners[arguments[i]] = [];
}
};

/* Method: addEventListener
 A public method that adds an event listener to be called when the hash changes. */
unFocus.Utilities.EventManager.prototype.addEventListener = function($type, $listener){

 for (var i = this._listeners[$type].length; -1 < --i;)
 if (this._listeners[$type][i] == $listener) return;

 this._listeners[$type].push($listener);
};

/* Method: removeListener
 A public method that removes an event listener. */
unFocus.Utilities.EventManager.prototype.removeEventListener = function($type, $listener){

 for (var i = this._listeners[$type].length; -1 < --i;){
 if (this._listeners[$type][i] == $listener){
 this._listeners.splice(i,1);
 break;
}
}
};

/* Method: notifyListeners
 Notifies listeners when an event accurs. */
unFocus.Utilities.EventManager.prototype.notifyListeners = function($type, $data){
 for (var i = this._listeners[$type].length; -1 < --i;)
 this._listeners[$type][i]($data);
};/* ######### history ######### */
/*
unFocus.History, version 1.9 (alpha) (2006/04/14)
Copyright: 2005-2006, Kevin Newman (http://www.unfocus.com/Projects/HistoryKeeper/)
License: http://creativecommons.org/licenses/LGPL/2.1/
*/
if (typeof unFocus == "undefined") var unFocus ={};

/*
 Class: unFocus.History
 A singleton with subscriber interface (<unFocus.Utilities.EventManager>) 
 that keeps a history and provides deep links for Flash and AJAX apps
*/
unFocus.History = (function(){

function Keeper(){

 var _this = this,

 _pollInterval = 200, _intervalID,

 _currentHash = _getHash();

 /*
 method: _getHash
 A private method that gets the Hash from the location.hash property.
 
 returns:
 a string containing the current hash from the url
 */
 function _getHash(){
 return location.hash.substring(1);
}
 
 /*
 method: _setHash
 A private method that sets the Hash on the location string (the current url).
 */
 function _setHash($newHash){
 window.location.hash = $newHash;
}
 
 /*
 method: _watchHash
 A private method that is called every n miliseconds (<_pollInterval>) to check if the hash has changed.
 This is the primary Hash change detection method for most browsers. It doesn't work to detect the hash
 change in IE 5.5+ or various other browsers. Workarounds like the iframe method are used for those 
 browsers (IE 5.0 will use an anchor creation hack).
 */
 function _watchHash(){
 var $newHash = _getHash();
 if (_currentHash != $newHash){
 _currentHash = $newHash;
 _this.notifyListeners("historyChange", $newHash);
}
}

 if (setInterval) _intervalID = setInterval(_watchHash, _pollInterval);
 
 /*
 method: getCurrentBookmark
 A public method to retrieve the current history string
 
 returns:
 The current History Hash
 */
 _this.getCurrent = function(){
 return _currentHash;
};
 
 /* 
 Method: _createAnchor
 Various browsers may need an achor to be present in the dom for the hash to actually be set,
 so we add one every time a history entry is made.
 */
 function _createAnchor($newHash){
 if (!_checkAnchorExists($newHash)){
 var $anchor = document.createElement("a");
 $anchor.setAttribute("name", $newHash);
 if (/MSIE/.test(navigator.userAgent) && !window.opera)
 $anchor = document.createElement('<a name="'+$newHash+'">'+$newHash+"</a>");
 $anchor.style.position = "absolute";
 $anchor.style.top = getScrollY()+"px";
 $anchor.style.left = getScrollX()+"px";


 document.body.insertBefore($anchor,document.body.firstChild);
}
}
 function _checkAnchorExists($name){
 var $anchors = document.anchors;
 for (var i = 0; i < $anchors.length; i++)
 if ($anchors[i].name == $name)
 return true;
 return false;
}


 if (typeof self.pageYOffset == "number"){
 function getScrollY(){
 return self.pageYOffset;
}
}else if (document.documentElement && document.documentElement.scrollTop){
 function getScrollY(){
 return document.documentElement.scrollTop;
}
}else if (document.body){
 function getScrollY(){
 return document.body.scrollTop;
}
}

 eval(String(getScrollY).toString().replace(/Top/g,"Left").replace(/Y/g,"X"));

 _this.addHistory = function(){};

 /**
 * These are the platform specific interface methods. Since some platforms (most notably, IE 5.5+)
 * require almost completely different techniques to create history entries, browser detection is
 * used and the appropriate method is created. It would be nice to use object or feature detection
 * here, but these workarounds deal mostly with very specific bugs and other oddities in the 
 * various implementations. So browser sniffing it is.
 */

 if (navigator.appVersion.indexOf("Safari") != -1){
 var _windowHistoryLength = history.length,
 _historyArray = [],
 _recentlyAdded = false;

 _historyArray[_windowHistoryLength] = location.hash;
 
 _this.addHistory = function($newHash){// adds history and bookmark hash
 if (_currentHash != $newHash){
 _createAnchor($newHash);
 _currentHash = $newHash;
 _setHash($newHash); // :NOTE: this doesn't update history.length right away
 _windowHistoryLength = history.length+1;
 _historyArray[_windowHistoryLength] = $newHash;
 _recentlyAdded = true;
 _this.notifyListeners("historyChange",$newHash);
}
};
 
 var _watchHistoryLength = function(){
 if (!_recentlyAdded){// :NOTE: for some reason the first time this is called, it can't tell that anything has changed.
 var _historyLength = history.length;
 if (_historyLength != _windowHistoryLength){// && _historyArray[_historyLength]
 _windowHistoryLength = _historyLength;
 
 var $newHash = _historyArray[_windowHistoryLength];
 if (_currentHash != $newHash){
 _currentHash = $newHash;
 _this.notifyListeners("historyChange", $newHash);
}
}
}else _recentlyAdded = false;
};

 clearInterval(_intervalID);

 _intervalID = setInterval(_watchHistoryLength, _pollInterval);

}else if (typeof ActiveXObject != "undefined" && window.print && 
 !window.opera && navigator.userAgent.match(/MSIE (\d\.\d)/)[1] >= 5.5){
 /* iframe references */
 var _historyFrameObj, _historyFrameRef;
 
 /*
 method: _createHistoryFrame
 
 This is for IE only for now.
 */
 function _createHistoryFrame(){
 var $historyFrameName = "unFocusHistoryFrame";
 _historyFrameObj = document.createElement("iframe");
 _historyFrameObj.setAttribute("name", $historyFrameName);
 _historyFrameObj.setAttribute("id", $historyFrameName);
 _historyFrameObj.style.position = "absolute";
 _historyFrameObj.style.top = "-900px";
 document.body.insertBefore(_historyFrameObj,document.body.firstChild);



 _historyFrameRef = frames[$historyFrameName];

 _createHistoryHTML(_currentHash, true);
}
 
 /*
 method: _createHistoryHTML
 This is an alternative to <_setHistoryHTML> that is used by IE (and others if I can get it to work).
 This method will create the history page completely in memory, with no need to download a new file
 from the server.
 */
 function _createHistoryHTML($newHash){
 _historyFrameRef.document.open("text/html");
 _historyFrameRef.document.write("<html><head></head><body onl",
 'oad="parent.unFocus.History._updateFromHistory(\''+$newHash+'\');">',
 $newHash+"</body></html>");
 _historyFrameRef.document.close();
}
 
 /*
 method: _updateFromHistory
 A private method that is meant to be called only from HistoryFrame.html.
 It is not meant to be used by an end user even though it is accessable as public.
 */
 _this._updateFromHistory = function(){

 _this._updateFromHistory = function($hash){
 _currentHash = $hash;
 _this.notifyListeners("historyChange", $hash);
};
};

 _this.addHistory = function($newHash){

 _createHistoryFrame();

 _this.addHistory = function($newHash){// adds history and bookmark hash
 if (_currentHash != $newHash){


 _currentHash = $newHash;

 _createHistoryHTML($newHash);
}
};

 _this.addHistory($newHash);
};

 _this.addEventListener("historyChange", function($hash){_setHash($hash)});

 
}else /*if (!/Safari/.test(navigator.userAgent))*/{
 _this.addHistory = function($newHash){// adds history and bookmark hash

 _createAnchor(_currentHash);

 _this.addHistory = function($newHash){
 if (_currentHash != $newHash){
 _createAnchor($newHash);
 _currentHash = $newHash;
 _setHash($newHash);
 _this.notifyListeners("historyChange",$newHash);
}
};

 _this.addHistory($newHash);
};
}
}
Keeper.prototype = new unFocus.Utilities.EventManager("historyChange");

return new Keeper();

})();/* ######### swf_upload ######### */
/**
 * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com
 *
 * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/
 *
 * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilzén and Mammon Media and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */

var flashVersion = getFlashVersion(); //Lekérem a Flash lejátszó verziószámát


/**
 * 9-nél nagyobb flash verzó esetén az új lejátszó
 */
if( parseInt(flashVersion) > 8 ){

 /*******************
 * SWFUploader 2.2 *
 *******************/

/* ******************* */
/* Constructor & Init */
/* ******************* */
var SWFUpload;

if (SWFUpload == undefined){
 SWFUpload = function (settings){
 this.initSWFUpload(settings);
};
}

SWFUpload.prototype.initSWFUpload = function (settings){
 try{
 this.customSettings ={}; // A container where developers can place their own settings associated with this instance.
 this.settings = settings;
 this.eventQueue = [];
 this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
 this.movieElement = null;

 SWFUpload.instances[this.movieName] = this;

 this.initSettings();
 this.loadFlash();
 this.displayDebugInfo();
}catch (ex){
 delete SWFUpload.instances[this.movieName];
 throw ex;
}
};

/* *************** */
/* Static Members */
/* *************** */
SWFUpload.instances ={};
SWFUpload.movieCount = 0;
SWFUpload.version = "2.2.0 Beta 3";
SWFUpload.QUEUE_ERROR ={
 QUEUE_LIMIT_EXCEEDED : -100,
 FILE_EXCEEDS_SIZE_LIMIT : -110,
 ZERO_BYTE_FILE : -120,
 INVALID_FILETYPE : -130
};
SWFUpload.UPLOAD_ERROR ={
 HTTP_ERROR : -200,
 MISSING_UPLOAD_URL : -210,
 IO_ERROR : -220,
 SECURITY_ERROR : -230,
 UPLOAD_LIMIT_EXCEEDED : -240,
 UPLOAD_FAILED : -250,
 SPECIFIED_FILE_ID_NOT_FOUND : -260,
 FILE_VALIDATION_FAILED : -270,
 FILE_CANCELLED : -280,
 UPLOAD_STOPPED : -290
};
SWFUpload.FILE_STATUS ={
 QUEUED : -1,
 IN_PROGRESS : -2,
 ERROR : -3,
 COMPLETE : -4,
 CANCELLED : -5
};
SWFUpload.BUTTON_ACTION ={
 SELECT_FILE : -100,
 SELECT_FILES : -110,
 START_UPLOAD : -120
};
SWFUpload.CURSOR ={
 ARROW : -1,
 HAND : -2
};
SWFUpload.WINDOW_MODE ={
 WINDOW : "window",
 TRANSPARENT : "transparent",
 OPAQUE : "opaque"
};

/* ******************** */
/* Instance Members */
/* ******************** */


SWFUpload.prototype.initSettings = function (){
 this.ensureDefault = function (settingName, defaultValue){
 this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
};

 this.ensureDefault("upload_url", "");
 this.ensureDefault("file_post_name", "Filedata");
 this.ensureDefault("post_params",{});
 this.ensureDefault("use_query_string", false);
 this.ensureDefault("requeue_on_error", false);
 this.ensureDefault("http_success", []);

 this.ensureDefault("file_types", "*.*");
 this.ensureDefault("file_types_description", "All Files");
 this.ensureDefault("file_size_limit", 0); // Default zero means "unlimited"
 this.ensureDefault("file_upload_limit", 0);
 this.ensureDefault("file_queue_limit", 0);

 this.ensureDefault("flash_url", "/flash/swfupload2.swf");
 this.ensureDefault("prevent_swf_caching", true);

 this.ensureDefault("button_image_url", "");
 this.ensureDefault("button_width", 1);
 this.ensureDefault("button_height", 1);
 this.ensureDefault("button_text", "");
 this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;");
 this.ensureDefault("button_text_top_padding", 0);
 this.ensureDefault("button_text_left_padding", 0);
 this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES);
 this.ensureDefault("button_disabled", false);

 this.ensureDefault("button_placeholder_id", "swfbutton"); 
 this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW);
 this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW);

 this.ensureDefault("debug", false);
 this.settings.debug_enabled = this.settings.debug; // Here to maintain v2 API

 this.settings.return_upload_start_handler = this.returnUploadStart;
 this.ensureDefault("swfupload_loaded_handler", null);
 this.ensureDefault("file_dialog_start_handler", null);
 this.ensureDefault("file_queued_handler", null);
 this.ensureDefault("file_queue_error_handler", null);
 this.ensureDefault("file_dialog_complete_handler", null);

 this.ensureDefault("upload_start_handler", null);
 this.ensureDefault("upload_progress_handler", null);
 this.ensureDefault("upload_error_handler", null);
 this.ensureDefault("upload_success_handler", null);
 this.ensureDefault("upload_complete_handler", null);
 
 this.ensureDefault("debug_handler", this.debugMessage);

 this.ensureDefault("custom_settings",{});

 this.customSettings = this.settings.custom_settings;

 if (this.settings.prevent_swf_caching){
 this.settings.flash_url = this.settings.flash_url + "?swfuploadrnd=" + Math.floor(Math.random() * 999999999);
}
 
 delete this.ensureDefault;
};

SWFUpload.prototype.loadFlash = function (){
 if (this.settings.button_placeholder_id !== ""){
 this.replaceWithFlash();
}else{
 this.appendFlash();
}
};


SWFUpload.prototype.appendFlash = function (){
 var targetElement, container;

 if (document.getElementById(this.movieName) !== null){
 throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
}

 targetElement = document.getElementsByTagName("body")[0];

 if (targetElement == undefined){
 throw "Could not find the 'body' element.";
}

 container = document.createElement("div");
 container.style.width = "1px";
 container.style.height = "1px";
 container.style.overflow = "hidden";

 targetElement.appendChild(container);
 container.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)

 if (window[this.movieName] == undefined){
 window[this.movieName] = this.getMovieElement();
}
 
 
};

SWFUpload.prototype.replaceWithFlash = function (){
 var targetElement, tempParent;

 if (document.getElementById(this.movieName) !== null){
 throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
}

 targetElement = document.getElementById(this.settings.button_placeholder_id);

 if (targetElement == undefined){
 throw "Could not find the placeholder element.";
}

 tempParent = document.createElement("div");
 tempParent.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
 targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement);

 if (window[this.movieName] == undefined){
 window[this.movieName] = this.getMovieElement();
}
 
};

SWFUpload.prototype.getFlashHTML = function (){

 return ['<object id="', this.movieName, '" type="application/x-shockwave-flash" data="', this.settings.flash_url, '" width="', this.settings.button_width, '" height="', this.settings.button_height, '" class="swfupload">',
 '<param name="wmode" value="', this.settings.button_window_mode , '" />',
 '<param name="movie" value="', this.settings.flash_url, '" />',
 '<param name="quality" value="high" />',
 '<param name="menu" value="false" />',
 '<param name="allowScriptAccess" value="always" />',
 '<param name="flashvars" value="' + this.getFlashVars() + '" />',
 '</object>'].join("");
};


SWFUpload.prototype.getFlashVars = function (){

 var paramString = this.buildParamString();
 var httpSuccessString = this.settings.http_success.join(",");

 return ["movieName=", encodeURIComponent(this.movieName),
 "&amp;uploadURL=", encodeURIComponent(this.settings.upload_url),
 "&amp;useQueryString=", encodeURIComponent(this.settings.use_query_string),
 "&amp;requeueOnError=", encodeURIComponent(this.settings.requeue_on_error),
 "&amp;httpSuccess=", encodeURIComponent(httpSuccessString),
 "&amp;params=", encodeURIComponent(paramString),
 "&amp;filePostName=", encodeURIComponent(this.settings.file_post_name),
 "&amp;fileTypes=", encodeURIComponent(this.settings.file_types),
 "&amp;fileTypesDescription=", encodeURIComponent(this.settings.file_types_description),
 "&amp;fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit),
 "&amp;fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit),
 "&amp;fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit),
 "&amp;debugEnabled=", encodeURIComponent(this.settings.debug_enabled),
 "&amp;buttonImageURL=", encodeURIComponent(this.settings.button_image_url),
 "&amp;buttonWidth=", encodeURIComponent(this.settings.button_width),
 "&amp;buttonHeight=", encodeURIComponent(this.settings.button_height),
 "&amp;buttonText=", encodeURIComponent(this.settings.button_text),
 "&amp;buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding),
 "&amp;buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding),
 "&amp;buttonTextStyle=", encodeURIComponent(this.settings.button_text_style),
 "&amp;buttonAction=", encodeURIComponent(this.settings.button_action),
 "&amp;buttonDisabled=", encodeURIComponent(this.settings.button_disabled),
 "&amp;buttonCursor=", encodeURIComponent(this.settings.button_cursor)
 ].join("");
};


SWFUpload.prototype.getMovieElement = function (){
 if (this.movieElement == undefined){
 this.movieElement = document.getElementById(this.movieName);
}

 if (this.movieElement === null){
 throw "Could not find Flash element";
}
 
 return this.movieElement;
};


SWFUpload.prototype.buildParamString = function (){
 var postParams = this.settings.post_params; 
 var paramStringPairs = [];

 if (typeof(postParams) === "object"){
 for (var name in postParams){
 if (postParams.hasOwnProperty(name)){
 paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString()));
}
}
}

 return paramStringPairs.join("&amp;");
};




SWFUpload.prototype.destroy = function (){
 try{

 this.cancelUpload(null, false);

 var movieElement = null;
 movieElement = this.getMovieElement();
 
 if (movieElement){

 for (var i in movieElement){
 try{
 if (typeof(movieElement[i]) === "function"){
 movieElement[i] = null;
}
}catch (ex1){}
}

 try{
 movieElement.parentNode.removeChild(movieElement);
}catch (ex){}
}

 window[this.movieName] = null;

 SWFUpload.instances[this.movieName] = null;
 delete SWFUpload.instances[this.movieName];

 this.movieElement = null;
 this.settings = null;
 this.customSettings = null;
 this.eventQueue = null;
 this.movieName = null;
 
 
 return true;
}catch (ex1){
 return false;
}
};




SWFUpload.prototype.displayDebugInfo = function (){
 this.debug(
 [
 "---SWFUpload Instance Info---\n",
 "Version: ", SWFUpload.version, "\n",
 "Movie Name: ", this.movieName, "\n",
 "Settings:\n",
 "\t", "upload_url: ", this.settings.upload_url, "\n",
 "\t", "flash_url: ", this.settings.flash_url, "\n",
 "\t", "use_query_string: ", this.settings.use_query_string.toString(), "\n",
 "\t", "requeue_on_error: ", this.settings.requeue_on_error.toString(), "\n",
 "\t", "http_success: ", this.settings.http_success.join(", "), "\n",
 "\t", "file_post_name: ", this.settings.file_post_name, "\n",
 "\t", "post_params: ", this.settings.post_params.toString(), "\n",
 "\t", "file_types: ", this.settings.file_types, "\n",
 "\t", "file_types_description: ", this.settings.file_types_description, "\n",
 "\t", "file_size_limit: ", this.settings.file_size_limit, "\n",
 "\t", "file_upload_limit: ", this.settings.file_upload_limit, "\n",
 "\t", "file_queue_limit: ", this.settings.file_queue_limit, "\n",
 "\t", "debug: ", this.settings.debug.toString(), "\n",

 "\t", "prevent_swf_caching: ", this.settings.prevent_swf_caching.toString(), "\n",

 "\t", "button_placeholder_id: ", this.settings.button_placeholder_id.toString(), "\n",
 "\t", "button_image_url: ", this.settings.button_image_url.toString(), "\n",
 "\t", "button_width: ", this.settings.button_width.toString(), "\n",
 "\t", "button_height: ", this.settings.button_height.toString(), "\n",
 "\t", "button_text: ", this.settings.button_text.toString(), "\n",
 "\t", "button_text_style: ", this.settings.button_text_style.toString(), "\n",
 "\t", "button_text_top_padding: ", this.settings.button_text_top_padding.toString(), "\n",
 "\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n",
 "\t", "button_action: ", this.settings.button_action.toString(), "\n",
 "\t", "button_disabled: ", this.settings.button_disabled.toString(), "\n",

 "\t", "custom_settings: ", this.settings.custom_settings.toString(), "\n",
 "Event Handlers:\n",
 "\t", "swfupload_loaded_handler assigned: ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n",
 "\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n",
 "\t", "file_queued_handler assigned: ", (typeof this.settings.file_queued_handler === "function").toString(), "\n",
 "\t", "file_queue_error_handler assigned: ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n",
 "\t", "upload_start_handler assigned: ", (typeof this.settings.upload_start_handler === "function").toString(), "\n",
 "\t", "upload_progress_handler assigned: ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n",
 "\t", "upload_error_handler assigned: ", (typeof this.settings.upload_error_handler === "function").toString(), "\n",
 "\t", "upload_success_handler assigned: ", (typeof this.settings.upload_success_handler === "function").toString(), "\n",
 "\t", "upload_complete_handler assigned: ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n",
 "\t", "debug_handler assigned: ", (typeof this.settings.debug_handler === "function").toString(), "\n"
 ].join("")
 );
};

/* Note: addSetting and getSetting are no longer used by SWFUpload but are included
 the maintain v2 API compatibility
*/

SWFUpload.prototype.addSetting = function (name, value, default_value){
 if (value == undefined){
 return (this.settings[name] = default_value);
}else{
 return (this.settings[name] = value);
}
};

SWFUpload.prototype.getSetting = function (name){
 if (this.settings[name] != undefined){
 return this.settings[name];
}

 return "";
};



SWFUpload.prototype.callFlash = function (functionName, argumentArray){
 argumentArray = argumentArray || [];
 
 var movieElement = this.getMovieElement();
 var returnValue, returnString;

 try{
 returnString = movieElement.CallFunction('<invoke name="' + functionName + '" returntype="javascript">' + __flash__argumentsToXML(argumentArray, 0) + '</invoke>');
 returnValue = eval(returnString);
}catch (ex){
 throw "Call to " + functionName + " failed";
}

 if (returnValue != undefined && typeof returnValue.post === "object"){
 returnValue = this.unescapeFilePostParams(returnValue);
}

 return returnValue;
};


/* *****************************
 -- Flash control methods --
 Your UI should use these
 to operate SWFUpload
 ***************************** */



SWFUpload.prototype.selectFile = function (){
 this.callFlash("SelectFile");
};






SWFUpload.prototype.selectFiles = function (){
 this.callFlash("SelectFiles");
};


SWFUpload.prototype.startUpload = function (fileID){
 this.callFlash("StartUpload", [fileID]);
};



SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent){
 if (triggerErrorEvent !== false){
 triggerErrorEvent = true;
}
 this.callFlash("CancelUpload", [fileID, triggerErrorEvent]);
};


SWFUpload.prototype.stopUpload = function (){
 this.callFlash("StopUpload");
};


 SWFUpload.prototype.cancelQueue = function (){
 this.customSettings.queue_cancelled_flag = true;
 this.stopUpload();
 
 var stats = this.getStats();
 while (stats.files_queued > 0){
 this.cancelUpload();
 stats = this.getStats();
}
};

/* ************************
 * Settings methods
 * These methods change the SWFUpload settings.
 * SWFUpload settings should not be changed directly on the settings object
 * since many of the settings need to be passed to Flash in order to take
 * effect.
 * *********************** */

SWFUpload.prototype.getStats = function (){
 return this.callFlash("GetStats");
};




SWFUpload.prototype.setStats = function (statsObject){
 this.callFlash("SetStats", [statsObject]);
};


SWFUpload.prototype.getFile = function (fileID){
 if (typeof(fileID) === "number"){
 return this.callFlash("GetFileByIndex", [fileID]);
}else{
 return this.callFlash("GetFile", [fileID]);
}
};



SWFUpload.prototype.addFileParam = function (fileID, name, value){
 return this.callFlash("AddFileParam", [fileID, name, value]);
};


SWFUpload.prototype.removeFileParam = function (fileID, name){
 this.callFlash("RemoveFileParam", [fileID, name]);
};

SWFUpload.prototype.setUploadURL = function (url){
 this.settings.upload_url = url.toString();
 this.callFlash("SetUploadURL", [url]);
};

SWFUpload.prototype.setPostParams = function (paramsObject){
 this.settings.post_params = paramsObject;
 this.callFlash("SetPostParams", [paramsObject]);
};

SWFUpload.prototype.addPostParam = function (name, value){
 this.settings.post_params[name] = value;
 this.callFlash("SetPostParams", [this.settings.post_params]);
};

SWFUpload.prototype.removePostParam = function (name){
 delete this.settings.post_params[name];
 this.callFlash("SetPostParams", [this.settings.post_params]);
};

SWFUpload.prototype.setFileTypes = function (types, description){
 this.settings.file_types = types;
 this.settings.file_types_description = description;
 this.callFlash("SetFileTypes", [types, description]);
};

SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit){
 this.settings.file_size_limit = fileSizeLimit;
 this.callFlash("SetFileSizeLimit", [fileSizeLimit]);
};

SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit){
 this.settings.file_upload_limit = fileUploadLimit;
 this.callFlash("SetFileUploadLimit", [fileUploadLimit]);
};

SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit){
 this.settings.file_queue_limit = fileQueueLimit;
 this.callFlash("SetFileQueueLimit", [fileQueueLimit]);
};

SWFUpload.prototype.setFilePostName = function (filePostName){
 this.settings.file_post_name = filePostName;
 this.callFlash("SetFilePostName", [filePostName]);
};

SWFUpload.prototype.setUseQueryString = function (useQueryString){
 this.settings.use_query_string = useQueryString;
 this.callFlash("SetUseQueryString", [useQueryString]);
};

SWFUpload.prototype.setRequeueOnError = function (requeueOnError){
 this.settings.requeue_on_error = requeueOnError;
 this.callFlash("SetRequeueOnError", [requeueOnError]);
};

SWFUpload.prototype.setHTTPSuccess = function (http_status_codes){
 if (typeof http_status_codes === "string"){
 http_status_codes = http_status_codes.replace(" ", "").split(",");
}
 
 this.settings.http_success = http_status_codes;
 this.callFlash("SetHTTPSuccess", [http_status_codes]);
};

SWFUpload.prototype.setDebugEnabled = function (debugEnabled){
 this.settings.debug_enabled = debugEnabled;
 this.callFlash("SetDebugEnabled", [debugEnabled]);
};

SWFUpload.prototype.setButtonImageURL = function (buttonImageURL){
 if (buttonImageURL == undefined){
 buttonImageURL = "";
}
 
 this.settings.button_image_url = buttonImageURL;
 this.callFlash("SetButtonImageURL", [buttonImageURL]);
};

SWFUpload.prototype.setButtonDimensions = function (width, height){
 this.settings.button_width = width;
 this.settings.button_height = height;
 
 var movie = this.getMovieElement();
 if (movie != undefined){
 movie.style.width = width + "px";
 movie.style.height = height + "px";
}
 
 this.callFlash("SetButtonDimensions", [width, height]);
};

SWFUpload.prototype.setButtonText = function (html){
 this.settings.button_text = html;
 this.callFlash("SetButtonText", [html]);
};

SWFUpload.prototype.setButtonTextPadding = function (left, top){
 this.settings.button_text_top_padding = top;
 this.settings.button_text_left_padding = left;
 this.callFlash("SetButtonTextPadding", [left, top]);
};

SWFUpload.prototype.setButtonTextStyle = function (css){
 this.settings.button_text_style = css;
 this.callFlash("SetButtonTextStyle", [css]);
};

SWFUpload.prototype.setButtonDisabled = function (isDisabled){
 this.settings.button_disabled = isDisabled;
 this.callFlash("SetButtonDisabled", [isDisabled]);
};

SWFUpload.prototype.setButtonAction = function (buttonAction){
 this.settings.button_action = buttonAction;
 this.callFlash("SetButtonAction", [buttonAction]);
};

SWFUpload.prototype.setButtonCursor = function (cursor){
 this.settings.button_cursor = cursor;
 this.callFlash("SetButtonCursor", [cursor]);
};

/* *******************************
 Flash Event Interfaces
 These functions are used by Flash to trigger the various
 events.
 
 All these functions a Private.
 
 Because the ExternalInterface library is buggy the event calls
 are added to a queue and the queue then executed by a setTimeout.
 This ensures that events are executed in a determinate order and that
 the ExternalInterface bugs are avoided.
******************************* */

SWFUpload.prototype.queueEvent = function (handlerName, argumentArray){

 
 if (argumentArray == undefined){
 argumentArray = [];
}else if (!(argumentArray instanceof Array)){
 argumentArray = [argumentArray];
}
 
 var self = this;
 if (typeof this.settings[handlerName] === "function"){

 this.eventQueue.push(function (){
 this.settings[handlerName].apply(this, argumentArray);
});

 setTimeout(function (){
 self.executeNextEvent();
}, 0);
 
}else if (this.settings[handlerName] !== null){
 throw "Event handler " + handlerName + " is unknown or is not a function";
}
};


SWFUpload.prototype.executeNextEvent = function (){


 var f = this.eventQueue ? this.eventQueue.shift() : null;
 if (typeof(f) === "function"){
 f.apply(this);
}
};



SWFUpload.prototype.unescapeFilePostParams = function (file){
 var reg = /[$]([0-9a-f]{4})/i;
 var unescapedPost ={};
 var uk;

 if (file != undefined){
 for (var k in file.post){
 if (file.post.hasOwnProperty(k)){
 uk = k;
 var match;
 while ((match = reg.exec(uk)) !== null){
 uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16)));
}
 unescapedPost[uk] = file.post[k];
}
}

 file.post = unescapedPost;
}

 return file;
};

SWFUpload.prototype.flashReady = function (){

 var movieElement = this.getMovieElement();

 if (typeof(movieElement.CallFunction) === "unknown"){// We only want to do this in IE
 this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)");
 for (var key in movieElement){
 try{
 if (typeof(movieElement[key]) === "function"){
 movieElement[key] = null;
}
}catch (ex){
}
}
}
 
 this.queueEvent("swfupload_loaded_handler");
};


/* This is a chance to do something before the browse window opens */
SWFUpload.prototype.fileDialogStart = function (){
 this.queueEvent("file_dialog_start_handler");
};


/* Called when a file is successfully added to the queue. */
SWFUpload.prototype.fileQueued = function (file){
 file = this.unescapeFilePostParams(file);
 this.queueEvent("file_queued_handler", file);
};


/* Handle errors that occur when an attempt to queue a file fails. */
SWFUpload.prototype.fileQueueError = function (file, errorCode, message){
 file = this.unescapeFilePostParams(file);
 this.queueEvent("file_queue_error_handler", [file, errorCode, message]);
};

/* Called after the file dialog has closed and the selected files have been queued.
 You could call startUpload here if you want the queued files to begin uploading immediately. */
SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued){
 this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued]);
};

SWFUpload.prototype.uploadStart = function (file){
 file = this.unescapeFilePostParams(file);
 this.queueEvent("return_upload_start_handler", file);
};

SWFUpload.prototype.returnUploadStart = function (file){
 var returnValue;
 if (typeof this.settings.upload_start_handler === "function"){
 file = this.unescapeFilePostParams(file);
 returnValue = this.settings.upload_start_handler.call(this, file);
}else if (this.settings.upload_start_handler != undefined){
 throw "upload_start_handler must be a function";
}


 if (returnValue === undefined){
 returnValue = true;
}
 
 returnValue = !!returnValue;
 
 this.callFlash("ReturnUploadStart", [returnValue]);
};



SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal){
 file = this.unescapeFilePostParams(file);
 this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]);
};

SWFUpload.prototype.uploadError = function (file, errorCode, message){
 file = this.unescapeFilePostParams(file);
 this.queueEvent("upload_error_handler", [file, errorCode, message]);
};

SWFUpload.prototype.uploadSuccess = function (file, serverData){
 file = this.unescapeFilePostParams(file);
 this.queueEvent("upload_success_handler", [file, serverData]);
};

SWFUpload.prototype.uploadComplete = function (file){
 file = this.unescapeFilePostParams(file);
 this.queueEvent("upload_complete_handler", file);
};

/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
 internal debug console. You can override this event and have messages written where you want. */
SWFUpload.prototype.debug = function (message){
 this.queueEvent("debug_handler", message);
};


/* **********************************
 Debug Console
 The debug console is a self contained, in page location
 for debug message to be sent. The Debug Console adds
 itself to the body if necessary.

 The console is automatically scrolled as messages appear.
 
 If you are using your own debug handler or when you deploy to production and
 have debug disabled you can remove these functions to reduce the file size
 and complexity.
********************************** */



SWFUpload.prototype.debugMessage = function (message){
 if (this.settings.debug){
 var exceptionMessage, exceptionValues = [];

 if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string"){
 for (var key in message){
 if (message.hasOwnProperty(key)){
 exceptionValues.push(key + ": " + message[key]);
}
}
 exceptionMessage = exceptionValues.join("\n") || "";
 exceptionValues = exceptionMessage.split("\n");
 exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: ");
 SWFUpload.Console.writeLine(exceptionMessage);
}else{
 SWFUpload.Console.writeLine(message);
}
}
};

SWFUpload.Console ={};
SWFUpload.Console.writeLine = function (message){
 var console, documentForm;

 try{
 console = document.getElementById("SWFUpload_Console");

 if (!console){
 documentForm = document.createElement("form");
 document.getElementsByTagName("body")[0].appendChild(documentForm);

 console = document.createElement("textarea");
 console.id = "SWFUpload_Console";
 console.style.fontFamily = "monospace";
 console.setAttribute("wrap", "off");
 console.wrap = "off";
 console.style.overflow = "auto";
 console.style.width = "700px";
 console.style.height = "350px";
 console.style.margin = "5px";
 documentForm.appendChild(console);
}

 console.value += message + "\n";

 console.scrollTop = console.scrollHeight - console.clientHeight;
}catch (ex){
 alert("Exception: " + ex.name + " Message: " + ex.message);
}
};

}// endif SWFUploader 2.2

else{//Ez pedig a régi
 /***************
 * SWFUploader *
 ***************/

var SWFUpload = function (init_settings){


 try{
 document.execCommand('BackgroundImageCache', false, true);
}catch (ex1){
}


 try{
 this.customSettings ={}; // A container where developers can place their own settings associated with this instance.
 this.settings ={};
 this.eventQueue = [];
 this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
 this.movieElement = null;

 SWFUpload.instances[this.movieName] = this;

 this.initSettings(init_settings);
 this.loadFlash();

 this.displayDebugInfo();

}catch (ex2){
 this.debug(ex2);
}
};

/* *************** */
/* Static thingies */
/* *************** */
SWFUpload.instances ={};
SWFUpload.movieCount = 0;
SWFUpload.QUEUE_ERROR ={
 QUEUE_LIMIT_EXCEEDED : -100,
 FILE_EXCEEDS_SIZE_LIMIT : -110,
 ZERO_BYTE_FILE : -120,
 INVALID_FILETYPE : -130
};
SWFUpload.UPLOAD_ERROR ={
 HTTP_ERROR : -200,
 MISSING_UPLOAD_URL : -210,
 IO_ERROR : -220,
 SECURITY_ERROR : -230,
 UPLOAD_LIMIT_EXCEEDED : -240,
 UPLOAD_FAILED : -250,
 SPECIFIED_FILE_ID_NOT_FOUND : -260,
 FILE_VALIDATION_FAILED : -270,
 FILE_CANCELLED : -280,
 UPLOAD_STOPPED : -290
};
SWFUpload.FILE_STATUS ={
 QUEUED : -1,
 IN_PROGRESS : -2,
 ERROR : -3,
 COMPLETE : -4,
 CANCELLED : -5
};


/* ***************** */
/* Instance Thingies */
/* ***************** */


SWFUpload.prototype.initSettings = function (init_settings){

 this.addSetting("upload_url", init_settings.upload_url, "");
 this.addSetting("hidden_id", init_settings.hidden_id, "");
 this.addSetting("file_post_name", init_settings.file_post_name, "Filedata");
 this.addSetting("post_params", init_settings.post_params,{});

 this.addSetting("file_types", init_settings.file_types, "*.gif;*.jpg;*.png;*.zip");
 this.addSetting("file_types_description", init_settings.file_types_description, "Common Web Image Formats (gif, jpg, png)");
 this.addSetting("file_size_limit", init_settings.file_size_limit, "0");
 this.addSetting("file_upload_limit", init_settings.file_upload_limit, "0");
 this.addSetting("file_queue_limit", init_settings.file_queue_limit, "0");

 this.addSetting("flash_url", init_settings.flash_url, "/flash/swfupload.swf");
 this.addSetting("flash_width", init_settings.flash_width, "1px");
 this.addSetting("flash_height", init_settings.flash_height, "1px");
 this.addSetting("flash_color", init_settings.flash_color, "#FFFFFF");

 this.addSetting("debug_enabled", init_settings.debug, false);
 this.debug_enabled = this.getSetting("debug_enabled");

 this.flashReady_handler = SWFUpload.flashReady; // This is a non-overrideable event handler
 this.swfUploadLoaded_handler = this.retrieveSetting(init_settings.swfupload_loaded_handler, SWFUpload.swfUploadLoaded);
 
 this.fileDialogStart_handler = this.retrieveSetting(init_settings.file_dialog_start_handler, SWFUpload.fileDialogStart);
 this.fileQueued_handler = this.retrieveSetting(init_settings.file_queued_handler, SWFUpload.fileQueued);
 this.fileQueueError_handler = this.retrieveSetting(init_settings.file_queue_error_handler, SWFUpload.fileQueueError);
 this.fileDialogComplete_handler = this.retrieveSetting(init_settings.file_dialog_complete_handler, SWFUpload.fileDialogComplete);
 
 this.uploadStart_handler = this.retrieveSetting(init_settings.upload_start_handler, SWFUpload.uploadStart);
 this.uploadProgress_handler = this.retrieveSetting(init_settings.upload_progress_handler, SWFUpload.uploadProgress);
 this.uploadError_handler = this.retrieveSetting(init_settings.upload_error_handler, SWFUpload.uploadError);
 this.uploadComplete_handler = this.retrieveSetting(init_settings.upload_complete_handler, SWFUpload.uploadComplete);
 this.fileComplete_handler = this.retrieveSetting(init_settings.file_complete_handler, SWFUpload.fileComplete);

 this.debug_handler = this.retrieveSetting(init_settings.debug_handler, SWFUpload.debug);


 this.addSetting("ui_container_id", init_settings.ui_container_id, "");
 this.addSetting("degraded_container_id", init_settings.degraded_container_id, "");

 
};



SWFUpload.prototype.loadFlash = function (){
 var html, target_element, container;

 if (document.getElementById(this.movieName) !== null){
 return false;
}

 try{
 target_element = document.getElementsByTagName("body")[0];
 if (typeof(target_element) === "undefined" || target_element === null){
 this.debug('Could not find an element to add the Flash too. Failed to find element for "flash_container_id" or the BODY element.');
 return false;
}
}catch (ex){
 return false;
}

 container = document.createElement("div");
 container.style.width = this.getSetting("flash_width");
 container.style.height = this.getSetting("flash_height");

 target_element.appendChild(container);
 container.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
};

SWFUpload.prototype.getFlashHTML = function (){
 var html = "";

 if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length){

 html = '<embed type="application/x-shockwave-flash" src="' + this.getSetting("flash_url") + '" width="' + this.getSetting("flash_width") + '" height="' + this.getSetting("flash_height") + '"';
 html += ' id="' + this.movieName + '" name="' + this.movieName + '" ';
 html += 'bgcolor="' + this.getSetting("flash_color") + '" quality="high" menu="false" flashvars="';

 html += this.getFlashVars();

 html += '" />';

}else{

 html = '<object id="' + this.movieName + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + this.getSetting("flash_width") + '" height="' + this.getSetting("flash_height") + '">';
 html += '<param name="movie" value="' + this.getSetting("flash_url") + '">';

 html += '<param name="bgcolor" value="' + this.getSetting("flash_color") + '" />';
 html += '<param name="quality" value="high" />';
 html += '<param name="menu" value="false" />';

 html += '<param name="flashvars" value="' + this.getFlashVars() + '" />';
 html += 'A tartalom megtekintéséhez flashplayer szükséges / Nem elérhető a tartalom';
 html += '</object>';

}
 
 if ((navigator.appName == "Microsoft Internet Explorer" &&
 navigator.appVersion.indexOf("Mac") == -1 && navigator.appVersion.indexOf("3.1") == -1) ||
 (navigator.plugins && navigator.plugins["Shockwave Flash"])
 || navigator.plugins["Shockwave Flash 2.0"]){

 return html;
}else{

 return 'Kérjük telepitsen flash playert';
}

};


SWFUpload.prototype.getFlashVars = function (){

 var param_string = this.buildParamString();

 var html = "";
 html += "movieName=" + encodeURIComponent(this.movieName);
 html += "&uploadURL=" + encodeURIComponent(this.getSetting("upload_url"));
 html += "&params=" + encodeURIComponent(param_string);
 html += "&filePostName=" + encodeURIComponent(this.getSetting("file_post_name"));
 html += "&fileTypes=" + encodeURIComponent(this.getSetting("file_types"));
 html += "&fileTypesDescription=" + encodeURIComponent(this.getSetting("file_types_description"));
 html += "&fileSizeLimit=" + encodeURIComponent(this.getSetting("file_size_limit"));
 html += "&fileUploadLimit=" + encodeURIComponent(this.getSetting("file_upload_limit"));
 html += "&fileQueueLimit=" + encodeURIComponent(this.getSetting("file_queue_limit"));
 html += "&debugEnabled=" + encodeURIComponent(this.getSetting("debug_enabled"));

 return html;
};

SWFUpload.prototype.getMovieElement = function (){
 if (typeof(this.movieElement) === "undefined" || this.movieElement === null){
 this.movieElement = document.getElementById(this.movieName);







}

 return this.movieElement;
};

SWFUpload.prototype.buildParamString = function (){
 var post_params = this.getSetting("post_params");
 var param_string_pairs = [];
 var i, value, name;

 if (typeof(post_params) === "object"){
 for (name in post_params){
 if (post_params.hasOwnProperty(name)){
 if (typeof(post_params[name]) === "string"){
 param_string_pairs.push(encodeURIComponent(name) + "=" + encodeURIComponent(post_params[name]));
}
}
}
}

 return param_string_pairs.join("&");
};

SWFUpload.prototype.addSetting = function (name, value, default_value){
 if (typeof(value) === "undefined" || value === null){
 this.settings[name] = default_value;
}else{
 this.settings[name] = value;
}

 return this.settings[name];
};

SWFUpload.prototype.getSetting = function (name){
 if (typeof(this.settings[name]) === "undefined"){
 return "";
}else{
 return this.settings[name];
}
};


SWFUpload.prototype.retrieveSetting = function (value, default_value){
 if (typeof(value) === "undefined" || value === null){
 return default_value;
}else{
 return value;
}
};


SWFUpload.prototype.displayDebugInfo = function (){
 var key, debug_message = "";

 debug_message += "----- SWFUPLOAD SETTINGS ----\nID: " + this.getMovieElement().id + "\n";

 debug_message += this.outputObject(this.settings);

 debug_message += "----- SWFUPLOAD SETTINGS END ----\n";
 debug_message += "\n";

 this.debug(debug_message);
};
SWFUpload.prototype.outputObject = function (object, prefix){
 var output = "", key;

 if (typeof(prefix) !== "string"){
 prefix = "";
}
 if (typeof(object) !== "object"){
 return "";
}

 for (key in object){
 if (object.hasOwnProperty(key)){
 if (typeof(object[key]) === "object"){
 output += (prefix + key + ":{\n" + this.outputObject(object[key], "\t" + prefix) + prefix + "}" + "\n");
}else{
 output += (prefix + key + ": " + object[key] + "\n");
}
}
}

 return output;
};

/* *****************************
 -- Flash control methods --
 Your UI should use these
 to operate SWFUpload
 ***************************** */

SWFUpload.prototype.selectFile = function (){
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.SelectFile) === "function"){
 try{
 movie_element.SelectFile();
}
 catch (ex){
 this.debug("Could not call SelectFile: " + ex);
}
}else{
 this.debug("Could not find Flash element");
}

};

SWFUpload.prototype.selectFiles = function (){
 var p={};
 miracle.ajax("miracle", "initialize_upload", p, function(dummy){}.bind(this));
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.SelectFiles) === "function"){
 try{
 movie_element.SelectFiles();
}
 catch (ex){
 this.debug("Could not call SelectFiles: " + ex);
}
}else{
 this.debug("Could not find Flash element");
}

};


/* Start the upload. If a file_id is specified that file is uploaded. Otherwise the first
 * file in the queue is uploaded. If no files are in the queue then nothing happens.
 * This call uses setTimeout since Flash will be calling back in to JavaScript
 */
SWFUpload.prototype.startUpload = function (file_id){
 var self = this;
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.StartUpload) === "function"){
 setTimeout(
 function (){
 try{
 movie_element.StartUpload(file_id);
}
 catch (ex){
 self.debug("Could not call StartUpload: " + ex);
}
}, 0
 );
}else{
 this.debug("Could not find Flash element");
}

};

/* Cancels a the file upload. You must specify a file_id */
SWFUpload.prototype.cancelUpload = function (file_id){
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.CancelUpload) === "function"){
 try{
 movie_element.CancelUpload(file_id);
}
 catch (ex){
 this.debug("Could not call CancelUpload: " + ex);
}
}else{
 this.debug("Could not find Flash element");
}

};

SWFUpload.prototype.stopUpload = function (){
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.StopUpload) === "function"){
 try{
 movie_element.StopUpload();
}
 catch (ex){
 this.debug("Could not call StopUpload: " + ex);
}
}else{
 this.debug("Could not find Flash element");
}

};

/* ************************
 * Settings methods
 * These methods change the settings inside SWFUpload
 * They shouldn't need to be called in a setTimeout since they
 * should not call back from Flash to JavaScript (except perhaps in a Debug call)
 * and some need to return data so setTimeout won't work.
 */

/* Gets the file statistics object. It looks like this (where n = number):
{
 files_queued: n,
 complete_uploads: n,
 upload_errors: n,
 uploads_cancelled: n,
 queue_errors: n
}
*/
SWFUpload.prototype.getStats = function (){
 var self = this;
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.GetStats) === "function"){
 try{
 return movie_element.GetStats();
}
 catch (ex){
 self.debug("Could not call GetStats");
}
}else{
 this.debug("Could not find Flash element");
}
};

SWFUpload.prototype.addFileParam = function (file_id, name, value){
 var self = this;
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.AddFileParam) === "function"){
 try{
 return movie_element.AddFileParam(file_id, name, value);
}
 catch (ex){
 self.debug("Could not call AddFileParam");
}
}else{
 this.debug("Could not find Flash element");
}
};

SWFUpload.prototype.removeFileParam = function (file_id, name){
 var self = this;
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.RemoveFileParam) === "function"){
 try{
 return movie_element.RemoveFileParam(file_id, name);
}
 catch (ex){
 self.debug("Could not call AddFileParam");
}
}else{
 this.debug("Could not find Flash element");
}

};

SWFUpload.prototype.setUploadURL = function (url){
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.SetUploadURL) === "function"){
 try{
 this.addSetting("upload_url", url);
 movie_element.SetUploadURL(this.getSetting("upload_url"));
}
 catch (ex){
 this.debug("Could not call SetUploadURL");
}
}else{
 this.debug("Could not find Flash element in setUploadURL");
}
};

SWFUpload.prototype.setPostParams = function (param_object){
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.SetPostParams) === "function"){
 try{
 this.addSetting("post_params", param_object);
 movie_element.SetPostParams(this.getSetting("post_params"));
}
 catch (ex){
 this.debug("Could not call SetPostParams");
}
}else{
 this.debug("Could not find Flash element in SetPostParams");
}
};

SWFUpload.prototype.setFileTypes = function (types, description){
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.SetFileTypes) === "function"){
 try{
 this.addSetting("file_types", types);
 this.addSetting("file_types_description", description);
 movie_element.SetFileTypes(this.getSetting("file_types"), this.getSetting("file_types_description"));
}
 catch (ex){
 this.debug("Could not call SetFileTypes");
}
}else{
 this.debug("Could not find Flash element in SetFileTypes");
}
};

SWFUpload.prototype.setFileSizeLimit = function (file_size_limit){
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.SetFileSizeLimit) === "function"){
 try{
 this.addSetting("file_size_limit", file_size_limit);
 movie_element.SetFileSizeLimit(this.getSetting("file_size_limit"));
}
 catch (ex){
 this.debug("Could not call SetFileSizeLimit");
}
}else{
 this.debug("Could not find Flash element in SetFileSizeLimit");
}
};

SWFUpload.prototype.setFileUploadLimit = function (file_upload_limit){
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.SetFileUploadLimit) === "function"){
 try{
 this.addSetting("file_upload_limit", file_upload_limit);
 movie_element.SetFileUploadLimit(this.getSetting("file_upload_limit"));
}
 catch (ex){
 this.debug("Could not call SetFileUploadLimit");
}
}else{
 this.debug("Could not find Flash element in SetFileUploadLimit");
}
};

SWFUpload.prototype.setFileQueueLimit = function (file_queue_limit){
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.SetFileQueueLimit) === "function"){
 try{
 this.addSetting("file_queue_limit", file_queue_limit);
 movie_element.SetFileQueueLimit(this.getSetting("file_queue_limit"));
}
 catch (ex){
 this.debug("Could not call SetFileQueueLimit");
}
}else{
 this.debug("Could not find Flash element in SetFileQueueLimit");
}
};

SWFUpload.prototype.setFilePostName = function (file_post_name){
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.SetFilePostName) === "function"){
 try{
 this.addSetting("file_post_name", file_post_name);
 movie_element.SetFilePostName(this.getSetting("file_post_name"));
}
 catch (ex){
 this.debug("Could not call SetFilePostName");
}
}else{
 this.debug("Could not find Flash element in SetFilePostName");
}
};

SWFUpload.prototype.setDebugEnabled = function (debug_enabled){
 var movie_element = this.getMovieElement();
 if (movie_element !== null && typeof(movie_element.SetDebugEnabled) === "function"){
 try{
 this.addSetting("debug_enabled", debug_enabled);
 this.debug_enabled = this.getSetting("debug_enabled");
 movie_element.SetDebugEnabled(this.getSetting("debug_enabled"));
}
 catch (ex){
 this.debug("Could not call SetDebugEnabled");
}
}else{
 this.debug("Could not find Flash element in SetDebugEnabled");
}
};



/* *******************************
 Internal Event Callers
 Don't override these! These event callers ensure that your custom event handlers
 are called safely and in order.
******************************* */

/* This is the callback method that the Flash movie will call when it has been loaded and is ready to go.
 Calling this or showUI() "manually" will bypass the Flash Detection built in to SWFUpload.
 Use a ui_function setting if you want to control the UI loading after the flash has loaded.
*/
SWFUpload.prototype.flashReady = function (){
 var self = this;
 if (typeof(self.fileDialogStart_handler) === "function"){
 this.eventQueue[this.eventQueue.length] = function(){self.flashReady_handler();};
 setTimeout(function (){self.executeNextEvent();}, 0);
}else{
 this.debug("fileDialogStart event not defined");
}
};

/*
 Event Queue. Rather can call events directly from Flash they events are
 are placed in a queue and then executed. This ensures that each event is
 executed in the order it was called which is not guarenteed when calling
 setTimeout. Out of order events was especially problematic in Safari.
*/
SWFUpload.prototype.executeNextEvent = function (){
 var f = this.eventQueue.shift();
 if (typeof(f) === "function"){
 f();
}
}

/* This is a chance to do something before the browse window opens */
SWFUpload.prototype.fileDialogStart = function (){
 var self = this;
 if (typeof(self.fileDialogStart_handler) === "function"){
 this.eventQueue[this.eventQueue.length] = function(){self.fileDialogStart_handler();};
 setTimeout(function (){self.executeNextEvent();}, 0);
}else{
 this.debug("fileDialogStart event not defined");
}
};


/* Called when a file is successfully added to the queue. */
SWFUpload.prototype.fileQueued = function (file){
 var self = this;
 if (typeof(self.fileQueued_handler) === "function"){
 this.eventQueue[this.eventQueue.length] = function(){self.fileQueued_handler(file);};
 setTimeout(function (){self.executeNextEvent();}, 0);
}else{
 this.debug("fileQueued event not defined");
}
};


/* Handle errors that occur when an attempt to queue a file fails. */
SWFUpload.prototype.fileQueueError = function (file, error_code, message){
 var self = this;
 if (typeof(self.fileQueueError_handler) === "function"){
 this.eventQueue[this.eventQueue.length] = function(){self.fileQueueError_handler(file, error_code, message);};
 setTimeout(function (){self.executeNextEvent();}, 0);
}else{
 this.debug("fileQueueError event not defined");
}
};

/* Called after the file dialog has closed and the selected files have been queued.
 You could call startUpload here if you want the queued files to begin uploading immediately. */
SWFUpload.prototype.fileDialogComplete = function (num_files_selected){
 var self = this;
 if (typeof(self.fileDialogComplete_handler) === "function"){
 this.eventQueue[this.eventQueue.length] = function(){self.fileDialogComplete_handler(num_files_selected);};
 setTimeout(function (){self.executeNextEvent();}, 0);
}else{
 this.debug("fileDialogComplete event not defined");
}
};

/* Gets called when a file upload is about to be started. Return true to continue the upload. Return false to stop the upload. 
 If you return false then uploadError and fileComplete are called (like normal).
 
 This is a good place to do any file validation you need.
 
 This is the only function that cannot be called on a setTimeout because it must return a value to Flash.
 You SHOULD NOT make any calls in to Flash (i.e., changing settings, getting stats, etc). A bug in the Flash Player
 causes function calls to fail they are circled through JS -> Flash -> JS -> Flash.
*/
SWFUpload.prototype.uploadStart = function (file){
 if (typeof(this.uploadStart_handler) === "function"){
 return this.uploadStart_handler(file);
}else{
 this.debug("uploadStart event not defined");
 return true;
}
};

/* Called during upload as the file progresses. Use this event to update your UI. */
SWFUpload.prototype.uploadProgress = function (file, bytes_complete, bytes_total){
 var self = this;
 if (typeof(self.uploadProgress_handler) === "function"){
 this.eventQueue[this.eventQueue.length] = function(){self.uploadProgress_handler(file, bytes_complete, bytes_total);};
 setTimeout(function (){self.executeNextEvent();}, 0);
}else{
 this.debug("uploadProgress event not defined");
}
};

/* Called when an error occurs during an upload. Use error_code and the SWFUpload.UPLOAD_ERROR constants to determine
 which error occurred. The fileComplete event is often called after an error code indicating that the next file is
 ready for upload. However for the UPLOAD_STOPPED and in some cases the UPLOAD_CANCELLED errors fileComplete will
 not be called. */
SWFUpload.prototype.uploadError = function (file, error_code, message){
 var self = this;
 if (typeof(this.uploadError_handler) === "function"){
 this.eventQueue[this.eventQueue.length] = function(){self.uploadError_handler(file, error_code, message);};
 setTimeout(function (){self.executeNextEvent();}, 0);
}else{
 this.debug("uploadError event not defined");
}
};

/* This gets called when a file finishes uploading and the server-side upload script has completed and returned a 200 
status code. Any text returned by the server is available in server_data. 
**NOTE: The upload script MUST return some text or the uploadComplete and fileComplete events will not fire and the
upload will become 'stuck'. */
SWFUpload.prototype.uploadComplete = function (file, server_data){
 var self = this;
 if (typeof(self.uploadComplete_handler) === "function"){
 this.eventQueue[this.eventQueue.length] = function(){self.uploadComplete_handler(file, server_data);};
 setTimeout(function (){self.executeNextEvent();}, 0);
}else{
 this.debug("uploadComplete event not defined");
}
};

/* fileComplete is called when the file is uploaded or an error occurred and SWFUpload is ready to make the next upload.
 If you want the next upload to start to automatically you can call startUpload() from this event. */
SWFUpload.prototype.fileComplete = function (file){
 var self = this;
 if (typeof(self.fileComplete_handler) === "function"){
 this.eventQueue[this.eventQueue.length] = function(){self.fileComplete_handler(file);};
 setTimeout(function (){self.executeNextEvent();}, 0);
}else{
 this.debug("fileComplete event not defined");
}
};

/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
 internal debug console. You can override this event and have messages written where you want. */
SWFUpload.prototype.debug = function (message){
 var self = this;
 if (typeof(self.debug_handler) === "function"){
 this.eventQueue[this.eventQueue.length] = function(){self.debug_handler(message);};
 setTimeout(function (){self.executeNextEvent();}, 0);
}else{
 this.eventQueue[this.eventQueue.length] = function(){self.debugMessage(message);};
 setTimeout(function (){self.executeNextEvent();}, 0);
}
};


/* **********************************
 Default Event Handlers.
 These event handlers are used by default if an overriding handler is
 not defined in the SWFUpload settings object.
 
 JS Note: even though these are defined on the SWFUpload object (rather than the prototype) they
 are attached (read: copied) to a SWFUpload instance and 'this' is given the proper context.
 ********************************** */

/* This is a special event handler that has no override in the settings. Flash calls this when it has
 been loaded by the browser and is ready for interaction. You should not override it. If you need
 to do something with SWFUpload has loaded then use the swfupload_loaded_handler setting.
*/
SWFUpload.flashReady = function (){
 try{
 this.debug("Flash called back and is ready.");

 if (typeof(this.swfUploadLoaded_handler) === "function"){
 this.swfUploadLoaded_handler();
}
}catch (ex){
 this.debug(ex);
}
}
/* This is the default action when SWFUpload has loaded. If you want something else to happen set
 swfupload_loaded_handler in your settings.
 By default the special ui_container_id and degraded_container_id settings are used to display the ui_container and
 hide the degraded_container.
*/
SWFUpload.swfUploadLoaded = function (){
 var ui_container_id, ui_target, degraded_container_id, degraded_target;
 try{
 ui_container_id = this.getSetting("ui_container_id");

 if (typeof(ui_container_id) === "string" && ui_container_id !== ""){
 ui_target = document.getElementById(ui_container_id);
 if (ui_target !== null){
 ui_target.style.display = "block";

 degraded_container_id = this.getSetting("degraded_container_id");
 if (typeof(degraded_container_id) && degraded_container_id !== ""){
 degraded_target = document.getElementById(degraded_container_id);
 if (degraded_target !== null){
 degraded_target.style.display = "none";
}
}
}

}

}catch (ex){
 this.debug(ex);
}
}

/* This is a chance to do something before the browse window opens */
SWFUpload.fileDialogStart = function (){
};


/* Called when a file is successfully added to the queue. */
SWFUpload.fileQueued = function (file){
};


/* Handle errors that occur when an attempt to queue a file fails. */
SWFUpload.fileQueueError = function (file, error_code, message){
 try{
 switch (error_code){
 case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
 this.debug("Error Code: File too big, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
 break;
 case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
 this.debug("Error Code: Zero Byte File, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
 break;
 case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:
 this.debug("Error Code: Upload limit reached, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
 break;
 case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
 this.debug("Error Code: File extension is not allowed, Message: " + message);
 break;
 default:
 this.debug("Error Code: Unhandled error occured. Errorcode: " + error_code);
}
}catch (ex){
 this.debug(ex);
}
};

/* Called after the file dialog has closed and the selected files have been queued.
 You could call startUpload here if you want the queued files to begin uploading immediately. */
SWFUpload.fileDialogComplete = function (num_files_selected){
};

/* Gets called when a file upload is about to be started. Return true to continue the upload. Return false to stop the upload. 
 If you return false then the uploadError callback is called and then fileComplete (like normal).
 
 This is a good place to do any file validation you need.
 
 This is the only function that cannot be called on a setTimeout because it must return a value to Flash.
 You MUST NOT make any calls in to Flash (e.i, changing settings, getting stats, etc).
*/
SWFUpload.uploadStart = function (file){
 return true;
};

SWFUpload.uploadProgress = function (file, bytes_complete, bytes_total){
 this.debug("File Progress: " + file.id + ", Bytes: " + bytes_complete + ". Total: " + bytes_total);
};

/* This gets called when a file finishes uploading and the upload script has completed and returned a 200 status code. Any text returned by the
server is available in server_data. The upload script must return some text or uploadComplete will not fire (neither will fileComplete). */
SWFUpload.uploadComplete = function (file, server_data){
};

/* This is called last. The file is uploaded or an error occurred and SWFUpload is ready to make the next upload.
 If you want to automatically start the next file just call startUpload from here.
*/
SWFUpload.fileComplete = function (file){
};


SWFUpload.debug = function (message){
 if (this.debug_enabled){
 this.debugMessage(message);
}
};

/* Called when an upload occurs during upload. For HTTP errors 'message' will contain the HTTP STATUS CODE */
SWFUpload.uploadError = function (file, error_code, message){
 try{
 switch (errcode){
 case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND:
 this.debug("Error Code: File ID specified for upload was not found, Message: " + msg);
 break;
 case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:
 this.debug("Error Code: HTTP Error, File name: " + file.name + ", Message: " + msg);
 break;
 case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL:
 this.debug("Error Code: No backend file, File name: " + file.name + ", Message: " + msg);
 break;
 case SWFUpload.UPLOAD_ERROR.IO_ERROR:
 this.debug("Error Code: IO Error, File name: " + file.name + ", Message: " + msg);
 break;
 case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:
 this.debug("Error Code: Security Error, File name: " + file.name + ", Message: " + msg);
 break;
 case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
 this.debug("Error Code: Upload limit reached, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
 break;
 case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:
 this.debug("Error Code: Upload Initialization exception, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
 break;
 case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:
 this.debug("Error Code: uploadStart callback returned false, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
 break;
 case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
 this.debug("Error Code: The file upload was cancelled, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
 break;
 case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
 this.debug("Error Code: The file upload was stopped, File name: " + file.name + ", File size: " + file.size + ", Message: " + msg);
 break;
 default:
 this.debug("Error Code: Unhandled error occured. Errorcode: " + errcode);
}
}catch (ex){
 this.debug(ex);
}
};



/* **********************************
 Debug Console
 The debug console is a self contained, in page location
 for debug message to be sent. The Debug Console adds
 itself to the body if necessary.

 The console is automatically scrolled as messages appear.
 
 You can override this console (to use FireBug's console for instance) by setting the debug event method to your own function
 that handles the debug message
 ********************************** */
SWFUpload.prototype.debugMessage = function (message){
 var exception_message, exception_values;

 if (typeof(message) === "object" && typeof(message.name) === "string" && typeof(message.message) === "string"){
 exception_message = "";
 exception_values = [];
 for (var key in message){
 exception_values.push(key + ": " + message[key]);
}
 exception_message = exception_values.join("\n");
 exception_values = exception_message.split("\n");
 exception_message = "EXCEPTION: " + exception_values.join("\nEXCEPTION: ");
 SWFUpload.Console.writeLine(exception_message);
}else{
 SWFUpload.Console.writeLine(message);
}
};

SWFUpload.Console ={};
SWFUpload.Console.writeLine = function (message){
 var console, documentForm;

 try{
 console = document.getElementById("SWFUpload_Console");

 if (!console){
 documentForm = document.createElement("form");
 document.getElementsByTagName("body")[0].appendChild(documentForm);

 console = document.createElement("textarea");
 console.id = "SWFUpload_Console";
 console.style.fontFamily = "monospace";
 console.setAttribute("wrap", "off");
 console.wrap = "off";
 console.style.overflow = "auto";
 console.style.width = "700px";
 console.style.height = "350px";
 console.style.margin = "5px";
 documentForm.appendChild(console);
}

 console.value += message + "\n";

 console.scrollTop = console.scrollHeight - console.clientHeight;
}catch (ex){
 alert("Exception: " + ex.name + " Message: " + ex.message);
}
};

}//endif SWFuploader Régi









/****************
 * KÖZÖS DOLGOK *
 ****************/





/* **********************
 Event Handlers
 These are my custom event handlers to make my
 web application behave the way I went when SWFUpload
 completes different tasks. These aren't part of the SWFUpload
 package. They are part of my application. Without these none
 of the actions SWFUpload makes will show up in my application.
 ********************** */

function cancelQueue(instance){
 document.getElementById(instance.customSettings.cancelButtonId).disabled = true;
 instance.stopUpload();
 var stats;
 
 do{
 stats = instance.getStats();
 instance.cancelUpload();
}while (stats.files_queued !== 0);
 
}

function fileDialogStart(){
 /* I don't need to do anything here */
}
function fileQueued(fileObj){
 try{


 var progress = new FileProgress(fileObj, this.customSettings.progressTarget);
 progress.SetStatus("Pending...");
 progress.ToggleCancel(true, this);

}catch (ex){this.debug(ex);}

}

function fileQueueError(fileObj, error_code, message){
 try{
 if (error_code === SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED){
 alert("Sajnos több file feltöltése nem engedélyezett!");
 return;
}

 var progress = new FileProgress(fileObj, this.customSettings.progressTarget);
 progress.SetError();
 progress.ToggleCancel(false);

 switch(error_code){
 case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
 progress.SetStatus("A file túl nagy!");
 this.debug("Error Code: File too big, File name: " + fileObj.name + ", File size: " + fileObj.size + ", Message: " + message);
 break;
 case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
 progress.SetStatus("Cannot upload Zero Byte files.");
 this.debug("Error Code: Zero byte file, File name: " + fileObj.name + ", File size: " + fileObj.size + ", Message: " + message);
 break;
 case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
 progress.SetStatus("Invalid File Type.");
 this.debug("Error Code: Invalid File Type, File name: " + fileObj.name + ", File size: " + fileObj.size + ", Message: " + message);
 break;
 case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:
 alert("You have selected too many files. " + (message > 1 ? "You may only add " + message + " more files" : "You cannot add any more files."));
 break;
 default:
 if (fileObj !== null){
 progress.SetStatus("Unhandled Error");
}
 this.debug("Error Code: " + error_code + ", File name: " + fileObj.name + ", File size: " + fileObj.size + ", Message: " + message);
 break;
}
}catch (ex){
 this.debug(ex);
}
}

function fileDialogComplete(num_files_queued){
 try{
 if (this.getStats().files_queued > 0){
 document.getElementById(this.customSettings.cancelButtonId).disabled = false;
}
 
 /* I want auto start and I can do that here */
 this.startUpload();
}catch (ex){
 this.debug(ex);
}
}

function uploadStart(fileObj){
 try{
 /* I don't want to do any file validation or anything, I'll just update the UI and return true to indicate that the upload should start */
 var progress = new FileProgress(fileObj, this.customSettings.progressTarget);
 progress.SetStatus("Feltöltés...");
 progress.ToggleCancel(true, this);
}
 catch (ex){}
 
 return true;
}

function uploadProgress(fileObj, bytesLoaded, bytesTotal){

 try{
 var percent = Math.ceil((bytesLoaded / bytesTotal) * 100);

 var progress = new FileProgress(fileObj, this.customSettings.progressTarget);
 progress.SetProgress(percent);
 progress.SetStatus("Feltöltés...");
}catch (ex){this.debug(ex);}
}

function uploadComplete(fileObj, server_data){
 try{
 var progress = new FileProgress(fileObj, this.customSettings.progressTarget);
 progress.SetComplete();
 progress.SetStatus("Feltöltés sikeres.");

 if(this.getSetting("hidden_id").length > 0)
{



 document.getElementById(this.getSetting("hidden_id")).value=document.getElementById(this.getSetting("hidden_id")).value + fileObj.name + ";";
 
}
 
 progress.ToggleCancel(false);

}catch (ex){this.debug(ex);}
}

function fileComplete(fileObj){
 try{
 /* I want the next upload to continue automatically so I'll call startUpload here */
 if (this.getStats().files_queued === 0){
 document.getElementById(this.customSettings.cancelButtonId).disabled = true;
}else{
 this.startUpload();
}
}catch (ex){this.debug(ex);}

}

function uploadError(fileObj, error_code, message){
 try{
 var progress = new FileProgress(fileObj, this.customSettings.progressTarget);
 progress.SetError();
 progress.ToggleCancel(false);

 switch(error_code){
 case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:
 progress.SetStatus("Upload Error: " + message);
 this.debug("Error Code: HTTP Error, File name: " + fileObj.name + ", Message: " + message);
 break;
 case SWFUpload.UPLOAD_ERROR.MISSING_UPLOAD_URL:
 progress.SetStatus("Configuration Error");
 this.debug("Error Code: No backend file, File name: " + fileObj.name + ", Message: " + message);
 break;
 case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:
 progress.SetStatus("Upload Failed.");
 this.debug("Error Code: Upload Failed, File name: " + fileObj.name + ", File size: " + fileObj.size + ", Message: " + message);
 break;
 case SWFUpload.UPLOAD_ERROR.IO_ERROR:
 progress.SetStatus("Server (IO) Error");
 this.debug("Error Code: IO Error, File name: " + fileObj.name + ", Message: " + message);
 break;
 case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:
 progress.SetStatus("Security Error");
 this.debug("Error Code: Security Error, File name: " + fileObj.name + ", Message: " + message);
 break;
 case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
 progress.SetStatus("Upload limit exceeded.");
 this.debug("Error Code: Upload Limit Exceeded, File name: " + fileObj.name + ", File size: " + fileObj.size + ", Message: " + message);
 break;
 case SWFUpload.UPLOAD_ERROR.SPECIFIED_FILE_ID_NOT_FOUND:
 progress.SetStatus("File not found.");
 this.debug("Error Code: The file was not found, File name: " + fileObj.name + ", File size: " + fileObj.size + ", Message: " + message);
 break;
 case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:
 progress.SetStatus("Failed Validation. Upload skipped.");
 this.debug("Error Code: File Validation Failed, File name: " + fileObj.name + ", File size: " + fileObj.size + ", Message: " + message);
 break;
 case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
 if (this.getStats().files_queued === 0){
 document.getElementById(this.customSettings.cancelButtonId).disabled = true;
}
 progress.SetStatus("Megszakítva");
 progress.SetCancelled();
 break;
 case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
 progress.SetStatus("Leállítva");
 break;
 default:
 progress.SetStatus("Unhandled Error: " + error_code);
 this.debug("Error Code: " + error_code + ", File name: " + fileObj.name + ", File size: " + fileObj.size + ", Message: " + message);
 break;
}
}catch (ex){
 this.debug(ex);
}
}



function FileProgress(fileObj, target_id){
 this.file_progress_id = fileObj.id;

 this.opacity = 100;
 this.height = 0;

 this.fileProgressWrapper = document.getElementById(this.file_progress_id);
 if (!this.fileProgressWrapper){
 this.fileProgressWrapper = document.createElement("div");
 this.fileProgressWrapper.className = "progressWrapper";
 this.fileProgressWrapper.id = this.file_progress_id;

 this.fileProgressElement = document.createElement("div");
 this.fileProgressElement.className = "progressContainer";

 var progressCancel = document.createElement("a");
 progressCancel.className = "progressCancel";
 progressCancel.href = "#";
 progressCancel.style.visibility = "hidden";
 progressCancel.appendChild(document.createTextNode(" "));

 var progressText = document.createElement("div");
 progressText.className = "progressName";
 progressText.appendChild(document.createTextNode(fileObj.name));

 var progressBar = document.createElement("div");
 progressBar.className = "progressBarInProgress";

 var progressStatus = document.createElement("div");
 progressStatus.className = "progressBarStatus";
 progressStatus.innerHTML = "&nbsp;";

 this.fileProgressElement.appendChild(progressCancel);
 this.fileProgressElement.appendChild(progressText);
 this.fileProgressElement.appendChild(progressStatus);
 this.fileProgressElement.appendChild(progressBar);

 this.fileProgressWrapper.appendChild(this.fileProgressElement);

 document.getElementById(target_id).appendChild(this.fileProgressWrapper);
}else{
 this.fileProgressElement = this.fileProgressWrapper.firstChild;
}

 this.height = this.fileProgressWrapper.offsetHeight;

}
FileProgress.prototype.SetProgress = function(percentage){
 this.fileProgressElement.className = "progressContainer green";
 this.fileProgressElement.childNodes[3].className = "progressBarInProgress";
 this.fileProgressElement.childNodes[3].style.width = percentage + "%";
};
FileProgress.prototype.SetComplete = function(){
 this.fileProgressElement.className = "progressContainer blue";
 this.fileProgressElement.childNodes[3].className = "progressBarComplete";
 this.fileProgressElement.childNodes[3].style.width = "";

 var oSelf = this;


};
FileProgress.prototype.SetError = function(){
 this.fileProgressElement.className = "progressContainer red";
 this.fileProgressElement.childNodes[3].className = "progressBarError";
 this.fileProgressElement.childNodes[3].style.width = "";

 var oSelf = this;
 setTimeout(function(){oSelf.Disappear();}, 5000);
};
FileProgress.prototype.SetCancelled = function(){
 this.fileProgressElement.className = "progressContainer";
 this.fileProgressElement.childNodes[3].className = "progressBarError";
 this.fileProgressElement.childNodes[3].style.width = "";

 var oSelf = this;
 setTimeout(function(){oSelf.Disappear();}, 2000);
};
FileProgress.prototype.SetStatus = function(status){
 this.fileProgressElement.childNodes[2].innerHTML = status;
};

FileProgress.prototype.ToggleCancel = function(show, upload_obj){
 this.fileProgressElement.childNodes[0].style.visibility = show ? "visible" : "hidden";
 if (upload_obj){
 var file_id = this.file_progress_id;
 this.fileProgressElement.childNodes[0].onclick = function(){upload_obj.cancelUpload(file_id); return false;};
}
};

FileProgress.prototype.Disappear = function(){

 var reduce_opacity_by = 15;
 var reduce_height_by = 4;
 var rate = 30; // 15 fps

 if (this.opacity > 0){
 this.opacity -= reduce_opacity_by;
 if (this.opacity < 0){
 this.opacity = 0;
}

 if (this.fileProgressWrapper.filters){
 try{
 this.fileProgressWrapper.filters.item("DXImageTransform.Microsoft.Alpha").opacity = this.opacity;
}catch (e){

 this.fileProgressWrapper.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + this.opacity + ")";
}
}else{
 this.fileProgressWrapper.style.opacity = this.opacity / 100;
}
}

 if (this.height > 0){
 this.height -= reduce_height_by;
 if (this.height < 0){
 this.height = 0;
}

 this.fileProgressWrapper.style.height = this.height + "px";
}

 if (this.height > 0 || this.opacity > 0){
 var oSelf = this;
 setTimeout(function(){oSelf.Disappear();}, rate);
}else{
 this.fileProgressWrapper.style.display = "none";
}
};






/*************************************
 * Flash plugin verziószám lekérdező *
 *************************************/


function getFlashVersion(){
 /**
 * A pluginból lekért név-verzióból kihámozza a verziószámot.
 */
 function getVersionNumber(desc){
 var matches = desc.match(/[\d]+/g);
 matches.length = 3; // To standardize IE vs FF
 return matches[0]; //Csak major verziót adjuk vissza

 return matches.join('.'); //Ez visszaadja a teljes verziószámot, csak éppen emiatt String lesz belőle
}

 var version;
 var axo;
 
 if(navigator.plugins && navigator.mimeTypes.length){
 axo = navigator.plugins["Shockwave Flash"];
 if( axo ) version = axo.description;
}
 else{
 try{
 axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
 if( axo ) version = axo.GetVariable("$version");
}
 catch (e){
 fResult = "Nincs flasplayer"; //IE
}
}
 
 if( axo ) fResult = getVersionNumber(version);
 else fResult = "Nincs flasplayer"; //FF
 
 return fResult;
}
/* ######### window ######### */























var Window = Class.create();
Window.prototype ={



 initialize: function(id){
 if ($(id))
 alert("Window " + id + " is already register is the DOM!!, be sure to use setDestroyOnClose()")
 
 this.hasEffectLib = String.prototype.parseColor != null;
 this.options = Object.extend({
 className: "dialog",
 minWidth: 100,
 minHeight: 20,
 resizable: true,
 closable: true,
 minimizable: true,
 maximizable: true,
 draggable: true,
 userData: null,
 showEffect: (this.hasEffectLib ? Effect.Appear : Element.show),
 hideEffect: (this.hasEffectLib ? Effect.Fade : Element.hide),
 showEffectOptions:{},
 hideEffectOptions:{},
 effectOptions: null,
 parent: document.getElementsByTagName("body").item(0),
 title: "&nbsp;",
 url: null,
 onload: Prototype.emptyFunction,
 width: 200,
 height: 300,
 opacity: 1
}, arguments[1] ||{});
 
 if (this.options.effectOptions){
 Object.extend(this.options.hideEffectOptions, this.options.effectOptions);
 Object.extend(this.options.showEffectOptions, this.options.effectOptions);
}
 if (this.options.hideEffect == Element.hide)
 this.options.hideEffect = function(){Element.hide(this.element); if (this.destroyOnClose) this.destroy();}.bind(this)
 
 this.element = this._createWindow(id);

 this.eventMouseDown = this._initDrag.bindAsEventListener(this);
 this.eventMouseUp = this._endDrag.bindAsEventListener(this);
 this.eventMouseMove = this._updateDrag.bindAsEventListener(this);
 this.eventKeyPress = this._keyPress.bindAsEventListener(this);
 this.eventOnLoad = this._getWindowBorderSize.bindAsEventListener(this);
 this.eventMouseDownContent = this.toFront.bindAsEventListener(this);
 this.eventResize = this._recenter.bindAsEventListener(this);
 
 this.topbar = $(this.element.id + "_top");
 this.bottombar = $(this.element.id + "_bottom");
 this.content = $(this.element.id + "_content");
 
 Event.observe(this.topbar, "mousedown", this.eventMouseDown);
 Event.observe(this.bottombar, "mousedown", this.eventMouseDown);
 Event.observe(this.content, "mousedown", this.eventMouseDownContent);
 Event.observe(window, "load", this.eventOnLoad);
 Event.observe(window, "resize", this.eventResize);
 Event.observe(window, "scroll", this.eventResize);
 
 if (this.options.draggable){
 this.bottombar.addClassName("bottom_draggable");
 this.topbar.addClassName("top_draggable");
}
 
 if (this.options.resizable){
 this.sizer = $(this.element.id + "_sizer");
 Event.observe(this.sizer, "mousedown", this.eventMouseDown);
}
 
 this.useLeft = null;
 this.useTop = null;
 if (arguments[1].left != null){
 this.element.setStyle({left: parseFloat(arguments[1].left) + 'px'});
 this.useLeft = true;
}
 if (arguments[1].right != null){
 this.element.setStyle({right: parseFloat(arguments[1].right) + 'px'});
 this.useLeft = false;
}
 if (this.useLeft == null){
 this.element.setStyle({left: "0px"});
 this.useLeft = true;
}
 
 if (arguments[1].top != null){
 this.element.setStyle({top: parseFloat(arguments[1].top) + 'px'});
 this.useTop = true;
}
 if (arguments[1].bottom != null){
 this.element.setStyle({bottom: parseFloat(arguments[1].bottom) + 'px'}); 
 this.useTop = false;
}
 if (this.useTop == null){
 this.element.setStyle({top: "0px"});
 this.useTop = true;
}

 this.storedLocation = null;
 
 this.setOpacity(this.options.opacity);
 if (this.options.zIndex)
 this.setZIndex(this.options.zIndex)

 this.destroyOnClose = false;

 this._getWindowBorderSize();
 this.width = this.options.width;
 this.height = this.options.height;
 
 if (this.width && this.height)
 this.setSize(this.options.width, this.options.height);
 this.setTitle(this.options.title)
 Windows.register(this); 
},

 destroy: function(){
 Windows.notify("onDestroy", this);
 
 Event.stopObserving(this.topbar, "mousedown", this.eventMouseDown);
 Event.stopObserving(this.bottombar, "mousedown", this.eventMouseDown);
 Event.stopObserving(this.content, "mousedown", this.eventMouseDownContent);
 
 Event.stopObserving(window, "load", this.eventOnLoad);
 Event.stopObserving(window, "resize", this.eventResize);
 Event.stopObserving(window, "scroll", this.eventResize);
 
 Event.stopObserving(this.content, "load", this.options.onload);

 if (this.sizer)
 Event.stopObserving(this.sizer, "mousedown", this.eventMouseDown);

 if (this.options.url)
 this.content.src = null

 if(this.iefix) 
 Element.remove(this.iefix);

 Element.remove(this.element);
 Windows.unregister(this);
 if ($("photogallery2_darken")){
 $("photogallery2_darken").style.display="none";
 var bodys = document.getElementsByTagName("body"); 
 bodys[0].removeClassName("no-scroll");
}
},

 setDelegate: function(delegate){
 this.delegate = delegate
},

 getDelegate: function(){
 return this.delegate;
},

 getContent: function (){
 return this.content;
},

 setContent: function(id, autoresize, autoposition){
 var d = null;
 var p = null;

 if (autoresize) 
 d = Element.getDimensions(id);
 if (autoposition) 
 p = Position.cumulativeOffset($(id));

 var content = this.getContent()
 content.appendChild($(id));
 $(id).show();
 if (autoresize) 
 this.setSize(d.width, d.height);
 if (autoposition) 
 this.setLocation(p[1] - this.heightN, p[0] - this.widthW); 
},
 
 setAjaxContent: function(url, options, showCentered, showModal){
 this.showFunction = showCentered ? "showCenter" : "show";
 this.showModal = showModal || false;
 
 if (options == null)
 options ={}
 this.onComplete = options.onComplete;
 options.onComplete = this._setAjaxContent.bind(this);
 
 new Ajax.Request(url, options);
},
 
 _setAjaxContent: function(originalRequest){
 this.getContent().innerHTML = originalRequest.responseText;
 if (this.onComplete)
 this.onComplete(originalRequest);
 this[this.showFunction](this.showModal)
},

 setCookie: function(name, expires, path, domain, secure){
 name = name || this.element.id;
 this.cookie = [name, expires, path, domain, secure];

 var value = WindowUtilities.getCookie(name)

 if (value){
 var values = value.split(',');
 var x = values[0].split(':');
 var y = values[1].split(':');

 var w = parseFloat(values[2]), h = parseFloat(values[3]);
 var mini = values[4];
 var maxi = values[5];

 this.setSize(w, h);
 if (mini == "true")
 this.doMinimize = true; // Minimize will be done at onload window event
 else if (maxi == "true")
 this.doMaximize = true; // Maximize will be done at onload window event

 this.useLeft = x[0] == "l";
 this.useTop = y[0] == "t";

 this.element.setStyle(this.useLeft ?{left: x[1]}:{right: x[1]});
 this.element.setStyle(this.useTop ?{top: y[1]}:{bottom: y[1]});
}
},

 getId: function(){
 return this.element.id;
},

 setDestroyOnClose: function(){
 Object.extend(this.options.hideEffectOptions,{afterFinish: this.destroy.bind(this)});
 this.destroyOnClose = true;
},

 _initDrag: function(event){

 this.pointer = [Event.pointerX(event), Event.pointerY(event)];

 if (Event.element(event) == this.sizer){
 this.doResize = true;
 this.widthOrg = this.width;
 this.heightOrg = this.height;
 this.bottomOrg = parseFloat(this.element.getStyle('bottom'));
 this.rightOrg = parseFloat(this.element.getStyle('right'));
 Windows.notify("onStartResize", this);
}
 else{
 this.doResize = false;

 var closeButton = $(this.getId() + '_close');
 if (closeButton && Position.within(closeButton, this.pointer[0], this.pointer[1])) 
 return;

 this.toFront();

 if (! this.options.draggable) 
 return;
 Windows.notify("onStartMove", this);
}

 Event.observe(document, "mouseup", this.eventMouseUp, false);
 Event.observe(document, "mousemove", this.eventMouseMove, false);

 WindowUtilities.disableScreen('__invisible__', '__invisible__');

 document.body.ondrag = function (){return false;};
 document.body.onselectstart = function (){return false;};
 
 Event.stop(event);
},

 _updateDrag: function(event){
 var pointer = [Event.pointerX(event), Event.pointerY(event)]; 
 var dx = pointer[0] - this.pointer[0];
 var dy = pointer[1] - this.pointer[1];

 if (this.doResize){
 this.setSize(this.widthOrg + dx , this.heightOrg + dy);
 
 dx = this.width - this.widthOrg
 dy = this.height - this.heightOrg

 if (! this.useLeft) 
 this.element.setStyle({right: (this.rightOrg -dx) + 'px'});

 if (! this.useTop) 
 this.element.setStyle({bottom: (this.bottomOrg -dy) + 'px'});
}

 else{
 this.pointer = pointer;
 
 if (this.useLeft) 
 this.element.setStyle({left: parseFloat(this.element.getStyle('left')) + dx + 'px'});
 else 
 this.element.setStyle({right: parseFloat(this.element.getStyle('right')) - dx + 'px'});
 
 if (this.useTop) 
 this.element.setStyle({top: parseFloat(this.element.getStyle('top')) + dy + 'px'});
 else 
 this.element.setStyle({bottom: parseFloat(this.element.getStyle('bottom')) - dy + 'px'});
}
 if (this.iefix) 
 this._fixIEOverlapping(); 
 
 this._removeStoreLocation();
 Event.stop(event);
},

 _endDrag: function(event){

 WindowUtilities.enableScreen('__invisible__');
 
 if (this.doResize)
 Windows.notify("onEndResize", this);
 else
 Windows.notify("onEndMove", this);

 Event.stopObserving(document, "mouseup", this.eventMouseUp,false);
 Event.stopObserving(document, "mousemove", this.eventMouseMove, false);

 this._saveCookie()

 Event.stop(event);

 document.body.ondrag = null;
 document.body.onselectstart = null;
},

 _keyPress: function(event){

},

 _createWindow: function(id){
 var className = this.options.className;
 var win = document.createElement("div");
 win.setAttribute('id', id);
 win.className = "dialog";

 var content;
 if (this.options.url)
 content= "<iframe name=\"" + id + "_content\" id=\"" + id + "_content\" src=\"" + this.options.url + "\"> </iframe>";
 else
 content ="<div id=\"" + id + "_content\" class=\"" +className + "_content\"> </div>";
 
 var closeDiv = this.options.closable ? "<div class='"+ className +"_close' id='"+ id +"_close' onmouseup='Windows.close(\""+ id +"\")'> </div>" : "";
 var minDiv = this.options.minimizable ? "<div class='"+ className + "_minimize' id='"+ id +"_minimize' onmouseup='Windows.minimize(\""+ id +"\")'> </div>" : "";
 var maxDiv = this.options.maximizable ? "<div class='"+ className + "_maximize' id='"+ id +"_maximize' onmouseup='Windows.maximize(\""+ id +"\")'> </div>" : "";
 var seAttributes = this.options.resizable ? "class='" + className + "_sizer' id='" + id + "_sizer'" : "class='" + className + "_se'";
 
 if (id=="photogallery2_window"){
 win.innerHTML = closeDiv + minDiv + maxDiv + "\
 <div id='"+ id +"_row1' class=\"top table_window\"><div id='"+ id +"_top'></div></div>\
 </table>\
 <table id='"+ id +"_row2' class=\"mid table_window\">\
 <tr>\
 <td class='"+ className +"_w'></td>\
 <td id='"+ id +"_table_content' class='"+ className +"_content' valign='top'>"+ content +"</td>\
 <td class='"+ className +"_e'></td>\
 </tr>\
 </table>\
 <div id='"+ id +"_row3' class=\"top table_window\"><div id='"+ id +"_bottom'></div></div>\
 ";
}
 else{
 win.innerHTML = closeDiv + minDiv + maxDiv + "\
 <table id='"+ id +"_row1' class=\"top table_window\">\
 <tr>\
 <td class='"+ className +"_nw'>&nbsp;</td>\
 <td class='"+ className +"_n'><div id='"+ id +"_top' class='"+ className +"_title title_window'>"+ this.options.title +"</div></td>\
 <td class='"+ className +"_ne'>&nbsp;</td>\
 </tr>\
 </table>\
 <table id='"+ id +"_row2' class=\"mid table_window\">\
 <tr>\
 <td class='"+ className +"_w'></td>\
 <td id='"+ id +"_table_content' class='"+ className +"_content' valign='top'>"+ content +"</td>\
 <td class='"+ className +"_e'></td>\
 </tr>\
 </table>\
 <table id='"+ id +"_row3' class=\"bot table_window\">\
 <tr>\
 <td class='"+ className +"_sw'>&nbsp;</td>\
 <td class='"+ className +"_s'><div id='"+ id +"_bottom' class='status_bar'>&nbsp;</div></td>\
 <td " + seAttributes + ">&nbsp;</td>\
 </tr>\
 </table>\
 ";
}
 Element.hide(win);
 this.options.parent.insertBefore(win, this.options.parent.firstChild);
 Event.observe($(id + "_content"), "load", this.options.onload);
 return win;
},

 setLocation: function(top, left){
 if (top < 0)
 top = 0;
 if (left < 0)
 left= 0
 this.element.setStyle({top: top + 'px'});
 this.element.setStyle({left: left + 'px'});
 this.useLeft = true;
 this.useTop = true;
},

 getSize: function(){
 return{width: this.width, height: this.height};
},

 setSize: function(width, height){
 width = parseFloat(width);
 height = parseFloat(height);

 if (width < this.options.minWidth)
 width = this.options.minWidth;

 if (height < this.options.minHeight)
 height = this.options.minHeight;
 
 if (this.options. maxHeight && height > this.options. maxHeight)
 height = this.options. maxHeight;

 if (this.options. maxWidth && width > this.options. maxWidth)
 width = this.options. maxWidth;

 this.width = width;
 this.height = height;
 this.element.setStyle({width: width + this.widthW + this.widthE + "px"})
 this.element.setStyle({height: height + this.heightN + this.heightS + "px"})

 var content = $(this.element.id + '_content')
 content.setStyle({height: height + 'px'});
 content.setStyle({width: width + 'px'});
},
 
 updateHeight: function(){
 this.setSize(this.width, this.content.scrollHeight)
},
 
 updateWidth: function(){
 this.setSize(this.content.scrollWidth, this.height)
},

 toFront: function(){
 this.setZIndex(Windows.maxZIndex + 20);
 Windows.notify("onFocus", this);
},

 show: function(modal){
 if (modal){
 WindowUtilities.disableScreen(this.options.className, 'overlay_modal', this.getId());
 this.modal = true; 
 this.setZIndex(Windows.maxZIndex + 20);
 Windows.unsetOverflow(this);
 Event.observe(document, "keypress", this.eventKeyPress); 
}

 if (this.oldStyle)
 this.getContent().setStyle({overflow: this.oldStyle});
 
 if (! this.width || !this.height){
 var size = WindowUtilities._computeSize(this.content.innerHTML, this.content.id, this.width, this.height, 0)
 if (this.height)
 this.width = size + 5
 else
 this.height = size + 5
}

 this.setSize(this.width, this.height);
 if (this.centered)
 this._center(this.centerTop, this.centerLeft); 
 
 if (this.options.showEffect != Element.show && this.options.showEffectOptions )
 this.options.showEffect(this.element, this.options.showEffectOptions); 
 else
 this.options.showEffect(this.element); 
 
 this._checkIEOverlapping();
 Windows.notify("onShow", this); 
},

 showCenter: function(modal, top, left){
 this.centered = true;
 this.centerTop = top;
 this.centerLeft = left;

 this.show(modal);
},
 
 isVisible: function(){
 return this.element.visible();
},
 
 _center: function(top, left){
 var windowScroll = WindowUtilities.getWindowScroll(); 
 var pageSize = WindowUtilities.getPageSize(); 

 if (!top)
 top = (pageSize.windowHeight - (this.height + this.heightN + this.heightS))/2;
 top += windowScroll.top
 
 if (!left)
 left = (pageSize.windowWidth - (this.width + this.widthW + this.widthE))/2;
 left += windowScroll.left 
 
 this.setLocation(top, left);
 this.toFront();
},
 
 _recenter: function(event){
 if (this.modal){
 var pageSize = WindowUtilities.getPageSize();

 if ($('overlay_modal')){
 $('overlay_modal').style.height = (pageSize.pageHeight + 'px');
 $('overlay_modal').style.width = (pageSize.pageWidth + 'px');
}
 if (this.centered)
 this._center(this.centerTop, this.centerLeft); 
}
},

 hide: function(){
 if (this.modal){
 WindowUtilities.enableScreen();
 Windows.resetOverflow();
 Event.stopObserving(document, "keypress", this.eventKeyPress); 
}

 this.oldStyle = this.getContent().getStyle('overflow') || "auto"
 this.getContent().setStyle({overflow: "hidden"});

 this.options.hideEffect(this.element, this.options.hideEffectOptions); 

 if(this.iefix) 
 this.iefix.hide();
 Windows.notify("onHide", this);
},

 minimize: function(){
 var r2 = $(this.getId() + "_row2");
 var dh = r2.getDimensions().height;
 
 if (r2.visible()){
 var h = this.element.getHeight() - dh
 r2.hide()
 this.element.setStyle({height: h + "px"})
 if (! this.useTop){
 var bottom = parseFloat(this.element.getStyle('bottom'));
 this.element.setStyle({bottom: (bottom + dh) + 'px'});
}
}
 else{
 var h = this.element.getHeight() + dh;
 this.element.setStyle({height: h + "px"})
 if (! this.useTop){
 var bottom = parseFloat(this.element.getStyle('bottom'));
 this.element.setStyle({bottom: (bottom - dh) + 'px'});
}
 r2.show();
 
 this.toFront();
}
 Windows.notify("onMinimize", this);

 this._saveCookie()
},
 
 maximize: function(){
 if (this.storedLocation != null){
 this._restoreLocation();
 if(this.iefix) 
 this.iefix.hide();
}
 else{
 this._storeLocation();
 Windows.unsetOverflow(this);
 
 var windowScroll = WindowUtilities.getWindowScroll();
 var pageSize = WindowUtilities.getPageSize(); 

 this.element.setStyle(this.useLeft ?{left: windowScroll.left}:{right: windowScroll.left});
 this.element.setStyle(this.useTop ?{top: windowScroll.top}:{bottom: windowScroll.top});

 this.setSize(pageSize.windowWidth - this.widthW - this.widthE, pageSize.windowHeight - this.heightN - this.heightS)
 this.toFront();
 if (this.iefix) 
 this._fixIEOverlapping(); 
}
 Windows.notify("onMaximize", this);

 this._saveCookie()
},
 
 isMinimized: function(){
 var r2 = $(this.getId() + "_row2");
 return !r2.visible();
},
 
 isMaximized: function(){
 return (this.storedLocation != null);
},
 
 setOpacity: function(opacity){
 if (Element.setOpacity)
 Element.setOpacity(this.element, opacity);
},
 
 setZIndex: function(zindex){
 this.element.setStyle({zIndex: zindex});
 Windows.updateZindex(zindex, this);
},

 setTitle: function(newTitle){
 if (!newTitle || newTitle == "") 
 newTitle = "&nbsp;";
 
 Element.update(this.element.id + '_top', newTitle);
},

 setStatusBar: function(element){
 var statusBar = $(this.getId() + "_bottom");

 if (typeof(element) == "object"){
 if (this.bottombar.firstChild)
 this.bottombar.replaceChild(element, this.bottombar.firstChild);
 else
 this.bottombar.appendChild(element);
}
 else
 this.bottombar.innerHTML = element;
},

 _checkIEOverlapping: function(){
 if(!this.iefix && (navigator.appVersion.indexOf('MSIE')>0) && (navigator.userAgent.indexOf('Opera')<0) && (this.element.getStyle('position')=='absolute')){
 new Insertion.After(this.element.id, '<iframe id="' + this.element.id + '_iefix" '+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
 this.iefix = $(this.element.id+'_iefix');
}
 if(this.iefix) 
 setTimeout(this._fixIEOverlapping.bind(this), 50);
},

 _fixIEOverlapping: function(){
 Position.clone(this.element, this.iefix);
 this.iefix.style.zIndex = this.element.style.zIndex - 1;
 this.iefix.show();
},
 
 _getWindowBorderSize: function(event){

 var div = this._createHiddenDiv(this.options.className + "_n")
 this.heightN = Element.getDimensions(div).height; 
 div.parentNode.removeChild(div)

 var div = this._createHiddenDiv(this.options.className + "_s")
 this.heightS = Element.getDimensions(div).height; 
 div.parentNode.removeChild(div)

 var div = this._createHiddenDiv(this.options.className + "_e")
 this.widthE = Element.getDimensions(div).width; 
 div.parentNode.removeChild(div)

 var div = this._createHiddenDiv(this.options.className + "_w")
 this.widthW = Element.getDimensions(div).width;
 div.parentNode.removeChild(div);

 if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
 this.setSize(this.width, this.height);
 if (this.doMaximize)
 this.maximize();
 if (this.doMinimize)
 this.minimize();
},
 
 _createHiddenDiv: function(className){
 var objBody = document.getElementsByTagName("body").item(0);
 var win = document.createElement("div");
 win.setAttribute('id', this.element.id+ "_tmp");
 win.className = className;
 win.style.display = 'none'
 win.innerHTML = ''
 objBody.insertBefore(win, objBody.firstChild) 
 return win
},
 
 _storeLocation: function(){
 if (this.storedLocation == null){
 this.storedLocation ={useTop: this.useTop, useLeft: this.useLeft, 
 top: this.element.getStyle('top'), bottom: this.element.getStyle('bottom'),
 left: this.element.getStyle('left'), right: this.element.getStyle('right'),
 width: this.width, height: this.height};
}
},
 
 _restoreLocation: function(){
 if (this.storedLocation != null){
 this.useLeft = this.storedLocation.useLeft;
 this.useTop = this.storedLocation.useTop;
 
 this.element.setStyle(this.useLeft ?{left: this.storedLocation.left}:{right: this.storedLocation.right});
 this.element.setStyle(this.useTop ?{top: this.storedLocation.top}:{bottom: this.storedLocation.bottom});
 this.setSize(this.storedLocation.width, this.storedLocation.height);
 
 Windows.resetOverflow();
 this._removeStoreLocation();
}
},
 
 _removeStoreLocation: function(){
 this.storedLocation = null;
},
 
 _saveCookie: function(){
 if (this.cookie){
 var value = "";
 if (this.useLeft)
 value += "l:" + (this.storedLocation ? this.storedLocation.left : this.element.getStyle('left'))
 else
 value += "r:" + (this.storedLocation ? this.storedLocation.right : this.element.getStyle('right'))
 if (this.useTop)
 value += ",t:" + (this.storedLocation ? this.storedLocation.top : this.element.getStyle('top'))
 else
 value += ",b:" + (this.storedLocation ? this.storedLocation.bottom :this.element.getStyle('bottom'))
 
 value += "," + (this.storedLocation ? this.storedLocation.width : this.width);
 value += "," + (this.storedLocation ? this.storedLocation.height : this.height);
 value += "," + this.isMinimized();
 value += "," + this.isMaximized();
 WindowUtilities.setCookie(value, this.cookie)
}
}
};

var Windows ={
 windows: [],
 observers: [],
 focusedWindow: null,
 maxZIndex: 0,

 addObserver: function(observer){
 this.removeObserver(observer);
 this.observers.push(observer);
},
 
 removeObserver: function(observer){
 this.observers = this.observers.reject( function(o){return o==observer});
},
 
 notify: function(eventName, win){// onStartResize(), onEndResize(), onStartMove(), onEndMove(), onClose(), onDestroy(), onMinimize(), onMaximize(), onHide(), onShow(), onFocus()
 this.observers.each( function(o){if(o[eventName]) o[eventName](eventName, win);});
},

 getWindow: function(id){
 return this.windows.detect(function(d){return d.getId() ==id});
},

 getFocusedWindow: function(){
 return this.focusedWindow;
},

 register: function(win){
 this.windows.push(win);
},

 unregister: function(win){
 this.windows = this.windows.reject(function(d){return d==win});
}, 

 close: function(id){
 var win = this.getWindow(id);

 if (win){
 if (win.getDelegate() && ! win.getDelegate().canClose(win)) 
 return;
 if ($(id + "_close"))
 $(id + "_close").onclick = null;
 if ($(id + "_minimize"))
 $(id + "_minimize").onclick = null; 
 if ($(id + "_maximize"))
 $(id + "_maximize").onclick = null; 
 
 this.notify("onClose", win);
 win.hide();
}
},

 closeAll: function(){
 this.windows.each( function(w){Windows.close(w.getId())});
},

 minimize: function(id){
 var win = this.getWindow(id)
 if (win)
 win.minimize();
},

 maximize: function(id){
 var win = this.getWindow(id)
 if (win)
 win.maximize();
},
 
 unsetOverflow: function(except){
 this.windows.each(function(d){d.oldOverflow = d.getContent().getStyle("overflow") || "auto" ; d.getContent().setStyle({overflow: "hidden"})});
 if (except && except.oldOverflow)
 except.getContent().setStyle({overflow: except.oldOverflow});
},

 resetOverflow: function(){
 this.windows.each(function(d){if (d.oldOverflow) d.getContent().setStyle({overflow: d.oldOverflow})});
},

 updateZindex: function(zindex, win){
 if (zindex > this.maxZIndex)
 this.maxZIndex = zindex;
 this.focusedWindow = win;
}
};

var Dialog ={
 dialogId: null,
 win: null,
 onCompleteFunc: null,
 callFunc: null, 
 parameters: null, 
 
 confirm: function(content, parameters){

 if (typeof content != "string"){
 Dialog._runAjaxRequest(content, parameters, Dialog.confirm);
 return 
}
 
 parameters = parameters ||{};
 var okLabel = parameters.okLabel ? parameters.okLabel : "Ok";
 var cancelLabel = parameters.cancelLabel ? parameters.cancelLabel : "Cancel";

 var windowParam = parameters.windowParameters ||{};
 windowParam.className = windowParam.className || "alert";

 okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'" 
 cancelButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " cancel_button'" 
 var content = "\
 <div class='" + windowParam.className + "_message'>" + content + "</div>\
 <div class='" + windowParam.className + "_buttons'>\
 <input type='button' value='" + okLabel + "' onclick='Dialog.okCallback()'" + okButtonClass + "/>\
 <input type='button' value='" + cancelLabel + "' onclick='Dialog.cancelCallback()' " + cancelButtonClass + "/>\
 </div>\
 ";
 this._openDialog(content, parameters)
 return this.win
},
 
 alert: function(content, parameters){

 if (typeof content != "string"){
 Dialog._runAjaxRequest(content, parameters, Dialog.alert);
 return 
}
 
 parameters = parameters ||{};
 var okLabel = parameters.okLabel ? parameters.okLabel : "Ok";

 var windowParam = parameters.windowParameters ||{};
 windowParam.className = windowParam.className || "alert";

 okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'" 
 var content = "\
 <div class='" + windowParam.className + "_message'>" + content + "</div>\
 <div class='" + windowParam.className + "_buttons'>\
 <input type='button' value='" + okLabel + "' onclick='Dialog.okCallback()'" + okButtonClass + "/>\
 </div>";
 return this._openDialog(content, parameters)
},
 
 info: function(content, parameters){

 if (typeof content != "string"){
 Dialog._runAjaxRequest(content, parameters, Dialog.info);
 return 
}
 
 parameters = parameters ||{};
 parameters.windowParameters = parameters.windowParameters ||{};
 
 var className = parameters.windowParameters.className || "alert";

 var content = "<div id='modal_dialog_message' class='" + className + "_message'>" + content + "</div>";
 if (parameters.showProgress)
 content += "<div id='modal_dialog_progress' class='" + className + "_progress'> </div>";

 parameters.windowParameters.ok = null;
 parameters.windowParameters.cancel = null;
 parameters.windowParameters.className = className;
 
 return this._openDialog(content, parameters)
},
 
 setInfoMessage: function(message){
 $('modal_dialog_message').update(message);
},
 
 closeInfo: function(){
 Windows.close(this.dialogId);
},
 
 _openDialog: function(content, parameters){

 if (this.win) 
 this.win.destroy();

 if (! parameters.windowParameters.height && ! parameters.windowParameters.width){
 parameters.windowParameters.width = WindowUtilities.getPageSize().pageWidth / 2;
}
 this.dialogId = parameters.id ? parameters.id : 'modal_dialog'

 if (! parameters.windowParameters.height || ! parameters.windowParameters.width){
 var size = WindowUtilities._computeSize(content, this.dialogId, parameters.windowParameters.width, parameters.windowParameters.height)
 if (parameters.windowParameters.height)
 parameters.windowParameters.width = size + 5
 else
 parameters.windowParameters.height = size + 5
}
 var windowParam = parameters && parameters.windowParameters ? parameters.windowParameters :{};
 windowParam.resizable = windowParam.resizable || false;
 
 windowParam.effectOptions = windowParam.effectOptions ||{duration: 1};
 windowParam.minimizable = false;
 windowParam.maximizable = false;
 windowParam.closable = false;
 this.win = new Window(this.dialogId, windowParam);
 this.win.getContent().innerHTML = content;
 this.win.showCenter(true, parameters.top, parameters.left); 
 
 this.win.cancelCallback = parameters.cancel;
 this.win.okCallback = parameters.ok;
 
 return this.win; 
},
 
 _getAjaxContent: function(originalRequest){
 Dialog.callFunc(originalRequest.responseText, Dialog.parameters)
},
 
 _runAjaxRequest: function(message, parameters, callFunc){
 if (message.options == null)
 message.options ={}
 Dialog.onCompleteFunc = message.options.onComplete;
 Dialog.parameters = parameters;
 Dialog.callFunc = callFunc;
 
 message.options.onComplete = Dialog._getAjaxContent;
 new Ajax.Request(message.url, message.options);
},
 
 okCallback: function(){
 if (!this.win.okCallback || this.win.okCallback(this.win))
 this.win.hide();
},

 cancelCallback: function(){
 this.win.hide();
 if (this.win.cancelCallback)
 this.win.cancelCallback(this.win);
}
}
/*
 Based on Lightbox JS: Fullsize Image Overlays 
 by Lokesh Dhakar - http://www.huddletogether.com

 For more information on this script, visit:
 http://huddletogether.com/projects/lightbox/

 Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
 (basically, do anything you want, just leave my name and link)
*/

var isIE = navigator.appVersion.match(/MSIE/) == "MSIE";

var WindowUtilities ={

 getWindowScroll: function(){
 var w = window;
 var T, L, W, H;
 with (w.document){
 if (w.document.documentElement && documentElement.scrollTop){
 T = documentElement.scrollTop;
 L = documentElement.scrollLeft;
}else if (w.document.body){
 T = body.scrollTop;
 L = body.scrollLeft;
}
 if (w.innerWidth){
 W = w.innerWidth;
 H = w.innerHeight;
}else if (w.document.documentElement && documentElement.clientWidth){
 W = documentElement.clientWidth;
 H = documentElement.clientHeight;
}else{
 W = body.offsetWidth;
 H = body.offsetHeight
}
}
 return{top: T, left: L, width: W, height: H};
 
}, 






 getPageSize: function(){
 var xScroll, yScroll;

 if (window.innerHeight && window.scrollMaxY){
 xScroll = document.body.scrollWidth;
 yScroll = window.innerHeight + window.scrollMaxY;
}else if (document.body.scrollHeight > document.body.offsetHeight){// all but Explorer Mac
 xScroll = document.body.scrollWidth;
 yScroll = document.body.scrollHeight;
}else{// Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
 xScroll = document.body.offsetWidth;
 yScroll = document.body.offsetHeight;
}

 var windowWidth, windowHeight;

 if (self.innerHeight){// all except Explorer
 windowWidth = self.innerWidth;
 windowHeight = self.innerHeight;
}else if (document.documentElement && document.documentElement.clientHeight){// Explorer 6 Strict Mode
 windowWidth = document.documentElement.clientWidth;
 windowHeight = document.documentElement.clientHeight;
}else if (document.body){// other Explorers
 windowWidth = document.body.clientWidth;
 windowHeight = document.body.clientHeight;
}
 var pageHeight, pageWidth;

 if(yScroll < windowHeight){
 pageHeight = windowHeight;
}else{
 pageHeight = yScroll;
}

 if(xScroll < windowWidth){
 pageWidth = windowWidth;
}else{
 pageWidth = xScroll;
}

 return{pageWidth: pageWidth ,pageHeight: pageHeight , windowWidth: windowWidth, windowHeight: windowHeight};
},

 disableScreen: function(className, overlayId, contentId){
 WindowUtilities.initLightbox(overlayId, className);
 var objBody = document.getElementsByTagName("body").item(0);

 var objOverlay = $(overlayId);

 var pageSize = WindowUtilities.getPageSize();

 if (contentId && isIE){
 $$('select').each(function(element){element.style.visibility = "hidden"});
 $$('#'+contentId+' select').each(function(element){element.style.visibility = "visible"});
}

 objOverlay.style.height = (pageSize.pageHeight + 'px');
 objOverlay.style.width = (pageSize.windowWidth + 'px');
 objOverlay.style.display = 'block'; 
},

 enableScreen: function(id){
 id = id || 'overlay_modal'
 var objOverlay = $(id);
 if (objOverlay){

 objOverlay.style.display = 'none';

 if (isIE){
 $$('select').each(function(element){element.style.visibility = "visible"});
}
 objOverlay.parentNode.removeChild(objOverlay);
}
},





 initLightbox: function(id, className){

 if ($(id)){
 Element.setStyle(id,{zIndex: Windows.maxZIndex + 10});
}

 else{
 var objBody = document.getElementsByTagName("body").item(0);
 var objOverlay = document.createElement("div");
 objOverlay.setAttribute('id', id);
 objOverlay.className = "overlay_" + className
 objOverlay.style.display = 'none';
 objOverlay.style.position = 'absolute';
 objOverlay.style.top = '0';
 objOverlay.style.left = '0';
 objOverlay.style.zIndex = Windows.maxZIndex + 10;
 objOverlay.style.width = '100%';
 objBody.insertBefore(objOverlay, objBody.firstChild);
}
},
 
 setCookie: function(value, parameters){
 document.cookie= parameters[0] + "=" + escape(value) +
 ((parameters[1]) ? "; expires=" + parameters[1].toGMTString() : "") +
 ((parameters[2]) ? "; path=" + parameters[2] : "") +
 ((parameters[3]) ? "; domain=" + parameters[3] : "") +
 ((parameters[4]) ? "; secure" : "");
},

 getCookie: function(name){
 var dc = document.cookie;
 var prefix = name + "=";
 var begin = dc.indexOf("; " + prefix);
 if (begin == -1){
 begin = dc.indexOf(prefix);
 if (begin != 0) return null;
}else{
 begin += 2;
}
 var end = document.cookie.indexOf(";", begin);
 if (end == -1){
 end = dc.length;
}
 return unescape(dc.substring(begin + prefix.length, end));
},
 
 _computeSize: function(content, id, width, height, margin){
 if (margin == null)
 margin = 5;

 var objBody = document.getElementsByTagName("body").item(0);
 var tmpObj = document.createElement("div");
 tmpObj.setAttribute('id', id);
 
 if (height)
 tmpObj.style.height = height + "px"
 else
 tmpObj.style.width = width + "px"
 
 tmpObj.style.position = 'absolute';
 tmpObj.style.top = '0';
 tmpObj.style.left = '0';
 tmpObj.style.display = 'none';

 tmpObj.innerHTML = content;
 objBody.insertBefore(tmpObj, objBody.firstChild);
 
 var size;
 if (height)
 size = $(id).getDimensions().width + margin;
 else
 size = $(id).getDimensions().height + margin;
 objBody.removeChild(tmpObj);
 
 return size;
}
}


/* ######### utils ######### */
/*
http://dean.edwards.name/weblog/2005/12/js-tip1/
*/
var addEvent;
if (document.addEventListener){
 addEvent = function(element, type, handler){
 element.addEventListener(type, handler, null);
};
}else if (document.attachEvent){
 addEvent = function(element, type, handler){
 element.attachEvent("on" + type, handler);
};
}else{
 addEvent = new Function; // not supported
}

function strReplace(from, to, str){
 var idx = str.indexOf( from );
 while ( idx > -1 ){
 str = str.replace( from, to );
 idx = str.indexOf( from );
}

 return str;
}

document.getElementsByTagNameAndAttribute = function(tagname, attribute, value){
 if (!value) value="/.+/";
 var elements=new Array();
 var inputs=document.getElementsByTagName(tagname);
 var j=0;
 if (value.substring(0,1)!="/"){
 value=new RegExp("^"+value+"$", "i");
}else{
 value=new RegExp(value.substring(1, value.length-1), "i");
}
 for (var i=0; i<inputs.length; i++){
 var attr=inputs[i].getAttribute(attribute);
 if (!attr) continue; // ha nincs ilyen attributum akkor megyunk tovabb
 var sattr=new String(attr);
 if (sattr.match(value)){
 elements[j]=inputs[i];
 j++;
}
}
 return elements;
}

if (typeof(HTMLElement)!="undefined"){
 HTMLElement.prototype.getElementsByTagNameAndAttribute = document.getElementsByTagNameAndAttribute;
}

function printfire(){
 if (window.atob && document.createEvent){
 printfire.args = arguments;
 var ev = document.createEvent("Events");
 ev.initEvent("printfire", false, true);
 dispatchEvent(ev);
}
}

if (typeof(console)=="undefined"){
 console ={};
 console.log = printfire;
}else{
 printfire = console.log;
}

function encode_utf8(rohtext){

 rohtext = rohtext.replace(/\r\n/g,"\n");
 var utftext = "";
 for(var n=0; n<rohtext.length; n++)
{

 var c=rohtext.charCodeAt(n);

 if (c<128)
 utftext += String.fromCharCode(c);

 else if((c>127) && (c<2048)){
 utftext += String.fromCharCode((c>>6)|192);
 utftext += String.fromCharCode((c&63)|128);}

 else{
 utftext += String.fromCharCode((c>>12)|224);
 utftext += String.fromCharCode(((c>>6)&63)|128);
 utftext += String.fromCharCode((c&63)|128);}
}
 return utftext;
}

String.prototype.trim = function(){
 return(this.replace(/^\s+/,'').replace(/\s+$/,''));
}

function createCookie(name,value,days){
 if (days){
 var date = new Date();
 date.setTime(date.getTime()+(days*24*60*60*1000));
 var expires = "; expires="+date.toGMTString();
}else 
 expires = "";

 document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name){
 var nameEQ = name + "=";
 var ca = document.cookie.split(';');
 for (var i=0;i < ca.length;i++){
 var c = ca[i];
 while (c.charAt(0)==' ') c = c.substring(1,c.length);
 if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
 return null;
}

function lz(nr){
 if (nr < 10) nr = "0" + nr;
 return nr;
}

function DOM_InsertAfter(afterNode, thisNode){
 var parent=afterNode.parentNode;
 if (parent.lastChild==afterNode){
 return parent.appendChild(thisNode);
}else{
 return parent.insertBefore(thisNode, afterNode.nextSibling);
}
}

function $N(value, nan){
 if (typeof(nan) == "undefined") nan = 0;
 var tmp = (tmp = parseInt(value)) ? tmp : nan;
 return tmp;
}



var base64s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

function base64_encode(decStr){
decStr=escape(decStr); 
 var bits, dual, i = 0, encOut = '';
 while(decStr.length >= i + 3){
 bits =
 (decStr.charCodeAt(i++) & 0xff) <<16 |
 (decStr.charCodeAt(i++) & 0xff) <<8 |
 decStr.charCodeAt(i++) & 0xff;
 encOut +=
 base64s.charAt((bits & 0x00fc0000) >>18) +
 base64s.charAt((bits & 0x0003f000) >>12) +
 base64s.charAt((bits & 0x00000fc0) >> 6) +
 base64s.charAt((bits & 0x0000003f));
}
 if(decStr.length -i > 0 && decStr.length -i < 3){
 dual = Boolean(decStr.length -i -1);
 bits =
 ((decStr.charCodeAt(i++) & 0xff) <<16) |
 (dual ? (decStr.charCodeAt(i) & 0xff) <<8 : 0);
 encOut +=
 base64s.charAt((bits & 0x00fc0000) >>18) +
 base64s.charAt((bits & 0x0003f000) >>12) +
 (dual ? base64s.charAt((bits & 0x00000fc0) >>6) : '=') +
 '=';
}
 return encOut
}

function base64_decode(encStr){
 var bits, decOut = '', i = 0;
 for(; i<encStr.length; i += 4){
 bits =
 (base64s.indexOf(encStr.charAt(i)) & 0xff) <<18 |
 (base64s.indexOf(encStr.charAt(i +1)) & 0xff) <<12 | 
 (base64s.indexOf(encStr.charAt(i +2)) & 0xff) << 6 |
 base64s.indexOf(encStr.charAt(i +3)) & 0xff;
 decOut += String.fromCharCode(
 (bits & 0xff0000) >>16, (bits & 0xff00) >>8, bits & 0xff);
}
 if(encStr.charCodeAt(i -2) == 61)
 undecOut=decOut.substring(0, decOut.length -2);
 else if(encStr.charCodeAt(i -1) == 61)
 undecOut=decOut.substring(0, decOut.length -1);
 else undecOut=decOut;
 
 return unescape(undecOut); 
}

function strcmp(str1 , str2){
 function stringCode(str){
 str = str.replace('Ăˇ',"azzz");
 str = str.replace('Ă©',"ezzz");
 str = str.replace('Ă­',"izzz");
 
 str = str.replace('Ăł',"oxxx");
 str = str.replace('Ă¶',"oyyy");
 str = str.replace('Ĺ‘',"ozzz");
 
 str = str.replace('Ăş',"uxxx");
 str = str.replace('ĂĽ',"uyyy");
 str = str.replace('Ĺ±',"uzzz");
 
 str = str.replace('Ă',"AZZZ");
 str = str.replace('Ă©',"EZZZ");
 str = str.replace('Ă­',"IZZZ");
 
 str = str.replace('Ăł',"OXXX");
 str = str.replace('Ă¶',"OYYY");
 str = str.replace('Ĺ‘',"OZZZ");
 
 str = str.replace('Ăş',"UXXX");
 str = str.replace('ĂĽ',"UYYY");
 str = str.replace('Ĺ±',"UZZZ");
 return str;
}

 var string1=stringCode(str1); 
 var string2=stringCode(str2); 
 
 if (string1<string2) val=-1;
 if (string1==string2) val=0;
 if (string1>string2) val=1;

 return (val);
}
/* ######### brod ######### */

var browser ={

 isIE: !!document.protocol,
 isGecko: !!window.atob,
 isOpera: !!window.opera,

 name: (
 document.protocol ? "ie" : (
 window.atob ? "gecko" : ( window.opera ? "opera" : undefined )
 )),

 version: (
 document.protocol ? (
 window.XMLHttpRequest ? 7 : (
 document.createComment ? 6 : (
 window.createPopup ? 5.5 : (
 window.clipboardData ? 5 : (
 window.showModalDialog ? 4 : undefined
 )
 )
 )
 )
 ) : undefined
 )

}/* ######### popup ######### */
/*
BUG: http://www.shaftek.org/blog/archives/000300.html
*/
function Popup(activeLink){
 
 this.activeLink=activeLink;
 this.href=this.activeLink.getAttribute("href");
 this.screenWidth=screen.width;
 this.screenHeight=screen.height;
 this.popupWidth=this.activeLink.getAttribute("popupwidth");
 this.popupHeight=this.activeLink.getAttribute("popupheight");
 this.scroll=this.activeLink.getAttribute("popupscroll");


 var parts=this.href.split(".");
 if ((parts[1]=="jpg") || (parts[1]=="gif") || (parts[1]=="png")){
 this.imageURL=this.href;
 this.createImage();
}

 this.left=(this.screenWidth-this.img.width)/2; 
 this.top=(this.screenHeight-this.img.height)/2-20;

 this.settings="toolbars='no'";
 this.settings+=",width="+this.img.width;
 this.settings+=",height="+this.img.height;
 this.settings+=",left="+this.left;
 this.settings+=",top="+this.top;
 if (this.scroll) this.settings+=",scrollbars=1";

 this.setTitle();
 this.openCenteredWindow();
}

Popup.prototype.setTitle=function(){
 this.title=this.activeLink.firstChild.getAttribute("title");
 if (!this.title){
 this.title="";
}
}



Popup.prototype.createImage=function(){
 this.maxWidth=Math.round(this.screenWidth*0.97);
 this.maxHeight=Math.round(this.screenHeight*0.86);
 this.img=document.createElement("img");
 this.img.src=this.imageURL;
 this.ratio=this.popupWidth/this.popupHeight;
 this.maxRatio=this.maxWidth/this.maxHeight;

 if ( (this.popupWidth>this.maxWidth) || (this.popupHeight>this.maxHeight) ){
 if (this.ratio<this.maxRatio){
 this.img.width=Math.round(this.popupWidth*(this.maxHeight/this.popupHeight));
 this.img.height=this.maxHeight;
}else{
 this.img.height=Math.round(this.popupHeight*(this.maxWidth/this.popupWidth));
 this.img.width=this.maxWidth;
}
}else{
 /* 
 ha nem kell atmeretezni, akkor akkora lesz a kep, amekkora meg volt adva a
 popupWidthben.
 - miert kell ezt megadni, hiszen a createElement("img") beallitja ezeket, nem?
 - NEM! ugyanis harabb lefut a script, mint a bongeszo letolteni a kepet, igy
 ha nem allitjuk be ezeket az ertekeket, akkor 0-t adnak vissza... :(
 
 irodalom: http://www.quirksmode.org/css/displayimg.html
 */
 this.img.width=this.popupWidth;
 this.img.height=this.popupHeight;
}
}


Popup.prototype.openCenteredWindow=function(){

 this.name=this.imageURL.split("/");
 this.name=this.name[this.name.length-1].replace(".", "_");

 var popup=window.open("", this.name, this.settings);


 var pd=popup.document;




 var innerHTML="<head><title>"+this.title+"</title></head><body style='margin: 0px; padding: 0px;'><table cellspacing=0 cellpadding=0 style='margin: 0; padding: 0; width: 100%; height: 100%;'><tr><td style='vertical-align: middle;'><img src='"+this.imageURL+"' style='display: block;'></td></tr></table></body>";
 pd.open();
 pd.write(innerHTML);
 pd.close();


 /*
 this.img.onclick=function(){
 alert(window.creator);
 alert(popup.wiktor); 
 self.close();
}
 */


/* if (pd.body.childNodes.length==0){
 pd.body.appendChild(this.img);
}*/
 popup.focus();
}


/**** POPUP HTML */


function PopupHTML(activeLink){
 
 if (isArray(activeLink)){
 this.href=activeLink[0];
 this.popupWidth=activeLink[1];
 this.popupHeight=activeLink[2];
 this.scroll=activeLink[3];
}else{
 this.activeLink=activeLink;
 this.href=this.activeLink.getAttribute("href");
 this.popupWidth=this.activeLink.getAttribute("popupwidth");
 this.popupHeight=this.activeLink.getAttribute("popupheight");
 this.scroll=this.activeLink.getAttribute("popupscroll");
}
 
 this.screenWidth=screen.width;
 this.screenHeight=screen.height;
 this.left=(this.screenWidth-this.popupWidth)/2; 
 this.top=(this.screenHeight-this.popupHeight)/2-20;

 this.settings="toolbars='no'";
 this.settings+=",width="+this.popupWidth;
 this.settings+=",height="+this.popupHeight;
 this.settings+=",left="+this.left;
 this.settings+=",top="+this.top;

 if (this.scroll) this.settings+=",scrollbars=yes";
 
 this.openCenteredWindow();
 
}

PopupHTML.prototype.openCenteredWindow=function(){








 var tmp="";

 this.name=this.href;

 for (i=0; i<this.name.length; i++){
 if (
 (this.name.charAt(i)<'a') ||
 (this.name.charAt(i)>'z')
 ){
 tmp=tmp+"";
}else{
 tmp=this.name.charAt(i).toLowerCase();
}
}
 this.name=tmp;


 
 this.mywindow=window.open(this.href, this.name, this.settings);


/* this.onclick=function(){
 this.close();
}*/
/* this.onbeforeunload=function(){
 return true;
}*/

 if (window.focus){
 this.mywindow.focus(); 
}
 
 return false;
}


function init_Popups(){
 var links=document.getElementsByTagName("a");
 for (var i=0; i<links.length; i++){
 if (links[i].getAttribute("rel")=="popup"){
 var parts=links[i].getAttribute("href").split(".");
 if (
 (parts[1]=="jpg") || (parts[1]=="gif") || (parts[1]=="png")
 ){
 var onclick_function=function (ev){
 if (!ev) var ev = window.event;


 new Popup(this);

 if (ev.preventDefault){
 ev.preventDefault(); ev.stopPropagation();
}else{
 ev.cancelBubble = true; ev.returnValue = false;
}
 return false;
}
}else{
 var onclick_function=function (ev){
 if (!ev) var ev = window.event;

 new PopupHTML(this);

 if (ev.preventDefault){
 ev.preventDefault(); ev.stopPropagation();
}else{
 ev.cancelBubble = true; ev.returnValue = false;
}
 return false;
}
}
 links[i].onclick=onclick_function;
}
}
}/* ######### treemenu ######### */
/**
 * w_treemenu_Init
 * Wiktor Tree Menu - Nyithato, csukhato fa-szerkezetu menurendszer inicializalo
 *
 * Started at: 2004.05.14.
 * Last modified: 2004.11.18.
 *
 */
var openedIDs;

function init_treemenu(divID)
{

 if (!document.getElementsByTagName) return; 

 var wtm_cookie='openedIDs';

 var buttonclass='wtmbutton';

 var imgOpen='/images/plus.png';
 var imgClose='/images/minus.png';
 var imgWidth=9;

 openedIDs=new Array();

 openedIDs=(document.getElementById('wtmactualid'))?document.getElementById('wtmactualid').value.split(','):[];

 openedIDs=(readCookie(wtm_cookie)?readCookie(wtm_cookie).split(','):openedIDs);



 if (!document.getElementById(divID)){return;}
 var wtmDIV = document.getElementById(divID); 
 var lists = wtmDIV.getElementsByTagName("li"); 
 for (var i=0; i<lists.length; i++) 
{
 var list=lists[i];
 list.menuid=i;

 if (list.getElementsByTagName('ul').length>0)
{

 var as=list.getElementsByTagName("a");

 for (var k=0; k<as.length; k++){

 var sHREF=as[k].getAttribute("href");
 var tHREF=document.location.pathname;

 if (sHREF.substr(sHREF.length-tHREF.length)==tHREF){


 openedIDs[openedIDs.length]=i;
}
}

/* for (var k=0; k<as.length; k++) 
{

 var a=as[k];
 list.onclick=function()
{
 alert('BUBLING '+this.menuid);
 if (openedIDs.inArray(this.menuid)==false)
{
 openedIDs[openedIDs.length]=this.menuid;
}

}
}*/


 /* mozilla elhasal az xhtml miatt az innerhtml-en
 http://www.quirksmode.org/dom/tests/innerhtmltest.xhtml
 az operanak, meg nem jo az insertbefore */
 if (browser.isGecko){
 newimg=document.createElement('img');
 newimg.src=imgOpen;
 newimg.setAttribute("class", buttonclass);

 list.insertBefore(newimg, list.firstChild);


}else{
 list.innerHTML='<img src='+imgOpen+' class="'+buttonclass+'"> '+list.innerHTML;
}

 var img=list.getElementsByTagName("img")[0];

 if (inArray(openedIDs,i))
{
 ul=list.getElementsByTagName("ul")[0];
 img.src=(ul.style.display=='block'?imgOpen:imgClose);
 ul.style.display=(ul.style.display=='block'?'none':'block');
}


}else 
{
 list.style.paddingLeft=(imgWidth+5)+"px";
}// endif
}// endfor


 var imgs=wtmDIV.getElementsByTagName("img"); 


 for (var i=0; i<imgs.length; i++) 
{
 var img=imgs[i];
 if (
 (img.getAttribute("className") == buttonclass) || // IE
 (img.getAttribute("class") == buttonclass) // NS
 )
{// Ha talalunk felprogramozzunk az onclick-et
 img.onclick=function()
{


 var li=this.parentNode;

 ul=li.getElementsByTagName("ul")[0];

 this.src=(ul.style.display=='block'?imgOpen:imgClose);

 ul.style.display=(ul.style.display=='block'?'none':'block');

 if (ul.style.display=='block') 
{

 openedIDs[openedIDs.length]=li.menuid;
}else
{// vagy a csukast, azaz kitoroljuk a tombbol

 openedIDs=delElementWithValue(openedIDs,li.menuid);
}





 createCookie(wtm_cookie,openedIDs);
}// end of onclick function

}// end if class is good
}// end for img tags

}// end of w_treemenu_Init/* ######### selector ######### */
/**
 * project name: miracle
 * task name: selector.js
 * author: wiktor
 * - - - - 
 * started @ 2005.06.27.
 * last modified @ see the timestamp ;)
 */

/**
 * a submitid is kell, mert ez alapjan lehet a kijelolteket etenyleg kijelolni
 */
function miracleSelector(id, submitid){


/** 
 * construct
 */
 
 
if (document.getElementById(id)){
 this.fieldset = document.getElementById(id);
}else{
 return false;
}

if (document.getElementById(submitid)){
 this.submit = document.getElementById(submitid);
}else{
 return false;
}


this.panels = new Array();
this.buttons = new Array();
this.original_si = new Array();

this.initPanels();

this.initButtons();

this.initSubmit();

}

/**
 * methods
 */
miracleSelector.prototype.Move = function(str){

}


miracleSelector.prototype.initPanels = function(){
 var panels=this.fieldset.getElementsByTagName("select");
 for (var i=0; i<panels.length; i++){
 this.panels[ panels[i].className ] = panels[i];

}
 
 var buttons=this.buttons;
 this.panels["left"].onfocus=function(){

 buttons["add"].style.display="inline";
}
 this.panels["right"].onfocus=function(){

 buttons["remove"].style.display="inline";
}
}

miracleSelector.prototype.initButtons = function(){
 var buttons=this.fieldset.getElementsByTagName("button");
 for (var i=0; i<buttons.length; i++){
 this.buttons[ buttons[i].className ] = buttons[i];
}

 var selector=this;
 this.buttons["add"].onclick=function(){

 selector.moveOptions("left", "right");
 return false;
}
 this.buttons["remove"].onclick=function(){

 selector.moveOptions("right", "left");
 return false;
}
}

function getFirstBiggerOption(select, option_text){
 var i=0;
 while (i<select.length && strcmp(select[i].firstChild.nodeValue, option_text)<=0){
 i++;
}
 return select[i];
}


function getSelectedOptions(select){
 var tmp=new Array();
 var j=0;
 for (var i=0; i<select.options.length; i++){
 if (select.options[i].selected){
 tmp[j]=i;
 j++;
}
}
 return tmp;
}


miracleSelector.prototype.moveOptions = function(from, to){

 var selected=getSelectedOptions(this.panels[from]);
 var selected_ids=new Array();

 var todo="add";
 if (to=="left") todo="del";

 for (var i=0; i<selected.length; i++){
 var si=selected[i]-i;
 var option=this.panels[from][si];

 selected_ids[i]=option.value;
 
 var clone=option.cloneNode(true);
 this.panels[from].removeChild(option);
 var firstbigger=getFirstBiggerOption(this.panels[to], option.firstChild.nodeValue);



 this.panels[to].appendChild(clone, firstbigger);

 
 
}
 
 var module=$('target_module');
 
 var destination_key=$('target_destination_key');

 if (destination_key){
 var destination = destination_key.value;
}

 handleUDRM(selected_ids,todo,module.value,destination);





}

/*
miracleSelector.prototype.addSelectedOptions = function(){
 var selected=this.getSelectedOptions(this.panels["left"]);

 var firstoption=this.panels["right"].options[0];
 if (firstoption && firstoption.value=='-1'){
 this.panels["right"].removeChild(firstoption);
}
 for (var i=0; i<selected.length; i++){
 var si=selected[i];
 var option=this.panels["left"][si];
 var clone=option.cloneNode(true);
 this.panels["left"].options[si].style.display="none";
 this.panels["right"].appendChild(clone);
 this.original_si[ this.panels["right"].length-1 ]=si;
}
}

miracleSelector.prototype.removeSelectedOptions = function(){
 var selected=this.getSelectedOptions(this.panels["right"]);
 for (var i=0; i<selected.length; i++){
 var si=selected[i];
 var original_index=this.original_si[si];
 this.panels["left"][original_index].style.display="block";

 var option=this.panels["right"][si-i];
 this.panels["right"].removeChild(option);
}
}
*/

miracleSelector.prototype.initSubmit = function(){
 var selector=this;
 this.submit.onclick=function(){
 var select=selector.panels["right"];
 for (var i=0; i<select.length; i++){
 select[i].selected=true;
}
 return true;
}
}
/* ######### tabs ######### */
/**
 * project name: miracle
 * task name: tabs.js
 * author: wiktor
 * - - - - 
 * started @ 2005.08.06.
 * last modified @ see the timestamp ;)
 */

addEvent(window, 'load', init_tabs);

function init_tabs(){
 tabBoxes=new Array();
 var tabPanels=document.getElementsByTagNameAndAttribute("*", "tabbox", "/.+/");
 
 for (var i=0; i<tabPanels.length; i++){
 var tabPanel=tabPanels[i];


 if (tabPanel.getAttribute("tabpanel")) continue;
 
 var tabBox_name=tabPanel.getAttribute("tabbox");
 if (!tabBoxes[tabBox_name]){
 tabBoxes[tabBox_name]=new tabBox(tabBox_name);
}
 tabBoxes[tabBox_name].addTabPanel(tabPanel);
}
}

/**
 * tabBox class
 */
function tabBox(name){

this.name = name;
this.panels = new Array();
this.tabs = new Array();

}

tabBox.prototype.addTabPanel = function(panel){

 var id=new String(panel.getAttribute("id"));
 if (!id.match(/tab_.+_.+/)){
 return alert("MIRACLE_TABS: Error in panel name id attribute: "+id);
}
 var panelName=panel.getAttribute("id").split("_")[2];
 this.panels[panelName]=panel;
 this.addTabForPanel(panelName);
}

tabBox.prototype.addTabForPanel = function(panelName){

 var tabs=document.getElementsByTagNameAndAttribute("*", "tabpanel", panelName);

 for (var i=0; i<tabs.length; i++){
 if (tabs[i].getAttribute("tabbox")==this.name) break;
}
 if (tabs[i].getAttribute("tabbox")==this.name){
 this.tabs[panelName]=tabs[i];
}

 var panels=this.panels;
 this.tabs[panelName].onclick=function(){
 var panelName=this.getAttribute("tabpanel");
 for (var i in panels){
 if (i==panelName){
 panels[i].style.display="block";
}else{
 panels[i].style.display="none";
}
}
}// end of onclick
}
/* ######### plug-in ######### */
/**
 * project name: miracle
 * task name: plug-in.js
 * author: wiktor
 * - - - - 
 * started @ 2005.08.17.
 * last modified @ c do timestamp ;)
 *
 */

addEvent(window, 'load', initPlugIns);

function initPlugIns(){
 if (miracle.config['miracle_plug-in']){

 var form=document.getElementsByTagName("form")[0];
 if (form){
 miracleSetFormButtonElements(form);

 Event.observe(form, "submit", function(event){
 this.submit();


 var parameters=new Array();
 parameters[0]=getBlockId();
 parameters[1]=arrayValues(miracleGetValuesFromForm(this));
 window.opener.miraclePlugInReturnValue=server_action("newsletter", "block_return", parameters, false);


 window.close();
 return false;
});
/* window.onbeforeunload=function(){
 var form=document.getElementsByTagName("form")[0];
 var p=arrayValues(miracleGetValuesFromForm(form));
 printfire(p);
 alert('onunload');
}*/
}
}
}

function getBlockId(){

 var url=new String(document.location).split("?");
 url=url[0];
 urlParts=new String(url).split("/");
 var tmp=urlParts[urlParts.length-1];

 return tmp;
}

function miracleSetFormButtonElements(form){
 var buttons=form.getElementsByTagName("button");
 for (var i in buttons){
 buttons[i].onclick=function(){
 form.submitButton=this.value;
}
}
}

function miracleGetValuesFromForm(form){
 var values=new Array();
 for (var i=0; i<form.elements.length; i++){
 var element=form.elements[i];
 var name=element.getAttribute("name");
 if (!name) continue; // ha nincs neve, akkor megyunk tovabb
 var value;
 switch (element.tagName){
 case "BUTTON":
 value=form.submitButton;
 break;
 default:
 value=element.value;
 break;
}
 values[name]=encode_utf8(value);
}
 return values;
}/* ######### file_upload ######### */
/**
 * project name: miracle
 * task name: file_upload.js
 * author: wiktor
 * - - - - 
 * started @ 2005.11.17.
 * last modified @ see the timestamp ;)
 */

function initSwfUpload(){
 var elements=new Array();
 var fups=new Array();
 var j=0;

 elements=document.getElementsByClassName("swf_file_upload");

 if( elements.length && isNaN(flashVersion) ){//flashVersion változó swf_upload.js-ben van
 elements[0].innerHTML = "Nincs Flash lejátszó telepítve, vagy a plugin ki lett kapcsolva.";
 elements[0].style.display = "block";
 return;
}

 for (var i=0; i<elements.length; i++){
 classname=elements[i].id.substr(0,elements[i].id.length-3);
 temp=document.getElementById(classname+"_hidden_id").name;
 maxfile=elements[i].getAttribute("maxfile");
 if (!maxfile) maxfile=1;
 maxsize=elements[i].getAttribute("maxsize");
 if (!maxsize) maxsize=102400;
 
 window[classname] = new SWFUpload({

 upload_url: "/upload.php?hidden_name="+classname+"_hidden_id&sesid="+temp, // Relative to the SWF file (or you can use absolute paths)
 post_params:{"PHPSESSID" : 1},
 hidden_id: classname+"_hidden_id",

 file_size_limit : maxsize, // "102400", // 100MB
 file_types : "*.*",
 file_types_description : "All Files",
 file_upload_limit : maxfile,
 file_queue_limit : "0",

 /*****************
 * SWFUpload 2.2 *
 *****************/

 button_image_url : "/images/miracle/SWFUploader2.2UploadButton.png",
 button_width: 61,
 button_height: 22,


 file_dialog_start_handler : fileDialogStart,
 file_queued_handler : fileQueued,
 file_queue_error_handler : fileQueueError,
 file_dialog_complete_handler : fileDialogComplete,
 upload_start_handler : uploadStart,
 upload_progress_handler : uploadProgress,
 upload_error_handler : uploadError,
 upload_complete_handler : uploadComplete,
 file_complete_handler : fileComplete,

 ui_container_id : classname+"_ui",


 debug: false
});

 if( flashVersion > 8 ){

 window[classname].flash_url = "/flash/swfupload2.swf"; // Relative to this file (or you can use absolute paths)

 var divs = $$("div.swf_file_upload");
 if( divs.length ){
 divs.each( function (div){
 div.style.display = "block";
});
}
}
 else{
 window[classname].flash_url = "/flash/swfupload.swf"; // Relative to this file (or you can use absolute paths)
}

 window[classname].customSettings.progressTarget = classname+"_progress"; // Add an additional setting that will later be used by the handler.
 window[classname].customSettings.cancelButtonId = classname+"_cancel"; // Add an additional setting that will later be used by the handler.
}

}
 
addEvent(window, "load", initSwfUpload);

var fileUpload=Class.create();
fileUpload.prototype ={

 initialize: function (fieldSetId){
 this.fieldSet=$(fieldSetId);
 this.id=this.fieldSet.getAttribute("id");
 this.legend=this.fieldSet.getElementsByTagName("legend")[0];
 this.files=this.fieldSet.getElementsByTagName("fieldset")[0];
 this.fileInputs=$(this.id+"_fileinput");
 this.maxFiles=this.fieldSet.getAttribute("maximum_files");

 this.fileInput=Form.getInputs(this.fieldSet, "file")[0];
 if (this.fileInput.getAttribute("accept")){
 this.accept=this.fileInput.getAttribute("accept").split(",");
 for (var i=0; i<this.accept.length; i++){
 this.accept[i]=this.accept[i].replace(/^\s+|\s+$/, '').toLowerCase();
}
}else{
 this.accept=new Array();
}

 this.fileInput.onchange=this.addFile.bindAsEventListener(this);
},

 fileExtension: function (filename){
 var tmp=filename.split(".");
 return tmp[tmp.length-1].toLowerCase();
},

 fileExists: function (filename){
 var files=Form.getInputs(this.files);
 for (var i=0; i<files.length; i++){
 if (files[i].value==filename){
 return true;
}
}
 return false;
},

 removeFile: function(e){
 var _this=Event.element(e);
 for (var i=0; i<this.selectedFiles.length; i++){
 if (this.selectedFiles[i].value==_this.id){
 new Element.remove(this.selectedFiles[i]);
 new Element.remove(_this.id);
 new Element.remove("fileinput_"+_this.id);
 this.fileInput.disabled=false;
}
}

 return false; 
},

 acceptableFile: function(filename){
 if (value.substring(0,1)!="/"){
 value=new RegExp("^"+value+"$", "i");
}else{
 value=new RegExp(value.substring(1, value.length-1), "i");
}
},

 getFileSize: function(filename){
 var tmp=Math.random()*1000;
 var iframe = document.createElement("iframe");
 var iframe = document.setAttribute("target");
 
 return tmp;
},

 addFile: function(e){
 if (this.fileExists(this.fileInput.value)){
 if ($("error")) new Element.remove("error");
 new Insertion.After(this.fileInput, '<span id="error">Ismétlés</span>')
}else{
 if ($("error")) new Element.remove("error");

 if (
 this.accept.length>0 &&
 !inArray(this.accept, this.fileExtension(this.fileInput.value))
 ){
 new Insertion.After(this.fileInput, '<span id="error">Érvénytelen fájltípus!</span>')
}else{

 if (this.maxFiles==1){
 this.fileInput.setAttribute('name', this.id);
}else{
 this.fileInput.setAttribute('name', this.id+"[]");
}

 var newInput = document.createElement("input");
 newInput.setAttribute('type', 'file');
 newInput.setAttribute('class', 'fileinput');
 $(this.fileInputs).appendChild(newInput);

 this.fileInput.setAttribute('id', "fileinput_"+this.fileInput.value);
 this.fileInput.style.display="none";

 var newDisplayInput=document.createElement("input");

 newDisplayInput.value=this.fileInput.value;
 this.files.appendChild(newDisplayInput);
 new Insertion.After(newDisplayInput, '<button id="'+newDisplayInput.value+'">Törlés</button>')
 $(newDisplayInput.value).onclick=this.removeFile.bindAsEventListener(this);
 this.selectedFiles=Form.getInputs(this.files);
 
 this.fileInput=newInput;
 this.fileInput.onchange=this.addFile.bindAsEventListener(this);
 if (this.selectedFiles.length==this.maxFiles){
 this.fileInput.disabled=true;
}
}
}
}


}/* ######### miracle_ajaxupdater ######### */
/**
 * @url http://slayeroffice.com/code/custom_checkbox/
 * @url http://www.encytemedia.com/blog/articles/2006/02/08/working-with-events-in-prototype
 */

var miracleAjaxUpdater = Class.create();

miracleAjaxUpdater.prototype ={
 
 initialize: function(){


 this.elements = document.getElementsByTagNameAndAttribute("a", "ajax_target", "/.+/");
 this.elements.each(
 function(element){
 Event.observe(element, "click", this.onClick.bindAsEventListener(this));
}.bind(this)
 );

 Ajax.Responders.register({
 onComplete: function(){

 document.body.style.cursor = 'default';
}
})
},

 onClick: function(event){
 var source = Event.element(event);
 document.body.style.cursor = 'wait';
 source.style.cursor = 'wait';

 new Ajax.Updater(
 source.getAttribute("ajax_target"),
 source.href, 
{
 method: "get", 
 requestHeaders: ["X-Miracle-Request", "ajax_html"],
 evalScripts: true
});
 Event.stop(event);
 return false;
}

}
/* ######### miracle_checkboxes ######### */
/**
 * @url http://slayeroffice.com/code/custom_checkbox/
 * @url http://www.encytemedia.com/blog/articles/2006/02/08/working-with-events-in-prototype
 */

var miracleCheckbox = Class.create();

miracleCheckbox.prototype ={
 
 initialize: function(){

 this.miracleId=0;
 this.imageDirectory = "/images/";


 this.checkboxes = document.getElementsByTagNameAndAttribute("input", "src", "/.+/");

 this.checkboxes.each(
 function(checkbox){
 if (checkbox.type != "checkbox") return;
 checkbox.miracle ={
 id : this.miracleId,
 onImage : this.imageDirectory+checkbox.getAttribute("src")+"_on.gif",
 offImage : this.imageDirectory+checkbox.getAttribute("src")+"_off.gif",
 image : document.createElement("img")
};

 checkbox.miracle.image.style.display = "inline";
 checkbox.miracle.image.src = checkbox.checked ? checkbox.miracle.onImage : checkbox.miracle.offImage;
 checkbox.miracle.image.miracle ={
 id : this.miracleId
}

 checkbox.parentNode.insertBefore(checkbox.miracle.image, checkbox.nextSibling);
 Event.observe(checkbox, "click", this.onClick.bindAsEventListener(this));
 Event.observe(checkbox.miracle.image, "click", this.onClick.bindAsEventListener(this));
 Element.hide(checkbox);
 this.miracleId++;
}.bind(this)
 );

},

 onClick: function(event){
 var source = Event.element(event);
 var id = source.miracle.id;
 var target = this.checkboxes[id];
 if (source.tagName == "IMG"){
 target.checked = !target.checked;
}
 target.miracle.image.src = target.checked ? target.miracle.onImage : target.miracle.offImage;
}

}
/* ######### miracle_form ######### */
var miracleForm = Class.create();

miracleForm.prototype ={
 
 initialize: function(){
 this.repeats ={};
},

 init: function(){

 this.formAcceptNumeric();
 this.initAutoComplete();
 this.initAddress();
 this.initNumberGrouping();

 $$("fieldset.miracle_address").each(function(fieldset){
 new this.address(fieldset);
}.bind(this));
},

 autoFocus: function(){
 var f;
 if (
 (mp = document.getElementById("main_padding"))
 && (f = mp.getElementsByTagName("form")[0])
 ){
 Form.focusFirstElement(f);
}
},

 replaceWithSelect: function(element){
 return this.replaceWith("select", element);
},

 replaceWithInput: function(element){
 return this.replaceWith("input", element);
},

 replaceWith: function(newElementType, element){
 var newElement = document.createElement(newElementType);
 newElement.id = element.id;
 newElement.name = element.name;
 element.parentNode.insertBefore(newElement, element);
 new Element.remove(element);
 return newElement;
},

 initNumberGrouping: function(){
 $A(document.getElementsByTagName("input")).each(function(element){
 if (element.getAttribute("type") == "text" && $(element).hasClassName("grouped")){
 element.style.textAlign = "right";
 element.style.paddingRight = "2px";
 element.observe("keyup", function(e){
 var _this = Event.element(e);
 var s = $N(parseInt(_this.value.toString().replace(/ /g, "")), "").toString().split('').reverse().join(''), r = ''; 
 for (var i = 0; i < s.length; i++){
 r += (i > 0 && i % 3 == 0 ? ' ' : '') + s.charAt(i);
}
 _this.value = r.split('').reverse().join('');
});
}
});
},

 initAddress: function(){
 this.address = Class.create();
 this.address.prototype ={
 initialize: function (fieldset){
 this.fieldset = fieldset;
 this.zipCode = document.getElementsByClassName("zipcode", fieldset).first();
 this.counties = document.getElementsByClassName("counties", fieldset).first();
 this.city = document.getElementsByClassName("city", fieldset).first();

 this.cities = document.getElementsByClassName("city", fieldset).first();
 
 this.streets = document.getElementsByClassName("street", fieldset).first();
 this.street_other = document.getElementsByClassName("street_other", fieldset).first();
 this.street_number = document.getElementsByClassName("street_number", fieldset).first();

 
 if (this.streets.value=="not_street"){
 this.street_number.disabled=1;
}
 
 if (this.counties.value>0){
}else{
 this.city.disabled = 1;
 this.streets.disabled = 1;
}
 
 if (this.cities.value!=0){
}else this.streets.disabled = 1;

 if ((this.streets.value!="other") || (this.streets.disabled==1)){
 this.street_other.value="NULL";
 this.street_other.style.disabled= 0;
 this.street_other.style.display ="none";
}
 

 Event.observe(this.counties, "change", this.updateCitiesByCountyId.bindAsEventListener(this));
 Event.observe(this.cities, "change", this.updateStreetsByCityIdAndStreet.bindAsEventListener(this));
 Event.observe(this.streets, "change", this.streetOtherOption.bindAsEventListener(this));
},

 resetOnce: function(event){
 var element = Event.element(event);
 if (element.value == element.getAttribute("value")){
 element.value = "";
}
},

 validateAddress: function(event){
 var t = this.streets[this.streets.selectedIndex].value.split("-");
 var streetId = t[0];
 var streetTypeId = t[1];
 var p ={
 city_id: this.city[this.city.selectedIndex].value,
 street_id: streetId,
 street_type_id: streetTypeId,
 street_number: parseInt(this.streetNumber.value)
};

 var p2 = $H(p).values().findAll(
 function(value){
 return (value == parseInt(value));
}
 );
 if (p2.length == $H(p).values().length){
 miracle.ajax("miracle", "validate_address", p,

 function(address){
 if (address.first().street_number){
 this.streetNumber.value = address.first().street_number;
}
}.bind(this)
 );
}else{
 this.streetNumber.value = $N(this.streetNumber.value, "");
}
},
 streetOtherOption : function(event){
 if (this.streets.options[this.streets.selectedIndex].value=="other"){
 this.street_other.value="";
 this.street_other.style.display="block";
 this.street_other.disabled=0;
}else{
 
 this.street_other.value="NULL";
 this.street_other.style.display="none";
 this.street_other.disabled=1;
}

 if (this.streets.options[this.streets.selectedIndex].value=="not_street"){
 
 
 this.street_number.disabled=1;
 if (this.street_number.value=="") this.street_number.value=Math.round((Math.random()*999)+1); 
}else{
 this.street_number.disabled=0;
}
 
},
 updateCities: function(event){
 var zipCode = Event.element(event);
 miracle.ajax("miracle", "get_cities_by_zipcode", 
{
 zipcode: zipCode.value
}, 

 function(cities){
 if (cities.length > 0){
 this.city.value = cities.first().option;
}
/* if (cities.length > 0){
 if (errors.first()){
 this.fieldset.removeChild(errors.first());
}
 this.city = miracle.form.replaceWithSelect(this.city);
 miracle.form.updateSelect(this.city, cities);
 Event.observe(this.city, "change", this.updateStreets.bindAsEventListener(this));
 this.updateStreets();
}else{
 if (errors.length == 0){
 new Insertion.Bottom(this.fieldset, "<div class=error>Nincs ilyen iranyitoszam.</div>");
}
 this.city.value = "";
 this.zipCode.value = "";
 this.zipCode.focus();
}*/
}.bind(this)
 );
},

 updateStreetsByCityIdAndStreet:function(event){
 this.streets.disabled=1;
 this.cityid=this.city.options[this.city.selectedIndex].value;
 miracle.ajax("miracle", "street_by_cityid", 
{
 city_id: this.cityid
 
}, 
 
 function(streets){
 if (streets.length!=0){
 miracle.form.updateSelect(this.streets, streets);
}
}.bind(this)
 );
 this.streets.disabled = 0;
},
 updateCitiesByCountyId: function(event){
 this.city.disabled = 1;
 this.streets.disabled = 1;
 miracle.ajax("miracle", "get_cities_by_county_id", 
{
 county_id: this.counties.options[this.counties.selectedIndex].value
}, 

 function(cities){
 var errors = document.getElementsByClassName("error", this.fieldset);
 if (cities.length > 0){

 if (errors.first()){
 this.fieldset.removeChild(errors.first());
}
 
 this.city = miracle.form.replaceWithSelect(this.city);
 
 miracle.form.updateSelect(this.city, cities);

 Event.observe(this.city, "change", this.updateZipCode.bindAsEventListener(this));
 this.updateZipCode();
 this.city.disabled = 0;

}else{

}
}.bind(this)
 );
},
 
 updateZipCode: function(event){

 this.cityId = this.city.options[this.city.selectedIndex].value;

 if (this.counties.options[this.counties.selectedIndex].value!=5){
 miracle.ajax("miracle", "get_zipcode_by_city", 
{
 city_id: this.cityId
}, 

 function(zipcode){
 this.zipCode.value=zipcode;
}.bind(this)
 );
}else this.zipCode.value='';
 this.streets.disabled=1;
 
 miracle.ajax("miracle", "street_by_cityid", 
{
 city_id: this.cityId
 
}, 
 
 function(streets){
 if (streets.length!=0){
 miracle.form.updateSelect(this.streets, streets);

}
}.bind(this)
 );
 this.streets.disabled=0;

}
 /*
 updateStreets: function(event){

 var cityId = this.city.options[this.city.selectedIndex].value;
 miracle.ajax("miracle", "get_streets_by_city_id_and_zipcode", 
{
 city_id: cityId,
 zipcode: 0
}, 

 function(streets){
 this.streets = miracle.form.replaceWithSelect(this.streets);
 miracle.form.updateSelect(this.streets, streets);


}.bind(this)
 );
},
 
 updateStreetTypes: function(event){
 var streetId = this.streets.options[this.streets.selectedIndex].value;
 var cityId = this.city.options[this.city.selectedIndex].value;
 miracle.ajax("miracle", "get_street_types_by_zipcode_and_cityid_and_streetid", 
{
 zipcode: this.zipCode.value,
 city_id: cityId,
 street_id: streetId
}, 

 function(streettypes){
 this.streettypes = miracle.form.replaceWithSelect(this.streettypes);
 miracle.form.updateSelect(this.streettypes, streettypes);
}.bind(this)
 );
}*/
 
}

},

 initAutoComplete: function(){
 $$("input[miracle_autocomplete]").each(function(input){
 var updateDivId = input.id + "_autocomplete";
 new Insertion.After(input, '<div id="' + updateDivId + '" class="miracle_autocomplete"></div>');
 new Ajax.Autocompleter(input.id, updateDivId, '/-',{
 paramName: "autocomplete://" + input.getAttribute("miracle_autocomplete").replace(".", "/"),
 minChars: 3,
 frequency: 0
});
});
},

 autoSubmit: function(event){
 var form = Event.findElement(event || window.event, "form");
 var forbidden = Form.getElements(form).pluck("name");
 $H(document.location.search.toQueryParams()).each(function(array){
 if (forbidden.indexOf(array[0]) < 0){
 var input = Builder.node("input",{
 type: "hidden",
 name: array[0],
 value: (array[1] ? array[1] : "")
});
 form.appendChild(input);
}
});
 form.submit();

},

 formFixRadios: function(){
 if (!document.getElementsByTagName("input")) return false;
 miracle.addEventSelectorRule(
 "input[type=radio]:click", function(input, event){
 if (!input.miracleFirst){
 input.miracleFirst = true;
 input.miracleChecked = input.checked;
}else{
 input.miracle = !input.miracle;
 input.checked = input.miracle; 
}
}
 );
},

 OBSOLATE_formAcceptNumeric: function(){
 if (!document.getElementsByTagName("input")) return false;
 miracle.addEventSelectorRule(
 "input[accept=numeric]:keypress", function(input, event){
 var key = event.which || event.keyCode;
/* printfire(event);
 printfire(event.which);
 printfire(event.keyCode);
 printfire(event.charCode);*/
 alert("WHICH " + event.which);
 alert("KEYCODE" + event.keyCode);
 alert("CHARCODE" + event.charCode);

 if (event.charCode == 0){


 return true;
}
 if ( (event.charCode != 0) && [
 Event.KEY_BACKSPACE,
 Event.KEY_TAB,
 Event.KEY_RETURN,
 Event.KEY_ESC,
 Event.KEY_LEFT,
 Event.KEY_UP,
 Event.KEY_RIGHT,
 Event.KEY_DOWN,
 Event.KEY_DELETE,
 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, // szamok
 96, 97, 98, 99, 100, 101, 102, 103, 104, 105
 ].member(key) == false){
 Event.stop(event);

}else{

}
}
 );
},

 XXX_formAcceptNumeric: function(){
 if (!document.getElementsByTagName("input")) return false;
 miracle.addEventSelectorRule(
 "input[accept=numeric]:keydown", function(input, event){
 var returnValue = false;
/* printfire(event);
 printfire(event.which);
 printfire(event.keyCode);
 printfire(event.charCode);*/
 var keyCode = (event.which) ? event.which : event.keyCode;

 if ( ((keyCode >= 48) && (keyCode <= 57)) || // All numerics
 (keyCode == 8) || // Backspace
 (keyCode == 13) 
 ){
 returnValue = true;
}

 if (event.returnValue){
 event.returnValue = returnValue;
}

 return returnValue; 
}
 );
},

 CCCC_formAcceptNumeric: function(){
 return true;
 if (!document.getElementsByTagName("input")) return false;
 miracle.addEventSelectorRule(
 "input[accept=numeric]:change", function(input, event){

 if (parseInt(input.value, 10) != input.value){
 input.value = 
 input.miraclePreviousValue ? input.miraclePreviousValue : "";
 Event.stop(event);
}else{
 input.miraclePreviousValue = input.value;
}
}
 );
},

 formAcceptNumeric: function(){
 if (!document.getElementsByTagName("input")) return false;
 $$("input[accept=numeric]").each(function(input){
 input.observe("keypress", function(event){
 var stop = miracle.form.maskInput(input, event, "9^");
 if (stop){
 Event.stop(event);
 stop = false;
}
});
});
},


 getRequiredFields: function(parent){
 var parent = parent || document;
 var tmp = document.getElementsByClassName("required", parent);
 return tmp;
},

 getValue: function(element){



 if ($(element.getAttribute("htmlfor"))){
 var input = $(element.getAttribute("htmlfor"));
 return input.value;
}
 if ($(element.getAttribute("for"))){
 var input = $(element.getAttribute("for"));
 return input.value;
}

 if (Element.hasClassName(element, "radio")){
 return this._getValueForRadio(element);
}

 if (Element.hasClassName(element, "checkbox")){
 return this._getValueForCheckbox(element);
}

 if (element.tagName.toLowerCase() == "select"){
 var tmp = element.options[element.options.selectedIndex].value;
 tmp = (tmp == "NULL") ? false : tmp;
 return tmp;
}

 tmp = !tmp ? null : tmp;
 return tmp;
},

 _getValueForRadio: function(parent){
 return this._getValueForInputSelector(parent, "radio");
},

 _getValueForCheckbox: function(parent){
 return this._getValueForInputSelector(parent, "checkbox");
},

 _getValueForInputSelector: function(parent, type){
 var tmp;
 var checked = Form.getInputs(parent, type).find(function(radio){
 return radio.checked;
});
 if (checked) tmp = checked.value;
 return tmp;
},

 findParentNode: function(element, parentNodeTagName){
 var parentNodeTagName = parentNodeTagName || "div";
 while (
 element.parentNode 
 && (!element.tagName 
 || (element.tagName.toUpperCase() != parentNodeTagName.toUpperCase()))
 ){
 element = element.parentNode;
}
 return element;
},

 errorForField: function(element, parentNodeTagName, action){
 var parentNode = this.findParentNode(element, parentNodeTagName);
 (action == "add" ) ? 
 Element.addClassName(parentNode, "error") :
 Element.removeClassName(parentNode, "error");
},

 isRequiredFieldsFilled: function(parent){

 var tmp = this.getRequiredFields(parent).all(function(element){
 var value = miracle.form.getValue(element);
 if (!value){
 miracle.form.errorForField(element, "td", "add");
/* if (element.focus){
 element.focus();
};*/
}else{
 miracle.form.errorForField(element, "td", "remove");
}
 return value;
});

 return tmp;
},

 limitTextArea: function(id, limit){
 if (!(t = document.getElementById(id))) return false;
 var c = document.createElement("div");
 var cs = c.style;
 cs.position = "absolute";
 tPos = miracle.findPos(t);
 cs.left = tPos[0] - 10 + "px";
 cs.top = tPos[1] - 10 + "px";
 Element.addClassName(c, "textarea_counter");
 document.getElementsByTagName("body")[0].appendChild(c);
 c.innerHTML = $N(t.value.length);
 var keyCodes = [8,33,34,36,35,37,38,39,40,46];
 Event.observe(t, "keydown", function(e){
 var k = (e.which + 1 || e.keyCode + 1) - 1 || 0;
 this.value = this.value.substring(0, 40);
 if (this.value.length > limit && !keyCodes.member(k)){
 Event.stop(e);
}
}.bindAsEventListener(t));

 Event.observe(t, "keyup", function(e){
 this.value = this.value.substring(0, 40);
 c.innerHTML = this.value.length;
}.bindAsEventListener(t));
},


 maskInput: function (f, e, m){
 e.key = (e.which + 1 || e.keyCode + 1) - 1 || 0;
 if (
 (document.protocol)
 && ($A([96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 15, 9, 37, 38, 39, 40, 46]).indexOf(e.key) != -1)
 ){
 return false;
}
/* printfire(f.value);
 printfire(e.key);
 printfire(m);*/
 var patterns ={"1": /[A-Z]/i, "2": /[0-9]/, "4": /[A-y]/i, "8": /./};
 var rules ={"a": 3, "A": 7, "9": 2, "C":5, "c": 1, "*": 8};

 function accept(c, rule){
 for (var i = 1, r = rules[rule] || 0; i <= r; i<<=1)
 if (r & i && patterns[i].test(c)) break;
 return i <= r || c == rule;
}

 function _stop(){
 stop = true;
 return;
}

 var stop = false;
 var k, mC, r, c = String.fromCharCode(k = e.key), l = f.value.length;
 (!k || k == 8 ? 1 : (r = /^(.)\^(.*)$/.exec(m)) && (r[0] = r[2].indexOf(c) + 1) + 1 ?
 r[1] == "O" ? r[0] : r[1] == "E" ? !r[0] : accept(c, r[1]) || r[0]
 : (l = (f.value += m.substr(l, (r = /[A|9|C|\*]/i.exec(m.substr(l))) ?
 r.index : l)).length) < m.length && 
 accept(c, m.charAt(l))) || _stop();
 return stop;
/* || e.preventDefault()*/
},

 /**
 * Egy <select> frissitese, felulirasa uj adatokkal
 *
 * @author wiktor@eworld.hu
 * @since 2006-06-19
 * @version 2006-06-19.wiktor
 * @param string|element id $()-nak atadhato parameter
 * @param object options az options "tomb" nev/ertek parok
 * @return boolean sikeres volt-e a modositas
 *
 * @see http://msdn.microsoft.com/workshop/author/perf/dhtmlperf.asp#Expand_Your_Options_in_a_SELECT_Element
 */
 updateSelect: function(id, options){
 var i = options.length;


 if (!(select = $(id))) return false;
 select.options.length = 0;



/* while (i--){
 select.options[i] = new Option(i + " " + options[i].option, options[i].value);
 if (i == 76) break;
}*/

 var innerHTM = "";
 for (var i = 0; i<options.length; i++){



 select.options[i] = new Option(options[i].option, options[i].value);
}


 return true;
},

 addOptions: function(id, options){
 if (!(select = $(id))) return false;
 var startLength = select.options.length;
 for (var i = 0; i<options.length; i++){
 select.options[startLength + i] = new Option(options[i].option, options[i].value);
}
},

 post: function(url){
 var form = Builder.node("form",{
 method: "post",
 action: url
});

 document.getElementsByTagName("body")[0].appendChild(form);
 form.submit();
},

 deleteLink: function(selector){
 $$(selector).each(function(element){
 Event.observe(element, "click", function(event){
 if (confirm(element.getAttribute("confirm"))){
 miracle.form.post(this.href);
}
 Event.stop(event);
}.bind(element));
}.bind(this));
}


}// end of class
/* ######### miracle_tabs ######### */
/**
 * @url http://slayeroffice.com/code/custom_checkbox/
 * @url http://www.encytemedia.com/blog/articles/2006/02/08/working-with-events-in-prototype
 */

var miracleTabs = Class.create();

Element._hide = function(element){
/* element.setStyle({
 visibility: "hidden",
 height: "0px",
 overflow: "hidden",
 margin: "0px",
 padding: "0px"
});*/
 Element.hide(element);
}

Element._show = function(element){
/* element.setStyle({
 visibility: "visible",
 overflow: "auto",
 display: "block"
});*/
 Element.show(element);
 element.getElementsByClassName("flexcroll").each(function(scroll){
 if (typeof(scroll.scrollUpdate) == "function"){
 scroll.scrollUpdate();
}
});
}

miracleTabs.prototype ={

 initialize: function(){

 this.containers = document.getElementsByClassName("miracle_tab_container");

 this.containers.each(function(container, i){



 container.miracle ={
 id: i
};
 this.initializeContainer(container);
}.bind(this)); 



 if (typeof(unFocus) == "object"){
 unFocus.History.addEventListener("historyChange", this.historyListener.bind(this));
 this.historyListener(unFocus.History.getCurrent());
}
},

 initializeContainer: function(container){

 var ulId = "miracle_tab_control_" + (container.miracle.id + 1);

 var tabControlHTML = "<ul id='"+ulId+"' class='miracle_tab_control'>";

 container.setAttribute("id", "miracle_tab_container_" + (container.miracle.id + 1));

 container.panels = $$("#" + container.id + " .miracle_tab_panel");
 var titles = $$("#" + container.id + " h1");

 container.panels.each(function(panel, i){


 panel.miracle ={
 id: i
};

 if (!Element.hasClassName(panel, "active")){
 Element._hide(panel);
 var active = " class='tab_" + (i + 1) + "'";
 var id = " id='" + ulId + "_tab_" + (i + 1) + "'";

}else{

 var active = " class='active tab_" + (i + 1) + "'";
 var id = " id='" + ulId + "_tab_" + (i + 1) + "_active'";

}


 tabControlHTML = tabControlHTML + "<li " + id + active + "><span><a href='#'>" + (titles[i].innerHTML) + "</a></span></li>";
 Element.hide(titles[i]);

}.bind(this)); // ugyanazert van itt a bind, bar most eppen nem hasznaltuk ki

 tabControlHTML = tabControlHTML + "</ul>";

 new Insertion.Top(container, tabControlHTML);

 container.tabControl = $(ulId);

 this.initializeTabControl(container);
 container.style.display = "block";
},

 initializeTabControl: function(tabContainer){

 $$("#"+tabContainer.tabControl.id+" li a").each(function(aTab, i){


 Event.observe(aTab, "click", this.switchTab.bindAsEventListener(this));

 aTab.miracle ={
 container: tabContainer,
 panel: tabContainer.panels[i]
};

 tabContainer.panels[i].miracle ={
 tab: aTab
};
}.bind(this)); // itt se hasznaltunk this-t, de ez mar megszokas... :)
},

 switchTab: function(event){


 var source = Event.element(event);

 Event.stop(event);

 if (Element.hasClassName(source.parentNode, "active")){

 source.parentNode.firstChild.blur();

 return false;
}

 var control = source.parentNode.parentNode.parentNode;

 var previousNotFilled;
 var actived;


 $$("#" + control.id + " li").any(function(liTab, i){


 var tab = liTab.firstChild.firstChild;

 /** nem tartozik a tab-okhoz **/

 $A(tab.miracle.panel.getElementsByTagName("td")).each(function(cell){
 Element.removeClassName(cell, "error");
});

 var notFilled = !miracle.form.isRequiredFieldsFilled(tab.miracle.panel);

 if ( (tab == source) ){
 actived = i;
 if (typeof(unFocus) == "object"){

 unFocus.History.addHistory(liTab.id.replace("miracle_tab_control", "mtc"));
}


 Element.addClassName(liTab, "active");
 liTab.setAttribute("id", liTab.getAttribute("id").replace("_active", "") + "_active");

 Element._show(tab.miracle.panel);


 liTab.firstChild.blur();
 if (notFilled) return notFilled;
}else{



 if (!notFilled || (i > actived)){


 Element.removeClassName(liTab, "active");
 liTab.setAttribute("id", liTab.getAttribute("id").replace("_active", ""));

 Element._hide(tab.miracle.panel);
}
}

 previousNotFilled = notFilled;
 return notFilled;
});

 return false;
},

 showTab: function(id){
 return false;
 if (!id) return false;
 var parts = id.split("_");
 var active = parts[3];
 var selector = "#miracle_tab_control_" + parts[1] + " .miracle_tab_panel";
 $$(selector).each(function(panel, i){
 printfire("panel");
 if (i == active){
 Element._show(panel);
}else{
 Element._hide(panel);
}
});
},

 historyListener: function(historyHash){

 var i = $N(historyHash.split("_")[3] - 1);
 if (!this.containers[0]){
 return false;
}
 var p = this.containers[0].panels[i];
 if (!Element.visible(p) && historyHash){
 this.switchTab({
 target: p.miracle.tab
});
}
/* if ($("pager")){
 $$("#pager a").each(function(a){
 
 if (a.href.indexOf("#") == -1){
 a.href += "#" + historyHash;
}else{
 a.href = a.href.replace(/#.+/, historyHash);
}
 
 a.alt = a.href;
});
}*/
}

}// end of class
/* ######### md5 ######### */
/*
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 * Digest Algorithm, as defined in RFC 1321.
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for more info.
 */

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
function hex_md5(s){return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function b64_md5(s){return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
function str_md5(s){return binl2str(core_md5(str2binl(s), s.length * chrsz));}
function hex_hmac_md5(key, data){return binl2hex(core_hmac_md5(key, data));}
function b64_hmac_md5(key, data){return binl2b64(core_hmac_md5(key, data));}
function str_hmac_md5(key, data){return binl2str(core_hmac_md5(key, data));}

/*
 * Perform a simple self-test to see if the VM is working
 */
function md5_vm_test()
{
 return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}

/*
 * Calculate the MD5 of an array of little-endian words, and a bit length
 */
function core_md5(x, len)
{
 /* append padding */
 x[len >> 5] |= 0x80 << ((len) % 32);
 x[(((len + 64) >>> 9) << 4) + 14] = len;

 var a = 1732584193;
 var b = -271733879;
 var c = -1732584194;
 var d = 271733878;

 for(var i = 0; i < x.length; i += 16)
{
 var olda = a;
 var oldb = b;
 var oldc = c;
 var oldd = d;

 a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
 d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
 c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
 b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
 a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
 d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
 c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
 b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
 a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
 d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
 c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
 b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
 a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
 d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
 c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
 b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);

 a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
 d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
 c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
 b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
 a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
 d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
 c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
 b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
 a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
 d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
 c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
 b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
 a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
 d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
 c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
 b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

 a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
 d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
 c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
 b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
 a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
 d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
 c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
 b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
 a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
 d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
 c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
 b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
 a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
 d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
 c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
 b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

 a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
 d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
 c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
 b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
 a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
 d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
 c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
 b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
 a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
 d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
 c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
 b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
 a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
 d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
 c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
 b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

 a = safe_add(a, olda);
 b = safe_add(b, oldb);
 c = safe_add(c, oldc);
 d = safe_add(d, oldd);
}
 return Array(a, b, c, d);

}

/*
 * These functions implement the four basic operations the algorithm uses.
 */
function md5_cmn(q, a, b, x, s, t)
{
 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}

/*
 * Calculate the HMAC-MD5, of a key and some data
 */
function core_hmac_md5(key, data)
{
 var bkey = str2binl(key);
 if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);

 var ipad = Array(16), opad = Array(16);
 for(var i = 0; i < 16; i++)
{
 ipad[i] = bkey[i] ^ 0x36363636;
 opad[i] = bkey[i] ^ 0x5C5C5C5C;
}

 var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
 return core_md5(opad.concat(hash), 512 + 128);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
 return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
function bit_rol(num, cnt)
{
 return (num << cnt) | (num >>> (32 - cnt));
}

/*
 * Convert a string to an array of little-endian words
 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
 */
function str2binl(str)
{
 var bin = Array();
 var mask = (1 << chrsz) - 1;
 for(var i = 0; i < str.length * chrsz; i += chrsz)
 bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
 return bin;
}

/*
 * Convert an array of little-endian words to a string
 */
function binl2str(bin)
{
 var str = "";
 var mask = (1 << chrsz) - 1;
 for(var i = 0; i < bin.length * 32; i += chrsz)
 str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
 return str;
}

/*
 * Convert an array of little-endian words to a hex string.
 */
function binl2hex(binarray)
{
 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
 var str = "";
 for(var i = 0; i < binarray.length * 4; i++)
{
 str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
 hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
}
 return str;
}

/*
 * Convert an array of little-endian words to a base-64 string
 */
function binl2b64(binarray)
{
 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 var str = "";
 for(var i = 0; i < binarray.length * 4; i += 3)
{
 var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
 | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
 | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
 for(var j = 0; j < 4; j++)
{
 if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
 else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
 return str;
}/* ######### sweetTitles ######### */




Array.prototype.inArray = function (value){
 var i;
 for (i=0; i < this.length; i++){
 if (this[i] === value){
 return true;
}
}
 return false;
};


var sweetTitles ={
 xCord : 0, // @Number: x pixel value of current cursor position
 yCord : 0, // @Number: y pixel value of current cursor position
 tipElements : ['abbr','acronym', 'img', 'a'], // @Array: Allowable elements that can have the toolTip
 obj : Object, // @Element: That of which you're hovering over
 tip : Object, // @Element: The actual toolTip itself
 active : 0, // @Number: 0: Not Active || 1: Active
 init : function(){
 if ( !document.getElementById ||
 !document.createElement ||
 !document.getElementsByTagName ){
 return;
}
 var i,j;
 this.tip = document.createElement('div');
 this.tip.id = 'toolTip';
 document.getElementsByTagName('body')[0].appendChild(this.tip);
 this.tip.style.top = '0';
 this.tip.style.visibility = 'hidden';
 var tipLen = this.tipElements.length;
 for ( i=0; i<tipLen; i++ ){
 var current = document.getElementsByTagName(this.tipElements[i]);
 var curLen = current.length;
 for ( j=0; j<curLen; j++ ){
 if (current[j].title){



 Event.observe(current[j], "mouseover", this.tipOver.bindAsEventListener(current[j]));
 Event.observe(current[j], "mouseout", this.tipOut.bindAsEventListener(current[j]));
 current[j].setAttribute('tip',current[j].title);
 current[j].removeAttribute('title');
}
}
}
},
 updateXY : function(e){
 if ( document.captureEvents ){
 sweetTitles.xCord = e.pageX;
 sweetTitles.yCord = e.pageY;
}else if ( window.event.clientX ){
 sweetTitles.xCord = window.event.clientX+document.documentElement.scrollLeft;
 sweetTitles.yCord = window.event.clientY+document.documentElement.scrollTop;
}
},
 tipOut: function(){
 if ( window.tID ){
 clearTimeout(tID);
}
 if ( window.opacityID ){
 clearTimeout(opacityID);
}
 sweetTitles.tip.style.visibility = 'hidden';
},
 checkNode : function(){
 var trueObj = this.obj;

 if (this.tipElements.inArray(trueObj.nodeName.toLowerCase()) ){
 return trueObj;
}else{
 return trueObj.parentNode;
}
},
 
 tipOver : function(e){
 sweetTitles.obj = this;
 tID = window.setTimeout("sweetTitles.tipShow()", 10);
 sweetTitles.updateXY(e);
},
 tipShow : function(){
 var scrX = Number(this.xCord);
 var scrY = Number(this.yCord);
 var tp = parseInt(scrY+15);
 var lt = parseInt(scrX+10);
 var anch = this.checkNode();
 var addy = '';
 var access = '';
 if ( anch.nodeName.toLowerCase() == 'a' ){


}else{
 if (anch.firstChild){
 addy = anch.firstChild.nodeValue;
}
}
 this.tip.innerHTML = "<p>"+anch.getAttribute('tip')+"<em>"+access+addy+"</em></p>";
 if ( parseInt(document.documentElement.clientWidth+document.documentElement.scrollLeft) < parseInt(this.tip.offsetWidth+lt) ){
 this.tip.style.left = parseInt(lt-(this.tip.offsetWidth+10))+'px';
}else{
 this.tip.style.left = lt+'px';
}
 if ( parseInt(document.documentElement.clientHeight+document.documentElement.scrollTop) < parseInt(this.tip.offsetHeight+tp) ){
 this.tip.style.top = parseInt(tp-(this.tip.offsetHeight+10))+'px';
}else{
 this.tip.style.top = tp+'px';
}
 this.tip.style.visibility = 'visible';
 this.tip.style.opacity = '.1';
 this.tipFade(10);
},
 tipFade: function(opac){
 var passed = parseInt(opac);
 var newOpac = parseInt(passed+10);
 if ( newOpac < 100 ){
 this.tip.style.opacity = '.'+newOpac;
 this.tip.style.filter = "alpha(opacity:"+newOpac+")";
 opacityID = window.setTimeout("sweetTitles.tipFade('"+newOpac+"')",20);
}
 else{
 this.tip.style.opacity = '1.0';
 this.tip.style.filter = "alpha(opacity:100)";
}
}
};
/* ######### jscolor ######### */
/**
 * jscolor, JavaScript Color Picker
 *
 * @version 1.2.2
 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
 * @author Honza Odvarko <honza@odvarko.cz>
 * @created 2008-06-15
 * @updated 2009-02-03
 * @link http://jscolor.com
 */


var jscolor ={


 dir : '', // location of jscolor directory (leave empty to autodetect)
 bindClass : 'color', // class name
 binding : true, // automatic binding via <input class="...">
 preloading : true, // use image preloading?


 install : function(){
 jscolor.addEvent(window, 'load', jscolor.init)
},


 init : function(){
 if(jscolor.binding){
 jscolor.bind()
}
 if(jscolor.preloading){
 jscolor.preload()
}
},


 getDir : function(){
 if(!jscolor.dir){
 var detected = jscolor.detectDir()
 jscolor.dir = detected!=false ? detected : 'jscolor/'
}
 return jscolor.dir
},


 detectDir : function(){
 var base = location.href

 var e = document.getElementsByTagName('base')
 for(var i=0; i<e.length; i++){
 if(e[i].href) base = e[i].href
}

 var e = document.getElementsByTagName('script')
 for(var i=0; i<e.length; i++){
 if(e[i].src && /(^|\/)jscolor\.js([?#].*)?$/i.test(e[i].src)){
 var src = new jscolor.URI(e[i].src)
 var srcAbs = src.toAbsolute(base)
 srcAbs.path = srcAbs.path.replace(/[^\/]+$/, '') // remove filename
 delete srcAbs.query
 delete srcAbs.fragment
 return srcAbs.toString()
}
}
 return false
},


 bind : function(){
 var matchClass = new RegExp('(^|\\s)('+jscolor.bindClass+')\\s*(\\{[^}]*\\})?', 'i')
 var e = document.getElementsByTagName('input')
 for(var i=0; i<e.length; i++){
 var m
 if(!e[i].color && e[i].className && (m = e[i].className.match(matchClass))){
 var prop ={}
 if(m[3]){
 try{
 eval('prop='+m[3])
}catch(eInvalidProp){}
}
 e[i].color = new jscolor.color(e[i], prop)
}
}
},


 preload : function(){
 for(var fn in jscolor.imgRequire){
 jscolor.loadImage(fn)
}
},


 images :{
 pad : [ 181, 101 ],
 sld : [ 16, 101 ],
 cross : [ 15, 15 ],
 arrow : [ 7, 11 ]
},


 imgRequire :{},
 imgLoaded :{},


 requireImage : function(filename){
 jscolor.imgRequire[filename] = true
},


 loadImage : function(filename){
 if(!jscolor.imgLoaded[filename]){
 jscolor.imgLoaded[filename] = new Image()
 jscolor.imgLoaded[filename].src = jscolor.getDir()+filename
}
},


 fetchElement : function(mixed){
 return typeof(mixed) == 'string' ? document.getElementById(mixed) : mixed
},


 addEvent : function(el, evnt, func){
 if(el.addEventListener){
 return el.addEventListener(evnt, func, false)
}else if(el.attachEvent){
 return el.attachEvent('on'+evnt, func)
}else{
 return false
}
},


 fireEvent : function(el, evnt){
 if(!el){
 return false
}else if(document.createEventObject){
 var ev = document.createEventObject()
 return el.fireEvent('on'+evnt, ev)
}else if(document.createEvent){
 var ev = document.createEvent('HTMLEvents')
 ev.initEvent(evnt, true, true)
 return el.dispatchEvent(ev)
}else if(el['on'+evnt]){// alternatively use the traditional event model (IE5)
 return el['on'+evnt]()
}else{
 return false
}
},


 getElementPos : function(e){
 var e1=e, e2=e
 var x=0, y=0
 if(e1.offsetParent){
 do{
 x += e1.offsetLeft
 y += e1.offsetTop
}while(e1 = e1.offsetParent)
}
 while((e2 = e2.parentNode) && e2.nodeName != 'BODY'){
 x -= e2.scrollLeft
 y -= e2.scrollTop
}
 return [x, y]
},


 getElementSize : function(e){
 return [e.offsetWidth, e.offsetHeight]
},


 getMousePos : function(e){
 if(!e) e = window.event
 if(typeof e.pageX == 'number'){
 return [e.pageX, e.pageY]
}else if(typeof e.clientX == 'number'){
 return [
 e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft,
 e.clientY + document.body.scrollTop + document.documentElement.scrollTop
 ]
}
},


 getViewPos : function(){
 if(typeof window.pageYOffset == 'number'){
 return [window.pageXOffset, window.pageYOffset]
}else if(document.body && (document.body.scrollLeft || document.body.scrollTop)){
 return [document.body.scrollLeft, document.body.scrollTop]
}else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)){
 return [document.documentElement.scrollLeft, document.documentElement.scrollTop]
}else{
 return [0, 0]
}
},


 getViewSize : function(){
 if(typeof window.innerWidth == 'number'){
 return [window.innerWidth, window.innerHeight]
}else if(document.body && (document.body.clientWidth || document.body.clientHeight)){
 return [document.body.clientWidth, document.body.clientHeight]
}else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)){
 return [document.documentElement.clientWidth, document.documentElement.clientHeight]
}else{
 return [0, 0]
}
},


 URI : function(uri){// See RFC3986

 this.scheme = null
 this.authority = null
 this.path = ''
 this.query = null
 this.fragment = null

 this.parse = function(uri){
 var m = uri.match(/^(([A-Za-z][0-9A-Za-z+.-]*)(:))?((\/\/)([^\/?#]*))?([^?#]*)((\?)([^#]*))?((#)(.*))?/)
 this.scheme = m[3] ? m[2] : null
 this.authority = m[5] ? m[6] : null
 this.path = m[7]
 this.query = m[9] ? m[10] : null
 this.fragment = m[12] ? m[13] : null
 return this
}

 this.toString = function(){
 var result = ''
 if(this.scheme != null) result = result + this.scheme + ':'
 if(this.authority != null) result = result + '//' + this.authority
 if(this.path != null) result = result + this.path
 if(this.query != null) result = result + '?' + this.query
 if(this.fragment != null) result = result + '#' + this.fragment
 return result
}

 this.toAbsolute = function(base){
 var base = new jscolor.URI(base)
 var r = this
 var t = new jscolor.URI

 if(base.scheme == null) return false

 if(r.scheme != null && r.scheme.toLowerCase() == base.scheme.toLowerCase()){
 r.scheme = null
}

 if(r.scheme != null){
 t.scheme = r.scheme
 t.authority = r.authority
 t.path = removeDotSegments(r.path)
 t.query = r.query
}else{
 if(r.authority != null){
 t.authority = r.authority
 t.path = removeDotSegments(r.path)
 t.query = r.query
}else{
 if(r.path == ''){
 t.path = base.path
 if(r.query != null){
 t.query = r.query
}else{
 t.query = base.query
}
}else{
 if(r.path.substr(0,1) == '/'){
 t.path = removeDotSegments(r.path)
}else{
 if(base.authority != null && base.path == ''){
 t.path = '/'+r.path
}else{
 t.path = base.path.replace(/[^\/]+$/,'')+r.path
}
 t.path = removeDotSegments(t.path)
}
 t.query = r.query
}
 t.authority = base.authority
}
 t.scheme = base.scheme
}
 t.fragment = r.fragment

 return t
}

 function removeDotSegments(path){
 var out = ''
 while(path){
 if(path.substr(0,3)=='../' || path.substr(0,2)=='./'){
 path = path.replace(/^\.+/,'').substr(1)
}else if(path.substr(0,3)=='/./' || path=='/.'){
 path = '/'+path.substr(3)
}else if(path.substr(0,4)=='/../' || path=='/..'){
 path = '/'+path.substr(4)
 out = out.replace(/\/?[^\/]*$/, '')
}else if(path=='.' || path=='..'){
 path = ''
}else{
 var rm = path.match(/^\/?[^\/]*/)[0]
 path = path.substr(rm.length)
 out = out + rm
}
}
 return out
}

 if(uri){
 this.parse(uri)
}

},


 /*
 * Usage example:
 * var myColor = new jscolor.color(myInputElement)
 */

 color : function(target, prop){


 this.required = true // refuse empty values?
 this.adjust = true // adjust value to uniform notation?
 this.hash = false // prefix color with # symbol?
 this.caps = true // uppercase?
 this.valueElement = target // value holder
 this.styleElement = target // where to reflect current color
 this.hsv = [0, 0, 1] // read-only 0-6, 0-1, 0-1
 this.rgb = [1, 1, 1] // read-only 0-1, 0-1, 0-1

 this.pickerOnfocus = true // display picker on focus?
 this.pickerMode = 'HSV' // HSV | HVS
 this.pickerPosition = 'bottom' // left | right | top | bottom
 this.pickerFace = 10 // px
 this.pickerFaceColor = 'ThreeDFace' // CSS color
 this.pickerBorder = 1 // px
 this.pickerBorderColor = 'ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight' // CSS color
 this.pickerInset = 1 // px
 this.pickerInsetColor = 'ThreeDShadow ThreeDHighlight ThreeDHighlight ThreeDShadow' // CSS color
 this.pickerZIndex = 10000


 for(var p in prop) this[p] = prop[p]


 this.hidePicker = function(){
 if(isPickerOwner()){
 removePicker()
}
}


 this.showPicker = function(){
 if(!isPickerOwner()){
 var tp = jscolor.getElementPos(target) // target pos
 var ts = jscolor.getElementSize(target) // target size
 var vp = jscolor.getViewPos() // view pos
 var vs = jscolor.getViewSize() // view size
 var ps = [ // picker size
 2*this.pickerBorder + 4*this.pickerInset + 2*this.pickerFace + jscolor.images.pad[0] + 2*jscolor.images.arrow[1] + jscolor.images.sld[0],
 2*this.pickerBorder + 2*this.pickerInset + 2*this.pickerFace + jscolor.images.pad[1]
 ]
 var a, b, c
 switch(this.pickerPosition.toLowerCase()){
 case 'left': a=1; b=0; c=-1; break
 case 'right':a=1; b=0; c=1; break
 case 'top': a=0; b=1; c=-1; break
 default: a=0; b=1; c=1; break
}
 var l = (ts[b]+ps[b])/2
 var pp = [ // picker pos
 -vp[a]+tp[a]+ps[a] > vs[a] ?
 (-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) : tp[a],
 -vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
 (-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) :
 (tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
 ]
 drawPicker(pp[a], pp[b])
}
}


 this.importColor = function(){
 if(!valueElement){
 this.exportColor()
}else{
 if(!this.adjust){
 if(!this.fromString(valueElement.value, leaveValue)){
 styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor
 styleElement.style.color = styleElement.jscStyle.color
 this.exportColor(leaveValue | leaveStyle)
}
}else if(!this.required && /^\s*$/.test(valueElement.value)){
 valueElement.value = ''
 styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor
 styleElement.style.color = styleElement.jscStyle.color
 this.exportColor(leaveValue | leaveStyle)

}else if(this.fromString(valueElement.value)){

}else{
 this.exportColor()
}
}
}


 this.exportColor = function(flags){
 if(!(flags & leaveValue) && valueElement){
 var value = this.toString()
 if(this.caps) value = value.toUpperCase()
 if(this.hash) value = '#'+value
 valueElement.value = value
}
 if(!(flags & leaveStyle) && styleElement){
 styleElement.style.backgroundColor = '#'+this.toString()

 styleElement.style.color =
 0.213 * this.rgb[0] +
 0.715 * this.rgb[1] +
 0.072 * this.rgb[2]
 < 0.5 ? '#FFF' : '#000'
}
 if(!(flags & leavePad) && isPickerOwner()){
 redrawPad()
}
 if(!(flags & leaveSld) && isPickerOwner()){
 redrawSld()
}
}


 this.fromHSV = function(h, s, v, flags){// null = don't change
 h<0 && (h=0) || h>6 && (h=6)
 s<0 && (s=0) || s>1 && (s=1)
 v<0 && (v=0) || v>1 && (v=1)
 this.rgb = HSV_RGB(
 h==null ? this.hsv[0] : (this.hsv[0]=h),
 s==null ? this.hsv[1] : (this.hsv[1]=s),
 v==null ? this.hsv[2] : (this.hsv[2]=v)
 )
 this.exportColor(flags)
}


 this.fromRGB = function(r, g, b, flags){// null = don't change
 r<0 && (r=0) || r>1 && (r=1)
 g<0 && (g=0) || g>1 && (g=1)
 b<0 && (b=0) || b>1 && (b=1)
 var hsv = RGB_HSV(
 r==null ? this.rgb[0] : (this.rgb[0]=r),
 g==null ? this.rgb[1] : (this.rgb[1]=g),
 b==null ? this.rgb[2] : (this.rgb[2]=b)
 )
 if(hsv[0] != null){
 this.hsv[0] = hsv[0]
}
 if(hsv[2] != 0){
 this.hsv[1] = hsv[1]
}
 this.hsv[2] = hsv[2]
 this.exportColor(flags)
}


 this.fromString = function(hex, flags){
 var m = hex.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i)
 if(!m){
 return false
}else{
 if(m[1].length == 6){// 6-char notation
 this.fromRGB(
 parseInt(m[1].substr(0,2),16) / 255,
 parseInt(m[1].substr(2,2),16) / 255,
 parseInt(m[1].substr(4,2),16) / 255,
 flags
 )
}else{// 3-char notation
 this.fromRGB(
 parseInt(m[1].charAt(0)+m[1].charAt(0),16) / 255,
 parseInt(m[1].charAt(1)+m[1].charAt(1),16) / 255,
 parseInt(m[1].charAt(2)+m[1].charAt(2),16) / 255,
 flags
 )
}
 return true
}
}


 this.toString = function(){
 return (
 (0x100 | Math.round(255*this.rgb[0])).toString(16).substr(1) +
 (0x100 | Math.round(255*this.rgb[1])).toString(16).substr(1) +
 (0x100 | Math.round(255*this.rgb[2])).toString(16).substr(1)
 )
}


 function RGB_HSV(r, g, b){
 var n = Math.min(Math.min(r,g),b)
 var v = Math.max(Math.max(r,g),b)
 var m = v - n
 if(m == 0) return [ null, 0, v ]
 var h = r==n ? 3+(b-g)/m : (g==n ? 5+(r-b)/m : 1+(g-r)/m)
 return [ h==6?0:h, m/v, v ]
}


 function HSV_RGB(h, s, v){
 if(h == null) return [ v, v, v ]
 var i = Math.floor(h)
 var f = i%2 ? h-i : 1-(h-i)
 var m = v * (1 - s)
 var n = v * (1 - s*f)
 switch(i){
 case 6:
 case 0: return [v,n,m]
 case 1: return [n,v,m]
 case 2: return [m,v,n]
 case 3: return [m,n,v]
 case 4: return [n,m,v]
 case 5: return [v,m,n]
}
}


 function removePicker(){
 delete jscolor.picker.owner
 document.getElementsByTagName('body')[0].removeChild(jscolor.picker.boxB)
}


 function drawPicker(x, y){
 if(!jscolor.picker){
 jscolor.picker ={
 box : document.createElement('div'),
 boxB : document.createElement('div'),
 pad : document.createElement('div'),
 padB : document.createElement('div'),
 padM : document.createElement('div'),
 sld : document.createElement('div'),
 sldB : document.createElement('div'),
 sldM : document.createElement('div')
}
 for(var i=0,segSize=4; i<jscolor.images.sld[1]; i+=segSize){
 var seg = document.createElement('div')
 seg.style.height = segSize+'px'
 seg.style.fontSize = '1px'
 seg.style.lineHeight = '0'
 jscolor.picker.sld.appendChild(seg)
}
 jscolor.picker.sldB.appendChild(jscolor.picker.sld)
 jscolor.picker.box.appendChild(jscolor.picker.sldB)
 jscolor.picker.box.appendChild(jscolor.picker.sldM)
 jscolor.picker.padB.appendChild(jscolor.picker.pad)
 jscolor.picker.box.appendChild(jscolor.picker.padB)
 jscolor.picker.box.appendChild(jscolor.picker.padM)
 jscolor.picker.boxB.appendChild(jscolor.picker.box)
}

 var p = jscolor.picker

 posPad = [
 x+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset,
 y+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset ]
 posSld = [
 null,
 y+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset ]

 p.box.onmouseup =
 p.box.onmouseout = function(){target.focus()}
 p.box.onmousedown = function(){abortBlur=true}
 p.box.onmousemove = function(e){holdPad && setPad(e); holdSld && setSld(e)}
 p.padM.onmouseup =
 p.padM.onmouseout = function(){if(holdPad){holdPad=false; jscolor.fireEvent(valueElement,'change')}}
 p.padM.onmousedown = function(e){holdPad=true; setPad(e)}
 p.sldM.onmouseup =
 p.sldM.onmouseout = function(){if(holdSld){holdSld=false; jscolor.fireEvent(valueElement,'change')}}
 p.sldM.onmousedown = function(e){holdSld=true; setSld(e)}

 p.box.style.width = 4*THIS.pickerInset + 2*THIS.pickerFace + jscolor.images.pad[0] + 2*jscolor.images.arrow[0] + jscolor.images.sld[0] + 'px'
 p.box.style.height = 2*THIS.pickerInset + 2*THIS.pickerFace + jscolor.images.pad[1] + 'px'

 p.boxB.style.position = 'absolute'
 p.boxB.style.clear = 'both'
 p.boxB.style.left = x+'px'
 p.boxB.style.top = y+'px'
 p.boxB.style.zIndex = THIS.pickerZIndex
 p.boxB.style.border = THIS.pickerBorder+'px solid'
 p.boxB.style.borderColor = THIS.pickerBorderColor
 p.boxB.style.background = THIS.pickerFaceColor

 p.pad.style.width = jscolor.images.pad[0]+'px'
 p.pad.style.height = jscolor.images.pad[1]+'px'

 p.padB.style.position = 'absolute'
 p.padB.style.left = THIS.pickerFace+'px'
 p.padB.style.top = THIS.pickerFace+'px'
 p.padB.style.border = THIS.pickerInset+'px solid'
 p.padB.style.borderColor = THIS.pickerInsetColor

 p.padM.style.position = 'absolute'
 p.padM.style.left = '0'
 p.padM.style.top = '0'
 p.padM.style.width = THIS.pickerFace + 2*THIS.pickerInset + jscolor.images.pad[0] + jscolor.images.arrow[0] + 'px'
 p.padM.style.height = p.box.style.height
 p.padM.style.cursor = 'crosshair'

 p.sld.style.overflow = 'hidden'
 p.sld.style.width = jscolor.images.sld[0]+'px'
 p.sld.style.height = jscolor.images.sld[1]+'px'

 p.sldB.style.position = 'absolute'
 p.sldB.style.right = THIS.pickerFace+'px'
 p.sldB.style.top = THIS.pickerFace+'px'
 p.sldB.style.border = THIS.pickerInset+'px solid'
 p.sldB.style.borderColor = THIS.pickerInsetColor

 p.sldM.style.position = 'absolute'
 p.sldM.style.right = '0'
 p.sldM.style.top = '0'
 p.sldM.style.width = jscolor.images.sld[0] + jscolor.images.arrow[0] + THIS.pickerFace + 2*THIS.pickerInset + 'px'
 p.sldM.style.height = p.box.style.height
 try{
 p.sldM.style.cursor = 'pointer'
}catch(eOldIE){
 p.sldM.style.cursor = 'hand'
}

 switch(modeID){
 case 0: var padImg = 'jscol_hs.png'; break
 case 1: var padImg = 'jscol_hv.png'; break
}




 p.padM.style.background = "url('/images/miracle/jscol_cross.gif') no-repeat"
 p.sldM.style.background = "url('/images/miracle/jscol_arrow.gif') no-repeat"
 p.pad.style.background = "url('/images/miracle/"+padImg+"') 0 0 no-repeat"

 redrawPad()
 redrawSld()

 jscolor.picker.owner = THIS
 document.getElementsByTagName('body')[0].appendChild(p.boxB)
}


 function redrawPad(){

 switch(modeID){
 case 0: var yComponent = 1; break
 case 1: var yComponent = 2; break
}
 var x = Math.round((THIS.hsv[0]/6) * (jscolor.images.pad[0]-1))
 var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.pad[1]-1))
 jscolor.picker.padM.style.backgroundPosition =
 (THIS.pickerFace+THIS.pickerInset+x - Math.floor(jscolor.images.cross[0]/2)) + 'px ' +
 (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.cross[1]/2)) + 'px'

 var seg = jscolor.picker.sld.childNodes

 switch(modeID){
 case 0:
 var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 1)
 for(var i=0; i<seg.length; i++){
 seg[i].style.backgroundColor = 'rgb('+
 (rgb[0]*(1-i/seg.length)*100)+'%,'+
 (rgb[1]*(1-i/seg.length)*100)+'%,'+
 (rgb[2]*(1-i/seg.length)*100)+'%)'
}
 break
 case 1:
 var rgb, s, c = [ THIS.hsv[2], 0, 0 ]
 var i = Math.floor(THIS.hsv[0])
 var f = i%2 ? THIS.hsv[0]-i : 1-(THIS.hsv[0]-i)
 switch(i){
 case 6:
 case 0: rgb=[0,1,2]; break
 case 1: rgb=[1,0,2]; break
 case 2: rgb=[2,0,1]; break
 case 3: rgb=[2,1,0]; break
 case 4: rgb=[1,2,0]; break
 case 5: rgb=[0,2,1]; break
}
 for(var i=0; i<seg.length; i++){
 s = 1 - 1/(seg.length-1)*i
 c[1] = c[0] * (1 - s*f)
 c[2] = c[0] * (1 - s)
 seg[i].style.backgroundColor = 'rgb('+
 (c[rgb[0]]*100)+'%,'+
 (c[rgb[1]]*100)+'%,'+
 (c[rgb[2]]*100)+'%)'
}
 break
}
}


 function redrawSld(){

 switch(modeID){
 case 0: var yComponent = 2; break
 case 1: var yComponent = 1; break
}
 var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.sld[1]-1))
 jscolor.picker.sldM.style.backgroundPosition =
 '0 ' + (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.arrow[1]/2)) + 'px'
}


 function isPickerOwner(){
 return jscolor.picker && jscolor.picker.owner == THIS
}


 function blurTarget(){
 if(valueElement == target) THIS.importColor()
 if(THIS.pickerOnfocus) THIS.hidePicker()
}


 function blurValue(){
 if(valueElement != target) THIS.importColor()
}


 function setPad(e){
 var posM = jscolor.getMousePos(e)
 var x = posM[0]-posPad[0]
 var y = posM[1]-posPad[1]
 switch(modeID){
 case 0: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), 1 - y/(jscolor.images.pad[1]-1), null, leaveSld); break
 case 1: THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), null, 1 - y/(jscolor.images.pad[1]-1), leaveSld); break
}
}


 function setSld(e){
 var posM = jscolor.getMousePos(e)
 var y = posM[1]-posPad[1]
 switch(modeID){
 case 0: THIS.fromHSV(null, null, 1 - y/(jscolor.images.sld[1]-1), leavePad); break
 case 1: THIS.fromHSV(null, 1 - y/(jscolor.images.sld[1]-1), null, leavePad); break
}
}


 var THIS = this
 var modeID = this.pickerMode.toLowerCase()=='hvs' ? 1 : 0
 var abortBlur = false
 var
 valueElement = jscolor.fetchElement(this.valueElement),
 styleElement = jscolor.fetchElement(this.styleElement)
 var
 holdPad = false,
 holdSld = false
 var
 posPad,
 posSld
 var
 leaveValue = 1<<0,
 leaveStyle = 1<<1,
 leavePad = 1<<2,
 leaveSld = 1<<3

 jscolor.addEvent(target, 'focus', function(){
 if(THIS.pickerOnfocus) THIS.showPicker()

})
 jscolor.addEvent(target, 'blur', function(){
 if(!abortBlur){
 setTimeout(function(){abortBlur || blurTarget(); abortBlur=false}, 0)
}else{
 abortBlur = false
}
})

 if(valueElement){
 var updateField = function(){
 THIS.fromString(valueElement.value, leaveValue)
}
 jscolor.addEvent(valueElement, 'keyup', updateField)
 jscolor.addEvent(valueElement, 'input', updateField)
 jscolor.addEvent(valueElement, 'blur', blurValue)
 valueElement.setAttribute('autocomplete', 'off')
}

 if(styleElement){

 styleElement.jscStyle ={
 backgroundColor : styleElement.style.backgroundColor,
 color : styleElement.style.color
}
}

 switch(modeID){
 case 0: jscolor.requireImage('hs.png'); break
 case 1: jscolor.requireImage('hv.png'); break
}
 jscolor.requireImage('cross.gif');
 jscolor.requireImage('arrow.gif');

 this.importColor()
}

}


jscolor.install()
/* ######### ddcode ######### */
var DDcode = Class.create();

DDcode.prototype ={
 /**
 * __constructor()
 */ 
 initialize: function(){

 addEvent(window, "load", this.init.bind(this));
},
 init: function(){
 $$("a[rel=ddcode_button]").each(function(element){

 var areas = (element.parentNode).parentNode.getElementsByTagName('textarea');

 element.textarea = (areas[0].id).substr(7);

 Event.observe(element, "click", function(event){

 var target = this.textarea;
 var div_id = $( this.id.substr(2,(this.id.length-2)) );

 var ddcode = div_id.getAttribute('code');
 var ddtype = div_id.getAttribute('type');
 var ddalt = div_id.getAttribute('alt');
 
 if(!ddcode && ddtype!='smile_btn')return true;

 var txt = $('ddcode_'+target).value;
 var sta = $('ddcode_'+target).selectionStart;
 var end = $('ddcode_'+target).selectionEnd;
 
 if(ddtype=='prompt'){

 var dd = ddcode.split('\%s'); 
 if(!dd)return true;
 
 if(sta==end){
 var prom = "";
 while(1){

 prom = prompt(ddalt, prom);
 if(!prom) return true;
 
 if(dd[0]=="[mail]")
 var regxp = new RegExp(/^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i);
 else if(dd[0]=="[url]")
 var regxp = new RegExp(/((ftp|http|https):\/\/|)(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/);
 else if(dd[0]=="[img]")
 var regxp = new RegExp(/((ftp|http|https):\/\/|)(.*)(jpg|png|gif)/);
 else return false;
 
 if(prom.match(regxp)) break;
 else alert('Hibás adat!');
}

 var txt1 = txt.substr(0,sta);
 var txt2 = txt.substr(end,txt.length);
 var new_txt = (txt1+" "+dd[0]+prom+dd[1]+txt2);
}
 else{

 var txt1 = txt.substr(0,sta);
 var txt2 = txt.substr(sta,(end-sta));
 var txt3 = txt.substr(end,txt.length);
 var new_txt = (txt1+dd[0]+txt2+dd[1]+txt3);
}
}

 else if(ddtype=='smile_btn') $('ddcode_layer_'+target+'_emoticons').toggle();

 else if(ddtype=='smile'){

 var txt1 = (txt.substr(0,sta))||"";
 var txt2 = (txt.substr(end,txt.length))||"";
 var new_txt = (txt1+" "+ddcode+" "+txt2);
}

 else if(ddtype=='help'){

 window.open('http://hu.wikipedia.org/wiki/BBCode', 'bbcodeinfo');
}

 else if(!ddtype){

 var dd = ddcode.split('\%s');
 if(!dd)return true;
 
 if(sta==end){

 var txt1 = (txt.substr(0,sta))||"";
 var txt2 = (txt.substr(end,txt.length))||"";
 var new_txt = (txt1+" "+dd[0]+dd[1]+txt2);
}
 else{

 var txt1 = (txt.substr(0,sta))||"";
 var txt2 = (txt.substr(sta,(end-sta)))||"";
 var txt3 = (txt.substr(end,txt.length))||"";
 var new_txt = (txt1+dd[0]+txt2+dd[1]+txt3);
}
}
 if(new_txt) $('ddcode_'+target).value = new_txt;


 
}.bind(element));
}.bind(this));
},
 vars:{
 container: false,
 textarea: false
}
};

var ddcode = new DDcode;
/**
 * MIRACLE
 *
 * A mi kis javascriptes konyvtarunk
 *
 */
var d = document;

document.documentElement.className = 'js';


/* backward compatibility */
var miracleConfig=new Array();

var FORBIDDEN="[[-- FORBIDDEN --]";


/*
if (document.protocol){
 document.attachEvent("onmouseover", function(e){
 var src = e.srcElement.firstChild;
 while (src = src.parentNode){
 src.className += " hover";
}
});
 document.attachEvent("onmouseout", function(e){
 var src = e.srcElement.firstChild;
 while (src = src.parentNode){
 src.className = src.className.replace(new RegExp(" hover\\b"), "");
}
});

}
*/


/* ######### miracle_base ######### */
var Miracle = Class.create();
Miracle.prototype ={
 /**
 * Ez a konstruktorunk.
 */
 initialize: function(){
 this.initActions = new Array();
 this.ajaxCache = [];
 this.eventSelectorRules = new Object();
 this.isEventSelectorRules = false;
 this.initDone = false;
 this.isIE = !!document.protocol;
 this.isIE6 = !!(document.protocol && !window.XMLHttpRequest);
 this.isIE7 = !!(document.protocol && window.XMLHttpRequest);

 if (this.isIE){
 this.ieCacheStyleSheet = document.createStyleSheet();
 this.ieCacheSelectors ={};
}

 this.config = new Array();
 this.config.fleXcroll=new Array();
 this.config.miracleHoverEmulation=new Array();

 this.config.fixEolas = true;
 this.config.initExtensions = new Array();
 this.config.initExtensions.lightBox = false;

 this.config.initExtensions.calendar = true;
 this.config.initExtensions.fleXcroll = true;
 this.config.initExtensions.mooFX = false;
 this.config.initExtensions.sweetTitles = false;
 this.config.initExtensions.wysiwyg = true;

 this.config.initExtensions.miracleAjaxUpdater = false;
 this.config.initExtensions.miracleCheckbox = false;
 this.config.initExtensions.miraclePopup = false;
 this.config.initExtensions.miracleTab = false;
 this.config.initExtensions.miracleHover = true;
 this.config.initExtensions.miracleTargetBlank = true;

 this.config.initExtensions.miracleFileUploads = true;

 this.form ={};
 this.tabs ={};
 this.tree ={};


},

 /**
 * Ez a method fut le a dean fele onload szerint
 */
 init: function(){

 if (this.initDone) return;

 this.initDone=true;

 if (_timer){
 clearInterval(_timer);
 _timer = null;
}

 this.loadMetaConfig();

 this.fixEolas();
 
 /* 
 zss - 2006.12.06
 muszaly a sorrendet felcserelnem mert a flexcroll kulonben nem 
 tud meretet szamolni ha tab-os megoldason belul van
 */
 
 if (this.config.initExtensions.miracleTab){
 this.tabs = new miracleTabs();
}

 if (this.config.initExtensions.fleXcroll){
 this.initFleXcroll();
}


 if (this.config.initExtensions.calendar){
 this.initCalendar();
}

 if (this.config.initExtensions.lightBox && typeof(Lightbox) == "function"){
 myLightbox = new Lightbox();
}

 if (this.config.initExtensions.mooFX){
 this.initMooFX();
}

 if (this.config.initExtensions.sweetTitles){
 sweetTitles.init();
}

 if (this.config.initExtensions.wysiwyg){
 this.initWysiwyg();
}

 if (this.config.initExtensions.miracleAjaxUpdater){
 new miracleAjaxUpdater();
}

 if (this.config.initExtensions.miracleCheckbox){
 new miracleCheckbox();
}

 if (this.config.initExtensions.miracleHover){
 this.initMiracleHover();
}

 if (this.config.initExtensions.miracleFileUploads){
 this.initMiracleFileUploads();
}

 if (this.config.initExtensions.miraclePopup){
 this.initMiraclePopups();
}

 /* if (this.config.initExtensions.miracleTab){
 this.tabs = new miracleTabs();
}*/

 if (this.config.initExtensions.miracleTargetBlank){
 this.initMiracleTargetBlank();
}

 this.initWindows();

 for (var i=0; this.initActions.length>i; i++){
 if (typeof this.initActions[i] == "function"){
 this.initActions[i]();
}
}


 this.initAjax();
 this.form.init();
 kwindow.init();

 this.startEventSelectors();
},

 forceInit: function(){
 this.initDone = false;
 this.init();
},

 /****************************************************************************/

 /**
 * Ez 
 * @param string selector css kivalaszto, hogy mire kell esemeny
 * @param function eventFunction a fuggveny, hogy mi az esemeny
 */
 addEventSelectorRule: function (selector, eventFunction){
 this.eventSelectorRules[selector] = eventFunction;
},

 /**
 * var rand_num = miracle.ajax("immola_base", "testmethod",{min: 1, max: 10});
 * FIXME: most minden kerest becachel ennek vhogy allithatonak kell majd lennie

 */
 ajax: function(module, method, parameters, callback){
 var options ={
 asynchronous: false, 
 method: "post",
 parameters: "module=" + module
 + "&method=" + method
 + "&parameters=" + JSON.stringify(parameters)
};
 var hash = hex_md5(options.parameters);

 if (false && callback && this.ajaxCache[hash]){
 return callback(this.ajaxCache[hash]);
}
 miracle.ajaxIndicator(true);

 if (callback){
 options.asynchronous = true;
 options.onSuccess = function (xmlhttp){
 var response = eval(xmlhttp.responseText);
 callback(response);
 miracle.ajaxIndicator(false);
 miracle.ajaxCache[hash] = response;
}
}
 var myAjax = new Ajax.Request("/-/", options);
 if (callback){
 return true;
}

 var tmp = myAjax.success() ? eval(myAjax.transport.responseText) : "";
 miracle.ajaxIndicator(false);
 miracle.ajaxCache[hash] = tmp;
 return tmp;
},

 ajaxAction: function(element, module, action, entity){

 if (browser.isOpera){
 action = action.split("/").last();
}
 var params = new Array();
 for (var i=4; i<arguments.length; i++){
 params[i-4]=arguments[i];
}
 if (!element.src){// ha nem kep
 var checked = element.getAttribute("inverse") ? !element.checked : element.checked;
 params.push(checked);
}
 if (
 (action.substring(0, 6)!="delete") ||
 (action.substring(0, 6)=="delete" && confirm("Biztos törlöd?")) 
 ){

 var tmp = miracle.ajax(module, action, params, false);
}


 switch (tmp){
 case FORBIDDEN: 
 if (!element.src){// ha nem kep
 element.checked=!element.checked;
}
 alert("Letiltva!");
 return false;
 break;

 case false:
 alert("Error... :(");
 return false;
 break;

 case null:
 case "":
 alert("Error in function call... :(");
 return false;
 break;
}

 if (tmp && (action=="delete" || action.substr(0,7) == "delete_")){
 var trId=entity+"_"+element.getAttribute("recordid")+"_tr";

 var tr=document.getElementById(trId);
 var parent=tr;

 if (parent){
 do{
 parent=parent.parentNode;
}while (parent.tagName != "TABLE");
 
 parent.deleteRow(tr.rowIndex);
 var recordCountId = "miracle_pager_record_count";
 if ($(recordCountId)){
 $(recordCountId).innerHTML = 
 $(recordCountId).innerHTML - 1;
}
}else{
 alert("Error! #"+trId+" not found! Can't delete the row!");
}
}
},

 ajaxIndicator: function(status){
 var indicatorId = "miracle_ajax_indicator";
 var indicator = $(indicatorId);
 if (indicator){
 if (status == false){
 Element.hide(indicator);
}else{
 Element.show(indicator);
}
}else if ($("body")){
 new Insertion.Top("body", "<div id='" + indicatorId + "' class='fixed'><img src='/images/miracle/icon_ajax.gif' /></div>");
}
},

 ajaxMessage: function(message){
 var id="miracle_ajax_message";
 var ajaxMessage = $(id);
 var fakeBody = $$("body div")[0];
 if (!ajaxMessage){
 var HTML="<div id='" + id + "'>" + message+ "</div>";
 new Insertion.Top(fakeBody, HTML);
}else{
 Effect.Appear('miracle_ajax_message',{duration: 0.0});
 ajaxMessage.innerHTML=message;
}
 window.setTimeout("Effect.Fade('miracle_ajax_message')", 4000);
},

 data: function(id){
 if (!(e=$("data_" + id))) return $A([]);
 var src = e.getAttribute("src");
 var data = eval(base64_decode(src.substring(src.indexOf(",") + 1)));
 return data;
},

 /* http://mantis.miracle.eworld.hu/view.php?id=513
 errorLogging: function(){
 window.onerror = function(message, url, line){
 var query="message="+escape(message);
 query+="&url="+escape(url);
 query+="&line="+escape(line);
 query+="&referer="+escape(document.referrer);
 var img=new Image();
 img.src="/javascript_error.png?"+query;
}
},
 */

 fixEolas: function(){
 if (!this.config.fixEolas || !this.isIE) return;
 $A(document.getElementsByTagName("noscript")).each(function(node){
 if (node.className == "eolas"){
 node.outerHTML = node.innerHTML.replace("<![endif]-->", "");
}
});
},

 /**
 * Erre az elemre hover-t kell emulalni.
 *
 * Az IE (<7.0) sajnos csak az A elemre tud :hover-t, igy ezt magunknak kell
 * megoldani. Tipikusan menuknel forul elo.
 *
 * @param string id Az felprogramozando elem ID-je
 * @return NULL
 * @author wiktor
 * @since 2006.05.18.
 */
 hoverEmulation: function(){
 if (!this.isIE6) return;

 this.config.miracleHoverEmulation = this.config.miracleHoverEmulation.concat($A(arguments));
},

 ieCacheSelector: function(selectors){
 var cssText = [];
 for (var i = 0; i < selectors.length; i++){
 var selector = selectors[i].replace(" ", "@");
 this.ieCacheSelectors[selector] = [];
 cssText.push(selectors[i] + "{behavior:expression(miracle.ieCacheStore('" + selector.replace(" ", "@") + "',this))}");
}
 this.ieCacheStyleSheet.cssText = cssText.join("\n");
},

 ieCacheStore: function(selector, element){
 miracle.ieCacheSelectors[selector].push(element);
 element.runtimeStyle.behavior = "none";
},

 /**
 * Egyedi scrollbart rak egy adott elemre.
 *
 * Akkor hasznalatos, ha a design megkoveteli egyedi gorgetosav kialakitasat.
 *
 * @param string id Az felprogramozando elem ID-je
 * @return NULL
 * @author wiktor
 * @since 2006.05.20.
 */
 fleXcroll: function(id){
 this.config.fleXcroll[this.config.fleXcroll.length]=id;
},

 findPos: function(obj){
 var curleft = curtop = 0;
 if (obj.offsetParent){
 curleft = obj.offsetLeft
 curtop = obj.offsetTop
 while (obj = obj.offsetParent){
 curleft += obj.offsetLeft
 curtop += obj.offsetTop
}
}
 return [curleft, curtop];
},

 IFrameShim: function(selector){
 if (!this.isIE6 || document.getElementsByTagName("select").length == 0) return false;
 $$(selector).each(function(e){
 var i = document.createElement("iframe");
 var is = i.style;
 i.frameBorder = 0;
 i.scrolling = "no";
 is.position = "absolute";
 is.left = 0;
 is.top = 0;
 is.width = e.offsetWidth;
 is.height = e.offsetHeight;
 is.left = e.offsetLeft + e.offsetParent.offsetLeft;
 is.top = e.offsetTop + e.offsetParent.offsetTop;
 is.zIndex = e.style.zIndex - 1;
 i.id = "__shim_" + e.uniqueID;
 e.parentNode.appendChild(i);
 Element.addClassName(e, "shimmed");
}.bind(this));
},

 include: function(url){
 var myAjax = new Ajax.Request(url /*+"?"+Math.random()*/,{
 method: "get",
 asynchronous: false
});

 var tmp = myAjax.success() ? myAjax.transport.responseText : "x";
 return tmp;
},

 includeExternalCSS: function(url){

 var node=document.createElement("link");
 node.setAttribute("rel", "stylesheet");
 node.setAttribute("type", "text/css");
 node.setAttribute("media", "screen");
 node.setAttribute("href", url);
 document.getElementsByTagName("head")[0].appendChild(node);
},

 initAction: function(event){
 this.initActions.push(event);
},

 /**
 * Altalanos adminon hasznalt, ajaxos fuggvenyeket elesito fuggveny
 *
 * Tipikusan listazoknal, aktivalasra, torlesre hasznaljuk
 *
 * @param string id Az felprogramozando elem ID-je
 * @return NULL
 *
 * @author wiktor
 * @since 2006.07.17.
 * @version 2006.07.17.wiktor
 */
 initAjax: function(selector){
 var selector = selector || "table.lister";
 $A($$(selector)).each(function(lister){
 var module = lister.getAttribute("module");

 var entity = lister.getAttribute("entity");
 if (!entity) entity = "record";

 if (lister.getAttribute("ajax")){
 $A(lister.getElementsByTagName("*")).each(function(element){
 var action = element.getAttribute("action");
 var parameters = element.getAttribute("parameters");
 if (action && parameters){
 var message = element.getAttribute("message");
 Event.observe(element, 'click', function(event){
 if (message) miracle.ajaxMessage(message);
 miracle.ajaxAction(element, module, action, entity, parameters);
});
}
});
}
});
 
},

 initCalendar: function(loc){


/**
* frissítem a js-t. Csavez 2010.02.09
* var dates=document.getElementsByTagNameAndAttribute("input", "accept", "/date|datetime/");
***/
 if(loc){loc += " ";}else{loc = '';}
 var dates = $$(loc + 'input[accept=datetime]', loc + 'input[accept=date]');
 if (dates.length==0) return false;
 eval(this.include("/jscalendar/calendar.js"));

 if (typeof(Calendar)!="function") return false;

 this.includeExternalCSS("/jscalendar/calendar-blue2.css");

 var icon=document.createElement("img");
 icon.setAttribute("src", "/images/miracle/icon_calendar.png");
 icon.setAttribute("width", 16);
 icon.setAttribute("height", 16);
 icon.setAttribute("class", "calendar");
 
 eval(this.include("/jscalendar/lang/calendar-hu-utf8.js"));
 eval(this.include("/jscalendar/calendar-setup.js"));

 for (var i=0; i<dates.length; i++){
 var id=dates[i].getAttribute("id");
 var imgId=id+"-calendar";
 switch (dates[i].getAttribute("accept")){
 case "datetime":
 var showsTime=true;
 var ifFormat="%Y-%m-%d %H:%M:%S";
 break;
 case "date":
 var showsTime=false;
 var ifFormat="%Y-%m-%d";
 break;
}
 var newIcon=icon.cloneNode(true);
 newIcon.setAttribute("id", imgId);
 DOM_InsertAfter(dates[i], newIcon);

 Calendar.setup({
 inputField: id, // id of the input field
 ifFormat: ifFormat, // format of the input field
 showsTime: showsTime, // will display a time selector
 button: imgId, // trigger for the calendar (button ID)
 singleClick: false, // double-click mode
 step: 1, // show all years in drop-down boxes (instead of every other year as default)
 timeFormat: 24,
 showOthers: true
});
}
}, // end of initCalendar


 initFleXcroll: function(){
 var tmp = new Array();
 this.config.fleXcroll.each(function(id){
 if (document.getElementById(id)){
 tmp[tmp.length] = id;
}
});
 if (tmp.length > 0 && typeof(CSBfleXcroll) != "function"){
 eval(this.include("/js/flexcroll.js"));

 if (typeof(CSBfleXcroll) != "function") return false;
}

 tmp.each(function(id){
 if (document.getElementById(id)){
 CSBfleXcroll(id);
}
});
},

 initMiracleCheckbox: function(){
 var inputs=document.getElementsByTagNameAndAttribute("input", "src", "/.+/");
 for (var i=0; i<inputs.length; i++){
 new miracleCheckbox(inputs[i]);
}
/* this.addEventSelectorRule(
 "input:click", function(input){
 alert(this);
}
 );*/
},

 initMiracleFileUploads: function(){
 var fups=new Array();
 var j=0;
 var elements=document.getElementsByTagNameAndAttribute("fieldset", "class", "file_upload");
 if( !elements.length ) elements=$$("fieldset[classname=file_upload]");
 for (var i=0; i<elements.length; i++){
 fups[j]=new fileUpload(elements[i].getAttribute("id"));
 j++;
}
},

 initMiracleHover: function(){
 if (!this.isIE6) return;
 
 this.config.miracleHoverEmulation.each(function(selector){





 $$(selector).each(function(node){



 node.observe('mouseover', function(){

/* var s = document.getElementsByTagName("select");
 for (var i=0; i<s.length; i++){
 s[i].style.visibility="hidden";
}*/
 this.className+=" hover";
}.bindAsEventListener(node));

 node.observe('mouseout', function(){
/* var s = document.getElementsByTagName("select");
 for (var i=0; i<s.length; i++){
 s[i].style.visibility="visible";
}*/

 this.className=this.className.replace(new RegExp(" hover\\b"), "");
}.bindAsEventListener(node));
});
}.bind(this));
 
},

 initMiraclePopups: function(){

 init_Popups();
},

 /**
 * FIXME
 * erre meg a form-ot ra kell tenni
 */
 initMiracleTargetBlank: function(){
 var nodes=document.getElementsByTagName("a");
 for (var i=0; i<nodes.length; i++){
 if (nodes[i].getAttribute("rel")=="external"){
 nodes[i].target = "_blank";
}
}
},

 initMooFX: function(){


},

 initWindows: function(){
 $$("a[rel=inner_popup]").each(function(element){
 Event.observe(element, "click", function(event){
 
 var element = this;
 var win = new Window("_window",{
 className: "dialog", 
 title: element.title, 
 width: 825, 
 height:518,
 draggable: true,
 minimizable: false,
 maximizable: false,
 resizable: false, 
 url: element.getAttribute("href") 
});
 win.show(); 
 win.setDestroyOnClose()
 win.showCenter();
 Event.stop(event); 
}.bind(element));
});
},


 initWysiwyg: function(){
 this.addEventSelectorRule(
 'textarea', function (element){
 var editor=element.getAttribute("wysiwyg");
 if (editor){
 var fn="miracle.initWysiwyg_"+editor;
 if (eval(fn)){
 eval(fn+"(element);");
}
}
}
 );
},

 initWysiwyg_fckeditor: function(textarea){
 window.oFCKeditors=new Array();

 if (typeof(FCKeditor)=="undefined"){
 eval(this.include("/fckeditor/fckeditor.js"));
}
 
 if (typeof(FCKeditor)!="undefined"){
 var name=textarea.getAttribute("name");
 var id=textarea.getAttribute("id");
 var height=textarea.getAttribute("wysiwyg_height");
 textarea.setAttribute("id", name);
 window.oFCKeditors[id]=new FCKeditor(name, "100%", height);
 window.oFCKeditors[id].Config['CustomConfigurationsPath']='/fckeditor/miracle_fckconfig.js';
 window.oFCKeditors[id].ToolbarSet = textarea.getAttribute("wysiwyg_toolbar") || "Default";
 window.oFCKeditors[id].ReplaceTextarea();
 textarea.setAttribute("id", id);
}
 
 if (typeof(FCKeditor)=="undefined"){
 eval(this.include("/fckeditor/fckeditor.js"));
}



},

 isImagesOn: function(){
 if (this.imagesOn){
 return true;
}
 this.imagesOn=false;
 var test = new Image();
 var tmp = new Date();
 var suffix = tmp.getTime();
 test.src = '/favicon.ico?'+suffix;
 test.onload = function(){
 miracle.imagesOn=true;
};
},

 loadMetaConfig: function(){
 var metas=document.getElementsByTagName("meta");
 for (var i=0; i<metas.length; i++){
 var name=new String(metas[i].getAttribute("name"));
 var content=metas[i].getAttribute("content");
 if (name.substring(0, 8)=="miracle_"){
 this.config[name]=content;
}
}
},

 /**
 * secondhand:EventSelector
 */
 startEventSelectors: function(){
 EventSelectors.start(this.eventSelectorRules);
}


}


var pvd_visible=true;
var last_keys = "";
var last_keys_css = "";
var last_time_keys = false;

function str_replace(search, replace, subject){
 var result = "";
 var oldi = 0;
 for (var i = subject.indexOf (search); i > -1; i = subject.indexOf (search, i))
{
 result += subject.substring (oldi, i);
 result += replace;
 i += search.length;
 oldi = i;
}
 return result + subject.substring (oldi, subject.length);
}

function loremipsum(num){
 var szavak = new Array("alma","dió","mogyoró","körte","dinnye","málna","meggy","cseresznye","kókusz","szilva","barack","szőlő","ribizli",
 "cica","kutya","majom","zsiráf","degu","nyuszi","rozmár","zebra","cinege","mókus","koala","sün","rókakoma","motkány","jak","hal","teknős","pulyka","tatu","ürge","tapír",
 "piros","kék","sárga","zöld","türkiz","okker","fekete","fehér","lila","barna","pink","egyetem","damil","lapát","bakancs","csizma","szalonna",
 "perec","koponya","virág","monitor","indigó","toboz","tank","kifli","bolygó","csillag","por","pokróc",
 "orgona","hegedű","brácsa","gordonka","zongora","gitár","furulya","cimbalom","dob","oboa","szakszofon","cintányér","balalajka","harmónika",
 "Delhusa Johnny","Dolly Rambo",
 "Hold","Nap","Föld","Mars","Vénusz","Merkúr","Jupiter","Szaturnusz","Uránusz","Neptunusz","Plútó","naprendszer"
 );

 var str="";
 for (var i=1; i<=num; i++){
 var k=parseInt(Math.random()*szavak.length);
 str+=szavak[k]+" ";
}
 return str;
}

function keyDown(event){
 var key, e, tag;
 (e = event) || (e = window.event);
 (tag = e.target) || (tag = e.srcElement);

 if (window.event) key = window.event.keyCode;
 else if (event.which) key = event.which;
 else return true; // Unknown browser


 if (window.location.href.substr(0,11)=="http://dev." && tag.tagName != "INPUT" && tag.tagName != "TEXTAREA"){

 if( (key == 68 || key == 65 || key == 86 || key == 73) ){
 clearTimeout(last_time_keys);
 last_keys=last_keys+""+key;
 var correct = "6865867368";
 var len = last_keys.length;
 var cor = correct.substr(0,len);
 if(last_keys != cor) last_keys = key;
 if(last_keys==correct){

}
 last_time_keys = setTimeout(function(){last_keys=false;},1000);
}
 else last_keys = "";

 if( (key == 67 || key == 83) ){
 clearTimeout(last_time_keys);
 last_keys_css = last_keys_css+""+key;
 var correct = "678383";
 var len = last_keys_css.length;
 var cor = correct.substr(0,len);
 if(last_keys_css != cor) last_keys_css = key;
 if(last_keys_css == correct){
 document.childNodes[0].nextSibling.childNodes[0].childNodes[8].href = '/css/miracle.css?force=' + Math.random();
}
 last_time_keys = setTimeout(function(){last_keys_css=false;},1000);
}
 else last_keys_css = "";


 if(key == 79 && tag.tagName != "INPUT" && tag.tagName != "TEXTAREA"){
 var obj = prompt('Add meg az objektumot:');
 var objName = prompt('Add meg az objektum nevét:');
 eval("showProps("+obj+", '"+objName+"');");
 return true;
}
 
 if (key == 80 && tag.tagName != "INPUT" && tag.tagName != "TEXTAREA"){
 if (pvd_visible){
 $A(document.getElementsByClassName('pvd')).each(function(element){
 element.style.display="none";
});
 pvd_visible=false;
}
 else{
 $A(document.getElementsByClassName('pvd')).each(function(element){
 element.style.display="block";
});
 pvd_visible=true;
}
}
 
 if (key == 81){

 auto_formkitoltes();
}
 
}// end of window.location if

 return true;
}

function auto_formkitoltes(){
 var firstnames=new Array("Kis","Nagy","Toth","Magyar","Liszkai","Kovacs","Olah","Erdos","Kiskunfelegyhazi","Lorinc","Hegedus","Asztalos","Bognar");
 var lastnames=new Array("Agota","Bernadett","Karoly","Antal","Anita","Krisztian","Laszlo","Szilvia","Daniel","Robert","Noemi","Henrietta","Norbert","Zsolt","Balazs","Erika");
 var FN=firstnames.length;
 var LN=lastnames.length;

 var elements=document.getElementsByTagName('input');
 var element;
 for (var ii=0; elements[ii]; ii++){
 element=elements[ii];
 var tmp=element.getAttribute('name');
 var name="";
 if (tmp){
 var n=tmp.split("[");
 if (n[1]) name=str_replace("]","",n[1]);
}

 if (element.getAttribute('type')=="text"){


 if (name=="name" || name=="fullname") element.value=firstnames[parseInt(Math.random()*FN)]+" "+lastnames[parseInt(Math.random()*LN)];
 else if (name=="email") element.value=lastnames[parseInt(Math.random()*LN)].toLowerCase()+"@akarmi.hu";
 else if (name=="webpage" || name=="weboldal") element.value="http://www."+lastnames[parseInt(Math.random()*LN)].toLowerCase()+"_"+firstnames[parseInt(Math.random()*FN)].toLowerCase()+".hu";
 else if (name=="lastname") element.value=firstnames[parseInt(Math.random()*FN)];
 else if (name=="firstname") element.value=lastnames[parseInt(Math.random()*LN)];
 else if (element.getAttribute('accept')=="numeric") element.value=parseInt(Math.random()*82500);
 else if (name=="phone") element.value="06 30 "+parseInt(Math.random()*999)+" "+parseInt(Math.random()*999);
 else if (name=="fax") element.value="06 35 "+parseInt(Math.random()*999)+" "+parseInt(Math.random()*999);
 else element.value=loremipsum(parseInt(Math.random()*4)+1);
}

 if (element.getAttribute('type')=="checkbox"){

 if (parseInt(Math.random()*2)==1) element.checked=true;
 else element.checked=false;
}
 if (element.getAttribute('type')=="radio"){

 if (parseInt(Math.random()*2)==1) element.checked=true;
 else element.checked=false;
}

 if (element.getAttribute('type')=="date"){
 var year=2000+(parseInt(Math.random()*14)-7);
 var month=parseInt(Math.random()*11)+1;
 if (month<10) month="0"+month;
 var day=parseInt(Math.random()*28)+1;
 if (day<10) day="0"+day;
 element.value=year+"-"+month+"-"+day;
}
}

 var elements=document.getElementsByTagName('select');
 var element;
 for (var ii=0; elements[ii]; ii++){
 element=elements[ii];
 for (var j=0; element.options[j]; j++);

 if (element.getAttribute('multiple')){

 for (var jj=0; element.options[jj]; jj++){
 if (element.options[jj]) element.options[jj].selected=false;
}

 for (var jj=0; jj<parseInt(Math.random()*6); jj++){
 var kij=parseInt(Math.random()*j);
 if (element.options[kij] && element.options[kij].value!="NULL") element.options[kij].selected=true;
}
}
 else{
 var kij=parseInt(Math.random()*j);
 element.selectedIndex=kij;
}
}

 var elements=document.getElementsByTagName('textarea');
 var element;
 for (var ii=0; elements[ii]; ii++){
 element=elements[ii];
 element.value=loremipsum(parseInt(Math.random()*105)+1);
}
}
document.onkeydown = keyDown;
 
function showProps(obj, objName){
 if (typeof(objName) == "undefined") objName = "object";
 var result = "";
 for (var i in obj){
 result += objName + "." + i + " = ";
 try{
 result += obj[i];
}
 catch (e){
 result += e;
}
 result += "\n";
}
 var w = window.open("", "w", "width=560,height=450,resizable=yes,scrollbars=yes");
 w.document.write("<pre>" + result + "</pre>");
 w.document.close();
}


/**
 * FF alatt nincs swapNode DOM, ezért ezzel működik minden böngésző alatt
 * 
 * Két DOM objektumot felcserél. Ha "van bennük valami" az is velük cserélődik.
 * 
 * Anti
 */
function swapNodes(item1,item2){
 var itemtmp = item1.cloneNode(1);
 var parent = item1.parentNode;
 item2 = parent.replaceChild(itemtmp,item2);
 parent.replaceChild(item2,item1);
 parent.replaceChild(item1,itemtmp);
 itemtmp = null;
}
/**
 * Ide be kell rakni a miracleConfig-os valtozokat, hogy a miracle objektum konstruktorat is tudjuk configolni
 * @url http://mantis.miracle.eworld.hu/view.php?id=719
 */


/**
 * Letrehozzuk a miracle peldanyunkat, amire ezek utan hivatkozunk
 */
var miracle = new Miracle();

miracle.form = new miracleForm();

/* ######### miracle_tree ######### */
/**
 * FIXME: cookie kezeles
 */
miracle.tree = Class.create();

miracle.tree.prototype ={
 
 initialize: function(id){

 if (!$(id)) return false;

 miracle.tree[id] = this;
 this.tree = $(id);
 Element.addClassName(this.tree, "miracle_tree");

 this.image ={
 open : "/images/plus.png",
 close :"/images/minus.png",
 width : 9
};

 $A(this.tree.getElementsByTagName("li")).each(function(liNode, liId){
 if (liNode.getElementsByTagName("ul").length > 0){
 this.addImage(liNode);
 $A(liNode.getElementsByTagName("a")).each(function(aNode, aId){
 if (aNode.href == document.location){

}
}.bind(this));
}
}.bind(this));
},

 addImage: function(liNode){
 var open = Element.visible(this.getSubMenu(liNode));
 var newImg = document.createElement('img');
 newImg.src = open ? this.image.close : this.image.open;
 Element.addClassName(newImg, "miracle_tree");
 liNode.insertBefore(newImg, liNode.firstChild);
 Event.observe(liNode, "click", this.doClick.bindAsEventListener(this));
},

 doClick: function(event){
 var liNode = Event.findElement(event, "li");
 Element.toggle(this.getSubMenu(liNode));
 this.getImageIcon(liNode).src = Element.visible(this.getSubMenu(liNode)) ?
 this.image.close : this.image.open;
},

 getImageIcon: function(liNode){
 return liNode.getElementsByTagName("img")[0];
},

 getSubMenu: function(liNode){
 return liNode.getElementsByTagName("ul")[0];
}


}// end of class/* ######### miracle_repeat ######### */
/**
 * FIXME: cookie kezeles
 */
miracle.form.repeat = Class.create();

miracle.form.repeat.prototype ={
 
 initialize: function(id, counter, counterRegExp, addButtonStr, removeButtonStr){
 if (!d.getElementById(id)) return false;
 this.maxCounter = counter || 999;
 this.addButtonStr = addButtonStr || "Add";
 this.removeButtonStr = removeButtonStr || "Remove";
 this.counterRegExp = counterRegExp || "[]";
 miracle.form.repeats[id] = this;
 this.id = id;
 this.container = $(this.id);
 this.counter = $$("#" + this.id +" .repeat").length;
 this.masterHTML = this.createMaster();
 this.newButtonId = this.id + "_new_button";
 this.newButtonClass = this.id + "_new_button_class";
 this.removeButtonClass = this.id + "_remove_button_class";
 this.addNewButton();
 this.addRemoveButtons();
/* if (!this.modify){
 this.doAdd();
}*/
},

 addNewButton: function(){



 this.newButton = document.createElement("button");

 this.newButton.id = this.newButtonId;
 this.newButton.setAttribute("class", this.newButtonClass);


 this.newButton.innerHTML = this.addButtonStr;
 this.container.appendChild(this.newButton);


 Event.observe(this.newButton, "click", this.doAdd.bindAsEventListener(this));
},

 addRemoveButtons: function(){
 $A(this.container.getElementsByClassName("repeat")).each(function(repeat){

 var removeButton = document.createElement("button");
 removeButton.innerHTML = this.removeButtonStr;
 removeButton.setAttribute("class", this.removeButtonClass);
 Event.observe(removeButton, "click", this.doRemove.bindAsEventListener(this));

/* 
 
 */

 repeat.appendChild(removeButton);
}.bind(this));
},
 
 createMaster: function(){
 var repeatable = $$("#" + this.id +" .repeat").first();
 if (!repeatable){
 return false;
}else{
 return this.reset(repeatable);
}
},

 doAdd: function(event){



 var removeButton = document.createElement("button");

 removeButton.innerHTML = this.removeButtonStr;
 removeButton.setAttribute("class", this.removeButtonClass);
 Event.observe(removeButton, "click", this.doRemove.bindAsEventListener(this));


 var newBlock = document.createElement("div");






 var clone = this.masterHTML.cloneNode(true);



 var options = clone.getElementsByTagName("option");
 for (var i = 0; i < options.length; i++){
 options[i].selected = false;
}
 newBlock.appendChild(clone);
 newBlock.appendChild(removeButton);
 Element.addClassName(newBlock, "repeat");



 var elements = Form.getElements(newBlock);
 elements.each(function(elem){
 var newName = elem.getAttribute("name").replace(new RegExp(this.counterRegExp), this.counter);
 elem.setAttribute("name", newName);
}.bind(this));

 this.container.insertBefore(newBlock, this.newButton);

 this.counter++;
 if (this.counter == this.maxCounter){
 Element.hide(this.newButton);
}
 if (event) Event.stop(event);
 return false;
},
 
 doRemove: function(event){

 var block = Event.element(event).parentNode;

 block.parentNode.removeChild(block);
 this.counter--;
 if (this.counter < this.maxCounter){
 Element.show(this.newButton);
}
 return false;
},

 reset: function(source){
 var master = source.cloneNode(true);
 Form.getElements(master).each(function(element){

 if (!element || !element.options || !element.options[0]) return false;
 switch (element.tagName){
 case "SELECT":

 element.options[0].selected = true;


 break;
 default: 
 element.setAttribute("value", "");

}
});




 return master;
}



}// end of class/* ######### kwindow ######### */
var Kwindow = Class.create();

function getScrollXY(){
 var scrOfX = 0, scrOfY = 0;
 if( typeof( window.pageYOffset ) == 'number' ){

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

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

 scrOfY = document.documentElement.scrollTop;
 scrOfX = document.documentElement.scrollLeft;
}
 return [ scrOfX, scrOfY ];
}

/* utilok hozza: */
function urldecode(str){
 if (str=="") return "";
 var ret = str;
 ret = ret.replace(/\+/g, '%20');
 ret = decodeURIComponent(ret);
 ret = ret.toString();
 return ret;
}

function urlencode(str){
 if (str=="") return "";
 var ret = str;
 ret = ret.toString();
 ret = ret.replace(/\?/g, 'xkerdojelx');
 ret = encodeURIComponent(ret);
 ret = ret.replace(/%20/g, '+');
 ret = ret.replace(/%3D/g, '=');
 ret = ret.replace(/%26/g, '&');
 return ret;
}

Kwindow.prototype ={

 kwindow_post_response_text : "",

 initialize: function(){

},
 
 init: function(loc){
 this.init_auto_kwindow(loc);
 this.init_kwindow(loc);
 this.init_kwindow_gallery(loc);


 this.gallery_move_up=false;
 this.gallery_move_down=false;
 this.gallery_scrollspeed=10;
 this.gray_layer_transparency=35;
},

 vIE: function(){
 return (navigator.appName=='Microsoft Internet Explorer')?parseFloat((new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})")).exec(navigator.userAgent)[1]):-1;
},

 init_auto_kwindow: function(loc){
 if(loc){loc+=" ";}else{loc='';}
 $$(loc+"a[rel=auto_kwindow]").each(function(element){
 kwindow.kwindow_show(element);
});
},

 init_kwindow: function(loc){

 if(loc){loc+=" ";}else{loc='';}
 $$(loc+"a[rel=kwindow]").each(function(element){
 Event.observe(element, "click", function(event){
 kwindow.kwindow_show(element);
 Event.stop(event);
}.bind(element));
});
},

 init_kwindow_gallery: function(loc){
 if(loc){loc+=" ";}else{loc='';}
 $$(loc+"a[rel=kwindow_gallery]").each(function(element){
 Event.observe(element, "click", function(event){
 Event.stop(event);
 if( element.getAttribute('rev') ){
 var p = element.getAttribute('rev');
 element.setAttribute('rev', '');
 var pa = p.split('|');
 if( pa.length ){
 element.setAttribute('template',pa[0]);
 element.setAttribute('gallery_id',pa[1]);
 element.setAttribute('startpic',pa[2]);
 element.setAttribute('thumb_image_size',pa[3]);
 element.setAttribute('main_image_size',pa[4]);
}
}
 kwindow.kwindow_show(element);
}.bind(element));
});
},

 init_kwindow_close: function(loc){
 if(loc){loc+=" ";}else{loc='';}
 $$(loc+"a[rel=kwindow_close]").each(function(element){
 Event.observe(element, "click", function(event){
 kwindow.kwindow_close();

 if (element.getAttribute('run_js')){
 var run_js_fgv_name = element.getAttribute('run_js');
 try{
 var ret = eval(run_js_fgv_name);
 if(typeof(ret) == 'function') eval(ret)();
}catch(err){
 
}
}

 if (element.getAttribute('module')) kwindow.kwindow_show(element);
 Event.stop(event);
}.bind(element));
});
},
 
 init_kwindow_post: function(loc){
 if(loc){loc+=" ";}else{loc='';}
 $$(loc+"a[rel=kwindow_post]").each(function(element){
 Event.observe(element, "click", function(event){

 if (element.getAttribute('check_form_js')){
 var check_js_fgv_name = element.getAttribute('check_form_js');
 try{
 var valid = eval(check_js_fgv_name);
 if(typeof(valid) == 'function') valid = eval(ret)();
}catch(err){
 
}
 if (valid) kwindow.kwindow_post(element);
}
 else // ha nincs akkor egybol mehet a post:
 kwindow.kwindow_post(element);
 Event.stop(event);
}.bind(element));
});
},
 
 kwindow_post: function(element){
 var form_id=element.getAttribute('form_id');
 var update_div=element.getAttribute('update_div');
 var url=element.getAttribute('url');

 var serializedForm = Form.serialize(form_id);

 if (update_div){

 var myAjax = new Ajax.Updater(update_div, url,
{
 asynchronous:true,
 evalScripts: true,
 onComplete: function(response){

 if (element.getAttribute('close_after_post')=="true") kwindow.kwindow_close();

 kwindow.kwindow_post_response_text=response.responseText;


 kwindow.init('#'+update_div);

 kwindow.init_kwindow_close('#'+update_div);

 kwindow.init_kwindow_post('#'+update_div);

 if (element.getAttribute('run_js_after_post')){
 var run_js_fgv_name=element.getAttribute('run_js_after_post');
 try{
 
 var ret = eval(run_js_fgv_name);
 if(typeof(ret) == 'function') eval(ret)();
}catch(err){
 
}
}
},
 parameters: serializedForm,
 method: 'post'
});
}
 else{

 var myAjax = new Ajax.Request(url,
{
 asynchronous:true,
 onComplete: function(response){

 if (element.getAttribute('close_after_post')=="true") kwindow.kwindow_close();

 kwindow.kwindow_post_response_text=response.responseText;

 if (element.getAttribute('run_js_after_post')){
 var run_js_fgv_name=element.getAttribute('run_js_after_post');
 try{
 
 var ret = eval(run_js_fgv_name);
 if(typeof(ret) == 'function') eval(ret)();
}catch(err){
 
}
}

 kwindow.init('#kwindow_content');

 kwindow.init_kwindow_close('#kwindow_content');

 kwindow.init_kwindow_post('#kwindow_content');
},
 parameters: serializedForm,
 method: 'post'
});
}
},
 
 kwindow_close: function(element_id){

 $("kwindow").style.display="none";

 if ($("kwindow_content").down(0) && !kwindow.vIE()) $("kwindow_content").removeChild($("kwindow_content").down(0));

 $("photogallery2_darken").style.display="none";

 if (element_id) kwindow.kwindow_show($(element_id));

 if (kwindow.vIE()==6)
 $("body").getElementsBySelector("select").each(function(element){
 element.style.visibility="visible";
});
},

 kwindow_show: function(element){

 var rel=element.getAttribute("rel");

 var bg_color=element.getAttribute('bg_color');
 if (bg_color) $("photogallery2_darken").style.background="#"+bg_color;

 var bg_transparency=this.gray_layer_transparency;
 bg_transparency=element.getAttribute('bg_transparency');
 if (bg_transparency){
 $("photogallery2_darken").style.filter = "alpha(opacity="+bg_transparency+")";
 $("photogallery2_darken").style.opacity = (bg_transparency/100);
 $("photogallery2_darken").style.MozOpacity = (bg_transparency/100);
 $("photogallery2_darken").style.KhtmlOpacity = (bg_transparency/100);
 this.gray_layer_transparency=bg_transparency;
}

 var positions=getScrollXY();
 $("kwindow_center").style.top=positions[1]+"px";

 var disable_darken=element.getAttribute('disable_darken');

 var url=element.getAttribute('url');

 var module=element.getAttribute('module');

 var template=element.getAttribute('template');

 var method=element.getAttribute('method');

 var params=element.getAttribute('params');
 if (params) params=urlencode(params);

 var width=element.getAttribute('width');
 if (width) $("kwindow").style.width=width+"px";
 else $("kwindow").style.width="500px";

 var height=element.getAttribute('height');
 if (height) $("kwindow").style.height=height+"px";
 else $("kwindow").style.height="auto";

 var kwclass=element.getAttribute('kwclass');
 if (kwclass && !$("kwindow").hasClassName(kwclass)) $("kwindow").toggleClassName(kwclass);

 var autoclose=parseInt(element.getAttribute('autoclose'),10);

 if (autoclose>0) var kwindow_after_autoclose=element.getAttribute('kwindow_after_autoclose');

 var loading_animation=element.getAttribute('loading_animation');


 var alert_text=element.getAttribute('alert');
 if (alert_text){
 alert_text=urlencode(alert_text);
 var alert_mode=element.getAttribute('mode');
 if (alert_mode) alert_mode=urlencode(alert_mode);
 else alert_mode='alert';
 url="/miracle/ajax__kwindow_alert/"+alert_text+"/"+alert_mode;
}

 var confirm_text=element.getAttribute('confirm');
 if (confirm_text){
 confirm_text=urlencode(confirm_text);
 var method=element.getAttribute('js_method');
 url="/miracle/ajax__kwindow_confirm/"+confirm_text+"/"+method;
}

 if (kwindow.vIE()==6)
 $("body").getElementsBySelector("select").each(function(element){
 element.style.visibility="hidden";
});

 if (disable_darken!="true")

 $("photogallery2_darken").style.display="block";

 var bodyHeight = $("body").offsetHeight - -($("body").offsetTop);
 $("photogallery2_darken").style.height=bodyHeight+"px";

 if (loading_animation!="false") $("kwindow_loading").style.display="block";


 $("kwindow_content").innerHTML="";

 $("kwindow").style.display="block";

 if (rel=="kwindow_gallery"){

 var gallery_id=element.getAttribute('gallery_id');
 if (!gallery_id) gallery_id="0";
 if (!template) template="1";
 var startpic=element.getAttribute('startpic');
 if (!startpic) startpic="0";
 var main_image_size=element.getAttribute('main_image_size');
 if (!main_image_size) main_image_size="400x300";
 var thumb_image_size=element.getAttribute('thumb_image_size');
 if (!thumb_image_size) thumb_image_size="100x100";
 var title=element.getAttribute('title');
 if (!title) title="-";
 title=urlencode(title);
 var filter_picture_title=element.getAttribute('filter_picture_title');
 if (!filter_picture_title) filter_picture_title="-";
 filter_picture_title=urlencode(filter_picture_title);
 var gallery_module=element.getAttribute('gallery_module');
 if (!gallery_module) gallery_module="gallery";
 var gallery_scrollspeed=parseInt(element.getAttribute('scrollspeed'));
 if (!gallery_scrollspeed) gallery_scrollspeed=10;
 kwindow.gallery_scrollspeed=gallery_scrollspeed;

 if (!width){
 var mis=main_image_size.split("x");
 var tis=thumb_image_size.split("x");
 width=parseInt(mis[0])+parseInt(tis[0])+50;
 if( width<800 ) width = 660;
 $("kwindow").style.width=width+"px";
}

 url="/ajax__get_kwindow_gallery_template/"+gallery_id+"/"+template+"/"+startpic+"/"+main_image_size+"/"+thumb_image_size+"/"+title+"/"+filter_picture_title+"/"+gallery_module;
}
 
 if (url && !alert_text && !confirm_text){
 url=url+"/params?"+params;
}else if (!method && template && rel!="kwindow_gallery" && !alert_text && !confirm_text){
 url="/ajax__get_kwindow_content_from_template/"+module+"/"+template+"/params?"+params;
}else if (method && !alert_text && !confirm_text){
 url="/ajax__get_kwindow_content_from_method/"+module+"/"+method+"/params?"+params;
}

 var pars = '';
 var myAjax = new Ajax.Updater('kwindow_content', url,{
 method: 'get',
 parameters: pars,
 evalScripts: true,
 onComplete : function(valasz){

 if (loading_animation!="false") $("kwindow_loading").style.display="none";

 kwindow.init('#kwindow_content');

 kwindow.init_kwindow_close('#kwindow_content');

 kwindow.init_kwindow_post('#kwindow_content');

 if (autoclose>0 && !kwindow_after_autoclose) setTimeout("kwindow.kwindow_close()",parseInt(autoclose));

 if (autoclose>0 && kwindow_after_autoclose) setTimeout("kwindow.kwindow_close('"+kwindow_after_autoclose+"')",autoclose);
}
});

},
 
 change_main_image: function(){
 if (!$("kwindow_gallery")) return;
 $A($("kwindow_gallery").getElementsByClassName("change_kwindow_main_image")).each(function(element){
 element.observe("click", function(event){
 $A($("kwindow_gallery").getElementsByClassName("main_image")).each(function(element2){
 if( !element2.hasClassName("hide") ) element2.addClassName("hide");
});
 var image_id=element.up('td',0).getAttribute('image_id');
 var vis = $("kg_image_"+image_id);
 if( vis.hasClassName("hide") ) vis.removeClassName("hide");

 $A($("kwindow").getElementsByClassName("image_title_row")).each(function(element2){
 element2.style.display="none";
});
 if( $("image_title_text_"+image_id) ) $("image_title_text_"+image_id).style.display="block";
 
});
});
},
 
 gallery_move: function(){
 if (!$("kwindow_gallery")) return;
 $A($("kwindow_gallery").getElementsByClassName("move_up")).each(function(element){
 element.observe("mouseover", function(event){
 kwindow.gallery_move_up=true;
 setTimeout("kwindow.gallery_scroll('up')",20);
});
});
 $A($("kwindow_gallery").getElementsByClassName("move_down")).each(function(element){
 element.observe("mouseover", function(event){
 kwindow.gallery_move_down=true;
 setTimeout("kwindow.gallery_scroll('down')",20);
});
});
 $A($("kwindow_gallery").getElementsByClassName("move_up")).each(function(element){
 element.observe("mouseout", function(event){
 kwindow.gallery_move_up=false;
});
});
 $A($("kwindow_gallery").getElementsByClassName("move_down")).each(function(element){
 element.observe("mouseout", function(event){
 kwindow.gallery_move_down=false;
});
});
 $A($("kwindow_gallery").getElementsByClassName("move_prev")).each(function(element){
 element.observe("click", function(event){

 for (i=1;;i++) if (!$("kg_image_"+i)) break;
 var image_number=i-1;

 for (i=1; i<=image_number; i++){
 var item = $("kg_image_"+i);
 if( !item.hasClassName("hide") ){
 var actual_image=i; break;
}

}

 var prev_image=actual_image-1;
 if (prev_image<1) prev_image=image_number;

 $A($("kwindow_gallery").getElementsByClassName("main_image")).each(function(element2){
 if( !element2.hasClassName("hide") ) element2.addClassName("hide");
});
 $("kg_image_"+prev_image).removeClassName("hide");
});
});
 $A($("kwindow_gallery").getElementsByClassName("move_next")).each(function(element){
 element.observe("click", function(event){

 for (i=1;;i++) if (!$("kg_image_"+i)) break;
 var image_number=i-1;

 for (i=1; i<=image_number; i++){
 var item = $("kg_image_"+i);
 if( !item.hasClassName("hide") ){
 var actual_image=i; break;
}
}
 if (!actual_image) var actual_image=1;

 var next_image=actual_image+1;
 if (next_image>image_number) next_image=1;

 $A($("kwindow_gallery").getElementsByClassName("main_image")).each(function(element2){
 if( !element2.hasClassName("hide") ) element2.addClassName("hide");
});
 $("kg_image_"+next_image).removeClassName("hide");
});
});
},

 gallery_scroll: function(dir){
 if (dir=="up"){
 var top=parseInt($("kwindow_gallery_thumbs").style.top);
 if (!top) top=0;
 top+=kwindow.gallery_scrollspeed;
 if (top>0) top=0;
 $("kwindow_gallery_thumbs").style.top=top+"px";
 if (kwindow.gallery_move_up) setTimeout("kwindow.gallery_scroll('up')",20);
}
 if (dir=="down"){

 var thumbsHeight=400;
 $A($("kwindow_gallery").getElementsByClassName("thumbs")).each(function(element){
 thumbsHeight=parseInt(element.style.height);
});

 var top=parseInt($("kwindow_gallery_thumbs").style.top);
 if (!top) top=0;
 top-=kwindow.gallery_scrollspeed;
 var hossz=-parseInt($("kwindow_gallery_thumbs").offsetHeight);

 hossz=hossz+thumbsHeight;

 if (top<=hossz) top=hossz;
 if (parseInt($("kwindow_gallery_thumbs").offsetHeight)<thumbsHeight) top=0;

 $("kwindow_gallery_thumbs").style.top=top+"px";
 if (kwindow.gallery_move_down) setTimeout("kwindow.gallery_scroll('down')",20);
}
}
 
}

var kwindow=new Kwindow;

function wheel_handle(delta){
 if (delta < 0){if (kwindow.gray_layer_transparency<100) kwindow.gray_layer_transparency+=5;}
 else{if (kwindow.gray_layer_transparency>0) kwindow.gray_layer_transparency-=5;}

 $("photogallery2_darken").style.filter = "alpha(opacity="+kwindow.gray_layer_transparency+")";
 $("photogallery2_darken").style.opacity = (kwindow.gray_layer_transparency/100);
 $("photogallery2_darken").style.MozOpacity = (kwindow.gray_layer_transparency/100);
 $("photogallery2_darken").style.KhtmlOpacity = (kwindow.gray_layer_transparency/100);
}

function wheel(event){
 if ($("kwindow").style.display=="block"){
 var delta = 0;
 if (!event) event = window.event;
 if (event.wheelDelta){
 delta = event.wheelDelta/120;
 if (window.opera) delta = -delta;
}
 else if (event.detail) delta = -event.detail/3;

 if (delta) wheel_handle(delta);

 if (event.preventDefault) event.preventDefault();

 event.returnValue = false;
}
}


/**
 * Dynamic Rating stars
 * @copyright 2006 Beau D. Scott http://beauscott.com
 * @
 */

var Stars = Class.create();
Stars.prototype ={
 /**
 * Mouse X position
 * @var{Number}options
 */
 _x: 0,
 /**
 * Mouse X position
 * @var{Number}options
 */
 _y: 0,
 /**
 * Constructor
 * @param{Object}options
 */
 initialize: function(options)
{

 /**
 * Initialized?
 * @var (Boolean)
 */
 this._initialized = false;

 /**
 * Base option values
 * @var (Object)
 */
 this.options ={
 bindField: null, // Form Field to bind the value to
 maxRating: 5, // Maximum rating, determines number of stars
 container: null, // Container of stars
 imagePath: 'images/', // Path to star images
 callback: null, // Callback function, fires when the stars are clicked
 actionURL: null, // URL to call when clicked. The rating will be appended to the end of the URL (eg: /rate.php?id=5&rating=)
 value: 0, // Initial Value
 locked: false
};
 Object.extend(this.options, options);
 this.locked = this.options.locked ? true : false;
 /**
 * Image sources for hover and user-set state ratings
 */
 this._starSrc ={
 empty: this.options.imagePath + "star-empty.gif",
 full: this.options.imagePath + "star.gif",
 half: this.options.imagePath + "star-half.gif"
};
 /**
 * Preload images
 */
 for(var x in this._starSrc)
{
 var y = new Image();
 y.src = this._starSrc[x];
}

 document.getElem

 /**
 * Images to show for pre-set values, changes when hovered, if not locked.
 */
 this._setStarSrc ={
 empty: this.options.imagePath + "star-ps-empty.gif",
 full: this.options.imagePath + "star-ps.gif",
 half: this.options.imagePath + "star-ps-half.gif"
};

 /**
 * Preload images
 */
 for(var x in this._setStarSrc)
{
 var y = new Image();
 y.src = this._setStarSrc[x];
}

 this.value = -1;
 this.stars = [];
 this._clicked = false;


 if(this.options.container)
{
 this._container = $(this.options.container);
 this.id = this._container.id;
}
 else
{
 this.id = 'starsContainer.' + Math.random(0, 100000);
 document.write('<span id="' + this.id + '"></span>');
 this._container = $(this.id);
}
 this._display();
 this.setValue(this.options.value);
 this._initialized = true;
},
 _display: function()
{
 for(var i = 0; i < this.options.maxRating; i++)
{
 var star = new Image();
 star.src = this.locked ? this._starSrc.empty : this._setStarSrc.empty;
 star.style.cursor = 'pointer';
 star.title = ' ' + (i + 1);
 !this.locked && Event.observe(star, 'mouseover', this._starHover.bind(this));
 !this.locked && Event.observe(star, 'click', this._starClick.bind(this));
 !this.locked && Event.observe(star, 'mouseout', this._starClear.bind(this));
 this.stars.push(star);
 this._container.appendChild(star);
}
},
 _starHover: function(e)
{
 if(this.locked) return;
 if(!e) e = window.event;
 var star = Event.element(e);

 var greater = false;
 for(var i = 0; i < this.stars.length; i++)
{
 this.stars[i].src = greater ? this._starSrc.empty : this._starSrc.full;
 if(this.stars[i] == star) greater = true;
}
},
 _starClick: function(e)
{
 if(this.locked) return;
 if(!e) e = window.event;
 var star = Event.element(e);
 this._clicked = true;
 for(var i = 0; i < this.stars.length; i++)
{
 if(this.stars[i] == star)
{
 this.setValue(i+1);
 break;
}
}
},
 _starClear: function(e)
{
 if(this.locked && this._initialized) return;
 var greater = false;
 for(var i = 0; i < this.stars.length; i++)
{
 if(i > this.value) greater = true;
 if((this._initialized && this._clicked) || this.value == -1)
 this.stars[i].src = greater ? (this.value + .5 == i) ? this._starSrc.half : this._starSrc.empty : this._starSrc.full;
 else
 this.stars[i].src = greater ? (this.value + .5 == i) ? this._setStarSrc.half : this._setStarSrc.empty : this._setStarSrc.full;
}
},
 /**
 * Sets the value of the star object, redraws the UI
 * @param{Number}value to set
 * @param{Boolean}optional, do the callback function, default true
 */
 setValue: function(val)
{
 var doCallBack = arguments.length > 1 ? !!arguments[1] : true;
 if(this.locked && this._initialized) return;
 this.value = val-1; //0-based
 if(this.options.bindField)
 $(this.options.bindField).value = val;
 if(this._initialized && doCallBack)
{
 if(this.options.actionURL)
 new Ajax.Request(this.options.actionURL + val,{onComplete: this.options['callback'], method: 'get'});
 else
 if(this.options.callback)
 this.options['callback'](val);
}
 this._starClear();
}
};
/** 
 * http://dean.edwards.name/weblog/2005/09/busted/
 * thank you dean! ;)
 */
function init(){
 miracle.init();
}

/* for Mozilla */
if (document.addEventListener){
 document.addEventListener("DOMContentLoaded", init, false);
}

if (browser.isIE){
 document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
 var script = document.getElementById("__ie_onload");
 script.onreadystatechange = function(){
 if (this.readyState == "complete"){
 init(); // call the onload handler
}
};
}

/* for Safari */
if (/WebKit/i.test(navigator.userAgent)){// sniff
 var _timer = setInterval(function(){
 if (/loaded|complete/.test(document.readyState)){
 init(); // call the onload handler
}
}, 10);
}

/* for other browsers */
window.onload = init;

/* webcommander miatt nem torolheto! */
function server_action(module, method, parameters){
 return miracle.ajax(module, method, parameters);
}/*
 *
 * Ajax Autocomplete for Prototype, version 1.0.4
 * (c) 2010 Tomas Kirda
 *
 * Ajax Autocomplete for Prototype is freely distributable under the terms of an MIT-style license.
 * For details, see the web site: http://www.devbridge.com/projects/autocomplete/
 *
 */

var Autocomplete = function(el, options){
 this.el = $(el);
 this.id = this.el.identify();
 this.el.setAttribute('autocomplete','off');
 this.suggestions = [];
 this.data = [];
 this.badQueries = [];
 this.selectedIndex = -1;
 this.currentValue = this.el.value;
 this.intervalId = 0;
 this.cachedResponse = [];
 this.instanceId = null;
 this.onChangeInterval = null;
 this.ignoreValueChange = false;
 this.serviceUrl = options.serviceUrl;
 this.options ={
 autoSubmit:false,
 minChars:1,
 maxHeight:300,
 deferRequestBy:0,
 width:0,
 container:null
};
 if(options){Object.extend(this.options, options);}
 if(Autocomplete.isDomLoaded){
 this.initialize();
}else{
 Event.observe(document, 'dom:loaded', this.initialize.bind(this), false);
}
};

Autocomplete.instances = [];
Autocomplete.isDomLoaded = false;

Autocomplete.getInstance = function(id){
 var instances = Autocomplete.instances;
 var i = instances.length;
 while(i--){if(instances[i].id === id){return instances[i];}}
};

Autocomplete.highlight = function(value, re){
 return value.replace(re, function(match){return '<strong>' + match + '<\/strong>'});
};

Autocomplete.prototype ={

 killerFn: null,

 initialize: function(){
 var me = this;
 this.killerFn = function(e){
 if (!$(Event.element(e)).up('.autocomplete')){
 me.killSuggestions();
 me.disableKillerFn();
}
}.bindAsEventListener(this);

 if (!this.options.width){this.options.width = this.el.getWidth();}

 var div = new Element('div',{style: 'position:absolute;'});
 div.update('<div class="autocomplete-w1"><div class="autocomplete-w2"><div class="autocomplete" id="Autocomplete_' + this.id + '" style="display:none; width:' + this.options.width + 'px;"></div></div></div>');

 this.options.container = $(this.options.container);
 if (this.options.container){
 this.options.container.appendChild(div);
 this.fixPosition = function(){};
}else{
 document.body.appendChild(div);
}

 this.mainContainerId = div.identify();
 this.container = $('Autocomplete_' + this.id);
 this.fixPosition();
 
 Event.observe(this.el, window.opera ? 'keypress':'keydown', this.onKeyPress.bind(this));
 Event.observe(this.el, 'keyup', this.onKeyUp.bind(this));
 Event.observe(this.el, 'blur', this.enableKillerFn.bind(this));
 Event.observe(this.el, 'focus', this.fixPosition.bind(this));
 this.container.setStyle({maxHeight: this.options.maxHeight + 'px'});
 this.instanceId = Autocomplete.instances.push(this) - 1;
},

 fixPosition: function(){
 var offset = this.el.cumulativeOffset();
 $(this.mainContainerId).setStyle({top: (offset.top + this.el.getHeight()) + 'px', left: offset.left + 'px'});
},

 enableKillerFn: function(){
 Event.observe(document.body, 'click', this.killerFn);
},

 disableKillerFn: function(){
 Event.stopObserving(document.body, 'click', this.killerFn);
},

 killSuggestions: function(){
 this.stopKillSuggestions();
 this.intervalId = window.setInterval(function(){this.hide(); this.stopKillSuggestions();}.bind(this), 300);
},

 stopKillSuggestions: function(){
 window.clearInterval(this.intervalId);
},

 onKeyPress: function(e){
 if (!this.enabled){return;}


 switch (e.keyCode){
 case Event.KEY_ESC:
 this.el.value = this.currentValue;
 this.hide();
 break;
 case Event.KEY_TAB:
 case Event.KEY_RETURN:
 if (this.selectedIndex === -1){
 this.hide();
 return;
}
 this.select(this.selectedIndex);
 if (e.keyCode === Event.KEY_TAB){return;}
 break;
 case Event.KEY_UP:
 this.moveUp();
 break;
 case Event.KEY_DOWN:
 this.moveDown();
 break;
 default:
 return;
}
 Event.stop(e);
},

 onKeyUp: function(e){
 switch (e.keyCode){
 case Event.KEY_UP:
 case Event.KEY_DOWN:
 return;
}
 clearInterval(this.onChangeInterval);
 if (this.currentValue !== this.el.value){
 if (this.options.deferRequestBy > 0){

 this.onChangeInterval = setInterval((function(){
 this.onValueChange();
}).bind(this), this.options.deferRequestBy);
}else{
 this.onValueChange();
}
}
},

 onValueChange: function(){
 clearInterval(this.onChangeInterval);
 this.currentValue = this.el.value;
 this.selectedIndex = -1;
 if (this.ignoreValueChange){
 this.ignoreValueChange = false;
 return;
}
 if (this.currentValue === '' || this.currentValue.length < this.options.minChars){
 this.hide();
}else{
 this.getSuggestions();
}
},

 getSuggestions: function(){
 var cr = this.cachedResponse[this.currentValue];
 if (cr && Object.isArray(cr.suggestions)){
 this.suggestions = cr.suggestions;
 this.data = cr.data;
 this.suggest();
}else if (!this.isBadQuery(this.currentValue)){
 new Ajax.Request(this.serviceUrl,{
 parameters:{query: this.currentValue},
 onComplete: this.processResponse.bind(this),
 method: 'get'
});
}
},

 isBadQuery: function(q){
 var i = this.badQueries.length;
 while (i--){
 if (q.indexOf(this.badQueries[i]) === 0){return true;}
}
 return false;
},

 hide: function(){
 this.enabled = false;
 this.selectedIndex = -1;
 this.container.hide();
},

 suggest: function(){
 if (this.suggestions.length === 0){
 this.hide();
 return;
}
 var content = [];
 var re = new RegExp('\\b' + this.currentValue.match(/\w+/g).join('|\\b'), 'gi');
 this.suggestions.each(function(value, i){
 content.push((this.selectedIndex === i ? '<div class="selected"' : '<div'), ' title="', value, '" onclick="Autocomplete.instances[', this.instanceId, '].select(', i, ');" onmouseover="Autocomplete.instances[', this.instanceId, '].activate(', i, ');">', Autocomplete.highlight(value, re), '</div>');
}.bind(this));
 this.enabled = true;
 this.container.update(content.join('')).show();
},

 processResponse: function(xhr){
 var response;
 try{
 response = xhr.responseText.evalJSON();
 if (!Object.isArray(response.data)){response.data = [];}
}catch (err){return;}
 this.cachedResponse[response.query] = response;
 if (response.suggestions.length === 0){this.badQueries.push(response.query);}
 if (response.query === this.currentValue){
 this.suggestions = response.suggestions;
 this.data = response.data;
 this.suggest(); 
}
},

 activate: function(index){
 var divs = this.container.childNodes;
 var activeItem;

 if (this.selectedIndex !== -1 && divs.length > this.selectedIndex){
 divs[this.selectedIndex].className = '';
}
 this.selectedIndex = index;
 if (this.selectedIndex !== -1 && divs.length > this.selectedIndex){
 activeItem = divs[this.selectedIndex]
 activeItem.className = 'selected';
}
 return activeItem;
},

 deactivate: function(div, index){
 div.className = '';
 if (this.selectedIndex === index){this.selectedIndex = -1;}
},

 select: function(i){
 var selectedValue = this.suggestions[i];
 if (selectedValue){
 this.el.value = selectedValue;
 if (this.options.autoSubmit && this.el.form){
 this.el.form.submit();
}
 this.ignoreValueChange = true;
 this.hide();
 this.onSelect(i);
}
},

 moveUp: function(){
 if (this.selectedIndex === -1){return;}
 if (this.selectedIndex === 0){
 this.container.childNodes[0].className = '';
 this.selectedIndex = -1;
 this.el.value = this.currentValue;
 return;
}
 this.adjustScroll(this.selectedIndex - 1);
},

 moveDown: function(){
 if (this.selectedIndex === (this.suggestions.length - 1)){return;}
 this.adjustScroll(this.selectedIndex + 1);
},

 adjustScroll: function(i){
 var container = this.container;
 var activeItem = this.activate(i);
 var offsetTop = activeItem.offsetTop;
 var upperBound = container.scrollTop;
 var lowerBound = upperBound + this.options.maxHeight - 25;
 if (offsetTop < upperBound){
 container.scrollTop = offsetTop;
}else if (offsetTop > lowerBound){
 container.scrollTop = offsetTop - this.options.maxHeight + 25;
}
 this.el.value = this.suggestions[i];
},

 onSelect: function(i){
 (this.options.onSelect || Prototype.emptyFunction)(this.suggestions[i], this.data[i]);
}

};

Event.observe(document, 'dom:loaded', function(){Autocomplete.isDomLoaded = true;}, false);

miracle.hoverEmulation("#menu li");
miracle.hoverEmulation("#menu li.hover ul li");
miracle.hoverEmulation("#menu-left li");
miracle.hoverEmulation("#menu-left li.hover ul li");

/*
if(Prototype.Browser.IE){
 Event.observe(window, "resize", function(){
 resizeMain();
});
 
 Event.observe(window, "load", function(){
 resizeMain();
});
}
*/


function resizeMain(){
 if( location.host == "ewizz.hu" ) return;
 var main = $("main");
 var f = $("footer");
 var diff = f.offsetTop-main.offsetTop-20; //Nem tom miért kell még 20-at levonni, de ez van
 main.style.height = diff;
}

/*
Csavez 2010.03.02
Nem tölti 1000x az FCK editort ha 1000 FVK editoros textarea van hanem csak 1x, de az XML-eket így is annyiszor húzza be és az is sok idő ....
*/
miracle.initWysiwyg = function(){
 var fck_editors = $$('textarea[wysiwyg]');
 if(fck_editors.length){

 eval(this.include("/fckeditor/fckeditor.js"));

 if (typeof(FCKeditor)!="function") return false;
 window.oFCKeditors=new Array();

 for(var i=0; i < fck_editors.length; i++){
 var element = fck_editors[i];
 var name = element.getAttribute("name");
 var id = element.getAttribute("id");
 var height = element.getAttribute("wysiwyg_height");
 element.setAttribute("id", name);
 window.oFCKeditors[id]=new FCKeditor(name, "100%", height);
 window.oFCKeditors[id].Config['CustomConfigurationsPath']='/fckeditor/fckconfig.js';
 window.oFCKeditors[id].ToolbarSet = element.getAttribute("wysiwyg_toolbar") || "Default";
 window.oFCKeditors[id].ReplaceTextarea();
 element.setAttribute("id", id);
}
}
}
/*
miracle.initWysiwyg_fckeditor = function(textarea){
 window.oFCKeditors=new Array();


 if (typeof(FCKeditor)=="function"){
 var name=textarea.getAttribute("name");
 var id=textarea.getAttribute("id");
 var height=textarea.getAttribute("wysiwyg_height");
 textarea.setAttribute("id", name);
 window.oFCKeditors[id]=new FCKeditor(name, "100%", height);
 window.oFCKeditors[id].Config['CustomConfigurationsPath']='/fckeditor/fckconfig.js';
 window.oFCKeditors[id].ToolbarSet = textarea.getAttribute("wysiwyg_toolbar") || "Default";
 window.oFCKeditors[id].ReplaceTextarea();
 textarea.setAttribute("id", id);
}
}
*/

Event.observe(window, 'load', function(){
 miracle.initAjax('table.ewizz_lister');

 ewizz_panel.init();
 ewizz_toggle.init();

/*

 if( $('flying_menu') ){
 var topSpace = document.createElement("div");
 topSpace.style.height = $('flying_menu').clientHeight + 'px';
 new Insertion.Top(document.body, topSpace);
}

 if($('site_css_panel')){
 $('site_css_panel').observe('scroll', function(element){
 $('maintitle').innerHTML = $(Event.element(element)).scrollTop;
});
}
*/
});

var eWizzPanel = Class.create();
eWizzPanel.prototype ={
 initialize : function(){
 this.initDone = false;
},

 init : function(){
 if( this.initDone ) return;
 this.initDone = true;

 this.initTabPanels();
},

/**
 * (!browser.ieIE) ? element.hasClassName('qs_select') : element.getAttribute('className')=='qs_select';
 * Utálom az IE-t még mindig 
 **/
 initTabPanels : function(selector){
 var selector = selector || 'div.ewizz_tab_panel';
 $A($$(selector)).each(function(tab_panel){
 $A(tab_panel.getElementsByTagName('a')).each(function(element){
 Event.observe(element, 'click', function(){

 if( (!browser.ieIE) ? element.hasClassName('active') : element.getAttribute('className')=='active' ) return;

 var change = false;
 $A(tab_panel.getElementsByTagName('a')).each(function(tmp){

 if( !tmp.getAttribute('rel') ) return false;

 if( !$(tmp.getAttribute('rel')) ) return false; 

 var className = (!browser.ieIE) ? tmp.hasClassName('active') : tmp.getAttribute('className')=='active';
 if(className && !change){

 $(tmp.getAttribute('rel')).fade({duration:0.3});

 tmp.removeClassName('active');

 element.addClassName('active');

 $(element.getAttribute('rel')).appear({duration:0.3, queue: 'end'});

 change = true;
}
});
});
});
});
}

/* Vége az osztálynak */
}
var ewizz_panel = new eWizzPanel();

var eWizzToggle = Class.create();
eWizzToggle.prototype ={
 initialize : function(){
 this.initDone = false;
},

 init : function(){
 if( this.initDone ) return;
 this.initDone = true;

 this.initToggle();
},

 initToggle : function(selector){

 var selector = selector || 'div.ewizz_toggle';
 $A($$(selector)).each(function(toggle){

 var title = toggle.down('.ewizz_toggle_title'); // ő lesz kattintható
 var divToggle = $(toggle.down('.ewizz_toggle_title').getAttribute('rel')); // ő fog eltünni/megjelenni
 if( title && divToggle ){

 Event.observe(title, 'click', function(event){

 Effect.toggle(divToggle, 'slide',{duration: 0.4, queue: 'end'});

 if( title.hasClassName('open') ){
 title.removeClassName('open');
 title.addClassName('close');
}else{
 title.removeClassName('close');
 title.addClassName('open');
}
});
}
});
}
}
var ewizz_toggle = new eWizzToggle();



/* LOADED_JS: /www/webwizard.portal/public/www/php/modules/phpcommander/phpcommander.js */


var phpcommander = function(module_name){
 this.module_name = module_name;
 phpcommander.prototype.module_name = this.module_name;
}

phpcommander.prototype.load = function(tree_id, node_id, side){

 if(!side)return false;
 switch(side){
 case("left"):case("right"):break;
 default:return false;break;
}
 miracle.ajax(
 "phpcommander",
 "get_urls",
{tree_id:tree_id,node_id:node_id,side:side}, 
 function(req){
 $(this.module_name+"_"+side).innerHTML=req;
 kwindow.init_kwindow();
/*

 var sels = $$("#module_jscommander table.colgroup select.type-select");
 if( !sels.length ) return;
 sels.each( function(item){
 Event.observe(item, "change", function(){phpcommander.change_type(item);}.bind(item));
});
*/ 
 $$("#module_jscommander table.colgroup select").each(function(item){
 if(item.hasClassName('type-select'))
 Event.observe(item, "change", function(){phpcommander.change_type(item);}.bind(item));

 else if(item.hasClassName('topic-select'))
 Event.observe(item, "change", function(){phpcommander.change_topic(item);}.bind(item));

 else if(item.hasClassName('location-select'))
 Event.observe(item, "change", function(){phpcommander.change_location(item);}.bind(item));

 else if(item.hasClassName('islink-select'))
 Event.observe(item, "change", function(){phpcommander.change_islink(item);}.bind(item));

 else if(item.hasClassName('rights-select'))
 Event.observe(item, "change", function(){phpcommander.change_rights(item);}.bind(item));
});

}.bind(this)
 );
}

phpcommander.prototype.delete_row = function(side, id){
 var row = $("tr_"+side+"_"+id);
 row.parentNode.removeChild(row);
}

phpcommander.prototype.delete_node = function(side, id){
 this.delete_row(side, id);
 miracle.ajax("phpcommander","delete_nodex",{id:id},function(req){/*do nothing*/}.bind(this));
}

phpcommander.prototype.delete_tree = function(side, id){
 this.delete_row(side, id);
 miracle.ajax("phpcommander","delete_treex",{id:id},function(req){/*do nothing*/}.bind(this));
}

phpcommander.prototype.copy = function(id, side){
 miracle.ajax("phpcommander","copy_nodex",{id:id,side:side},function(req){
 eval(req);
 alert('Sikeresen átmásolva!');
}.bind(this));
}

phpcommander.prototype.move = function(id, side){
 miracle.ajax("phpcommander","move_nodex",{id:id,side:side},function(req){
 eval(req);
 alert('Sikeres áthelyezés!');
}.bind(this));
}

phpcommander.prototype.swap = function(id, direction, side){
 miracle.ajax("phpcommander","swap_node",{id:id,direction:direction,side:side},function(req){
 var i = supervar = 0;
 var table = $("table_"+side);
 var row_id = "tr_"+side+"_"+id;
 var the_row = $(row_id);
 var rows = $('tbody_'+side).rows;

 var total_rows = $A(rows).length;
 $A(rows).each(function(row){

 if(row.id==row_id && supervar==false){

 if(direction=="up") var count = i-1;
 else if(direction=="down") var count = i+1;
 else return false;

 if( !(i==0 && count==-1) && !(total_rows==i+1 && total_rows==count)){
 supervar=true;

 if(document.all) rows[i].swapNode(rows[count]); 
 else{


 var move_id = rows[i].id;
 var move_innerHTML = rows[i].innerHTML;

 var real_id = rows[count].id;
 var real_innerHTML = rows[count].innerHTML;

 rows[i].id = real_id;
 rows[i].innerHTML = real_innerHTML;

 rows[count].id = move_id;
 rows[count].innerHTML = move_innerHTML;
}
}
 else if(supervar==false) eval(req);
}
 i++;
});
}.bind(this));
}

phpcommander.prototype.change_type = function(target){
 if( !target ) return;
 var type = target.value;
 var parent = target.up(1);
 if( parent.nodeName != "TR" ) return; 
 var tmp = parent.getAttribute("id").split("_");
 var tree_id = tmp[tmp.length-1];
 miracle.ajax("phpcommander", "change_tree_type",{"tree_id": tree_id, "type": type});
}

phpcommander.prototype.change_topic = function(target){
 if( !target ) return;
 var type = target.value;
 var parent = target.up(1);
 if( parent.nodeName != "TR" ) return; 
 var tmp = parent.getAttribute("id").split("_");
 var tree_id = tmp[tmp.length-1];
 miracle.ajax("phpcommander", "change_url_topic",{"tree_id": tree_id, "topic": type});
}

phpcommander.prototype.change_location = function(target){
 if( !target ) return;
 var type = target.value;
 var parent = target.up(1);
 if( parent.nodeName != "TR" ) return; 
 var tmp = parent.getAttribute("id").split("_");
 var tree_id = tmp[tmp.length-1];
 miracle.ajax("phpcommander", "change_tree_location",{"tree_id": tree_id, "location": type});
}

phpcommander.prototype.change_rights = function(target){
 if( !target ) return;
 var level = target.value;
 var parent = target.up(1);
 if( parent.nodeName != "TR" ) return; 
 var tmp = parent.getAttribute("id").split("_");
 var tree_id = tmp[tmp.length-1];
 miracle.ajax("phpcommander", "change_url_rights_level",{"tree_id": tree_id, "level": level});
}

phpcommander.prototype.change_islink = function(target){
 if( !target ) return;
 var type = target.value;
 var parent = target.up(1);
 if( parent.nodeName != "TR" ) return; 
 var tmp = parent.getAttribute("id").split("_");
 var tree_id = tmp[tmp.length-1];
 miracle.ajax("phpcommander", "change_tree_islink",{"tree_id": tree_id, "islink": type});
}

var phpcommander = new phpcommander("jscommander");

/* phpcommander js class-tol fuggetlen dolgok */
miracle.initAction(initLinkSelect);
miracle.initAction(initModuleSelect);
miracle.initAction(initURLSelect);

function initLinkSelect(){
 var element=$("phpcommander_tree_islink");
 if (!element) return;
 element.observe("change", function(event){
 if (element.value=="n") $("module_url").className="hide";
 else if (element.value=="y") $("module_url").className="";
});
}


function jscommander_node_edit(){

 kwindow.init_kwindow_close();

 kwindow.init_kwindow_post();








 miracle.ajax(
 "phpcommander",
 "replace_node",
{nodeid:nodeid, treeid:treeid, parentid:parentid},
 function(response){
 $("module_jscommander").innerHTML=response;
 kwindow.init_kwindow();

}.bind(this)
 );

}


function initModuleSelect(){
 var element=$("phpcommander_module_for_url");
 if (!element) return;
 element.observe("change", function(event){
 miracle.ajax(
 "phpcommander",
 "get_urls_by_module",
{module:element.value}, 
 function(response){
 $("url_select").innerHTML=response;
 initURLSelect();
}.bind(this)
 );
});
}

function initURLSelect(){
 var element=$("phpcommander_connected_url");
 if (!element) return;
 element.observe("change", function(event){
 miracle.ajax(
 "phpcommander",
 "get_url",
{url_id:element.value}, 
 function(response){

 Object.keys(response[0]).each(function(e){

 if ($("phpcommander_"+e)) $("phpcommander_"+e).value=response[0][e];
 else if ($(e)) $(e).value=response[0][e];
});
 Rights.prototype.initStatus('phpcommander');
}.bind(this)
 );
});
}

function reload_the_page(){
 window.location.reload();
}

/* LOADED_JS: /www/_miracle/miracle-3.1.5/modules/url/url.js */


/**
 * David @ 2008.11.12.
 *
 * Ajax Input Kereso 
 *
 */

function Engine(input_id, function_name){
 this.input = input_id;
 this.StartFunc = function_name;


 Engine.prototype.time = 300;

 Engine.prototype.exception = new Array(9,13,16,17,18,19,20,27,33,34,35,36,44,91,92,93,112,113,114,115,116,117,118,119,120,121,122,123,144,145);




 Engine.prototype.input = this.input;
 Engine.prototype.countdown = false;
 Engine.prototype.StartFunc = this.StartFunc;

 Engine.prototype.SearchAdvanced = new SearchAdvanced();
}

var actual_pid = 0;
var actual_search_object = false;
var actual_orderby = 'id_a';

Engine.prototype.test = function(){
 alert("Hi. I am "+ this.input + " " +this.time);
}

Engine.prototype.initSearchUrlForm = function(){

 if(!$(this.input)) return false;

 this.search_input = $(this.input);
 this.search_input.onkeypress = function(key){

 return Engine.prototype.KillCountDown(key);
}
 this.search_input.onkeyup = function(key){

 Engine.prototype.KillCountDown(key);

 return Engine.prototype.StartCountdown(key);
}
}

Engine.prototype.StartCountdown = function(key_str){
 var key = (window.event) ? window.event.keyCode : key_str.keyCode;
 if(in_array(this.exception,key)) return false;
 else{
 Engine.prototype.countdown = setTimeout(function(){Engine.prototype.Search(1);}, this.time);
 
 return true;
}
}

Engine.prototype.KillCountDown = function(x){
 clearTimeout( Engine.prototype.countdown );
}

Engine.prototype.Search = function(pid, where, order){
 var search = $F(this.input);
 if(!pid)var pid=1;

 if(!where)var where=false;

 if(!Engine.prototype.SearchAdvanced.show){
 where = false;
 
}

 if(!order)var order=actual_orderby;
 else actual_orderby = order;

 miracle.ajax(
 "url",
 "url_search",
{search:search,pid:pid,where:where,order:order},
 function(req){
 

 actual_pid = req['pid'];
 actual_search_object = req['urls'];




 eval("Engine.prototype."+Engine.prototype.StartFunc+"(req);");
}.bind(this)
 );
}

Engine.prototype.BuildLayer = function(object){

 this.data = object['urls'];
 this.pages = object['pages'];
 this.pid = object['pid'];
 this.count = object['count'];
 var html = "<table class='lister' id='lister'>\n<thead>\n";
 var menu = new Array(
 'ID', 'Module', 'Function', 'Url', 'Regxp', 'Lang', 'Status'
 );
 var menu_width = new Array(30,0,0,0,0,30,30);
 var by = "a";
 var size = "";
 var img = "";
 var i = 0;
 menu.each(function(x){
 img = "";
 if(actual_orderby == x.toLowerCase()+"_a") by = "d"; else by = "a";
 if(actual_orderby == x.toLowerCase()+"_a") img = "<img src='/images/miracle/icons/arrow_down.png' style='display:inline;vertical-align:bottom;' />";
 if(actual_orderby == x.toLowerCase()+"_d") img = "<img src='/images/miracle/icons/arrow_up.png' style='display:inline;vertical-align:bottom;' />";
 if(menu_width[i]!=0) size = " width='"+menu_width[i]+"'"; else size = "";
 html += "<th"+size+"><a href='javascript:void(0);' onclick='javascript:engine.Search(1, actual_search_object, \""+x.toLowerCase()+"_"+by+"\");'>"+x+img+"</a></th>\n"
 i++;
});
 html += "</thead>\n<tbody>\n";
 this.data.each(function(row){


 html += "<tr>\n";
 html += "<td><a id='kwindow_url_"+row["id"]+"' rel='kwindow' module='url' method='url_edit' params='parentid="+row["parentid"]+"&id="+row["id"]+"'>"+ row["id"] +"</a></td>\n"
 html += "<td><a rel='kwindow' module='url' method='url_edit' params='parentid="+row["parentid"]+"&id="+row["id"]+"'>"+ row["module"] +"</td>\n"
 html += "<td><a rel='kwindow' module='url' method='url_edit' params='parentid="+row["parentid"]+"&id="+row["id"]+"'>"+ row["function"] +"</td>\n"
 html += "<td><a rel='kwindow' module='url' method='url_edit' params='parentid="+row["parentid"]+"&id="+row["id"]+"'>"+ row["url"] +"</td>\n"
 html += "<td><a rel='kwindow' module='url' method='url_edit' params='parentid="+row["parentid"]+"&id="+row["id"]+"'>"+ row["regxp"] +"</td>\n"
 html += "<td align='center'><a rel='kwindow' module='url' method='url_edit' params='parentid="+row["parentid"]+"&id="+row["id"]+"'>"+ row["lang"] +"</td>\n"
 html += "<td align='center'><a rel='kwindow' module='url' method='url_edit' params='parentid="+row["parentid"]+"&id="+row["id"]+"'>"+ row["status"] +"</td>\n"
 html += "</tr>\n";
});

 var pages ="";
 if(this.pages > 1 ){
 for(var pid=1;pid<=this.pages;pid++){
 if(this.pid==pid) pages+=" <span class='actual'>"+pid+"</span> ";
 else pages+=" <a class='pager' href='javascript:void(0);' onclick='javascript:engine.SearchAdvanced.Search("+pid+");'>"+pid+"</a> ";
}
}
 html +="<tfoot>\n<th colspan='7' align='center'>\n";

 html +="<div class='pager'>\n<b>Rekordszám:</b> "+this.count+" db<br/>\n<b>Aktuális lapszám:</b> "+this.pid+"/"+this.pages+" <div id='pager'>\n"+pages+"\n</div>\n</div>\n";
 html +="</th>\n</tfoot>\n";
 html +="</tbody>\n</table>\n";
 $('search_container').innerHTML=html;
 kwindow.init();
}

/*
Engine.prototype.EditUrl = function(url_id){
 miracle.ajax(
 "url",
 "get_url",
{search:url_id}, 
 function(req){
 
}.bind(this)
 );
}
*/

Engine.prototype.CheckEditUrl = function(){
 var inputs = new Array(
 'title', 'url', 'function', 'template'
 )
 error = false;
 inputs.each(function(input){
 if( $F('kwindow_url_'+input)=="" ){
 if(!error) $('kwindow_url_'+input).focus()
 error = true;
}
});

 setTimeout( function(){
 Engine.prototype.Search(actual_pid, actual_search_object)
}, 2500);
 
 if(!error) return true;
 return false;
}

function SearchAdvanced(){
 this.div_id = "search_advanced_search";
 this.show = false;
}

SearchAdvanced.prototype.ChangeDisplay = function(){

 var layer = $(this.div_id); 
 if(!this.show) layer.style.display="none";
 else layer.style.display="block";
}

SearchAdvanced.prototype.Start = function(){

 if(!this.show) this.show=true;

 else this.show=false;

 this.ChangeDisplay();
}

SearchAdvanced.prototype.Search = function(pid){
 if(!pid)var pid=1;
 var Varius = new Vars();
 
 Engine.prototype.Search(pid, Varius);
}

function Vars(){

 this.url_name = $F('search_url');
 Vars.prototype.url_name = this.url_name;

 this.module_name = $F('search_module');
 Vars.prototype.module_name = this.module_name;

 this.function_name = $F('search_function');
 Vars.prototype.function_name = this.function_name;

 this.regxp_name = $F('search_regxp');
 Vars.prototype.regxp_name = this.regxp_name;

 this.lang_name = $F('search_lang');
 Vars.prototype.lang_name = this.lang_name;

}

var engine = new Engine("search_url", "BuildLayer");
addEvent(window, "load", function(){engine.initSearchUrlForm();});

function in_array(my_array,my_value){

 caseSensitive = in_array.arguments.length<3?0:in_array.arguments[2];
 for(i=0;i<my_array.length;i++){
 if((caseSensitive==0?my_array[i]:my_array[i].toUpperCase())==(caseSensitive==0?my_value:my_value.toUpperCase())){
 return true;
}
}
 return false;
}

function Rights(){}


Rights.prototype.initButton = function(input){
 

 Event.observe($('rights_1'), "click", function(x){
 $('RightsClass').className="hide";

});

 Event.observe($('rights_2'), "click", function(x){
 $('RightsClass').className="";

});

 Event.observe($(input+'_right_type'), "change", function(x){
 Rights.prototype.initStatus(input);

});
}

Rights.prototype.initStatus = function(x){
 
 var status = $F(x+'_right_type');

 $('Rights_Status').className="hide";
 $('Rights_Rights').className="hide";
 $('Rights_Condition').className="hide";
 switch(status){
 case("status"):
 

 $('Rights_Status').className="";
 break;
 case("rights"):
 

 $('Rights_Rights').className="";
 break;
 case("condition"):
 

 $('Rights_Condition').className="";
 break;
}
}

var rights = new Rights();

function Urlcommander(module_name){
 this.module_name = module_name;
 Urlcommander.prototype.module_name = this.module_name;
}

Urlcommander.prototype.load = function(site_id, parent_id, side){
 if(!side)return false;
 switch(side){
 case("left"):case("right"):break;
 default:return false;break;
}

 miracle.ajax(
 "url",
 "get_urls",
{site_id:site_id,parent_id:parent_id,side:side,back:back},
 function(req){
 $(Urlcommander.prototype.module_name+"_"+side).innerHTML=req;

}.bind(this)
 );
}

Urlcommander.prototype.delete_row = function(side, id){
 var row = $("tr_"+side+"_"+id);
 row.parentNode.removeChild(row);
 miracle.ajax("url","delete_url",{id:id},function(req){}.bind(this));
}

var urlcommander = new Urlcommander("davids_urlcommander");




/*****************
 * URL Relations *
 *****************/
var urRelations = function(){

 var self = this;

 function in_array(needle, haystack, strict){
 var found = false, key, strict = !!strict;
 for (key in haystack){
 if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)){
 found = true;
 break;
}
}
 return found;
}



 this.init = function(){
 var changeSiteId = $("davids_urlcommander_siteid");
 if( changeSiteId ){
 Event.observe(changeSiteId, "change", function(){self.sendForm(changeSiteId)});
}

 var selectParent = $("davids_urlcommander_parentid");
 if( selectParent ) Event.observe(selectParent, "change", function(){self.selectParent(selectParent)});

 var submitButton = $("miracle-form-submit");
 if( submitButton ) Event.observe(submitButton, "click", function(){self.sendForm(submitButton)});
},

 this.sendForm = function(element){
 var form = $("miracle-form-davids_urlcommander-relations");
 if( form ){
 form.submit();
}
},

 this.selectParent = function(element){
 var optionTags = $$("#davids_urlcommander_childids option");
 if( optionTags ){optionTags.each( function(tag){tag.selected = null;});}

 var response = miracle.ajax("url", "urSelectParent", element.value);
 if( response.length ){
 if( optionTags ){
 optionTags.each( function(tag){
 if( in_array(tag.value, response) ){
 tag.selected = 1;
}
});
}
}
}
}

var Relations = new urRelations();

Event.observe(window, "load", function(){
 Relations.init();
});




/***************
 * DEBUG Tools *
 ***************/

function showProps(obj, objName){
 if (typeof(objName) == "undefined") objName = "object";
 var result = "";
 for (var i in obj){
 result += objName + "." + i + " = ";
 try{
 result += obj[i];
}
 catch (e){
 result += e;
}
 result += "\n";
}
 var w = window.open("", "w", "width=560,height=450,resizable=yes,scrollbars=yes");
 w.document.write("<pre>" + result + "</pre>");
 w.document.close();
}

/* LOADED_JS: /www/webwizard.portal/public/_portal/modules/user/user.js */


/**
 * project name: miracle
 * task name: module.login.php
 * author: wiktor
 * - - - - 
 * started @ 2005.02.03.
 * last modified @ see the timestamp ;)
 */

/**
 * INITIALIZATION
 */

miracle.initAction(init_login);

/**
 * FUNCTIONS
 */
function init_login(){
 init_zipcode();
}

function init_zipcode(){
 zipcodes=document.getElementsByTagNameAndAttribute("input", "accept", "zipcode");


 for (var i=0; i<zipcodes.length; i++){
 zipcodes[i].onchange=getCityByZipCode;
}
}

function getCityByZipCode(){

 zipcode=parseInt(this.value, 10);
 if (zipcode>999 && zipcode<10000){
 pattern=new RegExp ('zipcode','ig');
 cityid=this.id.replace(pattern, 'city');
 if (document.getElementById(cityid)){
 params=new Array();
 params[0]=zipcode;
 cityNode=document.getElementById(cityid);
 handlerparams=new Array(cityNode)
 miracle.ajax("miracle", "zipcode", params, 
 function (response){
 cityHandler(handlerparams, response);
});
}
}else{
 cityNode.readOnly=false;
}
}

function cityHandler(handlerparams, response){
 if (response!=''){
 handlerparams[0].value=response;
 handlerparams[0].readOnly=true;
}else{
 handlerparams[0].readOnly=false;
}
}

function getZipCodeBy(){

 zipcode=parseInt(this.value, 10);
 if (zipcode>999 && zipcode<10000){
 pattern=new RegExp ('zipcode','ig');
 cityid=this.id.replace(pattern, 'city');
 if (document.getElementById(cityid)){
 params=new Array();
 params[0]=zipcode;
 cityNode=document.getElementById(cityid);
 city=server_action("miracle","zipcode", params, false);
 if (city!=''){
 cityNode.value=city;
}
}
}
}

/*
 
*/

function onlyInteger(){
/* if (!this.oldValue){
 this.oldValue=0;
}
 if (this.nodeValue.parseInt()!=this.nodeValue){
 this.nodeValue=this.oldValue;
}else{
 this.oldValue=this.value;
}*/
}

/* LOADED_JS: /www/webwizard.portal/public/www/php/modules/content/content.js */



 /*****************************
 * Címkézéshez kapcsolódó JS *
 *****************************/

var moduleTags = function(){
 var self = this;
 var tags = new Array(); // cimkék tomb elinditasa




 var miracleModuleName = "tags";
 var ModuleNameForAjax;
 var elementfocus = false;

 this.init = function(){

 var searchAttribute = $$("div[tagsmodulename]");
 if( !searchAttribute.length ) return false;
 ModuleNameForAjax = searchAttribute[0].getAttribute("tagsmodulename");

 var TagInput = $(miracleModuleName+'-tag'); // input mezo

 if(!TagInput) return false;
 TagInput.onkeypress = function(ev){
 if(ev.keyCode==13){
 self.AddNewTag();

 ev || (ev = window.event); 
 if (ev.preventDefault){
 ev.preventDefault(); ev.stopPropagation(); 
}else{
 ev.cancelBubble = true; ev.returnValue = false; 
}
 return false;
 
}
}

 var submitButton = $('tags-SubmitButton');
 if( submitButton ){
 submitButton.onclick = function(ev){
 var params ={};
 params.tags = tags; 
 
 var parentId = $(miracleModuleName+"-parentId");
 var parentTable = $(miracleModuleName+"-parentTable");
 var lang = $(miracleModuleName+"-lang");
 
 if( parentId ){
 params.parentId = parentId.value;
}
 if( parentTable ){
 params.parentTable = parentTable.value;
}
 if( lang ){
 params.lang = lang.value;
}
 
 miracle.ajax(ModuleNameForAjax, "add_tags", params);
 alert("Címkék sikeresen mentve!");
}
}

 if($('AddNewTagImage') && $('AddNewTag')){
 $('AddNewTagImage').style.display="none";
 $('AddNewTag').style.display="block";
}

 if(!$('tag_container')){
 return false;
}
 
 var Container = $('tag_container');
 if(Container.value!=""){
 tags = self.GenererateArrayFromContainer();
 self.UpdatePublicTags();
}
}

 this.get_tags = function(){
 var cont = $('tags_sample');
 var parentTable = $(miracleModuleName+"-parentTable");
 var lang = $(miracleModuleName+"-lang");
 var param ={};
 
 if( parentTable ) param.parentTable = parentTable.value;
 if( lang ) param.lang = lang.value;
 
 result = miracle.ajax(ModuleNameForAjax, "get_tags", param);
 if( typeof(result) == "object" ){
 var htmlContent = "";
 result.each( function(obj){
 htmlContent += '<span class="oftenTag"><a href="javascript:void(0)">'+obj+'</a>, </span>';
});
 cont.innerHTML = htmlContent;
 var oftenTags = $$("span.oftenTag a");
 oftenTags.each( function(oftenTag){
 oftenTag.onclick = function(){
 self.AddNewTagForce(oftenTag.innerHTML);
 oftenTag.parentNode.parentNode.removeChild(oftenTag.parentNode);
}
});
}
}

 this.AddNewTag = function(){
 var TagInput = $(miracleModuleName+'-tag'); // input mezo
 var Container = $('tag_container'); // textarea mezo
 
 TagInput.value = (TagInput.value.strip());
 TagInput.value = (TagInput.value.stripTags());
 
 if(self.CheckTagValidation()=="stop"){// kodmentesites, vesszotlenites, trim (strip), stb.
 return false;
}
 else if(self.CheckTagEmpty()=="stop"){// ellenorzi, hogy ne elgyen ures a cimke
 return false;
}
 else if(self.CheckTagHTML()=="stop"){// html elemek kezelese
 return false;
}
 else if(self.CheckTagRegExp()=="stop"){// nem lehet 1 betus cimke specialis karakter
 return false;
}
 
 var TagIsInvalid = self.CheckTag(TagInput.value);

 if(TagIsInvalid['error'] == false){// ellenorzi, hogy letezik -e mar ilyen cimke
 Container.value = (Container.value + TagInput.value+", ");
 tags.push( TagInput.value ); // beteszi a tombbe




 TagInput.value = "";

 self.UpdatePublicTags();
}
 else{
 self.NotAllowedTag(3, TagIsInvalid);

 TagInput.select();
}
}

 this.AddNewTagForce = function(x){
 if(!x)return false;
 var TagInput = $(miracleModuleName+'-tag'); // input mezo
 TagInput.value = x;
 self.AddNewTag();
}

 this.CheckTagRegExp = function(){
 var TagInput=$(miracleModuleName+'-tag'); // input mezo
 var re=new RegExp("\\b[a-zA-Z0-9]+\\b");
 if (TagInput.value.match(re)){

 return true;
}else{

 self.NotAllowedTag(4, false);
 TagInput.select();
 return "stop";
}
}

 this.CheckTag = function(newTag){
 var Output=new Array();
 var i=0;
 for (i;i<=(tags.length-1);i++){
 if(tags[i].toLowerCase()==newTag.toLowerCase()){

 Output['error']=true;
 if(tags[i]==newTag){
 Output[0]=newTag;
}
 else{
 Output[0]=tags[i]+" (<b>"+newTag+"</b>)";
}
 Output[1]=newTag;
 Output[2]=tags[i];
 return Output;
}
}

 Output[0] = Output[1] = Output[2] = Output['error'] = false;
 return Output;
}

 this.CheckTagValidation = function(){
 var TagInput=$(miracleModuleName+'-tag'); // input mezo
 var InValid=new RegExp(",");
 if(InValid.test(TagInput.value) == true){
 TagInput.value = (TagInput.value.replace(",", ""));
 TagInput.value = (TagInput.value.strip());
 TagInput.value = (TagInput.value.stripTags());
 if(!self.CheckTagValidation()){
 self.NotAllowedTag(1, false);
}
}
 /*

 else if(TagInput.value == "" || TagInput.value == ","){
 NotAllowedTag(2, false);
 return "stop";
}
 */
 
 /*

 else if(TagInput.value.length == 4){
 NotAllowedTag(6, false);
 return "stop";
 )
 */
 
 /*

 else if(TagInput.value.length > 10){
 NotAllowedTag(7, false);
 return "stop";
 )
 */
 else{
 self.CheckTagEmpty();
 return false;
}
}

 this.CheckTagEmpty = function(){
 var TagInput = $(miracleModuleName+'-tag'); // input mezo
 if(TagInput.value=="" || TagInput.value==","){
 self.NotAllowedTag(2,false);
 return "stop";
}
}
 
 this.CheckTagHTML = function(){
 var TagInput=$(miracleModuleName+'-tag');
 var InValid=new Array();
 InValid[0]=new RegExp("&");
 InValid[1]=new RegExp("\"");
 InValid[2]=new RegExp("\'");
 InValid[3]=new RegExp("<");
 InValid[4]=new RegExp(">");
 var i=0;
 for (i; i<=(InValid.length-1); i++){
 if(InValid[i].test(TagInput.value) == true){
 self.NotAllowedTag(5, false);
 TagInput.select();
 return "stop";
}
}
 return true;
}

 this.hideError = function(){
 var tagError = $('TagError');
 tagError.hide();
}
 
 this.showError = function(){
 var tagError = $('TagError');
 tagError.show();
}

 this.NotAllowedTag = function(errormsg, extramsg){
 var TagInput = $(miracleModuleName+'-tag'); // input mezo
 var TagContainer = $('Tags'); // 'Tags' div mezo

 if(errormsg<1){errormsg = 0;}
 if(errormsg>10){errormsg = 0;}
 
 if(errormsg == 0){
 $('TagError').innerHTML = self.ErrorMassage(0) +" <u>"+extramsg[0]+"</u>";
 self.showError();
 setTimeout(function(){self.hideError();}, 10000);
}
 else if(errormsg == 3){
 $('TagError').innerHTML = self.ErrorMassage(errormsg) +" <u>"+extramsg[0]+"</u>";
 self.showError();
 setTimeout(function(){self.hideError();}, 10000);
 TagContainer.innerHTML = (TagContainer.innerHTML.replace("> "+extramsg[2]+", ", "> <b>"+extramsg[2]+"</b>, "));
 setTimeout("$('Tags').innerHTML = ($('Tags').innerHTML.replace(' <b>"+extramsg[2]+"</b>, ', ' "+extramsg[2]+", '));", 10000);
}
 else{
 $('TagError').innerHTML = self.ErrorMassage(errormsg);
 self.showError();
 setTimeout(function(){self.hideError();}, 10000);
}
 return "";
}
 
 this.ErrorMassage = function(errorid){
 if(errorid < 0) errorid=0;
 var ReturnText = $('Lang'+(errorid)).value.strip();


 return ReturnText;
}

 this.Button = function(i){
 var button_layer = '<span id="TagContainer'+i+'">';
 var button_edit = '<span onclick="tagsControl.EditTag('+i+')"><img src="/images/miracle/icons/pencil.png" border="0" /></span>';
 var button_del = '<span onclick="tagsControl.RemoveTag('+i+')"><img src="/images/miracle/icons/delete.png" border="0" /></span>';



 return button_layer + button_edit + button_del + " ";
}

 this.UpdatePublicTags = function(){

 var TagContainer = $('Tags'); // ide mennek a tomb elemei (publikus)

 var AllTagInOne = "";
 /*
 if(InValid.test(TagContainer.innerHTML) == true){
 var j = ( tags.indexOf( tags.last() ) );
 if(tags[j]!=""){TagContainer.innerHTML += Button(j)+tags[j].stripTags()+", </span>";}

 setTimeout("UpdatePublicTags();", 10001);
 return false;
}
 */
 i=0;
 for (i; i<=(tags.length-1); i++){
 if(tags[i]!=""){
 AllTagInOne += self.Button(i)+tags[i].stripTags()+", </span>";
}
}
 TagContainer.innerHTML = AllTagInOne;
 self.UpdateBackendTags();
}

 this.UpdateBackendTags = function(){
 var Container = $('tag_container');
 var AllTagInOne = "";
 var i=0;
 for (i; i<=(tags.length-1); i++){
 if(tags[i]!=""){
 AllTagInOne += tags[i].stripTags()+', ';
}
}
 Container.value = AllTagInOne;
}

 this.EditTag = function(index){

 var TagInput = $(miracleModuleName+'-tag');
 var i=0;
 for (i; i<=(tags.length-1); i++){
 if(i == index){
 TagInput.value = tags[i];
 TagInput.select();
 tags[i] = "";
 self.KillTagSpan(index);
}
}
 self.UpdatePublicTags();
}

 this.RemoveTag = function(index){

 var i=0;
 for (i; i<=(tags.length-1); i++){
 if(i == index){
 tags[i] = "";
 self.KillTagSpan(index);
}
}
 self.UpdatePublicTags();
}
 
 this.KillTagSpan = function(index){
 var TagSpan = $('TagContainer'+index);
 TagSpan.innerHTML = "";
}

 this.GenererateArrayFromContainer = function(){
 var Container = $('tag_container');
 var AllTagFromCont = explode(', ', Container.value);
 var AllTagInOne = "";
 var i=0;
 /*
 for (i; i<=(AllTagFromCont.length-1); i++){
 if(AllTagFromCont[i]!=""){
 AllTagInOne += AllTagFromCont[
