"); transferDoc.parentWindow.PushStream = PushStream; transferDoc.close(); var ifrDiv = transferDoc.createElement("div"); transferDoc.appendChild(ifrDiv); ifrDiv.innerHTML = ""; this.connection = ifrDiv.getElementsByTagName("IFRAME")[0]; this.connection.onload = linker(onerrorCallback, this); this.transferDoc = transferDoc; } catch (e) { var ifr = document.createElement("IFRAME"); ifr.style.width = "1px"; ifr.style.height = "1px"; ifr.style.border = "none"; ifr.style.position = "absolute"; ifr.style.top = "-10px"; ifr.style.marginTop = "-10px"; ifr.style.zIndex = "-20"; ifr.PushStream = PushStream; document.body.appendChild(ifr); ifr.setAttribute("src", url); ifr.onload = linker(onerrorCallback, this); this.connection = ifr; } this.connection.setAttribute("id", this.iframeId); this.frameloadtimer = window.setTimeout(linker(onerrorCallback, this), this.pushstream.timeout); }, register: function (iframeWindow) { this.frameloadtimer = clearTimer(this.frameloadtimer); iframeWindow.p = linker(this.process, this); this.connection.onload = linker(this._onframeloaded, this); this.pushstream._onopen(); this.setPingTimer(); Log4js.info("[Stream] frame registered"); }, process: function (id, channel, data, eventid) { this.pingtimer = clearTimer(this.pingtimer); Log4js.info("[Stream] message received", arguments); this.pushstream._onmessage(unescapeText(data), id, channel, eventid, true); this.setPingTimer(); }, _onframeloaded: function () { Log4js.info("[Stream] frame loaded (disconnected by server)"); this.connection.onload = null; this.disconnect(); }, setPingTimer: function () { if (this.pingtimer) { clearTimer(this.pingtimer); } this.pingtimer = window.setTimeout(linker(onerrorCallback, this), this.pushstream.pingtimeout); } }; var LongPollingWrapper = function (pushstream) { this.type = LongPollingWrapper.TYPE; this.pushstream = pushstream; this.connection = null; this.lastModified = null; this.etag = 0; this.connectionEnabled = false; this.opentimer = null; this.messagesQueue = []; this._linkedInternalListen = linker(this._internalListen, this); this.xhrSettings = { timeout: this.pushstream.longPollingTimeout, data: {}, url: null, success: linker(this.onmessage, this), error: linker(this.onerror, this), load: linker(this.onload, this), beforeOpen: linker(this.beforeOpen, this), beforeSend: linker(this.beforeSend, this), afterReceive: linker(this.afterReceive, this) }; }; LongPollingWrapper.TYPE = "LongPolling"; LongPollingWrapper.prototype = { connect: function () { this.messagesQueue = []; this._closeCurrentConnection(); this.connectionEnabled = true; this.xhrSettings.url = getSubscriberUrl(this.pushstream, this.pushstream.urlPrefixLongpolling); var domain = extract_xss_domain(this.pushstream.host); var currentDomain = extract_xss_domain(window.location.hostname); var port = this.pushstream.port; var currentPort = window.location.port || (this.pushstream.useSSL ? 443 : 80); this.useJSONP = (domain !== currentDomain) || (port !== currentPort) || this.pushstream.longPollingUseJSONP; this.xhrSettings.scriptId = "PushStreamManager_" + this.pushstream.id; if (this.useJSONP) { this.pushstream.longPollingByHeaders = false; this.xhrSettings.data.callback = "PushStreamManager[" + this.pushstream.id + "].wrapper.onmessage"; } this._internalListen(); this.opentimer = window.setTimeout(linker(onopenCallback, this), 5000); Log4js.info("[LongPolling] connecting to:", this.xhrSettings.url); }, _listen: function () { if (this._internalListenTimeout) { clearTimer(this._internalListenTimeout); } this._internalListenTimeout = window.setTimeout(this._linkedInternalListen, this.pushstream.longPollingInterval); }, _internalListen: function () { if (this.connectionEnabled) { this.xhrSettings.data = extend({}, this.pushstream.extraParams(), this.xhrSettings.data); if (this.useJSONP) { Ajax.jsonp(this.xhrSettings); } else if (!this.connection) { this.connection = Ajax.load(this.xhrSettings); } } }, disconnect: function () { this.connectionEnabled = false; if (this.connection) { Log4js.debug("[LongPolling] closing connection to:", this.xhrSettings.url); this._closeCurrentConnection(); this.pushstream._onclose(); } }, _closeCurrentConnection: function () { this.opentimer = clearTimer(this.opentimer); if (this.connection) { try { this.connection.abort(); } catch (e) { /* ignore error on closing */ } this.connection = null; this.lastModified = null; this.xhrSettings.url = null; } }, beforeOpen: function (xhr) { if (this.lastModified === null) { var date = new Date(); if (this.pushstream.secondsAgo) { date.setTime(date.getTime() - (this.pushstream.secondsAgo * 1000)); } this.lastModified = dateToUTCString(date); } if (!this.pushstream.longPollingByHeaders) { this.xhrSettings.data[this.pushstream.longPollingTagArgument] = this.etag; this.xhrSettings.data[this.pushstream.longPollingTimeArgument] = this.lastModified; } }, beforeSend: function (xhr) { if (this.pushstream.longPollingByHeaders) { xhr.setRequestHeader("If-None-Match", this.etag); xhr.setRequestHeader("If-Modified-Since", this.lastModified); } }, afterReceive: function (xhr) { if (this.pushstream.longPollingByHeaders) { this.etag = xhr.getResponseHeader('Etag'); this.lastModified = xhr.getResponseHeader('Last-Modified'); } this.connection = null; }, onerror: function (status) { if (this.connectionEnabled) { /* abort(), called by disconnect(), call this callback, but should be ignored */ if (status === 304) { this._listen(); } else { Log4js.info("[LongPolling] error (disconnected by server):", status); this._closeCurrentConnection(); this.pushstream._onerror({ type: (status === 403) ? "load" : "timeout" }); } } }, onload: function () { this._listen(); }, onmessage: function (responseText) { Log4js.info("[LongPolling] message received", responseText); var lastMessage = null; var messages = isArray(responseText) ? responseText : responseText.split("\r\n"); for (var i = 0; i < messages.length; i++) { if (messages[i]) { lastMessage = parseMessage(messages[i], this.pushstream); this.messagesQueue.push(lastMessage); if (!this.pushstream.longPollingByHeaders && lastMessage.time) { this.etag = lastMessage.tag; this.lastModified = lastMessage.time; } } } this._listen(); while (this.messagesQueue.length > 0) { var message = this.messagesQueue.shift(); this.pushstream._onmessage(message.data, message.id, message.channel, message.eventid, (this.messagesQueue.length === 0)); } } }; /* mains class */ var PushStreamManager = []; var PushStream = function (settings) { settings = settings || {}; this.id = PushStreamManager.push(this) - 1; this.useSSL = settings.useSSL || false; this.host = settings.host || window.location.hostname; this.port = settings.port || (this.useSSL ? 443 : 80); this.timeout = settings.timeout || 15000; this.pingtimeout = settings.pingtimeout || 30000; this.reconnecttimeout = settings.reconnecttimeout || 3000; this.checkChannelAvailabilityInterval = settings.checkChannelAvailabilityInterval || 60000; this.secondsAgo = Number(settings.secondsAgo); this.longPollingByHeaders = (settings.longPollingByHeaders === undefined) ? true : settings.longPollingByHeaders; this.longPollingTagArgument = settings.longPollingTagArgument || 'tag'; this.longPollingTimeArgument = settings.longPollingTimeArgument || 'time'; this.longPollingUseJSONP = settings.longPollingUseJSONP || false; this.longPollingTimeout = settings.longPollingTimeout || 30000; this.longPollingInterval = settings.longPollingInterval || 100; this.reconnecttimer = null; this.urlPrefixPublisher = settings.urlPrefixPublisher || '/pub'; this.urlPrefixStream = settings.urlPrefixStream || '/sub'; this.urlPrefixEventsource = settings.urlPrefixEventsource || '/ev'; this.urlPrefixLongpolling = settings.urlPrefixLongpolling || '/lp'; this.urlPrefixWebsocket = settings.urlPrefixWebsocket || '/ws'; this.jsonIdKey = settings.jsonIdKey || 'id'; this.jsonChannelKey = settings.jsonChannelKey || 'channel'; this.jsonDataKey = settings.jsonDataKey || 'text'; this.jsonTagKey = settings.jsonTagKey || 'tag'; this.jsonTimeKey = settings.jsonTimeKey || 'time'; this.jsonEventIdKey = settings.jsonEventIdKey || 'eventid'; this.modes = (settings.modes || 'eventsource|websocket|stream|longpolling').split('|'); this.wrappers = []; this.wrapper = null; this.onopen = null; this.onmessage = null; this.onerror = null; this.onstatuschange = null; this.channels = {}; this.channelsCount = 0; this.channelsByArgument = settings.channelsByArgument || false; this.channelsArgument = settings.channelsArgument || 'channels'; this.extraParams = settings.extraParams || this.extraParams; for (var i = 0; i < this.modes.length; i++) { try { var wrapper = null; switch (this.modes[i]) { case "websocket": wrapper = new WebSocketWrapper(this); break; case "eventsource": wrapper = new EventSourceWrapper(this); break; case "longpolling": wrapper = new LongPollingWrapper(this); break; case "stream": wrapper = new StreamWrapper(this); break; } this.wrappers[this.wrappers.length] = wrapper; } catch (e) { Log4js.info(e); } } this._setState(0); }; /* constants */ PushStream.LOG_LEVEL = 'error'; /* debug, info, error */ PushStream.LOG_OUTPUT_ELEMENT_ID = 'Log4jsLogOutput'; /* status codes */ PushStream.CLOSED = 0; PushStream.CONNECTING = 1; PushStream.OPEN = 2; /* main code */ PushStream.prototype = { extraParams: function () { return {}; }, addChannel: function (channel, options) { if (escapeText(channel) !== channel) { throw "Invalid channel name! Channel has to be a set of [a-zA-Z0-9]"; } Log4js.debug("entering addChannel"); if (typeof (this.channels[channel]) !== "undefined") { throw "Cannot add channel " + channel + ": already subscribed"; } options = options || {}; Log4js.info("adding channel", channel, options); this.channels[channel] = options; this.channelsCount++; if (this.readyState !== PushStream.CLOSED) { this.connect(); } Log4js.debug("leaving addChannel"); }, removeChannel: function (channel) { if (this.channels[channel]) { Log4js.info("removing channel", channel); delete this.channels[channel]; this.channelsCount--; } }, removeAllChannels: function () { Log4js.info("removing all channels"); this.channels = {}; this.channelsCount = 0; }, _setState: function (state) { if (this.readyState !== state) { Log4js.info("status changed", state); this.readyState = state; if (this.onstatuschange) { this.onstatuschange(this.readyState); } } }, connect: function () { Log4js.debug("entering connect"); if (!this.host) { throw "PushStream host not specified"; } if (isNaN(this.port)) { throw "PushStream port not specified"; } if (!this.channelsCount) { throw "No channels specified"; } if (this.wrappers.length === 0) { throw "No available support for this browser"; } this._keepConnected = true; this._lastUsedMode = 0; this._connect(); Log4js.debug("leaving connect"); }, disconnect: function () { Log4js.debug("entering disconnect"); this._keepConnected = false; this._disconnect(); this._setState(PushStream.CLOSED); Log4js.info("disconnected"); Log4js.debug("leaving disconnect"); }, _connect: function () { this._disconnect(); this._setState(PushStream.CONNECTING); this.wrapper = this.wrappers[this._lastUsedMode++ % this.wrappers.length]; try { this.wrapper.connect(); } catch (e) { //each wrapper has a cleanup routine at disconnect method if (this.wrapper) { this.wrapper.disconnect(); } } }, _disconnect: function () { this.reconnecttimer = clearTimer(this.reconnecttimer); if (this.wrapper) { this.wrapper.disconnect(); } }, _onopen: function () { this.reconnecttimer = clearTimer(this.reconnecttimer); this._setState(PushStream.OPEN); if (this._lastUsedMode > 0) { this._lastUsedMode--; //use same mode on next connection } }, _onclose: function () { this.reconnecttimer = clearTimer(this.reconnecttimer); this._setState(PushStream.CLOSED); this._reconnect(this.reconnecttimeout); }, _onmessage: function (data, id, channel, eventid, isLastMessageFromBatch) { Log4js.debug("message", data, id, channel, eventid, isLastMessageFromBatch); if (id === -2) { if (this.onchanneldeleted) { this.onchanneldeleted(channel); } } else if ((id > 0) && (typeof (this.channels[channel]) !== "undefined")) { if (this.onmessage) { this.onmessage(data, id, channel, eventid, isLastMessageFromBatch); } } }, _onerror: function (error) { this._setState(PushStream.CLOSED); this._reconnect((error.type === "timeout") ? this.reconnecttimeout : this.checkChannelAvailabilityInterval); if (this.onerror) { this.onerror(error); } }, _reconnect: function (timeout) { if (this._keepConnected && !this.reconnecttimer && (this.readyState !== PushStream.CONNECTING)) { Log4js.info("trying to reconnect in", timeout); this.reconnecttimer = window.setTimeout(linker(this._connect, this), timeout); } }, sendMessage: function (message, successCallback, errorCallback) { message = escapeText(message); if (this.wrapper.type === WebSocketWrapper.TYPE) { this.wrapper.sendMessage(message); if (successCallback) { successCallback(); } } else { Ajax.post({ url: getPublisherUrl(this), data: message, success: successCallback, error: errorCallback }); } } }; PushStream.sendMessage = function (url, message, successCallback, errorCallback) { Ajax.post({ url: url, data: escapeText(message), success: successCallback, error: errorCallback }); }; // to make server header template more clear, it calls register and // by a url parameter we find the stream wrapper instance PushStream.register = function (iframe) { var matcher = iframe.window.location.href.match(/streamid=([0-9]*)&?/); if (matcher[1] && PushStreamManager[matcher[1]]) { PushStreamManager[matcher[1]].wrapper.register(iframe); } }; PushStream.unload = function () { for (var i = 0; i < PushStreamManager.length; i++) { try { PushStreamManager[i].disconnect(); } catch (e) {} } }; /* make class public */ window.PushStream = PushStream; window.PushStreamManager = PushStreamManager; if (window.attachEvent) { window.attachEvent("onunload", PushStream.unload); } if (window.addEventListener) { window.addEventListener.call(window, "unload", PushStream.unload, false); } })(window, document); //]]>
Pay attention while playing or this could happen GIF


Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque volutpat volutpat nibh nec posuere. Donec auctor arcut pretium consequat. Contact me 123@abc.com

2 comments: