<< ADD DESCRIPTION HERE http://java.net/jira/browse/JAVASERVERFACES-XXXX >> SECTION: Modified Files ---------------------------- M jsf-api/src/main/resources/jsf.js M jsf-ri/src/main/java/com/sun/faces/context/PartialViewContextImpl.java SECTION: Diffs ---------------------------- Index: jsf-api/src/main/resources/jsf.js =================================================================== --- jsf-api/src/main/resources/jsf.js (revision 9286) +++ jsf-api/src/main/resources/jsf.js (working copy) @@ -1337,6 +1337,163 @@ return req; }; + var IframeEngine = function(context) { + var req = { + FRAME_ID: 'mojarra_ajax_iframe', + frame: false, + context: context + }; + + req._createIframe = function() { + var frame = document.getElementById(this.FRAME_ID); + if (!frame) { + if (isIE()) { + raise ("create iframe for IE"); + } else { + frame = this.createElement(document.body, 'iframe', { + src: 'about:blank', + id: this.FRAME_ID, + name: this.FRAME_ID, + type: "content", + collapsed: true, + style: 'display:none' + }); + } + } + + return frame; + }; + + req.onload = function() { + var document = this.frame.contentWindow.document || this.frame.contentDocument || this.frame.document; + var body = document.body || document.documentElement ; + var request = {}; + try { + request.responseText = this.frame.innerHTML; + request.responseXML = document; + request.readyState = 4; + + // assume the best for now + request.status = 201; + jsf.ajax.response(request, this.context); + } catch (e) { + } finally { + // TODO: remove the iframe? + } + } + + req.createElement = function(parent, type, attrs) { + var el = document.createElement(type); + + for (key in attrs) { + el[key] = attrs[key]; + } + + parent.appendChild(el); + + return el; + } + + req.addAjaxParameters = function(form, args) { + this.createElement(form, "input", {name: 'Faces-Request', value:'partial/ajax'}); + this.createElement(form, "input", {id: 'javax.faces.partial.execute', name: 'javax.faces.partial.execute', value: args["javax.faces.partial.execute"]}); + this.createElement(form, "input", {id: 'javax.faces.partial.render', name: 'javax.faces.partial.render', value: args["javax.faces.partial.render"]}); + this.createElement(form, "input", {id: 'javax.faces.partial.ajax', name: 'javax.faces.partial.ajax', value: args["javax.faces.partial.ajax"]}); + this.createElement(form, "input", {id: 'javax.faces.partial.event', name: 'javax.faces.partial.event', value: args["javax.faces.partial.event"]}); + this.createElement(form, "input", {id: 'javax.faces.behavior.event', name: 'javax.faces.behavior.event', value: args["javax.faces.behavior.event"]}); + this.createElement(form, "input", {id: 'javax.faces.source', name: 'javax.faces.source', value: args["javax.faces.source"]}); + } + + req.removeAjaxParameters = function() { + + } + + req.sendRequest = function(form, args) { + this.frame = this._createIframe(); + + if (!isIE()) { + this.frame.onload = this.hitch(this, this.onload); + } else { + this.frame.onload_IE = this.hitch(this, this.onload); + } + + var saveTarget = form.target; + var saveMethod = form.method; + + try { + this.addAjaxParameters(form, args); + form.target = this.frame.name; + form.method = "POST"; + form.submit(); + } finally { + this.removeAjaxParameters(saveTarget); + form.target = saveTarget; + form.method = saveMethod; + } + } + + // Taken from MyFaces, which was taken from dojo. May need to rewrite + req.hitch = function(/*Object*/scope, /*Function|String*/method /*,...*/) { + // summary: + // Returns a function that will only ever execute in the a given scope. + // This allows for easy use of object member functions + // in callbacks and other places in which the "this" keyword may + // otherwise not reference the expected scope. + // Any number of default positional arguments may be passed as parameters + // beyond "method". + // Each of these values will be used to "placehold" (similar to curry) + // for the hitched function. + // scope: + // The scope to use when method executes. If method is a string, + // scope is also the object containing method. + // method: + // A function to be hitched to scope, or the name of the method in + // scope to be hitched. + // example: + // | myfaces._impl._util._Lang.hitch(foo, "bar")(); + // runs foo.bar() in the scope of foo + // example: + // | myfaces._impl._util._Lang.hitch(foo, myFunction); + // returns a function that runs myFunction in the scope of foo + if (arguments.length > 2) { + return this._hitchArgs._hitchArgs.apply(this._hitchArgs, arguments); // Function + } + if (!method) { + method = scope; + scope = null; + } + if (typeof method === 'string') { + scope = scope || window || function() { + }; + /*since we do not have dojo global*/ + if (!scope[method]) { + throw('error'); + } + return function() { + return scope[method].apply(scope, arguments || []); + }; // Function + } + return !scope ? method : function() { + return method.apply(scope, arguments || []); + }; // Function + } + + req._hitchArgs = function(scope, method /*,...*/) { + var pre = this.objToArray(arguments, 2); + var named = this.isString(method); + return function() { + // array-fy arguments + var args = this.objToArray(arguments); + // locate our method + var f = named ? (scope || this.global)[method] : method; + // invoke with collected args + return f && f.apply(scope || this, pre.concat(args)); // mixed + }; // Function + } + + return req; + + } /** * Error handling callback. * Assumes that the request has completed. @@ -1819,15 +1976,24 @@ args["url"] = encodedUrlField.value; } - var ajaxEngine = new AjaxEngine(); - ajaxEngine.setupArguments(args); - ajaxEngine.queryString = viewState; - ajaxEngine.context.onevent = onevent; - ajaxEngine.context.onerror = onerror; - ajaxEngine.context.sourceid = element.id; - ajaxEngine.context.formid = form.id; - ajaxEngine.context.render = args["javax.faces.partial.render"]; - ajaxEngine.sendRequest(); + var context = { + onevent : onevent, + onerror : onerror, + sourceid : element.id, + formid : form.id, + render : args["javax.faces.partial.render"] + } + if (form.encoding == "multipart/form-data") { + var iframeEngine = new IframeEngine(context); + iframeEngine.sendRequest(form, args); + } else { + var ajaxEngine = new AjaxEngine(); + ajaxEngine.setupArguments(args); + ajaxEngine.queryString = viewState; + ajaxEngine.context = context; + + ajaxEngine.sendRequest(); + } // null out element variables to protect against IE memory leak element = null; Index: jsf-ri/src/main/java/com/sun/faces/context/PartialViewContextImpl.java =================================================================== --- jsf-ri/src/main/java/com/sun/faces/context/PartialViewContextImpl.java (revision 9286) +++ jsf-ri/src/main/java/com/sun/faces/context/PartialViewContextImpl.java (working copy) @@ -107,8 +107,11 @@ assertNotReleased(); updateFacesContext(); if (ajaxRequest == null) { - ajaxRequest = "partial/ajax".equals(ctx. - getExternalContext().getRequestHeaderMap().get("Faces-Request")); + System.out.println("******* BLARGH!!!!!!"); + final ExternalContext externalContext = ctx.getExternalContext(); + ajaxRequest = + "partial/ajax".equals(externalContext.getRequestHeaderMap().get("Faces-Request")) || + "partial/ajax".equals(externalContext.getRequestParameterMap().get("Faces-Request")); } return ajaxRequest; @@ -122,9 +125,10 @@ assertNotReleased(); if (partialRequest == null) { + final ExternalContext externalContext = ctx.getExternalContext(); partialRequest = isAjaxRequest() || - "partial/process".equals(ctx. - getExternalContext().getRequestHeaderMap().get("Faces-Request")); + "partial/process".equals(externalContext.getRequestHeaderMap().get("Faces-Request")) || + "partial/process".equals(externalContext.getRequestParameterMap().get("Faces-Request")); } return partialRequest;