Skip to content

Commit

Permalink
Merge pull request #47 from brianjmiller/master
Browse files Browse the repository at this point in the history
CORS and IE6 Support
bscSCORM committed Jul 10, 2013
2 parents 1ddf779 + baa81a3 commit 9af2dc3
Showing 7 changed files with 216 additions and 146 deletions.
2 changes: 1 addition & 1 deletion build/tincan-min.js

Large diffs are not rendered by default.

158 changes: 92 additions & 66 deletions build/tincan.js
Original file line number Diff line number Diff line change
@@ -1634,7 +1634,7 @@ TinCan client library

// is same port?
|| locationPort !== (
urlParts[3] !== null ? urlParts[3] : (urlParts[1] === "http:" ? "80" : (urlParts[1] === "https:" ? "443" : ""))
(urlParts[3] !== null && typeof urlParts[3] !== "undefined" && urlParts[3] !== "") ? urlParts[3] : (urlParts[1] === "http:" ? "80" : (urlParts[1] === "https:" ? "443" : ""))
)
);
if (isXD) {
@@ -1727,6 +1727,7 @@ TinCan client library
@return {Object} XHR if called in a synchronous way (in other words no callback)
*/
sendRequest: function (cfg) {
/*global ActiveXObject*/
this.log("sendRequest");
var xhr,
finished = false,
@@ -1741,6 +1742,60 @@ TinCan client library
self = this
;

// Setup request callback
function requestComplete () {
self.log("requestComplete: " + finished + ", xhr.status: " + xhr.status);
var notFoundOk,
httpStatus;

//
// older versions of IE don't properly handle 204 status codes
// so correct when receiving a 1223 to be 204 locally
// http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
//
httpStatus = (xhr.status === 1223) ? 204 : xhr.status;

if (! finished) {
// may be in sync or async mode, using XMLHttpRequest or IE XDomainRequest, onreadystatechange or
// onload or both might fire depending upon browser, just covering all bases with event hooks and
// using 'finished' flag to avoid triggering events multiple times
finished = true;

notFoundOk = (cfg.ignore404 && httpStatus === 404);
if (httpStatus === undefined || (httpStatus >= 200 && httpStatus < 400) || notFoundOk) {
if (cfg.callback) {
cfg.callback(null, xhr);
}
else {
requestCompleteResult = {
err: null,
xhr: xhr
};
return requestCompleteResult;
}
}
else {
// Alert all errors except cancelled XHR requests
if (httpStatus > 0) {
requestCompleteResult = {
err: httpStatus,
xhr: xhr
};
if (self.alertOnRequestFailure) {
alert("[warning] There was a problem communicating with the Learning Record Store. (" + httpStatus + " | " + xhr.responseText+ ")");
}
if (cfg.callback) {
cfg.callback(httpStatus, xhr);
}
}
return requestCompleteResult;
}
}
else {
return requestCompleteResult;
}
}

// respect absolute URLs passed in
if (cfg.url.indexOf("http") === 0) {
fullUrl = cfg.url;
@@ -1789,7 +1844,17 @@ TinCan client library

this.log("sendRequest using XMLHttpRequest - async: " + (typeof cfg.callback !== "undefined"));

xhr = new XMLHttpRequest();
if (typeof XMLHttpRequest !== "undefined") {
xhr = new XMLHttpRequest();
}
else {
//
// IE6 implements XMLHttpRequest through ActiveX control
// http://blogs.msdn.com/b/ie/archive/2006/01/23/516393.aspx
//
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}

xhr.open(cfg.method, fullUrl, (typeof cfg.callback !== "undefined"));
for (prop in headers) {
if (headers.hasOwnProperty(prop)) {
@@ -1801,6 +1866,13 @@ TinCan client library
cfg.data += "";
}
data = cfg.data;

xhr.onreadystatechange = function () {
self.log("xhr.onreadystatechange - xhr.readyState: " + xhr.readyState);
if (xhr.readyState === 4) {
requestComplete();
}
};
}
else if (this._requestMode === XDR) {
this.log("sendRequest using XDomainRequest");
@@ -1832,76 +1904,30 @@ TinCan client library

xhr = new XDomainRequest ();
xhr.open("POST", fullUrl);

xhr.onload = function () {
requestComplete();
};
xhr.onerror = function () {
requestComplete();
};
}
else {
this.log("sendRequest unrecognized _requestMode: " + this._requestMode);
}

// Setup request callback
function requestComplete () {
self.log("requestComplete: " + finished + ", xhr.status: " + xhr.status);
var notFoundOk,
httpStatus;

//
// older versions of IE don't properly handle 204 status codes
// so correct when receiving a 1223 to be 204 locally
// http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
//
httpStatus = (xhr.status === 1223) ? 204 : xhr.status;

if (! finished) {
// may be in sync or async mode, using XMLHttpRequest or IE XDomainRequest, onreadystatechange or
// onload or both might fire depending upon browser, just covering all bases with event hooks and
// using 'finished' flag to avoid triggering events multiple times
finished = true;

notFoundOk = (cfg.ignore404 && httpStatus === 404);
if (httpStatus === undefined || (httpStatus >= 200 && httpStatus < 400) || notFoundOk) {
if (cfg.callback) {
cfg.callback(null, xhr);
}
else {
requestCompleteResult = {
err: null,
xhr: xhr
};
return requestCompleteResult;
}
}
else {
// Alert all errors except cancelled XHR requests
if (httpStatus > 0) {
requestCompleteResult = {
err: httpStatus,
xhr: xhr
};
if (self.alertOnRequestFailure) {
alert("[warning] There was a problem communicating with the Learning Record Store. (" + httpStatus + " | " + xhr.responseText+ ")");
}
if (cfg.callback) {
cfg.callback(httpStatus, xhr);
}
}
return requestCompleteResult;
}
}
else {
return requestCompleteResult;
}
//
// research indicates that IE is known to just throw exceptions
// on .send and it seems everyone pretty much just ignores them
// including jQuery (https://github.com/jquery/jquery/blob/1.10.2/src/ajax.js#L549
// https://github.com/jquery/jquery/blob/1.10.2/src/ajax/xhr.js#L97)
//
try {
xhr.send(data);
}
catch (ex) {
this.log("sendRequest caught send exception: " + ex);
}

xhr.onreadystatechange = function () {
self.log("xhr.onreadystatechange - xhr.readyState: " + finished + ", xhr.status: " + xhr.status);
if (xhr.readyState === 4) {
requestComplete();
}
};

xhr.onload = requestComplete;
xhr.onerror = requestComplete;

xhr.send(data);

if (! cfg.callback) {
// synchronous
158 changes: 92 additions & 66 deletions src/LRS.js
Original file line number Diff line number Diff line change
@@ -184,7 +184,7 @@ TinCan client library

// is same port?
|| locationPort !== (
urlParts[3] !== null ? urlParts[3] : (urlParts[1] === "http:" ? "80" : (urlParts[1] === "https:" ? "443" : ""))
(urlParts[3] !== null && typeof urlParts[3] !== "undefined" && urlParts[3] !== "") ? urlParts[3] : (urlParts[1] === "http:" ? "80" : (urlParts[1] === "https:" ? "443" : ""))
)
);
if (isXD) {
@@ -277,6 +277,7 @@ TinCan client library
@return {Object} XHR if called in a synchronous way (in other words no callback)
*/
sendRequest: function (cfg) {
/*global ActiveXObject*/
this.log("sendRequest");
var xhr,
finished = false,
@@ -291,6 +292,60 @@ TinCan client library
self = this
;

// Setup request callback
function requestComplete () {
self.log("requestComplete: " + finished + ", xhr.status: " + xhr.status);
var notFoundOk,
httpStatus;

//
// older versions of IE don't properly handle 204 status codes
// so correct when receiving a 1223 to be 204 locally
// http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
//
httpStatus = (xhr.status === 1223) ? 204 : xhr.status;

if (! finished) {
// may be in sync or async mode, using XMLHttpRequest or IE XDomainRequest, onreadystatechange or
// onload or both might fire depending upon browser, just covering all bases with event hooks and
// using 'finished' flag to avoid triggering events multiple times
finished = true;

notFoundOk = (cfg.ignore404 && httpStatus === 404);
if (httpStatus === undefined || (httpStatus >= 200 && httpStatus < 400) || notFoundOk) {
if (cfg.callback) {
cfg.callback(null, xhr);
}
else {
requestCompleteResult = {
err: null,
xhr: xhr
};
return requestCompleteResult;
}
}
else {
// Alert all errors except cancelled XHR requests
if (httpStatus > 0) {
requestCompleteResult = {
err: httpStatus,
xhr: xhr
};
if (self.alertOnRequestFailure) {
alert("[warning] There was a problem communicating with the Learning Record Store. (" + httpStatus + " | " + xhr.responseText+ ")");
}
if (cfg.callback) {
cfg.callback(httpStatus, xhr);
}
}
return requestCompleteResult;
}
}
else {
return requestCompleteResult;
}
}

// respect absolute URLs passed in
if (cfg.url.indexOf("http") === 0) {
fullUrl = cfg.url;
@@ -339,7 +394,17 @@ TinCan client library

this.log("sendRequest using XMLHttpRequest - async: " + (typeof cfg.callback !== "undefined"));

xhr = new XMLHttpRequest();
if (typeof XMLHttpRequest !== "undefined") {
xhr = new XMLHttpRequest();
}
else {
//
// IE6 implements XMLHttpRequest through ActiveX control
// http://blogs.msdn.com/b/ie/archive/2006/01/23/516393.aspx
//
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}

xhr.open(cfg.method, fullUrl, (typeof cfg.callback !== "undefined"));
for (prop in headers) {
if (headers.hasOwnProperty(prop)) {
@@ -351,6 +416,13 @@ TinCan client library
cfg.data += "";
}
data = cfg.data;

xhr.onreadystatechange = function () {
self.log("xhr.onreadystatechange - xhr.readyState: " + xhr.readyState);
if (xhr.readyState === 4) {
requestComplete();
}
};
}
else if (this._requestMode === XDR) {
this.log("sendRequest using XDomainRequest");
@@ -382,76 +454,30 @@ TinCan client library

xhr = new XDomainRequest ();
xhr.open("POST", fullUrl);

xhr.onload = function () {
requestComplete();
};
xhr.onerror = function () {
requestComplete();
};
}
else {
this.log("sendRequest unrecognized _requestMode: " + this._requestMode);
}

// Setup request callback
function requestComplete () {
self.log("requestComplete: " + finished + ", xhr.status: " + xhr.status);
var notFoundOk,
httpStatus;

//
// older versions of IE don't properly handle 204 status codes
// so correct when receiving a 1223 to be 204 locally
// http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
//
httpStatus = (xhr.status === 1223) ? 204 : xhr.status;

if (! finished) {
// may be in sync or async mode, using XMLHttpRequest or IE XDomainRequest, onreadystatechange or
// onload or both might fire depending upon browser, just covering all bases with event hooks and
// using 'finished' flag to avoid triggering events multiple times
finished = true;

notFoundOk = (cfg.ignore404 && httpStatus === 404);
if (httpStatus === undefined || (httpStatus >= 200 && httpStatus < 400) || notFoundOk) {
if (cfg.callback) {
cfg.callback(null, xhr);
}
else {
requestCompleteResult = {
err: null,
xhr: xhr
};
return requestCompleteResult;
}
}
else {
// Alert all errors except cancelled XHR requests
if (httpStatus > 0) {
requestCompleteResult = {
err: httpStatus,
xhr: xhr
};
if (self.alertOnRequestFailure) {
alert("[warning] There was a problem communicating with the Learning Record Store. (" + httpStatus + " | " + xhr.responseText+ ")");
}
if (cfg.callback) {
cfg.callback(httpStatus, xhr);
}
}
return requestCompleteResult;
}
}
else {
return requestCompleteResult;
}
//
// research indicates that IE is known to just throw exceptions
// on .send and it seems everyone pretty much just ignores them
// including jQuery (https://github.com/jquery/jquery/blob/1.10.2/src/ajax.js#L549
// https://github.com/jquery/jquery/blob/1.10.2/src/ajax/xhr.js#L97)
//
try {
xhr.send(data);
}
catch (ex) {
this.log("sendRequest caught send exception: " + ex);
}

xhr.onreadystatechange = function () {
self.log("xhr.onreadystatechange - xhr.readyState: " + finished + ", xhr.status: " + xhr.status);
if (xhr.readyState === 4) {
requestComplete();
}
};

xhr.onload = requestComplete;
xhr.onerror = requestComplete;

xhr.send(data);

if (! cfg.callback) {
// synchronous
4 changes: 2 additions & 2 deletions test/js/ContextActivities.js
Original file line number Diff line number Diff line change
@@ -248,7 +248,7 @@
versions: {
latest: { parent: [ commonRaw ], grouping: [ commonRaw ], other: [ commonRaw ] },
"0.95": { parent: commonRaw, grouping: commonRaw, other: commonRaw },
"0.9": { parent: commonRaw , grouping: commonRaw, other: commonRaw },
"0.9": { parent: commonRaw , grouping: commonRaw, other: commonRaw }
}
},
{
@@ -261,7 +261,7 @@
versions: {
latest: { parent: [ commonRaw, commonRaw2 ], grouping: [ commonRaw, commonRaw2 ], other: [ commonRaw, commonRaw2 ] },
"0.95": { parent: commonRaw, grouping: commonRaw, other: commonRaw },
"0.9": { parent: commonRaw , grouping: commonRaw, other: commonRaw },
"0.9": { parent: commonRaw , grouping: commonRaw, other: commonRaw }
}
}
],
12 changes: 6 additions & 6 deletions test/js/Group.js
Original file line number Diff line number Diff line change
@@ -209,42 +209,42 @@
{
name: "2 raw",
instanceConfig: {
member: [ raw, raw2 ],
member: [ raw, raw2 ]
},
checkMember: [ common, common2 ]
},
{
name: "1 precreated",
instanceConfig: {
member: [ common ],
member: [ common ]
},
checkMember: [ common ]
},
{
name: "2 precreated",
instanceConfig: {
member: [ common, common2 ],
member: [ common, common2 ]
},
checkMember: [ common, common2 ]
},
{
name: "2 mixed",
instanceConfig: {
member: [ raw, common2 ],
member: [ raw, common2 ]
},
checkMember: [ common, common2 ]
},
{
name: "2 mixed reversed",
instanceConfig: {
member: [ common, raw2 ],
member: [ common, raw2 ]
},
checkMember: [ common, common2 ]
},
{
name: "4 mixed",
instanceConfig: {
member: [ common, raw, common2, raw2 ],
member: [ common, raw, common2, raw2 ]
},
checkMember: [ common, common, common2, common2 ]
}
26 changes: 22 additions & 4 deletions test/js/TinCanTest.js
Original file line number Diff line number Diff line change
@@ -32,11 +32,29 @@ if (typeof console !== "undefined" && console.log) {

TinCanTest.assertHttpRequestType = function (xhr, name) {
var desc = "assertHttpRequestType: " + name;
if (TinCan.environment().useXDR) {
ok(xhr instanceof XDomainRequest, desc);
if (typeof XDomainRequest !== "undefined" && xhr instanceof XDomainRequest) {
ok(true, desc);
return;
}
else {
ok(xhr instanceof XMLHttpRequest, desc);

if (typeof XMLHttpRequest !== "undefined") {
//
// in IE7 at least XMLHttpRequest is an 'object' but it fails
// the instanceof check because it apparently isn't considered
// a constructor function
//
if (typeof XMLHttpRequest === "function") {
ok(xhr instanceof XMLHttpRequest, desc);
}
else if (typeof XMLHttpRequest === "object") {
ok(true, desc + " (XMLHttpRequest found but not constructor)");
}
else {
ok(true, desc + " (unplanned for xhr)");
}
return;
}

ok(false, desc + " (unrecognized request environment)");
};
}());
2 changes: 1 addition & 1 deletion yuidoc.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "0.6.0",
"version": "0.7.2",
"name": "TinCanJS",
"description": "Client library for working with TinCan API in JavaScript",
"url": "https://github.com/RusticiSoftware/TinCanJS",

0 comments on commit 9af2dc3

Please sign in to comment.