ICEfaces
  1. ICEfaces
  2. ICE-2860

InputFile IFRAME render sync mode update javascript

    Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.7Beta1
    • Fix Version/s: 1.7.1
    • Component/s: ICE-Components
    • Labels:
      None
    • Environment:
      All

      Description

      Right now the InputFile component renders out an IFRAME tag with a src attribute which consists of a Javascript call do document.write() with the contents of the IFRAME. This IFRAME rendering code, in InputFile.renderIFrame(-), is invoked by both the InputFileRenderer, whenever the page renders, and also by UploadServer, once the file has completed uploading.

      In synchronous mode, the InputFile.progressListener -> Bean -> OnDemandRenderer calls, and the InputFile -> PersistentFacesState.renderLater() call are both mostly useless, since they have no means to push those renders to the client.

      The only thing that is being sent to the client, is the UploadServer response, in the form of the InputFile.renderIFrame(-). If this code could be adapted, to notify the web browser to initiate an update from its end, then we could get file upload completion notification, in synchronous mode. Possibly, with multi-part MIME, we could even get file upload progress notification.

      Mircea says that because of security constraints in the web browser, we can't just render our javascript, to be executed from the IFRAME, to get the whole page's bridge to cause an update. Especially if using SSL. But, the IFRAME response could set a cookie, and the bridge could watch this cookie, and check for updates, based on it, much like how the receive-updated-views protocol works.

      Of course it would be simpler to just have the UI for the progress and completion right inside the IFRAME itself, and not have to use the cookie trick. But there might be arbitrarily numerous changes to the UI, so that might not be feasible.

        Issue Links

          Activity

          Hide
          Mark Collette added a comment -

          From our meeting:

          There are several Javascript techniques that Mircea will look into, so that the whole view can be notified.

          We'll investigate if we can get progress notifications, to support using a determinate progress bar. If not, then investigate getting begin upload [and the aforementioned finish upload] notifications, to support using an indeterminate progress bar.

          We won't be doing PersistentFacesState.renderLater() anymore, but will just have the IFRAME file upload POST response trigger the browser to initiate a full [partial?] submit of the inputFile's form, which will do the typical lifecycle and DOM updates.

          That should keep synchronous and asynchronous mode more similar, and simplify issues for Seam, Acegi, Spring, etc.

          Will have to decide what happens when the form validates, but the file upload fails, and when the form doesn't validate, but the file upload succeeded. Without unnecessarily throwing out the uploaded file.

          In that lifecycle is when the inputFile should be doing its success/fail FacesMessages, ActionEvent, etc. This is opposed to now, where it does all that from the UploadServer request handling method, which involves accessing beans outside of a lifecycle, which Seam does not like.

          For Seam, if at all possible, when the inputFile is rendered from a lifecycle, it will evaluate all necessary ValueBindings, and cache the values, so that when the UploadServer is accepting the file, it will just take those values from the component, and not access any beans.

          Ideas after the meeting:

          For the progressListener, we should consider executing a lifecycle, and then just queuing some ProgressListener event, to be broadcast at the right phase. This would be an incompatible change, that inverts how the progressListener works, since it right now is called outside of a lifecycle, and the bean code uses the RenderManager. Maybe add an attribute like progressExecuteLifecycle (Boolean), or something where you was a reference to the RanderManager/OnDemandRenderer.

          And a criterion attribute for how much progress should trigger a lifecycle. Something that could either be a percent or a time, so you could update for every 10% step, or every 5 seconds, or whichever comes first, or last.

          Show
          Mark Collette added a comment - From our meeting: There are several Javascript techniques that Mircea will look into, so that the whole view can be notified. We'll investigate if we can get progress notifications, to support using a determinate progress bar. If not, then investigate getting begin upload [and the aforementioned finish upload] notifications, to support using an indeterminate progress bar. We won't be doing PersistentFacesState.renderLater() anymore, but will just have the IFRAME file upload POST response trigger the browser to initiate a full [partial?] submit of the inputFile's form, which will do the typical lifecycle and DOM updates. That should keep synchronous and asynchronous mode more similar, and simplify issues for Seam, Acegi, Spring, etc. Will have to decide what happens when the form validates, but the file upload fails, and when the form doesn't validate, but the file upload succeeded. Without unnecessarily throwing out the uploaded file. In that lifecycle is when the inputFile should be doing its success/fail FacesMessages, ActionEvent, etc. This is opposed to now, where it does all that from the UploadServer request handling method, which involves accessing beans outside of a lifecycle, which Seam does not like. For Seam, if at all possible, when the inputFile is rendered from a lifecycle, it will evaluate all necessary ValueBindings, and cache the values, so that when the UploadServer is accepting the file, it will just take those values from the component, and not access any beans. Ideas after the meeting: For the progressListener, we should consider executing a lifecycle, and then just queuing some ProgressListener event, to be broadcast at the right phase. This would be an incompatible change, that inverts how the progressListener works, since it right now is called outside of a lifecycle, and the bean code uses the RenderManager. Maybe add an attribute like progressExecuteLifecycle (Boolean), or something where you was a reference to the RanderManager/OnDemandRenderer. And a criterion attribute for how much progress should trigger a lifecycle. Something that could either be a percent or a time, so you could update for every 10% step, or every 5 seconds, or whichever comes first, or last.
          Hide
          Mircea Toma added a comment -

          Trigger form submit on upload completion.

          Show
          Mircea Toma added a comment - Trigger form submit on upload completion.
          Hide
          Mircea Toma added a comment -

          Trigger form submit at the start of the upload as well.

          Show
          Mircea Toma added a comment - Trigger form submit at the start of the upload as well.
          Hide
          Mark Collette added a comment -

          We need the inputFile form submissions to pass info back to the server, so that the inputFile component can tell that it caused the submission, so it can fire off its progressListener, which will allow for controlling an indeterminant progress bar.

          Show
          Mark Collette added a comment - We need the inputFile form submissions to pass info back to the server, so that the inputFile component can tell that it caused the submission, so it can fire off its progressListener, which will allow for controlling an indeterminant progress bar.
          Hide
          Mark Collette added a comment -

          Now the javascript bridge includes information, in the pre-upload form post, and the post-upload form post, so that the inputFile component can broadcast progress events to the progress listener at those times. Two boolean fields have been added to the FileInfo datastructure that the progressListener can get from the InputFile, to be able to detect if it's the pre-upload, post-upload, or regular progress event.

          Here's how you would use the indeterminate progress bar in synchronous mode:

          <ice:inputFile progressListener="#

          {bean.fileUploadProgress}

          "/>
          <ice:outputProgress indeterminate="true" value="#

          {bean.inProgress}

          "/>

          public void fileUploadProgress(EventObject event)

          { InputFile ifile = (InputFile) event.getSource(); if (ifile.getFileInfo().isPreUpload()) inProgress = 1; if (ifile.getFileInfo().isPostUpload()) inProgress = 0; }

          public int getInProgress()

          { return inProgress; }

          private int inProgress = 0;

          TRUNK
          Subversion 16799
          icefaces\bridge\src\submit.js
          icefaces\component\src\com\icesoft\faces\component\inputfile\FileInfo.java
          icefaces\component\src\com\icesoft\faces\component\inputfile\InputFile.java
          icefaces\component\src\com\icesoft\faces\component\inputfile\InputFileRenderer.java
          icefaces\component\src\com\icesoft\faces\component\inputfile\InputFileProgressEvent.java
          icefaces\samples\component-showcase\common-web\WEB-INF\includes\examples\custom\inputFile.jspx

          ICEfaces 1.7 branch
          Subversion 16800
          icefaces\bridge\src\submit.js
          icefaces\component\src\com\icesoft\faces\component\inputfile\FileInfo.java
          icefaces\component\src\com\icesoft\faces\component\inputfile\InputFile.java
          icefaces\component\src\com\icesoft\faces\component\inputfile\InputFileRenderer.java
          icefaces\component\src\com\icesoft\faces\component\inputfile\InputFileProgressEvent.java
          icefaces\samples\component-showcase\common-web\WEB-INF\includes\examples\custom\inputFile.jspx

          Show
          Mark Collette added a comment - Now the javascript bridge includes information, in the pre-upload form post, and the post-upload form post, so that the inputFile component can broadcast progress events to the progress listener at those times. Two boolean fields have been added to the FileInfo datastructure that the progressListener can get from the InputFile, to be able to detect if it's the pre-upload, post-upload, or regular progress event. Here's how you would use the indeterminate progress bar in synchronous mode: <ice:inputFile progressListener="# {bean.fileUploadProgress} "/> <ice:outputProgress indeterminate="true" value="# {bean.inProgress} "/> public void fileUploadProgress(EventObject event) { InputFile ifile = (InputFile) event.getSource(); if (ifile.getFileInfo().isPreUpload()) inProgress = 1; if (ifile.getFileInfo().isPostUpload()) inProgress = 0; } public int getInProgress() { return inProgress; } private int inProgress = 0; TRUNK Subversion 16799 icefaces\bridge\src\submit.js icefaces\component\src\com\icesoft\faces\component\inputfile\FileInfo.java icefaces\component\src\com\icesoft\faces\component\inputfile\InputFile.java icefaces\component\src\com\icesoft\faces\component\inputfile\InputFileRenderer.java icefaces\component\src\com\icesoft\faces\component\inputfile\InputFileProgressEvent.java icefaces\samples\component-showcase\common-web\WEB-INF\includes\examples\custom\inputFile.jspx ICEfaces 1.7 branch Subversion 16800 icefaces\bridge\src\submit.js icefaces\component\src\com\icesoft\faces\component\inputfile\FileInfo.java icefaces\component\src\com\icesoft\faces\component\inputfile\InputFile.java icefaces\component\src\com\icesoft\faces\component\inputfile\InputFileRenderer.java icefaces\component\src\com\icesoft\faces\component\inputfile\InputFileProgressEvent.java icefaces\samples\component-showcase\common-web\WEB-INF\includes\examples\custom\inputFile.jspx
          Hide
          Mark Collette added a comment -

          We should probably add this synchronous mode / indeterminate progress code as an example / tutorial, linked to from the component-showcase (Facelets enhanced).

          Also, it might be good to document somewhere, at least in the change section of the release notes, this new behaviour of doing the pre-upload and post-upload form submissions.

          Show
          Mark Collette added a comment - We should probably add this synchronous mode / indeterminate progress code as an example / tutorial, linked to from the component-showcase (Facelets enhanced). Also, it might be good to document somewhere, at least in the change section of the release notes, this new behaviour of doing the pre-upload and post-upload form submissions.
          Hide
          Mark Collette added a comment -

          Since ICE-3122, you have to set submitOnUpload="preAndPostUpload" in the <ice:inputFile> tag, for this to work.

          Show
          Mark Collette added a comment - Since ICE-3122 , you have to set submitOnUpload="preAndPostUpload" in the <ice:inputFile> tag, for this to work.

            People

            • Assignee:
              Unassigned
              Reporter:
              Mark Collette
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: