/** * @constructor * @param input Reference to watched input element. Text input expected. * @param callBack Event handler. Function will be called on input change. Current value of input will be passed as 1st argument. * @param object Set variable this in called event handler, if event handler is non-static. * @param interval Set watch interval. Default is 200ms. * @class Instance of InputWatch watches input element and call event handler on input change. */ function InputWatch(input, callBack, object, interval) { if (interval==undefined) // 200ms interval by default interval = 200; /** @private */ this.input = input; /** @private */ this.callBack = callBack; /** @private */ this.object = object; /** @private */ this.lastVal = this.input.value; var cbInternal = function() { var val = this.input.value; if (val != this.lastVal) { this.lastVal = val; this.callBack.call(this.object, val); } } var cbInternalWrapper = function() { cbInternal.call(arguments.callee.object); } cbInternalWrapper.object = this; window.setInterval(cbInternalWrapper, interval); } /** * @constructor * @param searchStr Sting to search. * @class Search text in text. */ function SearchEngine(searchStr) { /** * Escape regular expressions in text * @param text Text to escape. * @return Escaped text. * @type String * @private */ SearchEngine.prototype.escapeRegExp = function(text) { text = text.replace(/\\/g, '\\\\'); text = text.replace(/\^/g, '\\^'); text = text.replace(/\$/g, '\\$'); text = text.replace(/\./g, '\\.'); text = text.replace(/\*/g, '\\*'); text = text.replace(/\+/g, '\\+'); text = text.replace(/\?/g, '\\?'); text = text.replace(/\=/g, '\\='); text = text.replace(/\!/g, '\\!'); text = text.replace(/\:/g, '\\:'); text = text.replace(/\|/g, '\\|'); text = text.replace(/\//g, '\\/'); text = text.replace(/\(/g, '\\('); text = text.replace(/\)/g, '\\)'); text = text.replace(/\[/g, '\\['); text = text.replace(/\]/g, '\\]'); text = text.replace(/\{/g, '\\{'); text = text.replace(/\}/g, '\\}'); return text; } /** * @private */ SearchEngine.prototype.escapePunctation = function(text) { text = text.replace(/[aá]/g, '[aá]'); text = text.replace(/[cč]/g, '[cč]'); text = text.replace(/[dď]/g, '[dď]'); text = text.replace(/[eéě]/g, '[eéě]'); text = text.replace(/[ií]/g, '[ií]'); text = text.replace(/[nň]/g, '[nň]'); text = text.replace(/[oó]/g, '[oó]'); text = text.replace(/[rř]/g, '[rř]'); text = text.replace(/[sš]/g, '[sš]'); text = text.replace(/[tť]/g, '[tť]'); text = text.replace(/[uúů]/g, '[uúů]'); text = text.replace(/[yý]/g, '[yý]'); text = text.replace(/[zž]/g, '[zž]'); return text; } /** @private */ this.empty = (searchStr==undefined || searchStr.length==0); if (!this.empty) { var pattern = searchStr; pattern = this.escapeRegExp(pattern); // Escape special chars pattern = this.escapePunctation(pattern); // Escape punctation pattern = '('+pattern+')'; // Mark re subgroup (for substitutions) /** @private */ this.re = new RegExp(pattern, 'gi'); } /** * Search pattern in given text. * @param text Text to search in. * @return Return true if pattern was matched. * @type bool */ SearchEngine.prototype.isMatch = function(text) { return !this.empty && (-1!= text.search(this.re)); } } /** * @constructor * @class Experimental! Will be documented later. */ function SearchEngineChain(searchStr) { /** @private */ this.list = new Array(); // Decomposite input to words using white spaces as separator var decomp = searchStr.split(/ +/); for (var i=0; iXMLHttp object. * (browser independency layer) * @return Return instance of XMLHttp object */ function createXmlHttp() { var xmlHttp = null; try { xmlHttp = new XMLHttpRequest(); } catch(e) { try { xmlHttp = new ActiveXObject('Microsoft.XMLHttp'); } catch(e) { } } return xmlHttp; } /** * Define DOM element's innerText property * if not already defined. * (browser independency layer) */ function patchInnerText() { if(typeof(HTMLElement) == "undefined" || typeof(document.documentElement.innerText) == "string") return; HTMLElement.prototype.__defineSetter__("innerText", function(text) { while (this.hasChildNodes()) this.removeChild(this.firstChild); this.appendChild(document.createTextNode(text)); }); HTMLElement.prototype.__defineGetter__("innerText", function() { return this.textContent; }); } /** * Dump object content to #jsLog block on page. * (useful for debug purposes) */ function dump(object) { if (null==object) return; log = document.getElementById('jsLog'); if (null==log) return; var h1 = document.createElement('h1'); h1.innerHTML = 'Dump'; log.appendChild(h1); var text = new String; for(tmp in object) text += '' + tmp + ': ' + object[tmp] + '
\n'; var p = document.createElement('p'); p.innerHTML = text; log.appendChild(p); } /** * @constructor * @class Experimental! Will be documented later. */ function PropStorage(obj, propList) { /** @private */ this.map = new Object; for (var i=0; i