var SysConfig = {}; SysConfig.serverPath = "/gs"; SysConfig.contentPath = "/gs/content"; SysConfig.tenantUuid = "0"; SysConfig.multiTenantMode = false; SysConfig.guidedShopUrl = "http://source.h1445626.stratoserver.net"; SysConfig.shopUuid = "shop"; SysConfig.shopUrl = "http://www.source-werbeartikel.com"; SysConfig.proxyPath = "/Online-Beratung/proxy.php"; SysConfig.shopServerPath = "/Online-Beratung"; SysConfig.shopContentPath = "/Online-Beratung/content"; /* Singleton instance. */ var Log = {}; Log.initializeWindow = function(aWindow) { Log.initialize(aWindow, Utils.get("elLogContent")); Log.logWindow = Utils.get("elLogWindow"); Utils.makeButton(Utils.get("elLogCloseButton"), Log.logButtonClicked); Utils.makeDraggable(Utils.get("elLogCaption"), Log.logWindow, document, null, null); } Log.initialize = function(aWindow, element) { aWindow.onerror = Log.errorHandler; if (element == null) { Log.contentElement = document.createElement("div"); Log.contentElement.setAttribute("id", "gsLog"); Log.contentElement.style.visibility = "hidden"; Log.contentElement.style.display = "none"; document.body.appendChild(Log.contentElement); } else { Log.contentElement = element; } } Log.debug = function(component, msg, ex) { Log.intern("debug", component, msg, ex); } Log.info = function(component, msg, ex) { Log.intern("info ", component, msg, ex); } Log.warn = function(component, msg, ex) { Log.intern("warn ", component, msg, ex); } Log.error = function(component, msg, ex) { Log.intern("error", component, msg, ex); } Log.intern = function(category, component, msg, ex) { var entry = document.createElement("div"); var str = new Date()+" - "+category+" - "+component+" - "; if (msg) { str += msg; } if (ex) { str += " - "+ex; } entry.appendChild(document.createTextNode(str)); Log.contentElement.insertBefore(entry, Log.contentElement.firstChild); if (window.console) { window.console.log(str); } } Log.errorHandler = function(msg, url, line) { Log.error("Window", msg+" - "+url+": "+line); // Pass to browsers error handling return false; } Log.logButtonClicked = function() { if (Log.logWindow.style.visibility == "visible") { // Hide window Log.logWindow.style.visibility = "hidden"; } else { // Show window Log.logWindow.style.visibility = "visible"; } } /* Singleton instance. */ var Utils = {}; Utils.get = function(htmlId) { return document.getElementById(htmlId); } /* * Check for Firefox. */ Utils.isFirefox = function() { if (navigator.userAgent.indexOf("Firefox/") != -1) { return true; } return false; } Utils.isIE = function() { if (navigator.userAgent.indexOf("MSIE") != -1) { return true; } return false; } /* * Check for IE 6. */ Utils.isIE6 = function() { if (navigator.userAgent.indexOf("MSIE 6") != -1) { return true; } return false; } /* * Check for Safari. */ Utils.isSafari = function() { if (navigator.userAgent.indexOf("Safari") != -1 && navigator.userAgent.indexOf("Chrome") == -1) { return true; } return false; } /* * Check for Chrome. */ Utils.isChrome = function() { if (navigator.userAgent.indexOf("Safari") != -1 && navigator.userAgent.indexOf("Chrome") > -1) { return true; } return false; }; Utils.getBrowser = function(userAgent) { if (userAgent.indexOf("Firefox/") != -1) { return "Firefox"; } if (userAgent.indexOf("MSIE 6") != -1) { return "IE 6"; } if (userAgent.indexOf("MSIE 7") != -1) { return "IE 7"; } if (userAgent.indexOf("MSIE 8") != -1) { return "IE 8"; } if (userAgent.indexOf("MSIE 9") != -1) { return "IE 9"; } if (userAgent.indexOf("Safari") != -1 && userAgent.indexOf("Chrome") == -1) { return "Safari"; } if (userAgent.indexOf("Chrome") != -1 && userAgent.indexOf("Chrome") != -1) { return "Chrome"; } if (userAgent.indexOf("Opera") != -1) { return "Opera"; } // TODO Go on return "unknown"; } Utils.observe = function(element, name, handler) { if (element.addEventListener) { element.addEventListener(name, handler, false); } else { element.attachEvent("on" + name, handler); } } Utils.stopObserving = function(element, name, handler) { if (element.removeEventListener) { element.removeEventListener(name, handler, false); } else { element.detachEvent("on" + name, handler); } } Utils.stop = function(event) { if (Utils.isIE()) { event.cancelBubble = true; event.returnValue = false; } else { event.preventDefault(); event.stopPropagation(); } }; Utils.getTarget = function(event) { if (event.currentTarget) { return event.currentTarget; } if (Utils.isIE()) { return event.srcElement; } }; Utils.getPointer = function(event) { return { x: event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)), y: event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop)) }; } Utils.makeDialog = function(element, blocker, aDocument) { element.show = function(modal) { element.style.visibility = "visible"; element.modal = modal; if (modal) { blocker.style.visibility = "visible"; } } element.hide = function() { element.style.visibility = "hidden"; if (element.modal) { blocker.style.visibility = "hidden"; } } return element; } Utils.makeDraggable = function(dragElement, dragWindow, aDocument, onStartDragging, onEndDragging) { Utils.observe(dragElement, "mousedown", function(event) { if (onStartDragging) { onStartDragging(dragWindow); } Utils.drag(event, dragWindow, aDocument, onEndDragging); }); } /* * Drag and Drop handler. */ Utils.drag = function(event, dragWindow, aDocument, onEndDragging) { startX = event.clientX; startY = event.clientY; origLeft = dragWindow.offsetLeft; origTop = dragWindow.offsetTop; Utils.observe(aDocument, "mousemove", mouseMove); Utils.observe(aDocument, "mouseup", mouseUp); Utils.stop(event); function mouseMove(event) { dragWindow.style.left = (event.clientX-startX+origLeft)+"px"; dragWindow.style.top = (event.clientY-startY+origTop)+"px"; Utils.stop(event); } function mouseUp(event) { Utils.stopObserving(aDocument, "mousemove", mouseMove); Utils.stopObserving(aDocument, "mouseup", mouseUp); Utils.stop(event); if (onEndDragging) { onEndDragging(dragWindow); } } } /* * Drag and Drop handler. */ Utils.resize = function(event, dragWindow, aDocument, callback) { startX = event.clientX; startY = event.clientY; origWidth = parseInt(dragWindow.style.width); origHeight = parseInt(dragWindow.style.height); Utils.observe(aDocument, "mousemove", mouseMove); Utils.observe(aDocument, "mouseup", mouseUp); Utils.stop(event); function mouseMove(event) { dragWindow.style.width = (event.clientX-startX+origWidth)+"px"; dragWindow.style.height = (event.clientY-startY+origHeight)+"px"; if (callback) { callback(event.clientX-startX+origWidth,event.clientY-startY+origHeight); } Utils.stop(event); } function mouseUp(event) { Utils.stopObserving(aDocument, "mousemove", mouseMove); Utils.stopObserving(aDocument, "mouseup", mouseUp); Utils.stop(event); } } Utils.getViewportWidth = function(aWindow, aDocument) { if (aWindow.innerWidth) { return aWindow.innerWidth; } else if (aDocument.documentElement && aDocument.documentElement.clientWidth) { return aDocument.documentElement.clientWidth; } else if (aDocument.body && aDocument.body.clientWidth) { return aDocument.body.clientWidth; } return 0; } Utils.getViewportHeight = function(aWindow, aDocument) { if (aWindow.innerHeight) { return aWindow.innerHeight; } else if (aDocument.documentElement && aDocument.documentElement.clientHeight) { return aDocument.documentElement.clientHeight; } else if (aDocument.body && aDocument.body.clientHeight) { return aDocument.body.clientHeight; } return 0; } Utils.resizeTo = function(aWindow, width, height) { if (Utils.isIE()) { window.resizeTo(width+25, height+118); } else { aWindow.innerWidth = width; aWindow.innerHeight = height; } } Utils.getScrollableWidth = function(aWindow, aDocument) { var contentWidth; if (Utils.isSafari() || Utils.isChrome()) { return aDocument.body.scrollWidth; } if (aWindow.innerWidth != null && aWindow.scrollMaxX != null) { contentWidth = aWindow.innerWidth + aWindow.scrollMaxX; } else { if (aDocument.compatMode == "BackCompat") { contentWidth = aDocument.body.scrollWidth; } else { contentWidth = aDocument.documentElement.scrollWidth; } } return contentWidth; } Utils.getScrollableHeight = function(aWindow, aDocument) { var contentHeight; if (Utils.isSafari() || Utils.isChrome()) { return aDocument.body.scrollHeight; } if (aWindow.innerHeight != null && aWindow.scrollMaxY != null) { contentHeight = aWindow.innerHeight + aWindow.scrollMaxY; } else { if (aDocument.compatMode == "BackCompat") { contentHeight = aDocument.body.scrollHeight; } else { contentHeight = aDocument.documentElement.scrollHeight; } } return contentHeight; } Utils.getScrollX = function(aWindow, aDocument) { if (aWindow.pageXOffset != null) { return aWindow.pageXOffset; } else if (aDocument.documentElement.scrollLeft != null) { return aDocument.documentElement.scrollLeft; } else if (aDocument.body.scrollLeft != null) { return aDocument.body.scrollLeft; } return 0; } Utils.getScrollY = function(aWindow, aDocument) { if (aWindow.pageYOffset != null) { return aWindow.pageYOffset; } else if (aDocument.documentElement.scrollTop != null) { return aDocument.documentElement.scrollTop; } else if (aDocument.body.scrollTop != null) { return aDocument.body.scrollTop; } return 0; } Utils.cookiesEnabled = function() { if (navigator.cookieEnabled != undefined && navigator.cookieEnabled) { return true; } return false; } Utils.findElement = function(element, tagName, attributeName, attributeValue, occurrence) { // Some browser extra handling if (attributeName != null && (attributeName == "class" || attributeName == "className")) { if (Utils.isIE()) { attributeName = "className"; } else { attributeName = "class"; } } if (occurrence == null) { occurrence = {}; occurrence.value = 1; } if (Utils.matches(element, tagName, attributeName, attributeValue)) { if (occurrence.value <= 1) { return element; } else { occurrence.value--; } } for (var i=0; i 0) { str = firstname; } if (str.length > 0) { str += " "; } if (lastname != null && lastname.length > 0) { str += lastname; } return str; } Utils.replaceEmpty = function(str, emptystr) { if (str == null || str.length == 0) { return emptystr; } return str; } Utils.printTimestamp = function(time) { if (time == null) { return null; } var hours = time.getHours().toString(); var minutes = time.getMinutes().toString(); var seconds = time.getSeconds().toString(); var mseconds = time.getMilliseconds().toString(); return Utils.leftPad(hours, 2, "0")+":"+Utils.leftPad(minutes, 2, "0")+":"+Utils.leftPad(seconds, 2, "0")+"."+Utils.leftPad(mseconds, 3, "0"); } Utils.timeToString = function(time) { var hours = time.getHours().toString(); var minutes = time.getMinutes().toString(); var seconds = time.getSeconds().toString(); return Utils.leftPad(hours, 2, "0")+":"+Utils.leftPad(minutes, 2, "0")+":"+Utils.leftPad(seconds, 2, "0"); } Utils.dateToString = function(date) { var year = date.getFullYear().toString(); var month = (date.getMonth()+1).toString(); var day = date.getDate().toString(); return Utils.leftPad(day, 2, "0")+"."+Utils.leftPad(month, 2, "0")+"."+Utils.leftPad(year, 4, "0"); } Utils.stringToDate = function(str) { try { var date = new Date(); date.setFullYear(str.substring(6,10)); // Important: Bug in parse int causes values '08' and '09' to fail if the base is not provided var month = parseInt(str.substring(3,5), 10); date.setMonth(month-1); date.setDate(str.substring(0,2)); // Check result if (Utils.dateToString(date) != str) { // Wrong format return null; } return date; } catch(ex) { return null; } } Utils.stringToTime = function(str) { try { var time = new Date(); time.setHours(str.substring(0,2)); time.setMinutes(str.substring(3,5)); if (str.length > 5) { // With seconds time.setSeconds(str.substring(6,8)); // Check result if (Utils.timeToString(time) != str) { // Wrong format return null; } } else { // Without seconds time.setSeconds(0); // Check result if (Utils.timeToString(time).substring(0,5) != str) { // Wrong format return null; } } return time; } catch(ex) { return null; } } Utils.leftPad = function(str, length, padChar) { var astr = str; while (astr.length < length) { astr = padChar+astr; } return astr; } /* * Removes fragment (part behind a # character) of an URL. */ Utils.removeFragment = function(url) { var index = url.indexOf("#"); if (index > -1) { return url.substring(0, index); } return url; } Utils.buildUrl = function(useShopUrl, selector, path) { var url = null; if (useShopUrl) { // Build shop frontend URL url = SysConfig.shopUrl; if (SysConfig.proxyPath.length > 0) { // Use proxy path url += SysConfig.proxyPath; } if (SysConfig.shopServerPath != null && SysConfig.shopServerPath.length > 0) { url += SysConfig.shopServerPath; } else { url += SysConfig.serverPath; } if (SysConfig.multiTenantMode) { url += "/" + SysConfig.tenantUuid; } url += "/"+SysConfig.shopUuid; } else { // Build backend URL url = SysConfig.guidedShopUrl; url += SysConfig.serverPath; if (SysConfig.multiTenantMode) { url += "/" + SysConfig.tenantUuid; } url += "/backend"; } if (SysConfig.sid != null && SysConfig.sid.length > 0) { url += "/sid"+SysConfig.sid; } url += selector; url += path; return url; } Utils.buildContentUrl = function(useShopUrl, path) { var url = null; if (useShopUrl) { // Build shop frontend URL url = SysConfig.shopUrl; if (SysConfig.proxyPath.length > 0) { // Use proxy path url += SysConfig.proxyPath; } if (SysConfig.shopContentPath != null && SysConfig.shopContentPath.length > 0) { url += SysConfig.shopContentPath; } else { url += SysConfig.contentPath; } if (SysConfig.multiTenantMode) { url += "/" + SysConfig.tenantUuid; } } else { // Build backend URL url = SysConfig.guidedShopUrl; url += SysConfig.contentPath; if (SysConfig.multiTenantMode) { url += "/" + SysConfig.tenantUuid; } } url += path; return url; } /* Singleton instance. */ var Transmission = {}; Transmission.initialize = function(forwardUrl, reverseUrl, dwrHandler, errorMessage) { Transmission.forwardUrl = forwardUrl; Transmission.reverseUrl = reverseUrl; Transmission.dwrHandler = dwrHandler; Transmission.errorMessage = errorMessage; Transmission.errorCount = 0; // Setup forward call settings dwrHandler._path = forwardUrl; dwr.engine.setMethod(dwr.engine.XMLHttpRequest); dwr.engine.setErrorHandler(Transmission.handleTransmissionError); dwr.engine.setWarningHandler(Transmission.handleTransmissionError); dwr.engine.setHttpMethod("POST"); // Workaround: In FF errors on JS tag loading are bypassing the DWR error handler window.onerror = function(msg, url, line) { if (msg == "Error loading script") { // FF error message Transmission.handleTransmissionError(msg, null); return false; } else { // Forward to standard error handler return Log.errorHandler(msg, url, line); } } if (reverseUrl != null) { // Setup RA connection settings dwr.engine._defaultPath = reverseUrl; Transmission.startReverseAjax(); } Log.debug("Transmission", "Initialized"); } /* * Starts reverse AJAX connection. Uses the shop URL. DWR implicitly uses the default path (= shop URL) * and the XHR method. So RA shouldn't conflict with the settings for the forward * connections (GuidedShop-Url + method JsTag). */ Transmission.startReverseAjax = function() { // Reverse Ajax error handling dwr.engine._pollErrorHandler = function(msg, ex) { Log.warn("Transmission", "Reverse Ajax poll failed: " + ex.name + " : " + ex.message); dwr.engine._debug("Reverse Ajax poll failed: " + ex.name + " : " + ex.message); // Retry in any case setTimeout(dwr.engine._poll, 10000); }; dwr.engine.setActiveReverseAjax(true); } Transmission.stopReverseAjax = function() { dwr.engine.setActiveReverseAjax(false); } /** * Call the given method with the given parameters. Uses the GuidedShop URL. */ Transmission.transmit = function(method, params, aCallback) { // Wrap callback var transmitCallback = function(result) { // Successful -> reset error counter if (Transmission.errorCount > 0) { Transmission.errorCount = 0; Log.warn("Transmission", "Request successful, reset errorCount"); } // Use callback if (aCallback != null) { aCallback(result); } }; // Add callback, error handler and timeout object to params params.push({ callback: transmitCallback }); // Call DWR object using reflection method.apply(null, params); } Transmission.handleTransmissionError = function(msg, ex) { var exceptStr = ""; if (ex != null) { if (ex.name != null) { exceptStr += ex.name; } if (ex.message != null) { exceptStr += ", message: "+ex.message; } if (ex.description != null) { exceptStr += ", description: "+ex.description; } } Log.error("Transmission", msg+", exception: "+exceptStr+", errorCount: "+Transmission.errorCount); if (ex != null && ex.name != null && ex.name == "dwr.engine.http.401") { // Special case: DWR message declined by security -> show login page window.location.href = window.location.href; return; } if (Transmission.errorCount < 3) { // Ignore error, just increase counter Transmission.errorCount++; } else { // No error message suppresses the message dialog if (Transmission.errorMessage != null) { // Display error message if (confirm(Transmission.errorMessage)) { // Request reload window.location.href = window.location.href; } } } }; /** * Change the forward URL. */ Transmission.setForwardUrl = function(newForwardUrl) { Transmission.forwardUrl = newForwardUrl; Transmission.dwrHandler._path = newForwardUrl; }; function PageMetaInfo(url, title) { this.url = url; this.title = title; this.useEventBlocker = true; this.category = ""; this.productPage = null; this.productIdent = null; this.productPrice = null; this.productCurrency = null; this.productImageUrl = null; this.cartItems = null; this.cartVolume = null; this.cartCurrency = null; } var GsEngine = {}; // ---- Public methods ------- GsEngine.registerPage = function(customCallback) { var gsWindow = GsEngine.getGsWindow(); if (gsWindow != null) { // Cobrowsing is active -> no page registration return false; } // Initialize standalone Log.initialize(window, null); // Important: Setting no error message for gsengine // suppresses the message dialog var url = Utils.buildUrl(true, "/ajax", ""); Transmission.initialize(url, null, GsEngineDwrHandler, null); // Initialize page meta info if (GsPageAdapter.url == null) { GsPageAdapter.url = window.location.toString(); } if (GsPageAdapter.title == null) { GsPageAdapter.title = window.document.title; } Log.debug("GsEngine", "GsEngineDwrHandler.registerPage"); Transmission.transmit(GsEngineDwrHandler.registerPage, [GsPageAdapter.url, GsPageAdapter.title, GsPageAdapter.category, GsPageAdapter.productPage, GsPageAdapter.productIdent, GsPageAdapter.productDescription, GsPageAdapter.productPrice, GsPageAdapter.productCurrency, GsPageAdapter.productImageUrl, GsPageAdapter.cartItems, GsPageAdapter.cartVolume, GsPageAdapter.cartCurrency], GsEngine.pageRegistered(customCallback)); return true; }; /* * Registers a HTML form element for form filling. */ GsEngine.observeFormElement = function(elementId, element) { // Empty. Will be redirected in Cobrowse._pageLoaded }; /* * Registers a HTML element for observing click events. */ GsEngine.observeClickElement = function(elementId, element) { // Empty. Will be redirected in Cobrowse._pageLoaded }; /* * Registers a handler for replaying custom states. */ GsEngine.setCustomStateHandler = function(type, customStateHandler) { GsEngine.customStateHandler[type] = customStateHandler; }; /* * Records a custom state for form filling. * * To be called when cobrowsing is initialized. */ GsEngine.recordCustomState = function(type, elementId, elementValue) { // Empty. Will be redirected in Cobrowse._pageLoaded }; /* * Registers a handler for replaying custom event. */ GsEngine.setCustomEventHandler = function(type, customEventHandler) { GsEngine.customEventHandler[type] = customEventHandler; }; /* * Records a custom event for form filling. * * To be called when cobrowsing is initialized. */ GsEngine.recordCustomEvent = function(type, elementId, elementValue) { // Empty. Will be redirected in Cobrowse._pageLoaded }; /** * Play the form filling effect on the given element. Useful when implementing form filling with custom events. */ GsEngine.showFormFieldEffect = function(element) { // Empty. Will be redirected in Cobrowse._showFormFieldEffect }; // ---- Hidden methods ------- GsEngine.pageRegistered = function(customCallback, gsInfoVO) { return function(gsInfoVO) { Log.info("GsEngine", "pageRegistered"); if (gsInfoVO != null && customCallback != null) { // Use custom callback customCallback(gsInfoVO); } } }; GsEngine.getGsWindow = function() { // Check for surrounding client or guide window // TODO improve if (window.parent != null) { if (window.parent.ClientWindow != null) { return window.parent.ClientWindow; } if (window.parent.GuideWindow != null) { return window.parent.GuideWindow; } } return null; };