Permalink
Browse files

Adds sniffer for XHR2 features (and loadend event) to SC.platform. Up…

…dates SC.Response to use centralized SC.platform sniffers. Updates SC.Request unit tests to pass!
  • Loading branch information...
1 parent 38640ef commit 249403ebf5d7f22a06c24375d6b05f5b9e6ec9da @dcporter dcporter committed Feb 20, 2014
View
10 frameworks/ajax/system/response.js
@@ -517,7 +517,7 @@ SC.XHRResponse = SC.Response.extend(
async = !!request.get('isAsynchronous');
if (async) {
- if (window.ProgressEvent) {
+ if (SC.platform.get('supportsXHR2ProgressEvent')) {
// XMLHttpRequest Level 2
// Add progress event listeners that were specified on the request.
@@ -548,8 +548,7 @@ SC.XHRResponse = SC.Response.extend(
}
}
- // Some older webkit browsers with ProgressEvent don't support loadend.
- if (rawRequest.onloadend || rawRequest.onloadend === null) {
+ if (SC.platform.get('supportsXHR2LoadEndEvent')) {
SC.Event.add(rawRequest, 'loadend', this, this.finishRequest);
} else {
SC.Event.add(rawRequest, 'load', this, this.finishRequest);
@@ -660,11 +659,10 @@ SC.XHRResponse = SC.Response.extend(
}, this);
// Avoid memory leaks
- if (window.ProgressEvent) {
+ if (SC.platform.get('supportsXHR2ProgressEvent')) {
// XMLHttpRequest Level 2
- // Some older webkit browsers with ProgressEvent don't support loadend.
- if (rawRequest.onloadend || rawRequest.onloadend === null) {
+ if (SC.platform.get('supportsXHR2LoadEndEvent')) {
SC.Event.remove(rawRequest, 'loadend', this, this.finishRequest);
} else {
SC.Event.remove(rawRequest, 'load', this, this.finishRequest);
View
44 frameworks/ajax/tests/system/request.js
@@ -28,6 +28,28 @@ module("SC.Request", {
});
+test("PRELIM: Verify basic functionality in testing environment.", function() {
+ if (SC.platform.get('supportsXHR2ProgressEvent')) {
+ var xhr = new XMLHttpRequest;
+ xhr.addEventListener('load', function() {
+ ok(true, 'Success: xhr.addEventListener for load event.');
+ nextTest();
+ });
+ xhr.open("get", url);
+ xhr.send();
+
+ window.stop(test_timeout);
+
+ function nextTest() {
+ request.notify('load', this, function() {
+ ok(true, 'Success: SC.Request#notify for load event.');
+ window.start();
+ });
+ request.send();
+ }
+ }
+});
+
test("Basic Requirements", function() {
ok(SC.Request, "SC.Request is defined");
ok("" !== url, "url variable is not empty");
@@ -459,12 +481,13 @@ test("Test event listeners on successful request.", function() {
request.notify(200, this, function(response) {
status = response.status;
- if (window.ProgressEvent) {
+ if (SC.platform.get('supportsXHR2ProgressEvent')) {
ok(loadstart, "Received a loadstart event.");
ok(progress, "Received a progress event.");
ok(load, "Received a load event.");
- ok(loadend, "Received a loadend event.");
+ if (SC.platform.get('supportsXHR2LoadEndEvent')) ok(loadend, "Received a loadend event.");
}
+
ok(!abort, "Did not receive an abort event.");
ok(!error, "Did not receive an error event.");
ok(!timeout, "Did not receive a timeout event.");
@@ -478,14 +501,13 @@ test("Test event listeners on successful request.", function() {
response = request.send();
});
-if (window.ProgressEvent) {
+if (SC.platform.get('supportsXHR2ProgressEvent')) {
test("Test event listeners on aborted request.", function() {
var abort = false,
error = false,
load = false,
- loadend = false,
loadstart = false,
- progress = false,
+ loadend = false,
response,
status,
timeout = false;
@@ -505,14 +527,18 @@ if (window.ProgressEvent) {
response.cancel();
});
- request.notify("loadend", this, function(evt) {
+ request.notify(SC.platform.get('supportsXHR2LoadEndEvent') ? 'loadend' : 'abort', this, function(evt) {
loadend = true;
ok(loadstart, "Received a loadstart event.");
ok(progress, "Received a progress event.");
ok(abort, "Received an abort event.");
ok(!load, "Did not receive a load event.");
- ok(loadend, "Received a loadend event.");
+ if (SC.platform.get('supportsXHR2LoadEndEvent')) {
+ ok(loadend, "Received a loadend event.");
+ } else {
+ ok(loadend, "loadend event not supported. Received terminal abort event.");
+ }
ok(!error, "Did not receive an error event.");
ok(!timeout, "Did not receive a timeout event.");
equals(status, undefined, "Did not receive a status notification.");
@@ -560,11 +586,11 @@ test("Test upload event listeners on successful request.", function() {
request.notify(200, this, function(response) {
status = response.status;
- if (window.ProgressEvent) {
+ if (SC.platform.get('supportsXHR2ProgressEvent')) {
ok(loadstart, "Received a loadstart event.");
ok(progress, "Received a progress event.");
ok(load, "Received a load event.");
- ok(loadend, "Received a loadend event.");
+ if (SC.platform.get('supportsXHR2LoadEndEvent')) ok(loadend, "Received a loadend event.");
}
ok(!abort, "Did not receive an abort event.");
ok(!error, "Did not receive an error event.");
View
28 frameworks/core_foundation/system/platform.js
@@ -398,6 +398,34 @@ SC.platform = SC.Object.create({
}(),
/**
+ Whether the browser supports the XHR2 ProgressEvent specification. This
+ reliably implies support for XMLHttpRequest 'loadstart' and 'progress'
+ events, as well as the terminal 'load', 'error' and 'abort' events. Support
+ for 'loadend', which fires no matter how the request terminats, is a bit
+ spottier and should be verified separately using `supportsXHR2LoadEndEvent`.
+
+ @type Boolean
+ */
+ supportsXHR2ProgressEvent: ('ProgressEvent' in window),
+
+ /**
+ Whether the browser supports the XHR2 FormData specification.
+
+ @type Boolean
+ */
+ supportsXHR2FormData: ('FormData' in window),
+
+ /**
+ Whether the browser supports the XHR2 ProgressEvent's loadend event. If not
+ supported, you should handle 'load', 'error' and 'abort' events instead.
+
+ @type Boolean
+ */
+ supportsXHR2LoadEndEvent: function() {
+ return (new XMLHttpRequest).onloadend === null;
+ }(),
+
+ /**
Whether the browser supports the orientationchange event.
@type Boolean

0 comments on commit 249403e

Please sign in to comment.