
// $Id: anticopy.js 117 2008-04-17 14:26:26Z jarda $

/**
 * Funkce pro kontrolu opisování.
 */
var Anticopy =
{
	working : false,
	progressbar : false,
	progressbarState : 0,
	bar: null,
	simple : false,
	simplePos : 0,	// pozice pro jednoduchý graf
	simpleRtl : true	// zprava doleva
};

/**
 * Odešle data.
 */
Anticopy.submit = function()
{
	// zpracovává se vždy pouze jedno hledání
	if (!Anticopy.working) {
		// skryje případně zobrazenou chybu nebo výsledky
		Anticopy.clear();

		Anticopy.progressbar = false;
		Anticopy.progressbarState = 0;
		Anticopy.simple = true;
		Anticopy.simplePos = 0;
		Anticopy.simpleRtl = true;
		Anticopy.bar = Util.get('#progressbar span')[0];

		Anticopy.simpleBar();
		Anticopy.progressbarStart();
		Anticopy.working = true;
	}
};

/**
 * Spustí jednoduchý graf.
 */
Anticopy.simpleBar = function()
{
	if (Anticopy.simple) {
		if (Anticopy.simpleRtl) {
			Anticopy.simplePos += 10;
			if (Anticopy.simplePos > 90) {
				Anticopy.simpleRtl = false;
				Anticopy.simplePos = 80;
			}
		} else {
			Anticopy.simplePos -= 10;
			if (Anticopy.simplePos < 0) {
				Anticopy.simpleRtl = true;
				Anticopy.simplePos = 10;
			}
		}
		Anticopy.bar.style.left = Anticopy.simplePos + '%';
		Anticopy.bar.style.width = '10%';

		window.setTimeout(Anticopy.simpleBar, 200);
	}
};


/**
 * Vyčistí vše, tzn. skryje některé prvky stránky.
 */
Anticopy.clear = function()
{
	Util.hide('progressbar');
	Util.hide('error');
	Util.hide('result');
	Util.hide('result-help');
	Util.hide('result-message');
};

/**
 * Spustí kontrolu stavu zpracování.
 */
Anticopy.progressbarStart = function()
{
	Anticopy.progressbar = true;
	Anticopy.progressbarState = 0;
	Util.get('#progressbar span')[0].style.width = '0%';
	Util.show('progressbar');
	window.setTimeout(function() {Anticopy.progressbarCheck();}, 1000);
};

/**
 * Zkontroluje stav zpracování.
 */
Anticopy.progressbarCheck = function()
{
	if (Anticopy.progressbar) {
		try {
			var ajax = new Ajax();
			ajax.get('/progress.php?time=' + new Date().getTime(), Anticopy, 'progressbarUpdate', 1, 3);   // čas se posílá kvůli IE, které jinak cachuje
		} catch (e) {
		}
	}
};

/**
 * Aktualizuje lištu stav zpracování.
 *
 * @param Object data
 */
Anticopy.progressbarUpdate = function(data)
{
	if (Anticopy.progressbar) {
		if ((data != null) && (data.error == null)) {
			// jako kontrola, kdyby nějaký stav dorazil se zpozděním
			if (data.done > 0) {
				Anticopy.simple = false;
				Anticopy.bar.style.left = 0;
			}
			if (Anticopy.progressbarState < data.done) {
				Anticopy.progressbarState = data.done;
				Util.get('#progressbar span')[0].style.width = Math.floor(data.done / data.total * 100) + '%';
			}
		}

		window.setTimeout(function() {Anticopy.progressbarCheck();}, 2000);
	}
};

/**
 * Ukončí kontrolu stavu zpracování.
 */
Anticopy.progressbarEnd = function()
{
	Anticopy.progressbar = false;
	Util.hide('progressbar');
};

/**
 * Vypíše výsledek.
 *
 * @param Object data
 */
Anticopy.result = function(data)
{
	if (data.error != null) {   // chyba ajaxu
		Anticopy.error('Nepodařilo se dokončit vyhledávání.');
	} else if (data.servererror != null) {  // chyba na serveru
		Anticopy.error(data.servererror);
	} else if (data.result != null) {   // zobrazí data
		var content = [];
		for (var url in data.result) {
			var currentResult = data.result[url];
			content.push('<tr><td><div><a href="' + url + '" title="' + url + '" onclick="return !window.open(this.href);">' + currentResult.title+ '</a>');
			content.push('<img src="/skin/info.gif" onclick="return !window.open(\'/detail.php?url=' + encodeURIComponent(url) + '#first\');" />');
			content.push('<a href="/pdf.php?url=' + encodeURIComponent(url) + '"><img src="/skin/save.gif" /></a>');
			content.push('</div>');
			content.push('</td>');
			content.push('<td class="count">' + currentResult.found + '%</td>');
			content.push('<td class="db">' + currentResult.database + '</td></tr>');
		}

		if (content.length > 0) {
			var result = Util.gE('result');
			// trochu komplikovanější vkládání obsah tabulky, ale jinak to v IE a Opeře nefunguje
			var table = Util.get('table', result)[0];
			var temp = document.createElement('span');
			temp.innerHTML = '<table><tbody>' + content.join('') + '</tbody></table>';
			table.replaceChild(temp.firstChild.firstChild, Util.get('tbody', result)[0]);
			Util.show(result);
			Util.show('result-help');
		} else {
			Util.show('result-message');
		}
	}

	Anticopy.progressbarEnd();
	Anticopy.working = false;
};

/**
 * Zobrazí/skryje chybovou hlášku.
 *
 * @param String error
 */
Anticopy.error = function(error)
{
	if (error != null) {
		Util.get('#error p')[0].innerHTML = error;
		Util.show('error');
	} else {
		Util.hide('error');
	}
	Anticopy.working = false;
};

/**
 * Vytvoří instanci Ajaxu.
 */
function Ajax()
{
	var self = this;

	var request = null;
	var requestUrl = '';
	var requestData = null;
	var requestMethod = 'GET';

	var requestAttempts = 3;
	var requestTimeout = 5;
	var requestTimeoutId = null;

	var requestCallbackObject = null;
	var requestCallbackFunc = null;

	/**
	 * Provede požadavek metodou GET.
	 *
	 * @param String url url adresa
	 * @param Object object objekt, ke kterému patří funkce
	 * @param String func jméno funkce, které se předají vrácená data
	 * @param integer attempts počet pokusů na odeslání požadavku
	 * @param integer timeout časový limit na jeden požadavek
	 */
	this.get = function(url, object, func, attempts, timeout)
	{
		requestUrl = url;
		requestCallbackObject = object || null;
		requestCallbackFunc = func || null;
		requestMethod = 'GET';
		requestAttempts = attempts || requestAttempts;
		requestTimeout = timeout || requestTimeout;

		// odešle požadavek
		send();
	};

	/**
	 * Provede požadavek metodou POST.
	 *
	 * @param String url url adresa
	 * @param String data data
	 * @param Object object objekt, ke kterému patří funkce
	 * @param String func jméno funkce, které se předají vrácená data
	 * @param integer attempts počet pokusů na odeslání požadavku
	 * @param integer timeout časový limit na jeden požadavek
	 */
	this.post = function(url, data, object, func, attempts, timeout)
	{
		requestUrl = url;
		requestData = data;
		requestCallbackObject = object || null;
		requestCallbackFunc = func || null;
		requestMethod = 'POST';
		requestAttempts = attempts || requestAttempts;
		requestTimeout = timeout || requestTimeout;

		// odešle požadavek
		send();
	};

	/**
	 * Ukončí probíhající požadavek.
	 */
	this.abort = function()
	{
		request.abort();
	};

	/**
	 * Provede se po vypršení časového limitu na požadavek.
	 *
	 * @access private
	 */
	this.timeout = function()
	{
		self.abort();
		window.clearTimeout(requestTimeoutId);

		requestAttempts--;
		if (requestAttempts > 0) {
			send();
		} else if (requestCallbackObject != null) {
			requestCallbackObject[requestCallbackFunc]({error : 500});
		}
	};

	/**
	 * Provede požadavek zvolenou metodou.
	 *
	 * @access private
	 */
	function send()
	{
		request = initialize();
		request.open(requestMethod, requestUrl, true);
		request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		request.onreadystatechange = onreadystatechange;

		requestTimeoutId = window.setTimeout(self.timeout, requestTimeout * 1000);
		request.send(requestData);
	};

	/**
	 * Kontroluje stav požadavku.
	 *
	 * @access private
	 */
	function onreadystatechange()
	{
		if (request.readyState == 4) {
			try {
				// zruší hlídání časového limitu
				window.clearTimeout(requestTimeoutId);

				if (request.status == 200) {
					if (requestCallbackObject != null) {
						try {
							eval('var data = (' + request.responseText + ');');
						} catch (e) {
							// server nevrátil JSON
							var data = {error : 500};
						}

						requestCallbackObject[requestCallbackFunc](data);
					}
				} else {
					requestAttempts--;
					if (requestAttempts > 0) {
						send();
					} else if (requestCallbackObject != null) {
						requestCallbackObject[requestCallbackFunc]({error : request.status});
					}
				}
			} catch (E) {
				// odchytává výjimku, která nastane po abort()
			}
		}
	};

	/**
	 * Vytvoří instanci XMLHttpRequestu.
	 *
	 * @access private
	 * @throws Error když se nevytvoří instance
	 */
	function initialize()
	{
		if (typeof XMLHttpRequest != 'undefined') {
			return new XMLHttpRequest();
		} else {
			try {
				return new ActiveXObject('Msxml2.XMLHTTP');
			} catch (e) {
				try {
					return new ActiveXObject('Microsoft.XMLHTTP');
				} catch (E) {
					throw new Error('XMLHttpRequest není dostupný.');
				}
			}
		}
	};
};

/**
 * Různé pomocné funkce.
 */
var Util = {};

/**
 * Vrátí element s daným id.
 *
 * @param String id
 * @return HTMLElement
 */
Util.gE = function(id)
{
	return document.getElementById(id);
};

/**
 * Vrátí elementy splňující daný selektor.
 *
 * @todo vylepšit, otestovat rychlost
 * @param String selector
 * @param HTMLElement from
 * @return Array
 */
Util.get = function(selector, from)
{
	/**
	 * Vrátí elementy splňující daný selector od určitého elementu.
	 *
	 * @access private
	 * @param String selector
	 * @param Object from
	 * @return Array
	 */
	this.parse = function(selector, from)
	{
		var elements = [];

		var parts = selector.split(' ');
		var first = parts[0];
		var rest = parts.slice(1);

		switch (first.charAt(0)) {
		case '#':
			var currentElement = Util.gE(first.substring(1));
			if (currentElement != null) {
				if (rest.length > 0) {
					elements = this.parse(rest.join(' '), currentElement);
				} else {
					elements.push(currentElement);
				}
			}
			break;
		case '.':
		default:
			var currentElements = (first.charAt(0) == '.')
				? Util.getElementsByClassName(from, first.substring(1))
				: from.getElementsByTagName(first);
			if (currentElements.length > 0) {
				if (rest.length > 0) {
					for (var i = 0; i < currentElements.length; i++) {
						var returnedElements = this.parse(rest.join(' '), currentElements[i]);
						for (var j = 0; j < returnedElements.length; j++) {
							elements.push(returnedElements[j]);
						}
					}
				} else {
					elements = currentElements;
				}
			}
			break;
		}

		return elements;
	};

	var elements = [];

	from = from || document;
	var selectors = selector.split(',');
	for (var i = 0; i < selectors.length; i++) {
		var currentElements = this.parse(selectors[i], from);
		for (var j = 0; j < currentElements.length; j++) {
			elements.push(currentElements[j]);
		}
	}

	return elements;
};

/**
 * Vrátí elementy s danou třídu.
 *
 * @param HTMLElement element
 * @param String className
 */
Util.getElementsByClassName = function(element, className)
{
	var children = element.getElementsByTagName('*');
	var childrenCount = children.length;

	var elements = [];
	var pattern = new RegExp('(^|\\s)' + className + '(\\s|$)');
	for (var i = 0; i < childrenCount; i++) {
		if (pattern.test(children[i].className)) {
			elements.push(children[i]);
		}
	}

	return elements;
};

/**
 * Zjistí, zda má elementu danou třídu.
 *
 * @param HTMLElement element
 * @param String className
 */
Util.hasClassName = function(element, className)
{
	if (element.className != null) {
		var pattern = new RegExp('(^|\\s)' + className + '(\\s|$)');
		if (pattern.test(element.className)) {
			return true;
		}
	}

	return false;
};

/**
 * Zobrazí element s daným id.
 *
 * @param String/Object element
 */
Util.show = function(element)
{
	Util.showHide(element, true);
};

/**
 * Skryje element s daným id.
 *
 * @param String/Object element
 */
Util.hide = function(element)
{
	Util.showHide(element, false);
};

/**
 * Skryje nebo zobrazí element s daným id.
 *
 * @param String/Object element
 * @param boolean show jestli má element schovat či skrýt (volitelné)
 */
Util.showHide = function(element, show)
{
	if (Util.isString(element)) {
		element = Util.gE(element);
	}

	if (element == null) {
		return;
	}

	if (show == null) {
		element.style.display = (element.style.display == 'none') ? 'block' : 'none';
	} else if (show) {
		element.style.display = 'block';
	} else {
		element.style.display = 'none';
	}
};

/**
 * Otestuje, zda je objekt řetězcem.
 *
 * @param Object object
 * @return boolean
 */
Util.isString = function(object)
{
	return (typeof object == 'string');
};