Skip to content

Instantly share code, notes, and snippets.

@mattparker
Last active December 16, 2015 21:49
Show Gist options
  • Save mattparker/5502902 to your computer and use it in GitHub Desktop.
Save mattparker/5502902 to your computer and use it in GitHub Desktop.
Patches for YUI2 Uploader for IE9+
////////////////////////////////////////////////////
////////////////////////////////////////////////////
// Patch
//
// Was using a non-standard quirk of IE to do
// document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />')
// when it should really be just document.createElement('iframe') and then add attributes
// IE9 is strict about this and breaks.
//
//
YAHOO.util.Connect.createFrame = function (secureUri) {
// IE does not allow the setting of id and name attributes as object
// properties via createElement(). A different iframe creation
// pattern is required for IE.
var frameId = 'yuiIO' + this._transaction_id,
io;
if(YAHOO.env.ua.ie){
// This doesn't work in IE9+ :
// io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
io = document.createElement('iframe');
io.id = frameId;
io.name = frameId;
// IE will throw a security exception in an SSL environment if the
// iframe source is undefined.
if(typeof secureUri == 'boolean'){
io.src = 'javascript:false';
}
}
else{
io = document.createElement('iframe');
io.id = frameId;
io.name = frameId;
}
io.style.position = 'absolute';
io.style.top = '-1000px';
io.style.left = '-1000px';
document.body.appendChild(io);
};
////////////////////////////////////////////////////
////////////////////////////////////////////////////
// Patch
//
// The test for IE8 was *only* for IE8: but IE9 (and presumably higher,
// I can't test IE10) behave in this respect in the same way as IE8.
//
// The particular issue was to do with the 'enctype' header - see the
// commment below.
//
// The only line that's changed is the one that sets the value of ie8.
//
//
YAHOO.util.Connect.uploadFile = function (o, callback, uri, postData) {
// Each iframe has an id prefix of "yuiIO" followed
// by the unique transaction id.
var frameId = 'yuiIO' + o.tId,
uploadEncoding = 'multipart/form-data',
io = document.getElementById(frameId),
// This was doing exact === 8 on the documentMode, so anything greater was in
// effect being treated as < 8.
ie8 = (document.documentMode && document.documentMode >= 8) ? true : false,
oConn = this,
args = (callback && callback.argument)?callback.argument:null,
oElements,
i,
prop,
obj,
rawFormAttributes,
uploadCallback;
// Track original HTML form attribute values.
rawFormAttributes = {
action:this._formNode.getAttribute('action'),
method:this._formNode.getAttribute('method'),
target:this._formNode.getAttribute('target')
};
// Initialize the HTML form properties in case they are
// not defined in the HTML form.
this._formNode.setAttribute('action', uri);
this._formNode.setAttribute('method', 'POST');
this._formNode.setAttribute('target', frameId);
if(YAHOO.env.ua.ie && !ie8){
// IE does not respect property enctype for HTML forms.
// Instead it uses the property - "encoding".
this._formNode.setAttribute('encoding', uploadEncoding);
}
else{
this._formNode.setAttribute('enctype', uploadEncoding);
}
if(postData){
oElements = this.appendPostData(postData);
}
// Start file upload.
this._formNode.submit();
// Fire global custom event -- startEvent
this.startEvent.fire(o, args);
if(o.startEvent){
// Fire transaction custom event -- startEvent
o.startEvent.fire(o, args);
}
// Start polling if a callback is present and the timeout
// property has been defined.
if(callback && callback.timeout){
this._timeOut[o.tId] = window.setTimeout(function(){ oConn.abort(o, callback, true); }, callback.timeout);
}
// Remove HTML elements created by appendPostData
if(oElements && oElements.length > 0){
for(i=0; i < oElements.length; i++){
this._formNode.removeChild(oElements[i]);
}
}
// Restore HTML form attributes to their original
// values prior to file upload.
for(prop in rawFormAttributes){
if(YAHOO.lang.hasOwnProperty(rawFormAttributes, prop)){
if(rawFormAttributes[prop]){
this._formNode.setAttribute(prop, rawFormAttributes[prop]);
}
else{
this._formNode.removeAttribute(prop);
}
}
}
// Reset HTML form state properties.
this.resetFormState();
// Create the upload callback handler that fires when the iframe
// receives the load event. Subsequently, the event handler is detached
// and the iframe removed from the document.
uploadCallback = function() {
if(callback && callback.timeout){
window.clearTimeout(oConn._timeOut[o.tId]);
delete oConn._timeOut[o.tId];
}
// Fire global custom event -- completeEvent
oConn.completeEvent.fire(o, args);
if(o.completeEvent){
// Fire transaction custom event -- completeEvent
o.completeEvent.fire(o, args);
}
obj = {
tId : o.tId,
argument : callback.argument
};
try
{
// responseText and responseXML will be populated with the same data from the iframe.
// Since the HTTP headers cannot be read from the iframe
obj.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:io.contentWindow.document.documentElement.textContent;
obj.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;
}
catch(e){}
if(callback && callback.upload){
if(!callback.scope){
callback.upload(obj);
}
else{
callback.upload.apply(callback.scope, [obj]);
}
}
// Fire global custom event -- uploadEvent
oConn.uploadEvent.fire(obj);
if(o.uploadEvent){
// Fire transaction custom event -- uploadEvent
o.uploadEvent.fire(obj);
}
YAHOO.util.Event.removeListener(io, "load", uploadCallback);
setTimeout(
function(){
document.body.removeChild(io);
oConn.releaseObject(o);
}, 100);
};
// Bind the onload handler to the iframe to detect the file upload response.
YAHOO.util.Event.addListener(io, "load", uploadCallback);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment