diff --git a/src/Microsoft.AspNet.SignalR.Client.JS/jquery.signalR.transports.foreverFrame.js b/src/Microsoft.AspNet.SignalR.Client.JS/jquery.signalR.transports.foreverFrame.js index 4ca15592e2..77e334f7fb 100644 --- a/src/Microsoft.AspNet.SignalR.Client.JS/jquery.signalR.transports.foreverFrame.js +++ b/src/Microsoft.AspNet.SignalR.Client.JS/jquery.signalR.transports.foreverFrame.js @@ -10,6 +10,11 @@ events = $.signalR.events, changeState = $.signalR.changeState, transportLogic = signalR.transports._logic, + createFrame = function () { + var frame = window.document.createElement("iframe"); + frame.setAttribute("style", "position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;"); + return frame; + }, // Used to prevent infinite loading icon spins in older versions of ie // We build this object inside a closure so we don't pollute the rest of // the foreverFrame transport with unnecessary functions/utilities. @@ -26,10 +31,11 @@ if (attachedTo === 0) { // Create and destroy iframe every 3 seconds to prevent loading icon, super hacky loadingFixIntervalId = window.setInterval(function () { - var tempFrame = $(""); + var tempFrame = createFrame(); + + window.document.body.appendChild(tempFrame); + window.document.body.removeChild(tempFrame); - $("body").append(tempFrame); - tempFrame.remove(); tempFrame = null; }, loadingFixInterval); } @@ -61,7 +67,11 @@ var that = this, frameId = (transportLogic.foreverFrame.count += 1), url, - frame = $(""); + frame = createFrame(), + frameLoadHandler = function () { + connection.log("Forever frame iframe finished loading and is no longer receiving messages, reconnecting."); + that.reconnect(connection); + }; if (window.EventSource) { // If the browser supports SSE, don't use Forever Frame @@ -72,6 +82,8 @@ return; } + frame.setAttribute("data-signalr-connection-id", connection.id); + // Start preventing loading icon // This will only perform work if the loadPreventer is not attached to another connection. loadPreventer.prevent(); @@ -81,21 +93,20 @@ url += "&frameId=" + frameId; // Set body prior to setting URL to avoid caching issues. - $("body").append(frame); + window.document.body.appendChild(frame); - frame.prop("src", url); - transportLogic.foreverFrame.connections[frameId] = connection; + connection.log("Binding to iframe's load event."); - connection.log("Binding to iframe's readystatechange event."); - frame.bind("readystatechange", function () { - if ($.inArray(this.readyState, ["loaded", "complete"]) >= 0) { - connection.log("Forever frame iframe readyState changed to " + this.readyState + ", reconnecting"); + if (frame.addEventListener) { + frame.addEventListener("load", frameLoadHandler, false); + } else if (frame.attachEvent) { + frame.attachEvent("onload", frameLoadHandler); + } - that.reconnect(connection); - } - }); + frame.src = url; + transportLogic.foreverFrame.connections[frameId] = connection; - connection.frame = frame[0]; + connection.frame = frame; connection.frameId = frameId; if (onSuccess) { @@ -137,7 +148,8 @@ }, receive: function (connection, data) { - var cw; + var cw, + body; transportLogic.processMessages(connection, data); // Delete the script & div elements @@ -145,8 +157,13 @@ if (connection.frameMessageCount > 50) { connection.frameMessageCount = 0; cw = connection.frame.contentWindow || connection.frame.contentDocument; - if (cw && cw.document) { - $("body", cw.document).empty(); + if (cw && cw.document && cw.document.body) { + body = cw.document.body; + + // Remove all the child elements from the iframe's body to conserver memory + while (body.firstChild) { + body.removeChild(body.firstChild); + } } } }, @@ -171,7 +188,12 @@ connection.log("SignalR: Error occured when stopping foreverFrame transport. Message = " + e.message); } } - $(connection.frame).remove(); + + // Ensure the iframe is where we left it + if (connection.frame.parentNode === window.document.body) { + window.document.body.removeChild(connection.frame); + } + delete transportLogic.foreverFrame.connections[connection.frameId]; connection.frame = null; connection.frameId = null; diff --git a/tests/Microsoft.AspNet.SignalR.Client.JS.Tests/Build/test.config.js b/tests/Microsoft.AspNet.SignalR.Client.JS.Tests/Build/test.config.js index 14b415501a..271898bb68 100644 --- a/tests/Microsoft.AspNet.SignalR.Client.JS.Tests/Build/test.config.js +++ b/tests/Microsoft.AspNet.SignalR.Client.JS.Tests/Build/test.config.js @@ -5,6 +5,8 @@ function failConnection() { $("iframe").each(function () { + var loadEvent; + if (this.stop) { this.stop(); } else { @@ -18,7 +20,20 @@ console.log("Network Mock Error occured, unable to stop iframe. Message = " + e.message); } } - $(this).triggerHandler("readystatechange"); + + if (window.document.createEvent) { + loadEvent = window.document.createEvent("Event"); + loadEvent.initEvent("load", true, true); + } else { + loadEvent = window.document.createEventObject(); + loadEvent.eventType = "load"; + } + + if (this.dispatchEvent) { + this.dispatchEvent(loadEvent); + } else { + this.fireEvent("onload", loadEvent); + } }); }