idCache = {};

function GetById (itemId) {
    var cached = idCache[itemId];
    if (!cached) {
        cached = document.getElementById (itemId);
        idCache[itemId] = cached;
    }
    return cached;
}

function CheckAll(event, name){
    if (!event) event = window.event;
    var control = event.target || event.srcElement;
    var frm = control.form; 
    if(!frm) return;
    var i;
    var e;
    var state = control.checked;
    var title = state ? 'Отменить выделенные' : 'Выделить все';

    for (i = 0; i < frm.elements.length; i++) {
        e = frm.elements[i];
        if (e.type == 'checkbox' && e.name == name) {
            e.checked = state;
        }
    }
}

function CheckGroup(event, name, group_id){
    if (!event) event = window.event;
    var control = event.target || event.srcElement;
    var frm = control.form;
    if(!frm) return;
    var i;
    var e;
    var state = control.checked;
    var title = state ? 'Отменить выделенные' : 'Выделить все';

    for (i = 0; i < frm.elements.length; i++) {
        e = frm.elements[i];
        if (e.type == 'checkbox' && e.name == name && e.id == group_id ) {
            if (e.checked != state) {
                e.checked = state;
            }
        }
    }
}


function CheckAmountOfCheckboxes(event, max) {

    if (!event) event = window.event;
    var control = event.target || event.srcElement;
	
	var frm = control.form;
	var checked_ammount = 0;
    for (i = 0; i < frm.elements.length; i++) {
		e = frm.elements[i];
        if (e.type == 'checkbox' && e.checked == 1) {
			checked_ammount++;
		}
	}
	if (checked_ammount > max) {
		alert ('Нельзя выбирать более '+max+' позиций');
		return false;
	}
	return true;
}

function CheckSeorostRules() {
	var chkbx = GetById('promote_rules');
	if (chkbx.checked != 1) {
		return confirm('Если Вы не согласны с условиями продвижения, то Ваш выбор запросов будет отменён. Продолжить?');
	}
	return 1;
}

function CheckLinesAmount(max) {
	if (max == '') {
		return true;
	}
    var frm = event.srcElement.form;
	var count = 0;
    for (i = 0; i < frm.elements.length; i++) {
		e = frm.elements[i];
		if (e.type == 'textarea') {
			var text = e.value;
			var entries = text.split(/[\r\n,\s+]/g);
			for (j = 0; j < entries.length; j ++) { 
				if (entries[j].length) {
					count ++;
				}
			}
			if (count > max) {
				alert('Вы ввели слишком много зеркал');
				return false;
			}
			return true;
		}
	}
	return false;
}

function AddWithAlias (url) {
	var withalias = confirm('Хотите ли вы также добавить алиас вместе с этим сайтом?');
	if (withalias) {
		window.location = url + '&add_aliases=1';
		return;
	}
	window.location = url;
}
function ChangeVis(element, target, url){
    var block = GetById(target);
    if(!block) return;

    if(!window.loader) window.loader = new net.ContentLoader();
    var str = '';
    for (i in element) {
        str += i + '\n';
    }
    if (element.innerText == '+') {
        window.loader.loadXMLDoc(url, target);
        element.innerHTML = '&#150;'
    } else {
        element.innerText = '+';
        block.innerHTML = '';
    } 
}


function Show (element) {
    if (!element.style) {
        element = GetById (element);
    }
	if (element) {
	    element.style.display = 'block';
	}
}

function Hide (element) {
    if (!element.style) {
        element = GetById (element);
    }
    if (element) {
	    element.style.display = 'none';
	}
}

function ShowHide (element) {
    if (!element.style) {
        element = GetById (element);
    }

    if (element.style.display == 'block') {
		element.style.display = 'none'
	} else {
		element.style.display = 'block'
	}
}

function ShowModalForm (formId) {
    Show (formId);
    var shadow = GetById ('shadow');
	var login_form = GetById ('login');
	var window_height = document.compatMode=='CSS1Compat' && !window.opera?document.documentElement.clientHeight:document.body.clientHeight;
	var page_height = GetYScroll() + 10;
	var result_height = window_height > page_height ? window_height : page_height;
    shadow.style.height = result_height + 'px'; 
    Show (shadow);
//	Hide ('flash_graph');
    Show ('modal');
	login_form.elements[0].focus();
}

function HideModalForm (formId) {
    Hide (formId);
    Hide ('shadow');
    Hide ('modal');
//	Show ('flash_graph');
}

if (document.getElementById) {
		document.onkeydown = escapekey;
}

function escapekey(e) {
    var code;
    if (!e) e = window.event;
    if (e.keyCode) code = e.keyCode;
    else if (e.which) code = e.which;
    if ((code == 27) && (e.ctrlKey == false) && (e.altKey == false)) {
		HideModalForm('modal');
		HideFaq();
	}
}


function SetInput () {
    for(var i = 0; i < arguments.length; i++) {
        GetById (arguments[i]).value = arguments[++i];
    }
}

function SetScalar () {
    for(var i = 0; i < arguments.length; i++) {
        GetById (arguments[i]).innerHTML = arguments[++i];
    }
}

function GetYScroll() {
    yScroll = 0;

    if (window.innerHeight && window.scrollMaxY || window.innerWidth && window.scrollMaxX) {
	    yScroll = window.innerHeight + window.scrollMaxY;
	    xScroll = window.innerWidth + window.scrollMaxX;
	
	    var deff = document.documentElement;
	    var wff = (deff&&deff.clientWidth) || document.body.clientWidth || window.innerWidth || self.innerWidth;
	    var hff = (deff&&deff.clientHeight) || document.body.clientHeight || window.innerHeight || self.innerHeight;
	
	    xScroll -= (window.innerWidth - wff);
	    yScroll -= (window.innerHeight - hff);
    } else if (document.body.scrollHeight > document.body.offsetHeight || document.body.scrollWidth > document.body.offsetWidth) { // all but Explorer Mac
	    yScroll = document.body.scrollHeight;
	    xScroll = document.body.scrollWidth;
    } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
	    yScroll = document.body.offsetHeight;
	    xScroll = document.body.offsetWidth;
    }

    return yScroll;
}

function getOffsetY()
{
  return self.pageYOffset || (document.documentElement && document.documentElement.scrollTop) || (document.body && document.body.scrollTop);
}

function PrepareChecked (form, targetFormId, controlName) {
    var values = {};
    var valuesCount = 0;
    for (i = 0; i < form.length; i ++) {
        var currField = form[i];
        if (currField.type != 'checkbox') continue;
        if (currField.checked) {
            values[currField.value] = 1;
            valuesCount ++;
        }
    }
    
    if (!valuesCount) {
        alert ("Вами не указан ни один элемент. Выберите как минимум один и намите на кнопку еще раз.");
        return 0;
    }
    
    var targetForm = GetById (targetFormId);
    //targetForm

    var baseInput = targetForm[controlName];
    
    var first = 1;
    
    for (var key in values) {
        if (first) {
            baseInput.setAttribute ('value', key);
            first = 0;
            continue;
        }
        var clone = baseInput.cloneNode (1);
        clone.setAttribute ('value', key);
        targetForm.appendChild (clone);
    }
    
    return 1;
}

