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);
+ }
});
}