(function(){ if(typeof(window.ShVTrack) === 'object' && !window.ShVTrack.state.rel){ //if ShVTrack object already exists - exit return; } /* * contains all common little functions used in vtrack and vbanner js */ if (!window.console){ var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; window.console = {}; for (var i = 0; i < names.length; ++i){ window.console[names[i]] = function() {}; } } //ie detection - FIXME var msieArr = /(msie) ([\w.]+)/i.exec(navigator.userAgent), msie = msieArr ? msieArr[1] : false, msieVer = msieArr ? msieArr[2] : false; //-----------------------------Drag-------------------- var _startX = 0; // mouse starting positions var _startY = 0; var _offsetX = 0; // current element offset var _offsetY = 0; var _dragElement; // needs to be passed from OnMouseDown to OnMouseMove var _oldZIndex = 0; // we temporarily increase the z-index during drag function OnMouseDown(e){ // IE is retarded and doesn't pass the event object if (e == null) e = window.event; // IE uses srcElement, others use target var target = e.target != null ? e.target : e.srcElement; var hasClass = (" " + target.className + " ").replace(/[\n\t]/g, " ").indexOf(" drag ") > -1; if ((e.button == 1 && window.event != null || e.button == 0) && hasClass){ // grab the mouse position _startX = e.clientX; _startY = e.clientY; // grab the clicked element's position var element = document.getElementById(target.parentNode.id), style = getComputedStyle(element), right = style['right'], //style.getPropertyValue('right'), bottom = style['bottom']; //style.getPropertyValue('bottom'); _offsetX = ExtractNumber(right); _offsetY = ExtractNumber(bottom); // bring the clicked element to the front while it is being dragged _oldZIndex = target.style.zIndex; target.style.zIndex = 10000; // we need to access the element in OnMouseMove _dragElement = document.getElementById('shi-chatMode'); // tell our code to start moving the element with the mouse document.onmousemove = OnMouseMove; // cancel out any text selections document.body.focus(); // prevent text selection in IE document.onselectstart = function () { return false; }; // prevent IE from trying to drag an image target.ondragstart = function() { return false; }; // prevent text selection (except IE) return false; } } //---- function OnMouseMove(e){ if (e == null) var e = window.event; var newRight = (_offsetX - e.clientX + _startX) ; var newBottom = (_offsetY - e.clientY + _startY) ; var bodyWidth = parseInt(document.body.clientWidth); var veiwPortHeight = window.innerHeight; var chatElement = document.getElementById('shi-chatMode'), style = getComputedStyle(chatElement), chatWidth = parseInt(style['width']/*style.getPropertyValue('width')*/), chatHeight = parseInt(style['height']/*style.getPropertyValue('height')*/); if(newRight < -10 || newBottom < -2 || (newRight+chatWidth > bodyWidth-25) || (newBottom+chatHeight > veiwPortHeight-5)){ return false; } _dragElement.style.right = newRight + 'px'; _dragElement.style.bottom = newBottom + 'px'; } //---- function OnMouseUp(e){ if (_dragElement != null){ _dragElement.style.zIndex = _oldZIndex; // we're done with these events until the next OnMouseDown document.onmousemove = null; document.onselectstart = null; _dragElement.ondragstart = null; // this is how we know we're not dragging _dragElement = null; } } //---- function ExtractNumber(value){ var n = parseInt(value); return n == null || isNaN(n) ? 0 : n; } // this is simply a shortcut for the eyes and fingers function $(id){ return document.getElementById(id); } function InitDragDrop(){ document.onmousedown = OnMouseDown; document.onmouseup = OnMouseUp; } InitDragDrop(); //-----------------------------------------------Drag------------------- function arrIndexOf(arr, elt /*, from*/) { var len = arr.length, from = Number(arguments[2]) || 0; from = (from < 0) ? Math.ceil(from) : Math.floor(from); if (from < 0){ from += len; } for (; from < len; from++) { if (from in arr && arr[from] === elt) { return from; } } return -1; } function arrRemove(arr, from, to) { var rest = arr.slice((to || from) + 1 || arr.length); arr.length = from < 0 ? arr.length + from : from; return arr.push.apply(arr, rest); } function forEach(arr, fun) { var i; if (typeof fun != 'function'){ throw new TypeError(); } for (i in arr){ if (Object.prototype.hasOwnProperty.call(arr, i)){ if(fun.call(arr, arr[i], i) === false){ //break; return; } } } } /** *trims leading and trailing spaces from argument *@param str string to trim *@return string */ function strTrim (str) { return str.replace(/\s+$/, '').replace(/^\s+/, ''); } /** *extracts error message from exception object */ function getErrorMessage(err) { if(err.message){ return err.message; }else { return err; } } /** * tests if the argument is an array */ function isArray(test) { return test instanceof Array; } /** * adds event listener in browser-safe way * @param elt - element or element id to add listener to * @param name name of event w/o 'on' * @param callback function to call upon fired event * @param useCapture */ function addEvent(elt, name, callback, useCapture) { if(typeof elt !== 'object' && !isArray(elt)) { elt = document.getElementById(elt); } if(!elt){ //neither object nor DOM node return false; } if(typeof(window.jQuery) === 'function' && elt === window && name === 'load'){ // fucking hack to avoid weird collision with jQuery(on site colman.ac.il) return window.jQuery(callback); } if(elt.addEventListener){ /* && !elt.addEventListener.apply*/ // bad return elt.addEventListener(name, callback, useCapture); } else if(elt.attachEvent){ //ie stuff return elt.attachEvent('on' + name, callback); } else if(isArray(elt)){ //array of elements for(var i in elt){ if(!Object.prototype.hasOwnProperty.call(elt, i)){ continue; } addEvent(elt[i], name, callback, useCapture); } } else { elt['on' + name] = callback; return true; } return false; //failed to attach event if got here.. } /** * tests whether the object is empty(has no properties) * @param {object} o object to test */ function isEmpty(o) { for(var i in o){ if(Object.prototype.hasOwnProperty.call(o, i)){ return false; } } return true; } /** *serializes object into param string. */ function param(obj/*, parent */){ var parts = [], type, x, parent = arguments[1] || false, self = parent; for(x in obj){ if(!Object.prototype.hasOwnProperty.call(obj, x)){ continue; } if(!parent){ self = x; } else { self = [parent, '[', x, ']'].join(''); } type = typeof obj[x]; if(type === 'function'){ parts.push([encodeURIComponent(self), encodeURIComponent(obj.x())].join('=')); }else if(type !== 'object'){ parts.push([encodeURIComponent(self), encodeURIComponent(obj[x])].join('=')); } else { //serialize object or array parts.push(param(obj[x], self)); } } return parts.join('&'); } /** * taken from www.stackoverflow.com forums - http://stackoverflow.com/questions/1131630/javascript-jquery-param-inverse-function * solution posted by Blixt * * restores object, previously serialized with jQuery.param * NO array handling(TODO), result can be of type string or boolean(true) */ function unparam(value) { if (!value) { //return empty object on empty string return {}; } var // Object that holds names => values. params = {}, // Get query string pieces (separated by &) pieces = value.split('&'), // Temporary variables used in loop. pair, pairVal, pairKey, i, l = pieces.length; //, tmp; // Loop through query string pieces and assign params. for (i = 0; i < l; i++) { pair = pieces[i].split('=', 2); // Repeated parameters with the same name are overwritten - FIXME. Parameters // with no value get set to boolean true. pairVal = (pair.length === 2 ? decodeURIComponent(pair[1].replace(/\+/g, ' ')) : true); pairKey = decodeURIComponent(pair[0]); params[pairKey] = pairVal; } return params; } /** * acquire parameters from current url(window.location) * author Shimon. * inspired by many similar works, especially http://jquery-howto.blogspot.com/2009/09/get-url-parameters-values-with-jquery.html */ function gups(){ if(!window.location.search) { return {}; } var res = {}, splits = window.location.search.substr(1).split('&'), len = splits.length, i, parts; for(i = 0; i < len; i++){ parts = splits[i].split('=', 2); res[parts[0]] = (parts.length > 1)? parts[1] : ''; } return res; } function gup(nm){ return gups()[nm]; } /** * returns proper key code value. * @param evt event object. */ function which(evt){ return evt.which ? evt.which : (evt.charCode ? evt.charCode : evt.keyCode); } /** * stops event propagation in cross-browser way * @param evt - event object */ function stopPropagation(evt){ if (evt && evt.stopPropagation) { evt.stopPropagation(); } else { evt.cancelBubble = true; } } /** * removes all cj\hildernof this node * @param node - node to clear */ function clearNode(node){ if(!node){ return; } //TODO - may be source for memory leaks while (node.firstChild) { node.removeChild(node.firstChild); } } /** * retrieves text of the node in cross-browser way * @param node node to get text from */ function getNodeText(node){ var res = ''; if(!node){ return ''; } // Get the text from text nodes and CDATA nodes if (node.nodeType === 3 || node.nodeType === 4) { return node.nodeValue; // Traverse everything else, except comment nodes } else if (node.nodeType !== 8) { var nodes = node.childNodes; for(var i = 0; nodes[i]; i++){ res += getNodeText(nodes[i]); } return res; } return ''; } /** * sets note detx in cross-browser way. the node's cleared first and then a text node containing the text is appended to if * @param node node to set text * @param text text to set */ function setNodeText(node, text){ if(!node){ return; } clearNode(node); node.appendChild(document.createTextNode(text)); } /** * retrieves computed value of specified css style for given node * @param elem node to get style for * @param style name of css style, in camelCase */ function getComputedStyle(elem, style){ var compStyle = false; if (document.defaultView && document.defaultView.getComputedStyle) { compStyle = document.defaultView.getComputedStyle(elem, null); } else if (elem.currentStyle) { compStyle = elem.currentStyle; } else if(elem.style) { compStyle = elem.style; } if (compStyle && style) { return compStyle[style]; } return compStyle; } /** * adds css class to specified node. if this node has this class, nothing happens. * @param node node to add class to. * @param cls class to add */ function addClass(node, cls){ if(!node){ return; } if(!node.className){ node.className = cls; return; } var classes = node.className; //string if(classes.indexOf(cls) < 0){ classes += ' ' + cls; } node.className = classes; } /** * removes class from node. if node has no such class, nothing happens. * @param {DOMNode} node dom node to remove class from * @param {string} cls class name to remove */ function removeClass(node, cls){ if(!node || !node.className || !cls){ return; } var classes = node.className, //string pos = classes.indexOf(cls); if(pos < 0){ return; } node.className = classes.replace(cls, ''); } function hasClass(node, cls){ if(!node || !node.className || !cls){ return false; } var classes = node.className, //string pos = classes.indexOf(cls); if(pos < 0){ return false; } return true; } function getElementsByClassName(classname, node, tag) { if(!node) { node = document.getElementsByTagName("body")[0]; } if(!tag){ tag = '*'; } var a = [], re = new RegExp('\\b' + classname + '\\b'), els = node.getElementsByTagName(tag), i, j = els.length; for(i = 0; i < j; i++){ if(re.test(els[i].className)){ a.push(els[i]); } } return a; } /** * create node list from its arguments */ function createDocFragment(){ var nodeList = document.createDocumentFragment(), len = arguments.length(), i = 0; for (; i < len; i++) { nodeList.appendChild(arguments[i]); } return nodeList; } /** *hides arguments(sets their style.display property to none). *accepts list of 0 - infinity DOM nodes */ function hide(){ var i, l = arguments.length, l1, j; for(i = 0; i < l; i++){ if(!arguments[i]){ continue; } if(typeof arguments[i].length !== 'undefined' && isArray(arguments[i])){ l1 = arguments[i].length; for(j = 0; j < l1; j++){ arguments[i][j].style.display = 'none'; } } else { arguments[i].style.display = 'none'; } } } /** *shows arguments(sets their style.display property to ''). *accepts list of 0 - infinity DOM nodes */ function show(){ var i, l = arguments.length, l1, j; for(i = 0; i < l; i++){ if(!arguments[i]){ continue; } if(typeof arguments[i].length !== 'undefined' && isArray(arguments[i])){ l1 = arguments[i].length; for(j = 0; j < l1; j++){ arguments[i][j].style.display = ''; } } else { arguments[i].style.display = ''; } } } function fadeIn(nodes, callback, speed){ if(!nodes) { return; } speed = (speed > 0) ? speed : 100; if(typeof nodes.length === 'undefined') { nodes = [nodes]; } var op = 0, i, len = nodes.length, timer; for(i = 0; i < len; i++){ nodes[i].style.opacity = 0; nodes[i].style.display = ''; } timer = setInterval(function () { op = op + 0.1; if(op > 1) { op = 1; } for(i = 0; i < len; i++){ nodes[i].style.opacity = op; } if(op === 1){ //done clearInterval(timer); if(typeof(callback) === 'function'){ callback(); } } }, speed); } function fadeOut(nodes, callback, speed){ if(!nodes) { return; } speed = (speed > 0) ? speed : 100; if(typeof nodes.length === 'undefined') { nodes = [nodes]; } var op = 1, i, timer = setInterval(function () { op = op - 0.1; if(op < 0.1) { op = 0; } if(op === 0){ //done clearInterval(timer); for(i = 0; i < nodes.length; i++){ nodes[i].style.display = 'none'; nodes[i].style.opacity = 1; } if(typeof(callback) === 'function'){ callback(); } return; } for(i = 0; i < nodes.length; i++){ nodes[i].style.opacity = op; } }, speed); } function shrink(node, min,callback, speed){ if(!node) { return; } speed = (speed > 0) ? speed : 50; if(!min){ min = 0; } var wid = node.offsetWidth, timer = setInterval(function () { if(wid <= min){ //done clearInterval(timer); node.style.width = min + 'px'; if(typeof(callback) === 'function'){ callback(); } return; } wid = wid - 20; node.style.width = wid + 'px'; }, speed); } function expand(node, max, callback, speed){ if(!node) { return; } speed = (speed > 0) ? speed : 50; if(!max){ console.log('no max value in expand'); return; } var wid = node.offsetWidth, timer = setInterval(function () { if(wid >= max){ //done clearInterval(timer); node.style.width = max + 'px'; if(typeof(callback) === 'function'){ callback(); } return; } wid = wid + 20; node.style.width = wid + 'px'; }, speed); } function printField(value){ var s = value, regExp=/\n/gi, pWin = window.open('','pWin','location=yes, menubar=yes, toolbar=yes'); s = s.replace(regExp,'
'); pWin.document.open(); pWin.document.write(''); pWin.document.write('function printMe(){window.print();window.close();}'); pWin.document.write(''); pWin.document.write(s); pWin.document.write(''); pWin.document.close(); } function emptyRespHandle(){ //empty method } var _testerDiv = 0; function safeTags(str) { if(!_testerDiv) { _testerDiv = document.createElement('div'); } if (typeof _testerDiv.textContent !== 'undefined'){ _testerDiv.textContent = str; } else { _testerDiv.innerText = str; } return _testerDiv.innerHTML; } // cookie methods /** * reads cookie * @param name String cookie name to read */ function readCookie(name) { if(!document || !document.cookie){ return false; } var c, i, nameEQ = name + '=', ca = document.cookie.split(';'); for(i = 0; i < ca.length; i++) { c = strTrim(ca[i]); //string if (c.indexOf(nameEQ) === 0){ return decodeURIComponent(c.substring(nameEQ.length, c.length)); } } return false; } /** * creates new cookie * @param name String cookie to set * @param val String value to set * @param options Object additional parameters(optional) */ function createCookie(name, val, options){ var path, domain, secure, expires = '', date, valType = typeof(val), tp; if (valType !== 'undefined' && valType !== 'unknown') { // name and value given, set cookie options = options || {}; if (val === null) { val = ''; options.expires = -1; } if (options.expires && (typeof options.expires === 'number' || options.expires.toUTCString)) { if (typeof options.expires === 'number') { date = new Date(); date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); } else { date = options.expires; } expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE } // CAUTION: Needed to parenthesize options.path and options.domain // in the following expressions, otherwise they evaluate to undefined // in the packed version for some reason... path = options.path ? '; path=' + (options.path) : '; path=/'; tp = typeof options.domain; if(tp === 'undefined' || tp === 'unknown'){ domain = '; domain=' + window.location.hostname; //((this.domain.dr in [1,3])? '.' : '') + this.domain.dn; } else { domain = '; domain=' + options.domain; } secure = options.secure ? '; secure' : ''; document.cookie = [name, '=', encodeURIComponent(val), expires, path, domain, secure].join(''); } } /** * contains references to DOM elements used in chat */ var dom = { head: false, body: false, /** * call this after DOM loaded(window.onload or later) */ init: function () { this.head = document.getElementsByTagName('head')[0]; this.body = document.getElementsByTagName('body')[0]; } }, /** * incapsulates script tag operations */ Scripter = { scriptNum: 0, //this field is incremented each time script is created getJSONP: function (url, data, callback) { var scriptId = (++this.scriptNum) % 100, scr = document.createElement('script'), callbackName = 'shClbk' + scriptId, domId = 'shScr' + scriptId; window[callbackName] = function (returnData) { var elt = document.getElementById(domId); try{ dom.head.removeChild(elt); }catch(e){ console.log(getErrorMessage(e)); elt.parentNode.removeChild(elt); } window[callbackName] = null; if(typeof(callback) === 'function'){ callback(returnData); } }; if(typeof(data) == 'object'){ data['clbk'] = callbackName; data['r'] = (new Date()).getTime() % 1000; data = param(data); } else { if(data){ data += '&'; } data += 'clbk=' + callbackName + '&r=' + ((new Date()).getTime() % 1000); } scr.id = domId; scr.setAttribute('type','text/javascript'); scr.setAttribute('src', url + '?' + data); scr.setAttribute('defer', 'defer'); dom.head.appendChild(scr); }, removeScript: function (id) { dom.head.removeChild(document.getElementById(id)); } }; function breakLongWords(text, len){ return (new String(text)).replace(new RegExp('(\\w{' + len + '})', 'g'), "$1​") } function createSWFEmbedTag(src){ var objectBeginTag = '', objectEndTag = '', paramTags = ['', '', '', '', '', '', ''], embedTag = ['']; var str = [objectBeginTag, paramTags.join(''), embedTag.join(''), objectEndTag].join(''); return str; } function doSound(path, tout){ var div = document.createElement('div'); div.innerHTML = createSWFEmbedTag(path); div.setAttribute('id', 'shi-sound-object'); dom.body.appendChild(div); if(isNaN(tout)){ tout = 3000; } setTimeout(function(){ if(div) { dom.body.removeChild(div); } div = false; }, tout); } /** * Ion.Sound * version 3.0.7 Build 89 * © Denis Ineshin, 2016 * * Project page: http://ionden.com/a/plugins/ion.sound/en.html * GitHub page: https://github.com/IonDen/ion.sound * * Released under MIT licence: * http://ionden.com/a/plugins/licence-en.html */ ;(function (window, navigator, $, undefined) { "use strict"; window.ion = window.ion || {}; if (ion.sound) { return; } var warn = function (text) { if (!text) text = "undefined"; if (window.console) { if (console.warn && typeof console.warn === "function") { console.warn(text); } else if (console.log && typeof console.log === "function") { console.log(text); } var d = $ && $("#debug"); if (d && d.length) { var a = d.html(); d.html(a + text + '
'); } } }; var extend = function (parent, child) { var prop; child = child || {}; for (prop in parent) { if (parent.hasOwnProperty(prop)) { child[prop] = parent[prop]; } } return child; }; /** * DISABLE for unsupported browsers */ if (typeof Audio !== "function" && typeof Audio !== "object") { var func = function () { warn("HTML5 Audio is not supported in this browser"); }; ion.sound = func; ion.sound.play = func; ion.sound.stop = func; ion.sound.pause = func; ion.sound.preload = func; ion.sound.destroy = func; func(); return; } /** * CORE * - creating sounds collection * - public methods */ var is_iOS = /iPad|iPhone|iPod/.test(navigator.appVersion), sounds_num = 0, settings = {}, sounds = {}, i; if (!settings.supported && is_iOS) { settings.supported = ["mp3", "mp4", "aac"]; } else if (!settings.supported) { settings.supported = ["mp3", "ogg", "mp4", "aac", "wav"]; } var createSound = function (obj) { var name = obj.alias || obj.name; if (!sounds[name]) { sounds[name] = new Sound(obj); sounds[name].init(); } }; ion.sound = function (options) { extend(options, settings); settings.path = settings.path || ""; settings.volume = settings.volume || 1; settings.preload = settings.preload || false; settings.multiplay = settings.multiplay || false; settings.loop = settings.loop || false; settings.sprite = settings.sprite || null; settings.scope = settings.scope || null; settings.ready_callback = settings.ready_callback || null; settings.ended_callback = settings.ended_callback || null; sounds_num = settings.sounds.length; if (!sounds_num) { warn("No sound-files provided!"); return; } for (i = 0; i < sounds_num; i++) { createSound(settings.sounds[i]); } }; ion.sound.VERSION = "3.0.7"; ion.sound._method = function (method, name, options) { if (name) { sounds[name] && sounds[name][method](options); } else { for (i in sounds) { if (!sounds.hasOwnProperty(i) || !sounds[i]) { continue; } sounds[i][method](options); } } }; ion.sound.preload = function (name, options) { options = options || {}; extend({preload: true}, options); ion.sound._method("init", name, options); }; ion.sound.destroy = function (name) { ion.sound._method("destroy", name); if (name) { sounds[name] = null; } else { for (i in sounds) { if (!sounds.hasOwnProperty(i)) { continue; } if (sounds[i]) { sounds[i] = null; } } } }; ion.sound.play = function (name, options) { ion.sound._method("play", name, options); }; ion.sound.stop = function (name, options) { ion.sound._method("stop", name, options); }; ion.sound.pause = function (name, options) { ion.sound._method("pause", name, options); }; ion.sound.volume = function (name, options) { ion.sound._method("volume", name, options); }; if ($) { $.ionSound = ion.sound; } /** * Web Audio API core * - for most advanced browsers */ var AudioContext = window.AudioContext || window.webkitAudioContext, audio; if (AudioContext) { audio = new AudioContext(); } var Sound = function (options) { this.options = extend(settings); delete this.options.sounds; extend(options, this.options); this.request = null; this.streams = {}; this.result = {}; this.ext = 0; this.url = ""; this.loaded = false; this.decoded = false; this.no_file = false; this.autoplay = false; }; Sound.prototype = { init: function (options) { if (options) { extend(options, this.options); } if (this.options.preload) { this.load(); } }, destroy: function () { var stream; for (i in this.streams) { stream = this.streams[i]; if (stream) { stream.destroy(); stream = null; } } this.streams = {}; this.result = null; this.options.buffer = null; this.options = null; if (this.request) { this.request.removeEventListener("load", this.ready.bind(this), false); this.request.removeEventListener("error", this.error.bind(this), false); this.request.abort(); this.request = null; } }, createUrl: function () { var no_cache = new Date().valueOf(); this.url = this.options.path + encodeURIComponent(this.options.name) + "." + this.options.supported[this.ext] + "?" + no_cache; }, load: function () { if (this.no_file) { warn("No sources for \"" + this.options.name + "\" sound :("); return; } if (this.request) { return; } this.createUrl(); this.request = new XMLHttpRequest(); this.request.open("GET", this.url, true); this.request.responseType = "arraybuffer"; this.request.addEventListener("load", this.ready.bind(this), false); this.request.addEventListener("error", this.error.bind(this), false); this.request.send(); }, reload: function () { this.ext++; if (this.options.supported[this.ext]) { this.load(); } else { this.no_file = true; warn("No sources for \"" + this.options.name + "\" sound :("); } }, ready: function (data) { this.result = data.target; if (this.result.readyState !== 4) { this.reload(); return; } if (this.result.status !== 200 && this.result.status !== 0) { warn(this.url + " was not found on server!"); this.reload(); return; } this.request.removeEventListener("load", this.ready.bind(this), false); this.request.removeEventListener("error", this.error.bind(this), false); this.request = null; this.loaded = true; //warn("Loaded: " + this.options.name + "." + settings.supported[this.ext]); this.decode(); }, decode: function () { if (!audio) { return; } audio.decodeAudioData(this.result.response, this.setBuffer.bind(this), this.error.bind(this)); }, setBuffer: function (buffer) { this.options.buffer = buffer; this.decoded = true; //warn("Decoded: " + this.options.name + "." + settings.supported[this.ext]); var config = { name: this.options.name, alias: this.options.alias, ext: this.options.supported[this.ext], duration: this.options.buffer.duration }; if (this.options.ready_callback && typeof this.options.ready_callback === "function") { this.options.ready_callback.call(this.options.scope, config); } if (this.options.sprite) { for (i in this.options.sprite) { this.options.start = this.options.sprite[i][0]; this.options.end = this.options.sprite[i][1]; this.streams[i] = new Stream(this.options, i); } } else { this.streams[0] = new Stream(this.options); } if (this.autoplay) { this.autoplay = false; this.play(); } }, error: function () { this.reload(); }, play: function (options) { delete this.options.part; if (options) { extend(options, this.options); } if (!this.loaded) { this.autoplay = true; this.load(); return; } if (this.no_file || !this.decoded) { return; } if (this.options.sprite) { if (this.options.part) { this.streams[this.options.part].play(this.options); } else { for (i in this.options.sprite) { this.streams[i].play(this.options); } } } else { this.streams[0].play(this.options); } }, stop: function (options) { if (this.options.sprite) { if (options) { this.streams[options.part].stop(); } else { for (i in this.options.sprite) { this.streams[i].stop(); } } } else { this.streams[0].stop(); } }, pause: function (options) { if (this.options.sprite) { if (options) { this.streams[options.part].pause(); } else { for (i in this.options.sprite) { this.streams[i].pause(); } } } else { this.streams[0].pause(); } }, volume: function (options) { var stream; if (options) { extend(options, this.options); } else { return; } if (this.options.sprite) { if (this.options.part) { stream = this.streams[this.options.part]; stream && stream.setVolume(this.options); } else { for (i in this.options.sprite) { stream = this.streams[i]; stream && stream.setVolume(this.options); } } } else { stream = this.streams[0]; stream && stream.setVolume(this.options); } } }; var Stream = function (options, sprite_part) { this.alias = options.alias; this.name = options.name; this.sprite_part = sprite_part; this.buffer = options.buffer; this.start = options.start || 0; this.end = options.end || this.buffer.duration; this.multiplay = options.multiplay || false; this.volume = options.volume || 1; this.scope = options.scope; this.ended_callback = options.ended_callback; this.setLoop(options); this.source = null; this.gain = null; this.playing = false; this.paused = false; this.time_started = 0; this.time_ended = 0; this.time_played = 0; this.time_offset = 0; }; Stream.prototype = { destroy: function () { this.stop(); this.buffer = null; this.source = null; this.gain && this.gain.disconnect(); this.source && this.source.disconnect(); this.gain = null; this.source = null; }, setLoop: function (options) { if (options.loop === true) { this.loop = 9999999; } else if (typeof options.loop === "number") { this.loop = +options.loop - 1; } else { this.loop = false; } }, update: function (options) { this.setLoop(options); if ("volume" in options) { this.volume = options.volume; } }, play: function (options) { if (options) { this.update(options); } if (!this.multiplay && this.playing) { return; } this.gain = audio.createGain(); this.source = audio.createBufferSource(); this.source.buffer = this.buffer; this.source.connect(this.gain); this.gain.connect(audio.destination); this.gain.gain.value = this.volume; this.source.onended = this.ended.bind(this); this._play(); }, _play: function () { var start, end; if (this.paused) { start = this.start + this.time_offset; end = this.end - this.time_offset; } else { start = this.start; end = this.end; } if (end <= 0) { this.clear(); return; } if (typeof this.source.start === "function") { this.source.start(0, start, end); } else { this.source.noteOn(0, start, end); } this.playing = true; this.paused = false; this.time_started = new Date().valueOf(); }, stop: function () { if (this.playing && this.source) { if (typeof this.source.stop === "function") { this.source.stop(0); } else { this.source.noteOff(0); } } this.clear(); }, pause: function () { if (this.paused) { this.play(); return; } if (!this.playing) { return; } this.source && this.source.stop(0); this.paused = true; }, ended: function () { this.playing = false; this.time_ended = new Date().valueOf(); this.time_played = (this.time_ended - this.time_started) / 1000; this.time_offset += this.time_played; if (this.time_offset >= this.end || this.end - this.time_offset < 0.015) { this._ended(); this.clear(); if (this.loop) { this.loop--; this.play(); } } }, _ended: function () { var config = { name: this.name, alias: this.alias, part: this.sprite_part, start: this.start, duration: this.end }; if (this.ended_callback && typeof this.ended_callback === "function") { this.ended_callback.call(this.scope, config); } }, clear: function () { this.time_played = 0; this.time_offset = 0; this.paused = false; this.playing = false; }, setVolume: function (options) { this.volume = options.volume; if (this.gain) { this.gain.gain.value = this.volume; } } }; if (audio) { return; } /** * Fallback for HTML5 audio * - for not so modern browsers */ var checkSupport = function () { var sound = new Audio(), can_play_mp3 = sound.canPlayType('audio/mpeg'), can_play_ogg = sound.canPlayType('audio/ogg'), can_play_aac = sound.canPlayType('audio/mp4; codecs="mp4a.40.2"'), item, i; for (i = 0; i < settings.supported.length; i++) { item = settings.supported[i]; if (!can_play_mp3 && item === "mp3") { settings.supported.splice(i, 1); } if (!can_play_ogg && item === "ogg") { settings.supported.splice(i, 1); } if (!can_play_aac && item === "aac") { settings.supported.splice(i, 1); } if (!can_play_aac && item === "mp4") { settings.supported.splice(i, 1); } } sound = null; }; checkSupport(); Sound.prototype = { init: function (options) { if (options) { extend(options, this.options); } this.inited = true; if (this.options.preload) { this.load(); } }, destroy: function () { var stream; for (i in this.streams) { stream = this.streams[i]; if (stream) { stream.destroy(); stream = null; } } this.streams = {}; this.loaded = false; this.inited = false; }, load: function () { var part; this.options.preload = true; this.options._ready = this.ready; this.options._scope = this; if (this.options.sprite) { for (i in this.options.sprite) { part = this.options.sprite[i]; this.options.start = part[0]; this.options.end = part[1]; this.streams[i] = new Stream(this.options, i); } } else { this.streams[0] = new Stream(this.options); } }, ready: function (duration) { if (this.loaded) { return; } this.loaded = true; var config = { name: this.options.name, alias: this.options.alias, ext: this.options.supported[this.ext], duration: duration }; if (this.options.ready_callback && typeof this.options.ready_callback === "function") { this.options.ready_callback.call(this.options.scope, config); } if (this.autoplay) { this.autoplay = false; this.play(); } }, play: function (options) { if (!this.inited) { return; } delete this.options.part; if (options) { extend(options, this.options); } console.log(1); if (!this.loaded) { if (!this.options.preload) { this.autoplay = true; this.load(); } else { this.autoplay = true; } return; } if (this.options.sprite) { if (this.options.part) { this.streams[this.options.part].play(this.options); } else { for (i in this.options.sprite) { this.streams[i].play(this.options); } } } else { this.streams[0].play(this.options); } }, stop: function (options) { if (!this.inited) { return; } if (this.options.sprite) { if (options) { this.streams[options.part].stop(); } else { for (i in this.options.sprite) { this.streams[i].stop(); } } } else { this.streams[0].stop(); } }, pause: function (options) { if (!this.inited) { return; } if (this.options.sprite) { if (options) { this.streams[options.part].pause(); } else { for (i in this.options.sprite) { this.streams[i].pause(); } } } else { this.streams[0].pause(); } }, volume: function (options) { var stream; if (options) { extend(options, this.options); } else { return; } if (this.options.sprite) { if (this.options.part) { stream = this.streams[this.options.part]; stream && stream.setVolume(this.options); } else { for (i in this.options.sprite) { stream = this.streams[i]; stream && stream.setVolume(this.options); } } } else { stream = this.streams[0]; stream && stream.setVolume(this.options); } } }; Stream = function (options, sprite_part) { this.name = options.name; this.alias = options.alias; this.sprite_part = sprite_part; this.multiplay = options.multiplay; this.volume = options.volume; this.preload = options.preload; this.path = settings.path; this.start = options.start || 0; this.end = options.end || 0; this.scope = options.scope; this.ended_callback = options.ended_callback; this._scope = options._scope; this._ready = options._ready; this.setLoop(options); this.sound = null; this.url = null; this.loaded = false; this.start_time = 0; this.paused_time = 0; this.played_time = 0; this.init(); }; Stream.prototype = { init: function () { this.sound = new Audio(); this.sound.volume = this.volume; this.createUrl(); this.sound.addEventListener("ended", this.ended.bind(this), false); this.sound.addEventListener("canplaythrough", this.can_play_through.bind(this), false); this.sound.addEventListener("timeupdate", this._update.bind(this), false); this.load(); }, destroy: function () { this.stop(); this.sound.removeEventListener("ended", this.ended.bind(this), false); this.sound.removeEventListener("canplaythrough", this.can_play_through.bind(this), false); this.sound.removeEventListener("timeupdate", this._update.bind(this), false); this.sound = null; this.loaded = false; }, createUrl: function () { var rand = new Date().valueOf(); this.url = this.path + encodeURIComponent(this.name) + "." + settings.supported[0] + "?" + rand; }, can_play_through: function () { if (this.preload) { this.ready(); } }, load: function () { this.sound.src = this.url; this.sound.preload = this.preload ? "auto" : "none"; if (this.preload) { this.sound.load(); } }, setLoop: function (options) { if (options.loop === true) { this.loop = 9999999; } else if (typeof options.loop === "number") { this.loop = +options.loop - 1; } else { this.loop = false; } }, update: function (options) { this.setLoop(options); if ("volume" in options) { this.volume = options.volume; } }, ready: function () { if (this.loaded || !this.sound) { return; } this.loaded = true; this._ready.call(this._scope, this.sound.duration); if (!this.end) { this.end = this.sound.duration; } }, play: function (options) { if (options) { this.update(options); } if (!this.multiplay && this.playing) { return; } this._play(); }, _play: function () { if (this.paused) { this.paused = false; } else { try { this.sound.currentTime = this.start; } catch (e) {} } this.playing = true; this.start_time = new Date().valueOf(); this.sound.volume = this.volume; this.sound.play(); }, stop: function () { if (!this.playing) { return; } this.playing = false; this.paused = false; this.sound.pause(); this.clear(); try { this.sound.currentTime = this.start; } catch (e) {} }, pause: function () { if (this.paused) { this._play(); } else { this.playing = false; this.paused = true; this.sound.pause(); this.paused_time = new Date().valueOf(); this.played_time += this.paused_time - this.start_time; } }, _update: function () { if (!this.start_time) { return; } var current_time = new Date().valueOf(), played_time = current_time - this.start_time, played = (this.played_time + played_time) / 1000; if (played >= this.end) { if (this.playing) { this.stop(); this._ended(); } } }, ended: function () { if (this.playing) { this.stop(); this._ended(); } }, _ended: function () { this.playing = false; var config = { name: this.name, alias: this.alias, part: this.sprite_part, start: this.start, duration: this.end }; if (this.ended_callback && typeof this.ended_callback === "function") { this.ended_callback.call(this.scope, config); } if (this.loop) { setTimeout(this.looper.bind(this), 15); } }, looper: function () { this.loop--; this.play(); }, clear: function () { this.start_time = 0; this.played_time = 0; this.paused_time = 0; }, setVolume: function (options) { this.volume = options.volume; if (this.sound) { this.sound.volume = this.volume; } } }; } (window, navigator, window.jQuery || window.$)); /* *End ion.sound */ function formatTime (t) { var h = t.getHours(), m = t.getMinutes(), s = t.getSeconds(); if(h < 10){ h = '0' + h; } if(m < 10){ m = '0' + m; } if(s < 10){ s = '0' + s; } return h + ':' + m + ':' + s; } var emailFilter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/, prtcl = location.protocol + '//', urlhead = prtcl + 'vtrack.sitehood.co.il/', urlStatic = prtcl + 'www.sitehood.co.il/static/', serverSide = 'vtrackbgr.php', visitoridM, visitidM;//for passing visitor to mobile page window.ShVTrack = { ver: { js: '1', css: '12', tpl: '3' }, visitor: { id: 0, name: '', lname: '', nickName: '', visit: 0, site: 0, department: 0, email: '', isnew: 0 }, oId: 0, state: { status: 0, lang: 0, blocked: 0, typing: 0, min: 0, cfbc: 0, //Contact Form Before Chat fbs: 0 //facebook status: 0 - uninitialized, 1 - logged in, 2 - don't want to login }, msg: { lastId: 0, last: '', lastBeeped: '', hidden: 0, unreadCount: 0, ltr: 0 }, pagetitle: '', domain: {}, agent: {}, update: { errCount: 0, errLimit: 100, requestFlag: false, timer: false, delay: 6000, closedDelay: 6000, openDelay: 3000, blockedDelay: 10000, timeout: { count: 0, threshold: 5 } }, news: { timer: false, step: 6, delay: 200 }, flags: {//various flags miniPos: 0, //2 means left, 1 - center and 0 - right hide: false, noHideMenu: false, //if true, prevents from hiding menu noHideLang: false, //if true, prevents from hiding lang menu showLast: false, //if true, allows update of dom component showing last message, feedbackAfterContact: false //if true, the feedback form will be shown after contact form is closed }, design: {}, settings: { pos: 0 //2 means left, 1 - center and 0 - right }, //site settings translations: {}, //object containing all translations panel: {}, // dom event handlers - all of 'em run outside of ShVTrack context onMinimize: function() { if (ShVTrack.state.min > 0) { // panel is in minimized state - maximize it ShVTrack.state.min = 0; ShVTrack.writeCookies(); removeClass(dom.min, 'sh-maximizeArrow'); addClass(dom.min, 'sh-minimizeArrow'); removeClass(dom.tb, 'sh-minimized'); removeClass(dom.container, ShVTrack.settings.posCls); setNodeText(dom.menuMin, ShVTrack.translations.minimize_chat); } else { // panel is in maximized state ShVTrack.state.min = 1; ShVTrack.writeCookies(); removeClass(dom.min, 'sh-minimizeArrow'); addClass(dom.min, 'sh-maximizeArrow'); addClass(dom.tb, 'sh-minimized'); addClass(dom.container, ShVTrack.settings.posCls); setNodeText(dom.menuMin, ShVTrack.translations.maximize_chat); } }, closeChat: function () { hide(dom.chat); ShVTrack.state.status = 2; ShVTrack.update.delay = ShVTrack.update.closedDelay; ShVTrack.writeCookies(); clearInterval(ShVTrack.update.timer); ShVTrack.update.timer = setInterval(ShVTrack.updateMessages, ShVTrack.update.delay); ShVTrack.updateMessages(); }, goToMobile: function() { document.location.href = 'https://www.sitehood.co.il/mobilechat/' + window.sh_siteid + '/?visitorid=' + ShVTrack.visitor.id+ '&visitid=' + ShVTrack.visitor.visit; ShVTrack.onCloseBubble2(); }, onChatToggle: function() { ShVTrack.parseCookies(); if (ShVTrack.state.status > 2) { //chat is open - close it hide(dom.chat); ShVTrack.state.status = 2; ShVTrack.update.delay = ShVTrack.update.closedDelay; removeClass(dom.tb, 'sh-chat-opened');//notify chat btn window is closed } else { //closed - open it hide(dom.bubble); ShVTrack.msg.last = ''; ShVTrack.msg.unreadCount = 0; //check for "Contat Form Before Chat" if (ShVTrack.settings.encf && ShVTrack.settings.cfbc && !ShVTrack.state.cfbc) { show(dom.infoForm); } else { show(dom.chat); ShVTrack.state.status = 3; ShVTrack.state.blocked = 0; ShVTrack.update.delay = ShVTrack.update.openDelay; dom.output.scrollTop = dom.output.scrollHeight; } addClass(dom.tb, 'sh-chat-opened');//notify chat btn window is open } ShVTrack.writeCookies(); ShVTrack.updateMessages(); clearInterval(ShVTrack.update.timer); ShVTrack.update.timer = setInterval(ShVTrack.updateMessages, ShVTrack.update.delay); }, /* * O.G: * onMobileBack is a new function to go back to the hosting site only for mobile devices * This replaces the minimize chat function and called from the shi-min btn. * (on mobile devices the chat is in a separate window) */ onMobileBack: function() { history.go(-1); }, onCloseBubble: function(e) { // removeClass(dom.fbFrame, 'sh-fb-frame-bubble'); // removeClass(dom.fbFrame, 'sh-fb-frame-chat'); hide(dom.bubble); ShVTrack.msg.last = ''; ShVTrack.msg.hidden = 1; ShVTrack.msg.unreadCount = 0; var evt = window.event || e; stopPropagation(evt); ShVTrack.updateMessages(); }, onComponentToggle: function(comp) { if (getComputedStyle(comp, 'display') === 'none') { //it's hidden - show it show(comp); } else { hide(comp); } }, onCloseBubble2: function(e) { hide(dom.bubble2); ShVTrack.msg.last = ''; ShVTrack.msg.hidden = 1; ShVTrack.msg.unreadCount = 0; var evt = window.event || e; stopPropagation(evt); ShVTrack.updateMessages(); }, onNameKeyPressed: function(e) { var evt = window.event || e, name = dom.nick.value; if (which(evt) != 13) { return true; } if (name === ShVTrack.visitor.nickName) { //name not changed xnick return true; } ShVTrack.changeName(name, true); stopPropagation(evt); return false; }, onChatKeyPressed: function(e) { var evt = window.event || e, w = which(evt); if (w == 27) { //esc dom.input.value = ''; dom.input.focus(); return true; } if (w != 13) { //enter ShVTrack.state.typing = true; return true; } var t = dom.input, msg = strTrim(t.value), oa = dom.output, elt; stopPropagation(evt); ShVTrack.state.typing = false; setTimeout(function() { // for some reason(keydown?) newline is added to textarea AFTER main callback returns. this stuff is to fix this. t.value = ''; //clear message input }, 0); if (!msg) { alert(ShVTrack.translations.cant_send_empty); return true; } //first show it to the user elt = ShVTrack.createMessage({ c: 'v', m: msg }, 'sh-transient'); oa.appendChild(elt); oa.scrollTop = oa.scrollHeight; //send to server ShVTrack.sendMessage(msg); // call user-specified callback if (ShVTrack.onSendMessage) { //call user function if present ShVTrack.onSendMessage(); } t.value = ''; //clear message input return false; }, /* * This is a new function for sending a message using a button for mobile only */ onSendBtnClick: function(e) { var t = dom.input, msg = strTrim(t.value), oa = dom.output, elt; setTimeout(function() { // for some reason(keydown?) newline is added to textarea AFTER main callback returns. this stuff is to fix this. t.value = ''; //clear message input }, 0); if (!msg) { alert(ShVTrack.translations.cant_send_empty); return true; } //first show it to the user elt = ShVTrack.createMessage({ c: 'v', m: msg }, 'sh-transient'); oa.appendChild(elt); oa.scrollTop = oa.scrollHeight; //send to server ShVTrack.sendMessage(msg); // call user-specified callback if (ShVTrack.onSendMessage) { //call user function if present ShVTrack.onSendMessage(); } t.value = ''; //clear message input return false; },//End onSendBtnClick function onToggleShop: function() { if (getComputedStyle(dom.shop, 'display') !== 'none') { //shop is open - close it hide(dom.shop); } else { //it's closed - open it hide(dom.news); //hide news when opening shop ShVTrack.stopNews(); show(dom.shop); } }, onToggleNews: function() { if (getComputedStyle(dom.news, 'display') !== 'none') { //shop is open - close it hide(dom.news); ShVTrack.stopNews(); } else { //it's closed - open it hide(dom.shop); //hide shop when opening news show(dom.news); ShVTrack.news.timer = setInterval(ShVTrack.scrollNews, ShVTrack.news.delay); } }, onLanguageSelected: function (evt) { var lsTplName = 'shTpl' + ShVTrack.visitor.site, //name of local storage tpl item e = evt ? evt : window.event, t = e.target ? e.target : e.srcElement, id = t.getElementsByTagName('input')[0]; if (ShVTrack.state.lang == id.value) { return; } ShVTrack.state.lang = id.value; ShVTrack.writeCookies(); if (window.localStorage && window.localStorage[lsTplName]) { window.localStorage[lsTplName] = ''; } window.location.href = window.location.href; //reload page - TODO }, onToggleBlock: function() { if (ShVTrack.state.blocked > 0) { //chat is blocked - unlock ShVTrack.state.blocked = 0; } else { //block it ShVTrack.state.blocked = 1; if (ShVTrack.state.status > 2) { //chat was open - close it too ShVTrack.onChatToggle(); } ShVTrack.update.delay = ShVTrack.update.blockedDelay; } ShVTrack.writeCookies(); ShVTrack.updateMessages(); clearInterval(ShVTrack.update.timer); ShVTrack.update.timer = setInterval(ShVTrack.updateMessages, ShVTrack.update.delay); }, // ajax event handlers - all of 'em run outside of ShVTrack context introduceOk: function(data) { if (data.error) { alert(data.error); dom.nick.value = ShVTrack.visitor.nickName; //xnick } else { dom.nick.value = ShVTrack.visitor.nickName = decodeURIComponent(data.name); } }, contactOk: function(data) { if (data.error) { alert(data.error); } else { var newName = dom.contName.value + ' ' + dom.contLname.value; if (strTrim(newName)) { ShVTrack.changeName(newName); } } if (ShVTrack.settings.cfbc && !ShVTrack.state.cfbc) { ShVTrack.state.cfbc = 1; show(dom.chat); ShVTrack.state.status = 3; ShVTrack.state.blocked = 0; ShVTrack.update.delay = ShVTrack.update.openDelay; dom.output.scrollTop = dom.output.scrollHeight; ShVTrack.writeCookies(); ShVTrack.updateMessages(); clearInterval(ShVTrack.update.timer); ShVTrack.update.timer = setInterval(ShVTrack.updateMessages, ShVTrack.update.delay); } }, onMessageEvent: function (event) { var rexp = new RegExp('\\bvtrack.sitehood.co.il\\b'), //FIXME PHP data = event.data; if (typeof data === 'string') { data = unparam(decodeURIComponent(data)); } if(rexp.test(event.origin)){ switch(data.stat){ // case -1: //just close bubble // case '-1': // ShVTrack.onCloseBubble(); // ShVTrack.closeChat(); // break; // case 0: //login cancelled, just open chat // case '0': // ShVTrack.onChatToggle(); // break; case 1: //login success, update visitor data, remove iframe and open chat case '1': ShVTrack.updateVisitorFBData(data); ShVTrack.state.fbs = 1; ShVTrack.writeCookies(); hide(dom.fbContainer); break; case 2: //don't want to login, save in cookies, remove iframe and open chat case '2': ShVTrack.state.fbs = 2; ShVTrack.writeCookies(); hide(dom.fbContainer); break; default: console.log('unexpected event', event, event.data); ShVTrack.onChatToggle(); } } }, //default ajax handler. only alerts on error defHandler: function(data) { if (!data.res) { // alert(data.error); console.log('SH defHandler - error: ' + data.msg); } }, // handling news scrolling stopNews: function() { if (this.news.timer) { clearInterval(this.news.timer); this.news.timer = null; } }, slowNews: function() { ShVTrack.news.step = 0; }, speedNews: function() { ShVTrack.news.step = 6; }, scrollNews: function() { var top = parseInt(getComputedStyle(dom.newsContent, 'top'), 10), bott = dom.newsContent.offsetHeight; if (top + bott < 0) { top = dom.newsContent.parentNode.offsetHeight + ShVTrack.news.step; } else { top -= ShVTrack.news.step; } dom.newsContent.style.top = top + 'px'; }, //initialization prepareDom: function() { dom.container = document.getElementById('shi-centering-container'); dom.tb = document.getElementById('shi-toolbar'); dom.chat = document.getElementById('shi-chatMode'); dom.chatTrigger = document.getElementById('shi-chatTb'); dom.chatClose = document.getElementById('shi-closeBtn'); dom.min = document.getElementById('shi-minimizeBtn'); dom.onIcon = document.getElementById('shi-onlineIcon'); dom.menu = document.getElementById('shi-optionsMenu'); dom.lang = document.getElementById('shi-languageSelector'); dom.nick = document.getElementById('shi-guestName'); dom.msgProto = document.getElementById('shi-msgProto'); dom.agentGreeting = document.getElementById('shi-agentRole'); dom.agentSpec = document.getElementById('shi-agentSpec'); dom.agentName = document.getElementById('shi-agentName'); dom.agentLogo = document.getElementById('shi-agentLogo').getElementsByTagName('img')[0]; dom.output = document.getElementById('shi-chatMessages'); // chat output - dom.input = document.getElementById('shi-userTyped'); // chat input - textarea where visitor writes messages dom.bubble = document.getElementById('shi-firstMessage'); // window where last unseen message is shown when chat is closed dom.bubbleAgent = document.getElementById('shi-agentTitle');// dom.bubbleMessage = document.getElementById('shi-messageContent'); dom.bubbleCount = document.getElementById('shi-count'); dom.shop = document.getElementById('shi-shopMode'); dom.news = document.getElementById('shi-newsView'); dom.newsContent = document.getElementById('shi-newsInnerContent'); dom.typing = document.getElementById('shi-isTyping'); dom.typingName = document.getElementById('shi-typingName'); dom.menuMin = document.getElementById('shi-menuMinimize'); dom.depName = document.getElementById('shi-depName'); dom.fbProto = document.getElementById('shi-fb-proto'); dom.infoFormTrigger = document.getElementById('shi-showUserInfo'); dom.infoForm = document.getElementById('shi-userInfoForm'); dom.contName = document.getElementById('shi-contName'); dom.contLname = document.getElementById('shi-contLastName'); if (window.sh_siteid === 2433) { dom.contComp = document.getElementById('shi-contComp'); } dom.contEmail = document.getElementById('shi-contEmail'); dom.contPhone = document.getElementById('shi-contPhone'); dom.contContent = document.getElementById('shi-userContent'); dom.feedbackForm = document.getElementById('shi-feedbackForm'); dom.fbFrame = document.getElementById('shi-fb-frame'); dom.fbContainer = document.getElementById('shi-fb-msg'); //New mobile divs: dom.sendBtn = document.getElementById('sendBtn');//submit button for mobile dom.mobilechatBtn = document.getElementById('shi-mobilechatButton');//mobile chat Btn }, onInitResponse: function (data){ //this function will run outside of ShVTrack context - use ShVTrack instead of 'this' var lnk, tmp, i, rnw, cCount = 0, lsTplName = 'shTpl' + ShVTrack.visitor.site; //name of local storage tpl item //test for errors if (data.error) { //error occured - do not continue console.log('SH init error: ' + data.error + ', ep:' + data.ep); return; } if (ShVTrack.visitor.site != data.si) { //site id does not fit - stop execution console.log("SH init error: siteid does't fit:" + ShVTrack.visitor.site + ' | ' + data.si); return; } if(data.si == 2668) { if (window.location.href.indexOf("lp_") > -1) { console.log('Landing page'); return; } } //set response values ShVTrack.visitor.id = data.vi; if (ShVTrack.visitor.visit != data.svi) { //if opening a new visit - start with closed chat ShVTrack.state.status = 2; // chat closed ShVTrack.state.cfbc = 0; ShVTrack.state.fbs = 0; } if (window.sh_chat_always_open) {//FIXME Temporary ShVTrack.state.status = 3; // chat open ShVTrack.state.cfbc = 1; } ShVTrack.visitor.visit = data.svi; //New visitor var ShVTrack.visitor.isnew = data.isn; //add returned visitor data ShVTrack.visitor.email = data.cont.cem; ShVTrack.visitor.name = data.cont.cn; ShVTrack.visitor.lname = data.cont.cln; if (window.sh_siteid === 2433) { ShVTrack.visitor.company = data.cont.cc; } ShVTrack.visitor.nickName = data.vn; if (data.ver.css) { ShVTrack.ver.css = data.ver.css; } if (data.ver.tpl) { ShVTrack.ver.tpl = data.ver.tpl; } if (window.sh_siteid === 2433) { ShVTrack.contact = { name: data.cont.cn, last: data.cont.cln, company: data.cont.cc, phone: data.cont.cph, email: data.cont.cem, content: data.cont.cnt }; } else { ShVTrack.contact = { name: data.cont.cn, last: data.cont.cln, phone: data.cont.cph, email: data.cont.cem, content: data.cont.cnt }; } ShVTrack.oId = data.oi; ShVTrack.state.lang = data.lng; ShVTrack.state.ltr = data.ltr; ShVTrack.agent = data.agt; ShVTrack.settings = data.settings; ShVTrack.translations = data.trans; ShVTrack.langs = data.lngs; ShVTrack.domain = data.domain; ShVTrack.domain.cook = ((ShVTrack.domain.dr in [1, 3]) ? '.' : '') + ShVTrack.domain.dn; ShVTrack.panel = data.pnl.bar; //Temporary commented out // if(window.localStorage){ //local storage enabled on this machine // if(data.pnl.bar){ //template was sent from server - cache it locally // window.localStorage[lsTplName] = data.pnl.bar; // } else if(window.localStorage[lsTplName]){ // template weren't sent - use cached // ShVTrack.panel = window.localStorage[lsTplName]; // } // //TODO deal with the case when cache is empty and server sent nothing // } ShVTrack.flags.nonews = data.flags.nonews; if (ShVTrack.state.status < 1) { ShVTrack.state.status = 2; } if (data.dep) { ShVTrack.visitor.department = data.dep.id; setNodeText(dom.depName, data.dep.nm); } //write cookies ShVTrack.writeCookies(); //load css file if (typeof window.sh_chat_iframe == 'undefined') { // only when not in iframe rnw = ShVTrack.ver.css ? '?v=' + ShVTrack.ver.css : ''; if (document.createStyleSheet) { //IE document.createStyleSheet(urlStatic + 'css/vtrack/chat.css' + rnw); } else { //others lnk = document.createElement('link'); lnk.setAttribute('rel', 'stylesheet'); lnk.setAttribute('type', 'text/css'); lnk.setAttribute('href', urlStatic + 'css/vtrack/chat.css' + rnw); dom.head.appendChild(lnk); } if (ShVTrack.state.ltr) { //fixes for ltr langs lnk = document.createElement('link'); lnk.setAttribute('rel', 'stylesheet'); lnk.setAttribute('type', 'text/css'); lnk.setAttribute('href', urlStatic + 'css/vtrack/chat-ltr.css' + rnw); dom.head.appendChild(lnk); } if (ShVTrack.settings.ccss) { //custom css lnk = document.createElement('link'); lnk.setAttribute('rel', 'stylesheet'); lnk.setAttribute('type', 'text/css'); lnk.setAttribute('href', ShVTrack.settings.ccss + rnw); dom.head.appendChild(lnk); } if (msie) { //IE fixes var fixFile = false; if (msieVer < 7 || document.documentMode < 7) { fixFile = 'ie6fixes.css'; } else if (document.documentMode == 8) { fixFile = 'ie8fixes.css'; } else if (document.documentMode == 9) { } else if (msieVer == 7 || document.documentMode == 7) { fixFile = 'ie7fixes.css'; } if (fixFile) { lnk = document.createElement('link'); lnk.setAttribute('rel', 'stylesheet'); lnk.setAttribute('type', 'text/css'); lnk.setAttribute('href', urlStatic + 'css/vtrack/' + fixFile + rnw); dom.head.appendChild(lnk); } } } //create bar tmp = document.createElement('div'); tmp.id = 'shi-centering-container'; tmp.innerHTML = ShVTrack.panel; dom.body.appendChild(tmp); //append to DOM ShVTrack.prepareDom(); // init dom references //Mobile stuff if(window.location.pathname.indexOf('/mobilechat/') == 0){//if on mobile page updateViews();//Mobile style adaptation see js/mobile/mobilechat.js refreshMobile()//Refresh JQM - fro textareas and inputs. } // * apply state //if minimized - minimize it if ((ShVTrack.state.min === undefined || isNaN(ShVTrack.state.min)) && ShVTrack.settings.min > 0) { ShVTrack.state.min = 1; } /* * Mobile detect and changes: */ var viewport = document.querySelector('meta[name="viewport"]');//site is responsive - has viewport meta tag if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) && viewport ) {//if mobile device and site is responsive if(window.location.pathname.indexOf('/mobilechat/') != 0){//Only if not on mobilechat page hide(dom.tb); addClass(dom.bubble, 'mobileMessage'); addEvent('shi-firstMessage', 'click', ShVTrack.goToMobile); document.getElementById('shi-closeBubble').innerHTML = 'X'; dom.mobilechatBtn.href='https://www.sitehood.co.il/mobilechat/' + window.sh_siteid + '/?visitorid=' + ShVTrack.visitor.id+ '&visitid=' + ShVTrack.visitor.visit;//Change chat page url to send visitor data show(dom.mobilechatBtn); isMobile = true; } } //end mobile //online status if (data.onl) { addClass(dom.onIcon, 'sh-online'); removeClass(dom.onIcon, 'sh-offline'); dom.onIcon ? dom.onIcon.setAttribute('title', ShVTrack.translations.ML_PNL_AGENT_OFFLINE) : ''; } //Check if chat is open. and let the toolbar know if (ShVTrack.state.status > 2) { //chat is open addClass(dom.tb, 'sh-chat-opened'); } dom.nick.value = ShVTrack.visitor.nickName; if (dom.contName) { //test whether contact form is present dom.contName.value = ShVTrack.contact.name; dom.contLname.value = ShVTrack.contact.last; if (window.sh_siteid === 2433) { dom.contComp.value = ShVTrack.contact.company; } dom.contEmail.value = ShVTrack.contact.email; dom.contPhone.value = ShVTrack.contact.phone; dom.contContent.value = ShVTrack.contact.content; } //bind event handlers addEvent(dom.min, 'click', ShVTrack.onMinimize); addEvent(dom.menuMin, 'click', ShVTrack.onMinimize); addEvent(dom.chatTrigger, 'click', ShVTrack.onChatToggle); addEvent('shi-firstMessage', 'click', ShVTrack.onChatToggle); addEvent('shi-firstMessage2', 'click', ShVTrack.goToMobile); if(window.location.pathname.indexOf('/mobilechat/') == 0){//if on mobile page addEvent(dom.chatClose, 'click', ShVTrack.onMobileBack);//O.G change the btn to go back to the site } else { addEvent(dom.chatClose, 'click', ShVTrack.onChatToggle); } addEvent('shi-settingsBtn', 'click', function() { ShVTrack.onComponentToggle(dom.menu); ShVTrack.flags.noHideMenu = true; }); addEvent(dom.infoFormTrigger, 'click', function() { show(dom.infoForm); }); addEvent('shi-contSend', 'click', ShVTrack.onInfoSend); addEvent('shi-contBack', 'click', function() { hide(dom.infoForm); if (ShVTrack.flags.feedbackAfterContact) { show(dom.feedbackForm); } }); addEvent('shi-langTrigger', 'click', function() { ShVTrack.onComponentToggle(dom.lang); ShVTrack.flags.noHideMenu = true; ShVTrack.flags.noHideLang = true; }); addEvent(dom.nick, 'keypress', ShVTrack.onNameKeyPressed); addEvent(dom.input, 'keypress', ShVTrack.onChatKeyPressed); addEvent(dom.sendBtn, 'click', ShVTrack.onSendBtnClick);//new send btn for mobile addEvent('shi-closeBubble', 'click', ShVTrack.onCloseBubble); addEvent('shi-closeBubble2', 'click', ShVTrack.onCloseBubble2);//for mobile if (ShVTrack.settings.s > 0) { //shop's enabled addEvent('shi-shopTb', 'click', ShVTrack.onToggleShop); addEvent('shi-closeShop', 'click', ShVTrack.onToggleShop); cCount++; } else { //hide shop icon hide(document.getElementById('shi-shopTb'), document.getElementById('shi-shopSeparator')); } if (!ShVTrack.flags.nonews && ShVTrack.settings.n > 0) { // news're enabled addEvent('shi-newsTb', 'click', ShVTrack.onToggleNews); addEvent('shi-closeNews', 'click', ShVTrack.onToggleNews); cCount++; } else { //hide news button hide(document.getElementById('shi-newsTb'), document.getElementById('shi-newsSeparator')); } if (!cCount) { addClass(dom.tb, 'sh-noBtn'); ShVTrack.state.min = 1; } else if (cCount == 1) { addClass(dom.tb, 'sh-onlyOneBtn'); } if (ShVTrack.state.min > 0) { removeClass(dom.min, 'sh-minimizeArrow'); addClass(dom.min, 'sh-maximizeArrow'); addClass(dom.tb, 'sh-minimized'); addClass(dom.container, ShVTrack.settings.posCls); setNodeText(dom.menuMin, ShVTrack.translations.maximize_chat); } switch (ShVTrack.settings.pos) { // Contact Form positioning case 0: // Right addClass(dom.infoForm, 'sh-infoFormLeft'); break; case 1: // Center addClass(dom.infoForm, 'sh-infoFormLeft'); break; case 2: // Left addClass(dom.infoForm, 'sh-infoFormRight'); addClass(dom.infoForm, 'sh-feedbackFormRight'); break; case 3: // Custom pos var c = ShVTrack.settings.custPos, vert = (c.va == 3) ? 'top' : 'bottom', vert2 = (c.va != 3) ? 'top' : 'bottom', pos; if (c.ha == 2) { //relative to left hrz = 'left'; hrz2 = 'right'; pos = c.x; } else { hrz2 = 'left'; hrz = 'right'; pos = dom.body.offsetWidth - c.x - dom.container.offsetWidth; } dom.container.style[hrz] = c.x + 'px'; dom.container.style[hrz2] = 'auto'; dom.container.style[vert] = c.y + 'px'; dom.container.style[vert2] = 'auto'; dom.container.style.width = 'auto'; if (!c.s) { dom.container.style.position = 'absolute'; } if (pos < 110) { //too close to left border of the window addClass(dom.container, 'sh-leftAlign'); } if (pos < 300) { // Too Close for Contact form addClass(dom.infoForm, 'sh-infoFormRight'); addClass(dom.infoForm, 'sh-feedbackFormRight'); } else { addClass(dom.infoForm, 'sh-infoFormLeft'); } break; } //recaptcha if (window.sh_siteid === 2156) {//only for traklin.co.il function loadrecaptcha(){ var fileref=document.createElement('script') fileref.setAttribute("type","text/javascript") fileref.setAttribute("src", "https://www.google.com/recaptcha/api.js?hl=he") if (typeof fileref!="undefined") { document.getElementsByTagName("head")[0].appendChild(fileref) } } loadrecaptcha() } //end recaptcha addEvent('shi-menuBlock', 'click', ShVTrack.onToggleBlock); //print button - TODO styles for printing addEvent('shi-menuPrint', 'click', function() { printField(dom.output.innerHTML); }); addEvent('shi-menuEmail', 'click', function() { var email = prompt(ShVTrack.translations.enter_email), dataObj = { vi: ShVTrack.visitor.id, svi: ShVTrack.visitor.visit, si: ShVTrack.visitor.site, email: email, op: 'toemail' }; if(!email){ return; } if (!emailFilter.test(email)) { alert(ShVTrack.translations.wrong_email_format); return; } Scripter.getJSONP(urlhead + serverSide, dataObj, function (data) { if (!data.res) { alert(data.error); console.log('SH defHandler - error: ' + data.msg); } else { alert(ShVTrack.translations.email_will_sent_soon); } }); }); //hide menu if pressed outside of menu addEvent(dom.body, 'click', function() { if (!ShVTrack.flags.noHideMenu) { hide(dom.menu); } else { ShVTrack.flags.noHideMenu = false; } if (!ShVTrack.flags.noHideLang) { hide(dom.lang); } else { ShVTrack.flags.noHideLang = false; } }); // init news addEvent(dom.newsContent, 'mouseover', ShVTrack.slowNews); addEvent(dom.newsContent, 'mouseout', ShVTrack.speedNews); if (ShVTrack.settings.h > 0 || (typeof sh_hide !== 'undefined' && typeof sh_hide !== 'unknown')) { hide(dom.container); } if (!ShVTrack.settings.h) { //add push bar - bar that pushes entire site upwards tmp = document.createElement('div'); tmp.className = 'sh-pushBar'; dom.body.appendChild(tmp); } //language selectors tmp = getElementsByClassName('sh-language', dom.tb, 'a'); for (i = 0; i < tmp.length; i++) { addEvent(tmp[i], 'click', ShVTrack.onLanguageSelected); } if (ShVTrack.state.status > 2) { //chat open show(dom.chat); ShVTrack.update.delay = ShVTrack.update.openDelay; } else if (!ShVTrack.state.blocked) { //chat closed ShVTrack.update.delay = ShVTrack.update.closedDelay; } else { //chat blocked //TODO blocked indicator addClass(dom.onIcon, 'sh-blocked'); removeClass(dom.onIcon, 'sh-online'); removeClass(dom.onIcon, 'sh-offline'); ShVTrack.update.delay = ShVTrack.update.blockedDelay; } //feedback form addEvent('shi-closeFeedbackBtn', 'click', ShVTrack.onResetFeedback); addEvent('shi-feedbackSubmit', 'click', ShVTrack.onSubmitFeedback); //ie6 only stuff - fixes the lack of support for 'position:fixed' if (msie && (msieVer <= 7 || !document.documentMode || document.documentMode < 7) && !ShVTrack.settings.cjs && (!ShVTrack.settings.custPos || ShVTrack.settings.custPos.s)) { //FIXME find a way to prevent this from custom js var ieDocElement = (document.compatMode === "CSS1Compat") ? document.documentElement : document.body, ieFix; dom.container.style.position = 'absolute'; if (document.body.style.position === 'relative') { dom.container.style.bottom = 'auto'; ieFix = function() { dom.container.style.top = (ieDocElement.clientHeight + ieDocElement.scrollTop - 33) + 'px'; }; } else { ieFix = function() { dom.container.style.bottom = (-ieDocElement.scrollTop) + 'px'; }; } window.onresize = window.onscroll = ieFix; window.onscroll(); } if (ShVTrack.settings.cjs) { //custom js lnk = document.createElement('script'); lnk.setAttribute('type', 'text/javascript'); lnk.setAttribute('defer', 'defer'); lnk.setAttribute('src', ShVTrack.settings.cjs); dom.head.appendChild(lnk); } //initiate update sequence ShVTrack.updateMessages(); //FIXME wrap with timeout for chrome ShVTrack.update.timer = setInterval(ShVTrack.updateMessages, ShVTrack.update.delay); //start listening on messages from fb frame addEvent(window, 'message', ShVTrack.onMessageEvent, false); //create FB frame only if FB state is uninitialized if (ShVTrack.state.fbs < 1 && ShVTrack.settings.fb > 0) { // not logged in addEvent('shi-close-fb-msg', 'click', function () { //close fb stuff ShVTrack.state.fbs = 2; ShVTrack.writeCookies(); hide(dom.fbContainer); }, false); } else { hide(dom.fbContainer); } //test for user's 'onload' event if (typeof(window.sh_onload) === 'function') { window.sh_onload(); //call the onload event } }, init: function() { //start operating ***** try { //test site id if (typeof(window.sh_siteid) === 'undefined' || typeof(window.sh_siteid) === 'unknown') { console.log('Sitehood error: no siteid!'); return; //no siteid - nothing to do } this.visitor.site = sh_siteid; //fix page title for explorer var titleElement = dom.head.getElementsByTagName('title'); var outerTitle = document.getElementsByTagName('title');//if title is outside the head if ((titleElement && titleElement.length) || (outerTitle && outerTitle.length)) { if (msie && msieVer < 9) { this.pagetitle = titleElement[0].innerHTML ? titleElement[0].innerHTML : outerTitle[0].innerHTML; } else { //use outer title only if head title is undefined this.pagetitle = getNodeText(titleElement[0]) ? getNodeText(titleElement[0]) : getNodeText(outerTitle[0]); } } else { this.pagetitle = ''; } this.parseCookies(); //create initial request if (window.location.pathname.indexOf('/mobilechat/') == 0) {//On mobile chat page. get visitor's details var url = new URL(window.location.href); visitoridM = url.searchParams.get("visitorid"); visitidM = url.searchParams.get("visitid"); } else { visitoridM = visitidM = '';//Empty these values } var req = urlhead + serverSide, data = { op: 'init', si: this.visitor.site, st: this.state.status, vm: visitoridM,//pass user details for mobile page svm: visitidM//pass user details for mobile page }, refr = document.referrer; //generate init request if (this.visitor.id) { data.vi = this.visitor.id; } if (this.visitor.visit) { data.svi = this.visitor.visit; } if (this.state.blocked > 0) { data.bl = 1; } if (refr) { data.au = refr; } if (this.state.lang) { data.l = this.state.lang; } // if(window.localStorage && window.localStorage.['shTpl' + ShVTrack.visitor.site]){ // data.ntpl = 1; // } data.su = location.hostname; data.pg = this.pagetitle; data.pth = location.pathname; data.q = location.search; ShVTrack.onSh = 0; if (window.location.hostname.indexOf('sitehood') > -1) { //test if we're on sitehood //FIXME check against full url try {//test for owner login if (typeof(window.assets) !== 'undefined' && typeof(window.assets) !== 'unknown' && typeof(window.assets.oi) !== 'undefined' && typeof(window.assets.oi) !== 'unknown') { data.ol = window.assets.oi; } } catch (e) { data.ol = ''; } ShVTrack.onSh = 1; } if (!gup('NO_SITEHOOD')) { Scripter.getJSONP(req, data, this.onInitResponse); } } catch (err) { ShVTrack.errorHandler(err, 'general init error'); } }, //update methods updateMessages: function() { //ShVTrack method issues update request if no other ur pending, or postpones it until previous one's complete' try { if (ShVTrack.update.requestFlag) { //check if previous request hasn't been finished yet. if not - postpone update and increase timeout counter if (ShVTrack.update.timeout.count <= ShVTrack.update.timeout.threshold) { //timeout count is less than threshold - continue waiting ShVTrack.update.timeout.count++; return false; } //otherwise proceed with new request ShVTrack.update.requestFlag = false; } //reset timeout counter ShVTrack.update.timeout.count = 0; var dataObj = {//data object op: 'hb', //heartbeat vi: ShVTrack.visitor.id, svi: ShVTrack.visitor.visit, si: ShVTrack.visitor.site, st: ShVTrack.state.status, l: ShVTrack.state.lang, lmi: ShVTrack.msg.lastId }; if (ShVTrack.msg.hidden > 0) { dataObj.hm = ShVTrack.msg.hidden; ShVTrack.msg.hidden = 0; } if (ShVTrack.state.typing > 0) { //reset typing state ShVTrack.state.typing = 0; dataObj.ty = 1; } if (ShVTrack.state.blocked > 0) { dataObj.bl = 1; } if (ShVTrack.visitor.department) { dataObj.dep = ShVTrack.visitor.department; } //send request Scripter.getJSONP(urlhead + serverSide, dataObj, ShVTrack.updateHandle); ShVTrack.update.requestFlag = true; //set update flag - disallow updates until this one's complete return true; } catch (err) { ShVTrack.errorHandler(err, 'call update error'); return false; } return true; }, onUpdatePanel: function(resp) { //parses response on update request if (!resp) { return true; } var removePtr, addPtr = [], i, addCls, t = typeof(resp.error), storageCntMsgId = 'shLastCntId' + ShVTrack.visitor.visit, storageFeedMsgId = 'shLastFeedId' + ShVTrack.visitor.visit; if (t !== 'undefined' && t !== 'unknown') { //test for error or 'disconnected' status if (resp.error === 'cont') { console.log('SH recoverable error: ' + (ShVTrack.update.errCount++)); return true; } else { console.log('SH error: ' + resp.error + ', ep: ' + resp.ep); return false; } } if (resp.st < 0) { //test for error or 'disconnected' status console.log('SH: disconnected'); return false; } //test for new agent if (resp.agtc) { if (window.sh_siteid !== 2572 && window.sh_siteid !== 2573 ) {//dont replace agent display details if on TlVModa setNodeText(dom.agentGreeting, resp.agtc.gr); setNodeText(dom.agentName, resp.agtc.nm); setNodeText(dom.agentSpec, resp.agtc.spec); ShVTrack.agent = resp.agtc; dom.agentLogo.setAttribute('src', resp.agtc.l); dom.agentLogo.style.cssText = resp.agtc.stl; } if (ShVTrack.onAgentChanged) { //call user function if present ShVTrack.onAgentChanged(ShVTrack.agent.id, ShVTrack.agent.u); } } //process updates for chat if (typeof resp.chu != 'undefined' && resp.chu) { removePtr = getElementsByClassName('sh-transient', dom.output); for (i = 0; i < removePtr.length; i++) { //remove all transient messages dom.output.removeChild(removePtr[i]); removePtr[i] = null; } removePtr = null; forEach(resp.chu, function(item) { var elt; if (item.ty == 2 || item.ty == 4) { //unread or offline unread if (item.f & 8 && (!window.localStorage[storageCntMsgId] || window.localStorage[storageCntMsgId] < item.id)) { //check if contact form needs to be open window.localStorage[storageCntMsgId] = item.id; show(dom.infoForm); ShVTrack.flags.feedbackAfterContact = false; } if (item.f & 16 && (!window.localStorage[storageFeedMsgId] || window.localStorage[storageFeedMsgId] < item.id)) { //check if feedback form needs to be open window.localStorage[storageFeedMsgId] = item.id; if (item.f & 8) { //contact form is also to be shown - queue feedback ShVTrack.flags.feedbackAfterContact = true; } else { show(dom.feedbackForm); } } } if (item.f & 32 || item.f & 64) { //check if this is a contact form notification item.m = ShVTrack.translations.contact_form_saved_success; if (window.sh_siteid === 11 || window.sh_siteid === 2805) {//Disable message. return; } } elt = ShVTrack.createMessage(item); if (!addPtr) { addPtr = []; } if (elt) { addPtr.push(elt); } if (ShVTrack.state.status < 3 && (item.ty == 4 || item.ty == 2) && (item.at == 1) && ShVTrack.msg.lastId != item.id) { //type unread, issued not by visitor ShVTrack.msg.last = item.m; ShVTrack.msg.lastAgent = item.agt; ShVTrack.msg.unreadCount++; ShVTrack.flags.showLast = true; } ShVTrack.msg.lastId = item.id; }); if (addPtr) { for (i = 0; i < addPtr.length; i++) { dom.output.appendChild(addPtr[i]); } } dom.output.scrollTop = dom.output.scrollHeight; //scroll chat to the bottom //show panel if on sitehood - TODO if (ShVTrack.onSh == 2 || ShVTrack.settings.sm > 0) { show(dom.container); } else if (ShVTrack.onSh == 1) { ShVTrack.onSh = 2; } } //online status if (ShVTrack.state.blocked == 0) { if (resp.onl && resp.onl == 1) { removeClass(dom.onIcon, 'sh-blocked'); removeClass(dom.onIcon, 'sh-offline') addClass(dom.onIcon, 'sh-online') dom.onIcon ? dom.onIcon.setAttribute('title', ShVTrack.translations.ML_PNL_AGENT_ONLINE) : ''; if (window.sh_siteid == '2646') {//for certain site dom.mobilechatBtn.innerHTML = ' צ\'אט'; } else if (window.sh_siteid == '2742') { dom.mobilechatBtn.innerHTML = 'צ'אט ללא עלות עם נציגה אנושית';//O.G: addition for new mobile div } else {//to all others dom.mobilechatBtn.innerHTML = ShVTrack.translations.live_chat_online;//O.G: addition for new mobile div } } else { removeClass(dom.onIcon, 'sh-blocked'); removeClass(dom.onIcon, 'sh-online') addClass(dom.onIcon, 'sh-offline') dom.onIcon ? dom.onIcon.setAttribute('title', ShVTrack.translations.ML_PNL_AGENT_OFFLINE) : ''; if (window.sh_siteid == '2646') {//for certain site dom.mobilechatBtn.innerHTML = ' השאירי הודעה'; } else {//to all others dom.mobilechatBtn.innerHTML = ShVTrack.translations.live_chat_offline; //O.G: addition for new mobile div } } } else { addClass(dom.onIcon, 'sh-blocked'); removeClass(dom.onIcon, 'sh-online'); removeClass(dom.onIcon, 'sh-offline'); dom.onIcon ? dom.onIcon.setAttribute('title', ShVTrack.translations.chat_blocked_by_you) : ''; } //typing if (resp.ty) { setNodeText(dom.typingName, resp.ty); dom.typing.style.visibility = 'visible'; } else { dom.typing.style.visibility = 'hidden'; } //last message if (ShVTrack.flags.showLast && ShVTrack.msg.last && ShVTrack.state.status < 3 && !ShVTrack.state.blocked) {//do not update on dnd and opened chat setNodeText(dom.bubbleAgent, ShVTrack.msg.lastAgent || ShVTrack.agent.nm); if (ShVTrack.settings.b) { hide(dom.bubble); dom.bubbleMessage.innerHTML = breakLongWords(ShVTrack.msg.last, 20); // addClass(dom.fbFrame, 'sh-fb-frame-bubble'); fadeIn(dom.bubble); } else { ShVTrack.onChatToggle(); } if (ShVTrack.settings.beep && ShVTrack.msg.lastBeeped != ShVTrack.msg.lastId) { //sounds enabled - play it ShVTrack.msg.lastBeeped = ShVTrack.msg.lastId; ShVTrack.writeCookies(); //doSound(ShVTrack.settings.beep); ion.sound({//Load all sounds sounds: [ {name: 'panel_sound'}, {name: 'panel_sound_2'}, {name: 'panel_sound_3'} ], // main config path: 'https://' + 'www.sitehood.co.il/static/' + 'sounds/', preload: false, multiplay: false, volume: 1 }); ion.sound.play(ShVTrack.settings.beep); } ShVTrack.flags.showLast = false; } if (ShVTrack.state.status > 2) { clearNode(dom.bubbleCount); } else { setNodeText(dom.bubbleCount, ShVTrack.msg.unreadCount); } if (resp.nn) { //name changed by owner/agent/system dom.nick.value = resp.nn; ShVTrack.visitor.nickName = resp.nn; //xnick } if (resp.dep) { //department changed from server ShVTrack.visitor.department = resp.dep.id; if ((!resp.dep.id) === (!resp.dep.nm)) { //both are either set or unset setNodeText(dom.depName, resp.dep.nm); } } return true; }, updateHandle: function(data, status) { //this methid is called upon success of update request if (ShVTrack.onUpdatePanel(data)) { //renew update sequence if response parsed ok ShVTrack.update.requestFlag = false; //reenable updates } }, //send methods sendMessage: function(msg) { var dataObj = { op: 'msg', vi: ShVTrack.visitor.id, si: ShVTrack.visitor.site, l: ShVTrack.state.lang, st: ShVTrack.state.status, svi: ShVTrack.visitor.visit, msg: msg }; Scripter.getJSONP(urlhead + serverSide, dataObj, function(response) { if (response && response.error) { alert(response.error); } }); }, onInfoSend: function() { if (window.sh_siteid == 2156 && typeof grecaptcha == 'object'){ var isHuman = grecaptcha.getResponse(); if (isHuman.length == 0) { alert(ShVTrack.translations.need_captcha); show(dom.infoForm); //The form is closed if you send it empty. this is to show it again. return; } } if (dom.contName.value === ShVTrack.contact.name && dom.contLname.value === ShVTrack.contact.last && dom.contPhone.value === ShVTrack.contact.phone && dom.contEmail.value === ShVTrack.contact.email && dom.contContent.value === ShVTrack.contact.content) { hide(dom.infoForm); // No changes made } // check if email addr is valid if (!emailFilter.test(dom.contEmail.value)) { if (window.sh_siteid != 2606 && window.sh_siteid != 2607) {//if not ayala dom.contEmail.style.color = 'red'; alert(ShVTrack.translations.wrong_email_format); show(dom.infoForm); //The form is closed if you send it empty. this is to show it again. return; } } //Require phone if (window.sh_siteid == 2156 || window.sh_siteid == 2606 || window.sh_siteid == 2607 || window.sh_siteid == 2694) {//only for certain sites var phone = dom.contPhone.value, intRegex = /[0-9 -()+]+$/; if((phone.length < 6) || (!intRegex.test(phone))) { dom.contPhone.style.color = 'red'; alert(ShVTrack.translations.phone_required); show(dom.infoForm); //The form is closed if you send it empty. this is to show it again. return; } } if (ShVTrack.settings.cfbc && !ShVTrack.state.cfbc) { //additional checks if (!dom.contName.value) { alert(ShVTrack.translations.need_name); return; } if (!dom.contLname.value) { alert(ShVTrack.translations.need_last_name); return; } } if (window.sh_siteid === 2433) { if (!dom.contName.value) {//required name alert(ShVTrack.translations.need_name); show(dom.infoForm); //The form is closed if you send it empty. this is to show it again. return; } if (!dom.contComp.value) {//required company alert(ShVTrack.translations.need_company_name); show(dom.infoForm); //The form is closed if you send it empty. this is to show it again. return; } var dataObj = { op: 'cntct', vi: ShVTrack.visitor.id, si: ShVTrack.visitor.site, l: ShVTrack.state.lang, st: ShVTrack.state.status, svi: ShVTrack.visitor.visit, cn: dom.contName.value, cln: dom.contLname.value, cc: dom.contComp.value, cem: dom.contEmail.value, cph: dom.contPhone.value, cnt: dom.contContent.value }; } else { var dataObj = { op: 'cntct', vi: ShVTrack.visitor.id, si: ShVTrack.visitor.site, l: ShVTrack.state.lang, st: ShVTrack.state.status, svi: ShVTrack.visitor.visit, cn: dom.contName.value, cln: dom.contLname.value, cem: dom.contEmail.value, cph: dom.contPhone.value, cnt: dom.contContent.value }; }//end of else Scripter.getJSONP(urlhead + serverSide, dataObj, ShVTrack.contactOk); hide(dom.infoForm); if (dom.contEmail.style.color === 'red') { dom.contEmail.style.color = 'black'; } document.getElementById('shi-contSend').setAttribute('disabled', 'disabled');//prevent duplicate forms.. document.getElementById('shi-contSend').style.opacity = '0.5'; if (window.sh_siteid === 11 || window.sh_siteid === 2805) {//create success div instead of chat message succDiv = document.createElement('div');//container succDiv.setAttribute('class', 'contact-sent'); succDiv.setAttribute('id', 'contact-sent'); succImg = document.createElement('span');//image succImg.setAttribute('class', 'success-icon'); succSpan = document.createElement('span');//text succSpan.setAttribute('class', 'success-text'); succSpan.innerHTML = ShVTrack.translations.contact_form_saved_success; succBtn = document.createElement('div');//text succBtn.setAttribute('class', 'success-confirm'); succBtn.setAttribute('id', 'success-confirm'); succBtn.innerHTML = 'אישור'; succDiv.appendChild(succImg); succDiv.appendChild(succSpan); succDiv.appendChild(succBtn); dom.container.appendChild(succDiv); addEvent('success-confirm', 'click', function() { hide(document.getElementById('contact-sent')); }); } }, //helper methods errorHandler: function(errObj, errFunc) { try { if (!errFunc) { console.log(getErrorMessage(errObj)); } else if (typeof(errFunc) === 'function') { errFunc(errObj); } else { if (errObj) { console.log(errFunc + ': ' + getErrorMessage(errObj)); } else { console.log(errFunc); } } } catch (err) { console.log('err func: ' + getErrorMessage(err)); } }, parseCookies: function() { var cookieName = '__shvc' + this.visitor.site, lsName = 'shObj' + this.visitor.site, //name of local storage item cook = readCookie(cookieName) || readCookie('__shvc'), //use old style as a fallback cObj = unparam(cook), store; if (window.localStorage && window.localStorage[lsName]) { //try to load from local storage store = unparam(window.localStorage[lsName]); store.vr = cObj.vr; store.vt = cObj.vt; store.fbs = cObj.fbs; cObj = store; } if (cObj) { this.visitor.id = parseInt(cObj.vr); this.visitor.visit = parseInt(cObj.vt); this.state.lang = cObj.l; this.state.status = parseInt(cObj.st) || 0; this.state.blocked = parseInt(cObj.b) || 0; this.state.min = parseInt(cObj.m); this.state.cfbc = parseInt(cObj.cfbc); this.msg.lastBeeped = cObj.lb || 0; this.state.fbs = parseInt(cObj.fbs) || 0; } }, writeCookies: function() { var cookieName = '__shvc' + this.visitor.site, lsName = 'shObj' + this.visitor.site, //name of local storage item cObj = { vr: this.visitor.id, vt: this.visitor.visit, l : this.state.lang, st: this.state.status, b : this.state.blocked, m : this.state.min, lb: this.msg.lastBeeped, cfbc: this.state.cfbc, fbs: this.state.fbs }; if (window.localStorage) { cObj.ts = (new Date()).getTime(); window.localStorage[lsName] = param(cObj); cObj = {//this will be stored in cookies for cross-protocol access vr: this.visitor.id, vt: this.visitor.visit, fbs: this.state.fbs } } createCookie(cookieName, param(cObj), { expires: 180, domain: ShVTrack.domain.cook }); }, createFbLike: function() { if (typeof dom.fbProto !== 'object') { return; } if (!dom.fbLike) { dom.fbLike = dom.fbProto.cloneNode(true); dom.fbLike.removeAttribute('id'); show(dom.fbLike); } return dom.fbLike; }, createMessage: function(item /*, addCls*/) { var cls, nm, clon = dom.msgProto.cloneNode(true), msg = breakLongWords(item.m, 24), tmp, frag = document.createDocumentFragment(); clon.removeAttribute('id'); switch (item.c) { case 'v': cls = 'sh-userMsg'; nm = ShVTrack.translations.ML_PNL_ME; break; case 'o': cls = 'sh-agentMsg'; if (!item.agt) { nm = ShVTrack.translations.ML_SITE_REPRESENTATIVE; //ShVTrack.agent.nm; } else { nm = item.agt; } break; default: cls = 'sh-systemMsg'; nm = ShVTrack.translations.ML_PNL_SYSTEM_MSG; } addClass(clon, cls); if (arguments.length > 1) { //additional classes addClass(clon, arguments[1]); } tmp = new Date(); if (item.f & 4 && (tmp.getTime() - item.t * 1000 < 300000)) { //this is a 'reopen conversation` message and it was sent in last 5 minutes from now msg += ' ' + ShVTrack.translations.reopen + ''; } if (item.t) { //there is a message time - show it tmp.setTime(item.t * 1000); setNodeText(clon.getElementsByTagName('span')[0], formatTime(tmp)); } if(item.m){ //show the message itself only when there is a text in it clon.getElementsByTagName('em')[0].innerHTML = (safeTags(nm) + ': ' + msg); show(clon); frag.appendChild(clon); } if ((item.f & 2) == 2) { //facebook like was sent frag.appendChild(this.createFbLike()); } return frag; }, changeDepartment: function(depId) { if (this.visitor.department == depId) { //nothing changed return; } this.visitor.department = depId; //TODO resend update immediatelly }, changeDepByTag: function(depName) { if (depName == undefined) {//no dep name supplied return;//do nothing } var dataObj = { op: 'getDep', si: ShVTrack.visitor.site, dn: depName }; Scripter.getJSONP(urlhead + serverSide, dataObj, function(response) {//fetch the deps //response - eighter the id of the existing dep or a new one just created if (response) { ShVTrack.visitor.department = response;//Change the department } else {//something went wrong. No id received return; } }); //TODO resend update immediatelly }, changeName: function(name /*, notify = false */) { name = strTrim(name); if (name === ShVTrack.visitor.nickName) { //name not changed xnick return; } var dataObj = { op: 'name', vi: ShVTrack.visitor.id, si: ShVTrack.visitor.site, l: ShVTrack.state.lang, st: ShVTrack.state.status, svi: ShVTrack.visitor.visit, name: name }; if (arguments.length > 1) { //assume second argument dataObj['ntfy'] = +arguments[1]; //convert to number } Scripter.getJSONP(urlhead + serverSide, dataObj, ShVTrack.introduceOk); }, setProperties: function(propObj) { var dataObj = { op: 'props', vi: ShVTrack.visitor.id, si: ShVTrack.visitor.site, l: ShVTrack.state.lang, st: ShVTrack.state.status, svi: ShVTrack.visitor.visit, props: propObj }; Scripter.getJSONP(urlhead + serverSide, dataObj, ShVTrack.defHandler); }, openChat: function() { show(dom.container); // removeClass(dom.fbFrame, 'sh-fb-frame-bubble'); hide(dom.bubble); ShVTrack.msg.last = ''; ShVTrack.msg.unreadCount = 0; show(dom.chat); ShVTrack.state.status = 3; ShVTrack.state.blocked = 0; ShVTrack.update.delay = ShVTrack.update.openDelay; dom.output.scrollTop = dom.output.scrollHeight; ShVTrack.writeCookies(); ShVTrack.updateMessages(); clearInterval(ShVTrack.update.timer); ShVTrack.update.timer = setInterval(ShVTrack.updateMessages, ShVTrack.update.delay); }, onReopenConversationCallback: function(data) { if (!data.res) { alert(data.error); } }, onReopenConversation: function() { var dataObj = { op: 'reopen', vi: ShVTrack.visitor.id, si: ShVTrack.visitor.site, l: ShVTrack.state.lang, st: ShVTrack.state.status, svi: ShVTrack.visitor.visit }; Scripter.getJSONP(urlhead + serverSide, dataObj, ShVTrack.onReopenConversationCallback); }, onResetFeedback: function() { hide(dom.feedbackForm); var radios = getElementsByClassName('sh-feedbackMark', dom.feedbackForm, 'input'); for (var i = 0; i < radios.length; i++) { radios[i].checked = false; } }, onSubmitFeedback: function() { var i, j, sel, groups = getElementsByClassName('sh-questionGroup', dom.feedbackForm, 'div'), radios, id, data = { op:'feedback', vi: ShVTrack.visitor.id, svi: ShVTrack.visitor.visit, si: ShVTrack.visitor.site, st: ShVTrack.state.status, l: ShVTrack.state.lang, clauses: {} }; if (groups.length < 1) { //nothing to do if feedback form has no clauses return; } for (i = 0; i < groups.length; i++) { radios = getElementsByClassName('sh-feedbackMark', groups[i], 'input'); id = getElementsByClassName('sh-groupId', groups[i], 'input')[0].value; sel = -1; for (j = 0; j < radios.length; j++) { if (radios[j].checked) { sel = radios[j].value; break; } } if (sel < 0) { //no answer for this clause alert(ShVTrack.translations.must_answer_all_questions); return; } data.clauses[id] = sel; } Scripter.getJSONP(urlhead + serverSide, data, function(data) { if (data.res > 0) { alert(ShVTrack.translations.feedback_saved_success); hide(dom.feedbackForm); ShVTrack.onResetFeedback(); } else { alert(data.error ? data.error : 'Failed to save feedback!'); } }); }, updateVisitorFBData: function(data) { dom.nick.value = ShVTrack.visitor.nickName = data.nick; dom.contName.value = ShVTrack.contact.name = ShVTrack.visitor.name = data.name; dom.contLname.value = ShVTrack.contact.last = ShVTrack.visitor.lname = data.last; if (data.email){ dom.contEmail.value = ShVTrack.contact.email = ShVTrack.visitor.email = data.email; } var dataObj = { op: 'FBdata', vi: ShVTrack.visitor.id, si: ShVTrack.visitor.site, l: ShVTrack.state.lang, st: ShVTrack.state.status, svi: ShVTrack.visitor.visit, nkn: ShVTrack.visitor.nickName, nm: ShVTrack.visitor.name, ln: ShVTrack.visitor.lname, eml: ShVTrack.visitor.email, usr: data.user }; Scripter.getJSONP(urlhead + serverSide, dataObj, function(data) { if (data.error) { alert(data.error); } }); } }; //call init var loadIt = function() { console.log('sh load started');//debug dom.init(); ShVTrack.init(); // make flash and other embed objects to not overlap(set wmode attribute to opaque) var embeds = document.getElementsByTagName('embed'), objs = document.getElementsByTagName('object'), clon, par, next, i, item, iType; for (i = 0; i < embeds.length; i++) { item = embeds[i]; iType = typeof item; if (!Object.prototype.hasOwnProperty.call(embeds, i)) { continue; } if (iType !== 'object' && iType !== 'function') { continue; } par = item.parentNode; if (!par) { continue; } next = item.nextSibling; clon = (typeof item.cloneNode === 'function') ? item.cloneNode(true) : item; par.removeChild(item); clon.setAttribute('wmode', 'transparent'); if (next) { par.insertBefore(clon, next); } else { par.appendChild(clon); } } var flag = false, func = function(prm) { if (prm.getAttribute('name') !== 'wmode') { return true; } prm.setAttribute('value', 'transparent'); flag = true; return false; //break the cycle }; for (i = 0; i < objs.length; i++) { item = objs[i]; iType = typeof item; if (!Object.prototype.hasOwnProperty.call(objs, i)) { continue; } if (iType !== 'object' && iType !== 'function') { continue; } //skip objects which already have wmode:transparent par = item.parentNode; next = item.nextSibling; clon = item.cloneNode(true); par.removeChild(item); var params = clon.getElementsByTagName('param'), attr; flag = false; for (var j = 0; j < params.length; j++) { if (!func(params[j])) { break; } } if (!flag) { attr = document.createElement('param'); attr.setAttribute('name', 'wmode'); attr.setAttribute('value', 'transparent'); item.appendChild(attr); } if (next) { par.insertBefore(clon, next); } else { par.appendChild(clon); } } }, loadTimer = setInterval(function() { console.log(document.readyState); if (/loaded|complete/.test(document.readyState)) { clearInterval(loadTimer); loadIt(); } }, 100); // try each 100 milliseconds }());