function GetCookie (name) {
	
	var start = document.cookie.indexOf (name + "=");
	var len = start + name.length + 1;
	if ((!start) && (name != document.cookie.substring (0, name.length))) {
		return null;
	}
	if (start == -1) return null;
	var end = document.cookie.indexOf(";", len);
	if (end == -1)
		end = document.cookie.length;
	return unescape( document.cookie.substring (len, end));
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

function ToggleDetails (id, src) {
	
	obj = src.parentNode.parentNode;
	if (!obj) return;

	var str = src.innerHTML;

	var nextObj = obj.nextSibling;
	if (nextObj && nextObj.tagName == 'TR' && nextObj.className == 'details_' + id) {
		//src.innerHTML = str.replace('-', '+');
		obj.parentNode.removeChild(nextObj);
		return;
	}

	//src.innerHTML = str.replace('+', '-');
	
	var detailsObj = GetById('details_' + id);
	if (!detailsObj) return; 

	var tr = document.createElement('TR');
	tr.className = 'details_' + id;
	var td = document.createElement('TD');
	
	td.innerHTML = detailsObj.innerHTML;
	td.setAttribute('colspan', detailsColspan);
	td.colSpan = detailsColspan; // for IE
	td.className = 'site_info';

	tr.appendChild(td);
	obj.parentNode.insertBefore(tr, obj.nextSibling);
	
}


var dom = (document.getElementById) ? true : false;
var ns5 = (!document.all && dom || window.opera) ? true: false;
var ie5 = ((navigator.userAgent.indexOf("MSIE")>-1) && dom) ? true : false;
var ie4 = (document.all && !dom) ? true : false;

var offX = 25;
var offY = 10; 

var t1,t2;	// for setTimeouts

function PopupDetails (event, siteId, object) {
	var infoBlock   = GetById ('info-popup');
	var infoContent = GetById ('info-popup-content');
	if (!(infoBlock && infoContent)) return;
	
	var infoStyle = infoBlock.style;
	
	if (object.className != 'site') {
		var sibling = object.previousSibling;
		while (sibling.className != 'site') {
			sibling = sibling.previousSibling;
		}
		object = sibling;
	}
	
	// we show info block before get it width;
	infoContent.innerHTML = GetById ('details_'+siteId).innerHTML;
	infoStyle.display = 'block';
	
	/*var infoW = (ie4||ie5)? infoBlock.clientWidth: infoBlock.offsetWidth;
	var infoH = (ie4||ie5)? infoBlock.clientHeight: infoBlock.offsetHeight;
	var infoL = (ie4||ie5)? object.clientLeft: object.offsetLeft;*/
	var infoW = infoBlock.offsetWidth;
	var infoH = infoBlock.offsetHeight;
	var infoL = object.offsetLeft + object.offsetParent.offsetLeft;

	infoStyle.left = infoL+offX;
	
	if (t1) clearTimeout(t1);
	if (t2) clearTimeout(t2);

	//create reference to common "body" across doctypes
	var standardBody = (document.compatMode=="CSS1Compat")
		? document.documentElement
		: document.body;
	
	var mouseX, mouseY, winW, winH;
	
	if (ns5) {
		mouseX = event.pageX;
		mouseY = event.pageY;
		winW = window.innerWidth-20 + window.pageXOffset;
		winH = window.innerHeight-20 + window.pageYOffset;
	} else {
		mouseX = window.event.clientX + standardBody.scrollLeft;
		mouseY = window.event.clientY + standardBody.scrollTop;
		winW = standardBody.clientWidth + standardBody.scrollLeft;
		winH = standardBody.clientHeight + standardBody.scrollTop;
	}
	
	/*if ((mouseX+offX+infoW)>winW) {
		infoStyle.left = mouseX-(infoW+offX)+"px";
	} else {
		infoStyle.left = mouseX+offX+"px";
	}*/
	
	if ((mouseY+offY+infoH)>winH) { 
		infoStyle.top = mouseY-(infoH+offY)+"px";
		infoBlock.className = 'upper';
	} else {
		infoStyle.top = mouseY+offY+"px";
		infoBlock.className = '';
	}
	
	infoContent.innerHTML += '';
}

function PopdownDetails () {
	var infoBlock = GetById ('info-popup');
	var infoStyle = infoBlock.style;

	infoStyle.display = 'none';
}


function ShowFaq (href, height) {
    var y = getOffsetY();

    HideFaq();
	
    var ifr = document.createElement('IFRAME');
    ifr.setAttribute('id', 'faq_div');
    ifr.setAttribute('frameBorder', 'no');
    ifr.setAttribute('scrolling', 'no');
    ifr.src = href;
    ifr.style.top = y + 135 + 'px';
	if (height) {
	    ifr.style.height = height;
	};
    document.body.appendChild(ifr);
    ifr.style.display = 'block';
    return false;
}

function HideFaq() {
    var iframe = document.getElementById('faq_div');
    if (iframe) {
        document.body.removeChild(iframe);
    }
}

function set_fullday (wday) {
    var input_field = GetById(wday);
    input_field.value = '00:00-23:59';
    return 0;
}

function isEnterKey (event) {
	return (event.keyCode == 13);
}

function load_url (href, id) {
	var Loader = new Ajax.Updater(id, href, {method: 'get'});
}

function load_ajax_page(id, url, param) {
	if (!param) {
		param = $H(url.toQueryParams());
		var arrChunks = url.split('?');
		url = arrChunks[0];
	}
	param.set('rnd', Math.floor(Math.random()*1000));
	
	var Loader = new Ajax.Updater(
		id,
		url,
		{
			parameters: param
		}
	);

	$(id).scrollTo();
}

var strModalWindow;

function escapeKeyDown (e) {
	var element = Event.element(e);
	if (strModalWindow && e.keyCode == 27) {
		hideModalWindow(strModalWindow);
	}
}

function showModalWindow (id) {
	var element = $(id);
	if (element) {
		var shadow = $('shadow');
		if (shadow) {
			var window_height = document.compatMode=='CSS1Compat' 
				&& !window.opera
				?document.documentElement.clientHeight
				:document.body.clientHeight;
			var page_height = GetYScroll() + 10;
			var result_height = window_height > page_height ? window_height : page_height;
//			shadow.style.height = result_height + 'px';
			Show('shadow');
			Show(id);
		}

		var v = document.viewport;
		var intLeft = parseInt(v.getWidth() / 2 - element.getWidth() / 2);
		var intTop = parseInt(v.getHeight() / 3 - element.getHeight() / 2);
		element.setStyle({
			'top' : intTop + 'px',
			'left' : intLeft + 'px'
		});
		return true;
	}
	return false;
}

function hideModalWindow (id) {
	var element = $(id);
	if (element) {
		if (element.onHide) {
			element.onHide();
		}
		Hide(id);
	}
	Hide('shadow');
}

var Controls = $H({
	serp_top: {
		initialize: function (args) {
			var dataset = args.get('dataset');
			var id = dataset.createId(args.get('id'));
			this.dataset = dataset;
			var obj = $(id);
			if (obj) {
				var positions = $(id + '0');
				var engines = $(id + '1');
				if (positions && engines) {
					this.positions = positions;
					this.engines = engines;
					this.updateVisibility();
					Event.observe(positions.id, 'change', this.valueChange.bind(this));
					Event.observe(engines.id, 'change', this.valueChange.bind(this));
				}
			}
			this.updateType = 'none';
		},
		updateVisibility: function () {
			this.engines.style.visibility = this.positions.selectedIndex > 1 
				? 'visible' : 'hidden';
		},
		valueChange: function (event) {
			var param = $H();
			var positions = this.positions;
			var position = this.positions.value;
			param.set(positions.name, positions.value);
			var engines = this.engines;
			var engineName = engines.name;
			if (positions.selectedIndex > 1) {
				param.set(engineName, engines.value);
			} else {
				this.dataset.deleteState(engineName);
			}
			this.dataset.update(param);
			this.dataset.setState(param);
			this.updateVisibility();
		}
	},
	accept: {
		initialize: function (args) {
			var dataset = args.get('dataset');
			var id = dataset.createId(args.get('id'));
			this.dataset = dataset;
			var obj = $(id);
			var checkbox = $(id + '_checkbox');
			if (obj && checkbox) {
				Event.observe(obj, 'click', this.buttonClick.bind(this));
				this.checkbox = checkbox;
				this.name = obj.name;
			}
		},
		buttonClick: function (event) {
			var param = $H();
			param.set(this.name, 1);
			var checkbox = this.checkbox;
			param.set(checkbox.name, checkbox.checked ? 1 : 0);
			var elements = checkbox.form.elements;
			var promoteParam = 'q';
			var affectedParam = 'qq';
			var promoteValues = [];
			var affectedValues = [];
			for (var i = 0; i < elements.length; i ++) {
				var element = elements[i];
				if (element.type == 'checkbox' && element.name == promoteParam) {
					var value = element.value;
					if (element.checked) {
						promoteValues.push(value);
					} 
					affectedValues.push(value);
				}
			}
			param.set(promoteParam, promoteValues);
			param.set(affectedParam, affectedValues);
			this.dataset.update(param);
		}
	}
});

var Recordset = Class.create({
	initialize: function (args) {
		args = $H(args);
		this.id = args.get('id');
		var url = args.get('url');
		this.url = url ? url : this.id + '.html';
		var bypass = args.get('bypass');
		if (!bypass) {
			bypass = $H();
		} 
		this.bypass = $H(bypass);
		var options = args.get('options') || [];
		options.push('exp');
		this.options = options;
		this.optionSelector = '.option'
		this.expandSelector = '.icon';

		this.controls = $H(args.get('controls') || {});

		this.sortId = 0;
		this.page = 1;
		this.pageParam = 'p';
		this.sortParam = args.get('sort_param') || 'o';
		this.searchParam = 'search';
		this.initProgressCapture();
		this.initControls();
		this.loaded = 1;
		this.state = $H();
	},
	initControls: function () {
		this.initDisplayArea();
		this.initPager();
		this.initHeaders();
		this.initOptions();
		this.initSearchControl();
		this.initCopyText(); 
		var controls = this.controls;
		var keys = controls.keys();
		if (this.loaded) {
			var objects = this.controlObjects;
			for (var i = 0; i < objects.length; i ++) {
				var object = objects[i];
				if(object.update) {
					object.update();
				}
			}
		} else {
			this.controlObjects = [];
			for (var i = 0; i < keys.length; i ++) {
				var key = keys[i];
				var definition = Controls.get(key);
				if (definition) {
					var classObj = Class.create(definition);
					var args = $H(controls.get(key));
					args.set('dataset', this);
					var control = new classObj(args);
					this.controlObjects.push(control);
				}
			}
		}
	},
	initPager: function () {
		var inputPage = $(this.createId('input_page'));
		if (inputPage) {
			this.page = inputPage.value;
			this.usePager = true;
			Event.observe(inputPage.id, 'keydown', this.inputPageKeyDown.bind(this));
		}
		var controls = new Array('first', 'last', 'back', 'forward');
		for (var i = 0; i < controls.length; i ++) {
			var controlName = controls[i];
			var controlId = this.createId(controlName);
			var element = $(controlId);
			if (element && element.name) {
				Event.observe(controlId, 'click', this.pageButtonClick.bind(this));
			}
		}
	},
	inputPageKeyDown: function (event) {
		var element = Event.element(event);
		if (element && isEnterKey(event)) {
			var page = element.value;
			if (isNaN(page) || page < 1) {
				alert('Недопустимое значение!');
			} else {
				this.goPage(page);
			}
		}
	},
	pageButtonClick: function (event) {
		var element = Event.element(event);	
		if (element && element.name) {
			Event.stopObserving(element.id, 'click');
			this.goPage(element.name);
		}	
	},
	initProgressCapture: function () {
		var capture = this.getProgressCapture();
		if (capture) {
			capture.hide();
			capture.innerHTML = '<p>идёт загрузка...</p>';
			capture.absolutize();
		}
	},
	initHeaders: function () {
		var headers = $(this.id).getElementsByClassName('sort_link');
		var headersCount = headers.length;
		if (headersCount > 0) {
			this.useHeaders = true;
			for (var i = 0; i < headers.length; i ++) {
				var header = headers[i];
				Event.observe(header.id, 'click', this.sortLinkClick.bind(this));
			}
		}
	},
	initDisplayArea: function () {
		var scrollObj = $(this.createId('scrollarea'));
		if (scrollObj) {
			var height = document.viewport.getHeight();
			height = height - height/3;
			var objHeight = scrollObj.getHeight();
			if (objHeight > height) {
				scrollObj.setStyle({
					'height' : height + 'px',
					'overflow' : 'auto'
				});
			}
		}
	},
	initSearchControl: function () {
		var searchFieldId = this.createId('search_text');
		var searchField = $(searchFieldId);
		if (searchField) {
			if (!this.searchFieldReady) {
				var objForm = searchField.form;
				if (objForm) {
					this.replaceFormSubmit(objForm);
				}
				this.useSearch = true;
				this.searchParam = 'search';
				this.searchFieldId = searchFieldId;
				this.searchText = searchField.value;
				Event.observe(searchField.id, 'keydown', this.searchTextKeyDown.bind(this));
				var searchButton = $(this.createId('search'));
				if (searchButton) {
					Event.observe(searchButton.id, 'click', this.searchButtonClick.bind(this));
				}
				var cancelButton = $(this.createId('cancel_search'));
				if (cancelButton) {
					Event.observe(cancelButton.id, 'click', this.cancelButtonClick.bind(this));
				}
				this.searchFieldReady = true;
			}
			var searchLinkId = this.createId('search_link');
			var searchLink = $(searchLinkId);
			if (searchLink) {
				this.searchLinkId = searchLinkId;
				Event.observe(searchLinkId, 'click', this.searchLinkClick.bind(this));
			}
		}
	},
	replaceFormSubmit: function (objForm) {
		objForm.setAttribute('onsubmit', 'return false');
	},
	searchLinkClick: function (event) {
		var element = Event.element(event);
		if (element && element.id == this.searchLinkId) {
			this.showSearchBox();
		}
	},
	showSearchBox: function () {
		var windowId = this.createId('search_box');
		var textBoxId = this.createId('search_text');
		var textBox = $(textBoxId);	
		if (textBox && showModalWindow(windowId)) {
			textBox.focus();
			var searchBox = $(windowId);
			searchBox.onHide = function () {
				textBox.value = '';
			};
			Event.observe(document, 'keydown', escapeKeyDown);
			strModalWindow = windowId;
		}
	},
	searchTextKeyDown: function (event) {
		var element = Event.element(event);
		if (element && isEnterKey(event)) {
			this.goSearch(element.value);
		}
	},
	searchButtonClick: function (event) {
		var element = $(this.searchFieldId);
		if (element) {
			this.goSearch(element.value);
		}
	},
	cancelButtonClick: function (event) {
		var element = $(this.searchFieldId);
		if (element) {
			element.value = '';
			this.goSearch('');
		}
	},
	goSearch: function (text) {
		var modalWindow = $(strModalWindow);
		if (modalWindow) {
			if (modalWindow.onHide) {
				modalWindow.onHide = null;
			}
			hideModalWindow(strModalWindow);
		}
		this.searchText = text;
		var param = $H();
		param.set(this.searchParam, text);
		this.update(param);
		this.setState(param);
	},
	table: function () {
		return $(this.createId('table'));
	},
	initOptions: function () {
		var table = this.table();
		if (table) {
			var options = this.options;
			var optionIds = [];
			for (var i = 0; i < options.length; i ++) {
				optionIds.push(this.createId(options[i]));
			}
			
			var arrOptions = table.select(this.optionSelector).concat(table.select(this.expandSelector));

			for (var s = 0; s < arrOptions.length; s ++) {
				var option = arrOptions[s];
				var optionId = option.id;
				if (optionId) {
					for (var i = 0; i < optionIds.length; i ++) {
						if (optionId.startsWith(optionIds[i])) {
							Event.observe(optionId, 'click', this.optionClick.bind(this));	
						}
					}
				}
			}
		}
	},
	optionClick: function (event) {
		var element = Event.findElement(event, this.optionSelector)
			|| Event.findElement(event, this.expandSelector);
		if (element) {
			var elementId = element.id;
			var arrChunks = elementId.split(':');
			arrChunks = arrChunks[1].split('_');
			var optionName = arrChunks.shift();
			var paramName;
			var optionValue;
			if (optionName == 'exp') {
				paramName = '_' + arrChunks.shift();
			} else {
				paramName = optionName;
			}
			optionValue = arrChunks.join('_');
			var param = $H();
			param.set(paramName, optionValue);
			this.update(param);
		}
	},
	deleteElement: function (id) {
		var param = $H();
		param.set('delete', id);
		this.update(param);
	},
	createId: function (name) {
		return this.id + ':' + name;
	},
	extractId: function (str) {
		var chunks = str.split(':');
		return chunks[1];
	},
	extractValue: function (str) {
		var chunks = this.extractId(str).split('_');
		return chunks[1];
		
	},
	setState: function (param) {
		var keys = param.keys();
		for (var i = 0; i < keys.length; i ++) {
			var key = keys[i];
			this.state.set(key, param.get(key));
		}
	},
	deleteState: function (key) {
		this.state.unset(key);
	},
	update: function (args) {
		if (!args) {
			args = $H();
		}
		var param = $H();
		param.set('rnd', Math.floor(Math.random()*1000));
		
		var bypass = this.bypass;
		var keys = bypass.keys();
		for (var i = 0; i < keys.length; i ++) {
			var key = keys[i];
			param.set(key, bypass.get(key));
		}

		var state = this.state;
		keys = state.keys();
		for (var i = 0; i < keys.length; i ++) {
			var key = keys[i];
			param.set(key, state.get(key));
		}

		keys = args.keys();
		for (var i = 0; i < keys.length; i ++) {
			var key = keys[i];
			param.set(key, args.get(key));	
		}
	
		var Loader = new Ajax.Updater(
			this.id,
			this.url,
			{
				parameters: param,
				onCreate: function () {
					this.showProgressCapture();
				}.bind(this),
				onComplete: function (response) {
					this.hideProgressCapture();
					this.initControls();
				}.bind(this)
			}
		);
	},
	getProgressCapture: function () {
		var captureId = this.createId('progress');
		return $(captureId);
	},
	showProgressCapture: function () {
		var capture = this.getProgressCapture();
		if (capture) {
			capture.clonePosition($(this.id));
			capture.absolutize();
			capture.show();
		}
	},
	hideProgressCapture: function () {
		var capture = this.getProgressCapture();
		if (capture) {
			capture.hide();
		}
	},
	sortLinkClick: function (event) {
		var element = Event.element(event);
		if (element) {
			var elementId = element.id;
			Event.stopObserving(elementId, 'click');
			this.sort(this.extractValue(elementId));
		}
	},
	updateIntParam: function (name, value, positive) {
		if (!isNaN(value) && (positive && value > 0 || value != 0)) {
			var param = $H();
			param.set(name, value);
			this.update(param);
			this.setState(param);
		}
	},
	goPage: function (page) {
		this.updateIntParam(this.pageParam, page, true);
	},
	sort: function(sortId) {
		this.updateIntParam(this.sortParam, sortId, false);
	},
	initCopyText: function () {
		var table = $(this.createId('table'));
		var strClass = 'shorten';
		if (table) {
			var elements = table.getElementsByClassName(strClass);

			for (var i = 0; i < elements.length; i ++) {
				var element = elements[i];
				Event.observe(element, 'click', this.copyTextClick.bind(this));	
			}
		}

	},
	copyTextClick: function (event) {
		var element = Event.element(event);
		if (element) {
			var strTitle = element.getAttribute('title');
			if (strTitle) {
				alert(strTitle);
			}
		}
	}
});
