/** * Soubor s tridou pro generovani Heatmapy *  * @category   jnHeatmap * @package    API * @author     Michal Danhel, mailto:danhel@jannovak.cz * @copyright  Copyright (c) 2010 Ing. JAN NOVAK - Velka Hradebni 484/2, 400 01 Usti nad Labem - Ceska Republika - mailto:info@jannovak.cz * @link       http://www.jannovak.cz  * @version    $Id: main.js 3287 2011-06-20 15:58:18Z Michal Danhel $ *//** * Trida pro generovani Heatmapy *  * @category   jnHeatmap * @package    API * @author     Michal Danhel, mailto:danhel@jannovak.cz * @copyright  Copyright (c) 2010 Ing. JAN NOVAK - Velka Hradebni 484/2, 400 01 Usti nad Labem - Ceska Republika - mailto:info@jannovak.cz * @link       http://www.jannovak.cz  */var JNHeatmap = {	serverScriptLogURLFormat: '/jnHeatmap/addclick?x={x}&y={y}&url={url}&sid={sid}&cookie={cookie}&host={host}',	clickImagePath: '/jnHeatmap/img/mouse-click.png',	clickImageSize: {'width':'30', 'height':'30'},	calendarImagePath: '/jnCalendar/img/ico.gif',	spyMapId: 'backout',	spyMap: null,	leftTopClickMapOffset: null,	forceDocumentHost: '',	forceDocumentUrl: '',	documentUrl: '',	documentHost: '',	logClick: true,	initCheck: false,		/**	 * Inicializacni metoda objektu	 * 	 * @return void	 */	init: function() {		if (!this.spyMap || !this.spyMap.tagName || this.spyMap.tagName == '') {			if (this.spyMapId != '') {				this.spyMap = document.getElementById(this.spyMapId);				this.leftTopSpyMapOffset = this.getElementOffset(this.spyMap);				this.initCheck = true;			}		}				if (this.initCheck) {			// for resizing window			this.addListener(window, 'resize', function() {				JNHeatmap.leftTopSpyMapOffset = JNHeatmap.getElementOffset(JNHeatmap.spyMap);			});						var urlRE = new RegExp('^https?:\\/\\/([_a-zA-Z0-9\\.\\-]+\\.[a-zA-Z]{2,})(\\/{1}.*)$','i');			var hashmarkRE = new RegExp('([^#]*)#.*$','i');						var hostRE = new RegExp('^https?:\\/\\/([_a-zA-Z0-9\\.\\-]+\\.[a-zA-Z]{2,})\\/?$','i');			var urlOnlyRE = new RegExp('^\\/.*$','i');						if (this.forceDocumentHost.length && this.forceDocumentHost.length > 0 && hostRE.test(this.forceDocumentHost)) {				this.documentHost = this.forceDocumentHost.replace(hostRE, '$1');			}			else {				this.documentHost = document.URL.replace(urlRE, '$1');			}			if (this.forceDocumentUrl.length && this.forceDocumentUrl.length > 0 && urlOnlyRE.test(this.forceDocumentUrl)) {				this.documentUrl = this.forceDocumentUrl;			}			else {				this.documentUrl = document.URL.replace(urlRE, '$2').replace(hashmarkRE, '$1');			}						var paramsRE = new RegExp('\\?([^#]*)(#?.*)$');			if (this.documentUrl.indexOf('?') >= 0 && this.documentUrl.indexOf('?') < this.documentUrl.indexOf('&')) {				var arrMatches = this.documentUrl.match(paramsRE);				var arrParams = arrMatches[1].split('&').sort();				this.documentUrl = this.documentUrl.replace(paramsRE, '?' + arrParams.join('&') + '$2');			}						this.addListener(document, 'mousedown', this.sendClick);			/*			this.addListener(this.spyMap, 'mousemove', this.mouseMove);			this.spyMap.onmousemove = function(e){				if (!e) var e = window.event;				var data = JNHeatmap.getMouseXY(e);				//alert('x'+data.x+'=y'+data.y);			}			*/						this.serverScriptLogURLFormat = this.serverScriptLogURLFormat.replace("{url}", encodeURIComponent(this.documentUrl));			this.serverScriptLogURLFormat = this.serverScriptLogURLFormat.replace("{host}", encodeURIComponent(this.documentHost));			this.serverScriptLogURLFormat = this.serverScriptLogURLFormat.replace("{sid}", this.getPHPSID());			this.serverScriptLogURLFormat = this.serverScriptLogURLFormat.replace("{cookie}", encodeURIComponent(this.getGAValues()));		}	},		/*	mouseMove: function(e) {		if (!e) var e = window.event;		var data = JNHeatmap.getMouseXY(e);		//alert('x'+data.x+'=y'+data.y);	},	*/		/**	 * Pridava udalost do registru	 * 	 * @param Object element Sledovany prvek dokumentu	 * @param string strEvent Udalost	 * @param Object fnHandler Funkce pro reakci na udalost	 * @return void	 */	addListener: function (element, strEvent, fnHandler) {		if (element.addEventListener) {			element.addEventListener(strEvent, fnHandler, false);		}		else if (element.attachEvent) {			element.attachEvent('on' + strEvent, fnHandler);		}	},		/**	 * Vraci pozici leveho horniho rohu prvku v DOM	 * 	 * @param Object obj Prvek dokumentu	 * @return array Souradnice {'x':int, 'y':int}	 */	getElementOffset: function(obj) {		var curleft = 0;		var curtop = 0;				if (obj.offsetParent) {			while (obj.offsetParent){				curleft += obj.offsetLeft;				curtop += obj.offsetTop;				obj = obj.offsetParent;			}		}		else {			if (obj.x) {				curleft += obj.x;			}			if (obj.y) {				curtop += obj.y;			}		}		if (document.all) {			var marginLeftExplorer = parseInt(document.body.style.marginLeft);			var marginTopExplorer = parseInt(document.body.style.marginTop);						if (isNaN(marginLeftExplorer)) {				marginLeftExplorer = 0;			}			if (isNaN(marginTopExplorer)) {				marginTopExplorer = 0;			}						curleft = curleft + marginLeftExplorer;			curtop = curtop + marginTopExplorer;		}				return {'x':curleft, 'y':curtop};	},		/**	 * Vraci unikatni PHP SSID navstevy webu	 * 	 * @return string Hash	 */	getPHPSID: function() {		var re = new RegExp('^.*PHPSESSID=([a-zA-Z0-9]+).*$', 'i');				if (!re.test(document.cookie)) {			return '';		}		else {			var sid = document.cookie.replace(re, '$1');			return (sid != '') ? sid : '';		}	},		/**	 * Vraci obsah cookie v pripade, ze je nasazena sluzba Google Analytics	 * 	 * @return string Cookie sluzby Google Analytics	 */	getGAValues: function() {		var reUTMA = new RegExp('^.*(__utma=[^$;]+).*$', 'i');		var parUTMA = '';				if (reUTMA.test(document.cookie)) {			parUTMA = document.cookie.replace(reUTMA, '$1');		}				var reUTMZ = new RegExp('^.*(__utmz=[^$;]+).*$', 'i');		var parUTMZ = '';				if (reUTMZ.test(document.cookie)) {			parUTMZ = document.cookie.replace(reUTMZ, '$1');		}				return (parUTMA != '' || parUTMZ != '') ? (parUTMA + ';' + parUTMZ) : '';	},		/**	 * Vraci aktualni souradnice kurzoru mysi	 * 	 * @param Object e Objekt udalosti	 * @return array Souradnice {'x':int, 'y':int}	 */	getMouseXY: function(e) {		if (!e) var e = window.event;				var mouseX = (e.pageX) ? e.pageX : (e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft);		var mouseY = (e.pageY) ? e.pageY : (e.clientY + document.body.scrollTop + document.documentElement.scrollTop);				mouseX -= this.leftTopSpyMapOffset.x;		mouseY -= this.leftTopSpyMapOffset.y;				return {'x':mouseX, 'y':mouseY};	},		/**	 * Uklada navstevnikovo kliknuti mysi	 * 	 * @param Object e Objekt udalosti	 * @return void	 */	sendClick: function(e) {		if (JNHeatmap.logClick) {			if (!e) var e = window.event;			var mouseXYObj = JNHeatmap.getMouseXY(e);					var url = JNHeatmap.serverScriptLogURLFormat.replace("{x}", mouseXYObj.x);			url = url.replace("{y}", mouseXYObj.y);						var img = new Image();			img.src = url;		}	},		/**	 * Zobrazuje bod kliknuti mysi	 * 	 * @param array data Data bodu kliknuti	 * @return void	 */	showClick: function(data) {		var click = document.createElement('div');		click.className = 'jnheatmap-click';		click.style.position = 'absolute';		click.style.zIndex = '2103';		click.style.top = (data.y - (this.clickImageSize.height / 2)) + 'px';		click.style.left = (data.x - (this.clickImageSize.width / 2)) + 'px';		click.style.width = this.clickImageSize.width + 'px';		click.style.height = this.clickImageSize.height + 'px';		click.style.background = "url('" + this.clickImagePath + "') no-repeat";		JNHeatmap.spyMap.appendChild(click);	},		/**	 * Odeslani XMLHttp pozadavku	 * 	 * @param Function state_change Funkce zajistujici obsluhu pri zmene stavu pozadavku, dostane parametr s XMLHttp objektem	 * @param string method [GET|POST]	 * @param string url URL pozadavku	 * @param string content Telo zpravy	 * @param array headers Predane hlavicky ve tvaru {'hlavicka':'obsah'}	 * @return boolean true v pripade uspechu, false jinak	 * @copyright Jakub Vrana, http://php.vrana.cz/	 */	sendXHR: function (state_change, method, url, content, headers) {	    var xmlhttp = (window.XMLHttpRequest ? new XMLHttpRequest() : (window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : false));	    if (!xmlhttp) {	        return false;	    }	    xmlhttp.open(method, url);	    xmlhttp.onreadystatechange = function () {	        state_change(xmlhttp);	    };	    headers = headers || {};	    headers['X-Requested-With'] = headers['X-Requested-With'] || 'XMLHttpRequest';	    for (var key in headers) {	        xmlhttp.setRequestHeader(key, headers[key]);	    }	    xmlhttp.send(content);	    return true;	},		/**	 * Zobrazuje/skryva heatmapu	 * 	 * @param boolean state Stav [true:zobrazit|false:skryt]	 * @return boolean	 */	showHeatmap: function(state) {		if (state == true) {			var data = 'url=' + encodeURIComponent(this.documentUrl) + '&dateFrom=' + document.getElementById('dateFrom').value + '&dateTo=' + document.getElementById('dateTo').value;		    if (!this.sendXHR(function(xmlhttp) {				if (xmlhttp.readyState == 4) {					if (xmlhttp.status < 200 || xmlhttp.status >= 300) {						return false;					}										eval('var data = ' + xmlhttp.responseText + ';');					for (var i = 0; i < data.length; i++) {						JNHeatmap.showClick(data[i]);					}					JNHeatmap.showSublayer(true);				}			}, 'POST', '/jnHeatmap/getclicks', data, {'Content-Type':'application/x-www-form-urlencoded', 'Content-length':data.length, 'Connection':'close'})) {		        return false;		    }		    return true;		}		else {			if (JNHeatmap.spyMap.getElementsByTagName) {				var objects = JNHeatmap.spyMap.getElementsByTagName('div');				for (var i=0; i<objects.length; i++) {					if (objects[i].className && (objects[i].className.indexOf('jnheatmap-click') != -1)) {						objects[i].style.display = 'none';					}				}				return JNHeatmap.showSublayer(false);			}		}		return false;	},		/**	 * Zobrazuje/skryva podkladovou vrstvu heatmapy	 * 	 * @param boolean state Stav [true:zobrazit|false:skryt]	 * @return boolean	 */	showSublayer: function(state) {		if (state == true) {			var documentHeight = Math.max(				Math.max(document.body.scrollHeight, document.documentElement.scrollHeight),				Math.max(document.body.offsetHeight, document.documentElement.offsetHeight),				Math.max(document.body.clientHeight, document.documentElement.clientHeight)			);						var sublayer = document.createElement('div');			sublayer.id = 'heatmap-sublayer';			sublayer.style.position = 'absolute';			sublayer.style.zIndex = '2101';			sublayer.style.top = '0';			sublayer.style.left = '0';			sublayer.style.width = '100%';			sublayer.style.height = documentHeight + 'px';			sublayer.style.opacity = 0.5;			sublayer.style.filter = 'alpha(opacity = 50)';			sublayer.style.backgroundColor = '#000';			JNHeatmap.spyMap.appendChild(sublayer);						return true;		}		else {			var sublayer = document.getElementById('heatmap-sublayer');			JNHeatmap.spyMap.removeChild(sublayer);						return true;		}		return false;	},		/**	 * Zobrazuje/skryva ovladaci panel heatmapy	 * 	 * @param boolean state Stav [true:zobrazit|false:skryt]	 * @return void	 */	showControlPanel: function(state) {		if (state == true) {			this.logClick = false;						var panel = document.createElement('div');			panel.id = 'heatmap-control-panel';			panel.style.position = 'fixed';			panel.style.zIndex = '2901';			panel.style.top = '6px';			panel.style.left = '150px';			panel.innerHTML = '';						panel.innerHTML += '&nbsp;&nbsp; Datum od: <a class="btn" href="#" onfocus="lcs(\'dateFrom\', \'onlypast\');" onclick="event.cancelBubble=true; lcs(\'dateFrom\');" title="Klikněte pro výběr datumu"><img src="' + this.calendarImagePath + '" width="16" height="16" alt="Zobrazit kalendář" /></a>&nbsp;&nbsp;<input class="input-text shorter" id="dateFrom" name="dateFrom" value="" maxlength="10" onfocus="lcs(\'dateFrom\', \'onlypast\');" onclick="event.cancelBubble=true; lcs(\'dateFrom\');" size="8" readonly="readonly" />';			panel.innerHTML += '&nbsp;&nbsp; Datum do: <a class="btn" href="#" onfocus="lcs(\'dateTo\', \'onlypast\');" onclick="event.cancelBubble=true; lcs(\'dateTo\');" title="Klikněte pro výběr datumu"><img src="' + this.calendarImagePath + '" width="16" height="16" alt="Zobrazit kalendář" /></a>&nbsp;&nbsp;<input class="input-text shorter" id="dateTo" name="dateTo" value="" maxlength="10" onfocus="lcs(\'dateTo\', \'onlypast\');" onclick="event.cancelBubble=true; lcs(\'dateTo\');" size="7" readonly="readonly" />';			panel.innerHTML += '&nbsp;&nbsp; <input id="heatmap-btn" type="button" name="send" value="Zobrazit" />';						JNHeatmap.spyMap.appendChild(panel);						var showClicksBtnState = 'off';			var heatmapBtn = document.getElementById('heatmap-btn');			heatmapBtn.onclick = function() {				if (showClicksBtnState == 'on') {					if (JNHeatmap.showHeatmap(false)) {						showClicksBtnState = 'off';						document.getElementById('heatmap-btn').value = 'Zobrazit';					}				}   				else {					if (JNHeatmap.showHeatmap(true)) {						showClicksBtnState = 'on';						document.getElementById('heatmap-btn').value = 'Skrýt';					}				}			}		}	}};
