Feb 2022. wsurvey.uploadFiles.js, and wsurvey.uploadFiles.php, documentation.

These functions simplify file uploads using <input type="file" ...>, and drop zones, and more.

I.       Introduction
I.a         Setup
I.b         What is "echoback"?
II.      Functions in the wsurvey.uploadFiles files
II.a        Function list -- javascript and php
II.a.1         Function list: wsurvey.uploadFiles.js
II.a.2.        Function list: wsurvey.uploadFiles.php
II.b.       Descriptions of javascript functions:
II.b.1.       wsurvey.uploadFiles.setup and vey.uploadFiles.textUpload
II.b.2        Functions to view and modify the data to be uploded
II.b.2.i.         Modifying the data to be uploaded.
II.b.3.        Other javascript functions  (submit)
II.c.       Descriptions of php functions:
II.d.       wsurvey.uploadFiles.echoback.php
III.     wsurvey.uploadFiles.setup options
III.a.        Details on callback
IV.      Simple example of useage
IV.a.       Fields in uploadData
IV.b        Uploading in pieces
V.       Contact and disclaimer

    ----------------------
I.  Introduction

wsurvey.uploadFiles is designed to make the contents of a file upload accessible to ajax, so as to give control
over sending the uploaded files to a server.

  In particular, suppose you wish to use ajax to transfer information to a php script; rather
  than using a <form>. In such a case, you will need to explicitily access the contents of a file upload.
  These functions make that easy.

  survey.uploadFiles has a number of features, including:

    * Easy specification: just specify the ids of "file upload" HTML elements, and submit, buttons.

    * Simple means of echoing a file back -- including strings created dynamically.
      And multiple files will be returned as a .zip

    * Build a list of files in several st eps, and selectively delete from this list. Or clear the entire list

    * Preview what will be sent

    * For those who want greater control, several javascript functions are available.


For an example of usage, see wsurvey.uploadFiles_demo.php.

    --------

I.a: Setup

    wsurvey.uploadFiles.js uses jquery, and uses the wsurvey.utils1.js library.
    On the server side, the php script (that contains these javascript founds)
    should include wsurvey.uploadFile.php/

  For example, in the html file (that the client links to)
     <script type="text/javascript" src="jquery-3.6.0.min"></script>
     <script type="text/javascript" src="wsurvey,utils1.js"></script>
     <script type="text/javascript" src="wsurvey.uploadFiles.js"></script>

  and in the php file that will receive the uploaded file (via a jQuery ajax call):

     require_once('wsurvey.uploadFiles.php');

   Note that the "html file" and the "php file" code are most conveniently in the same file!
   But they do not have to be.

       --------

I.b:  What is "echoback"?

  A feature of wsurvey.uploadFiles is the ease of "echoing back" content.
  "Echoing back" means the server recieves some content (i.e.; a list of uploaded files, or text strings);
  and sends them back to the server in a fashion that allows the user to save the contents as a file

  For existing files this isn't that useful. But for dynamically created strings (such as text entered into a textarea),
  this makes it easy for a user to save content to a file on his own machine.


  -----------------

II. Using the wsurvey.uploadFiles libaries

  In a .php file (or a .html file) you will call the wsurvey.uploadFiles javascript functions  -- to setup
  various html elements to read files, and upload them.

  The upload is to a .php script that uses wsurvey.uploadFiles php functions to read the uploaded files, and
  do something with them (such as an echoback)

  There is also a demo "echoback" php script that can be used as a shortcut to "echoback" a file (or files)

II.a  Function list -- javascript and php

   The javascript and php libraries are in different files. Be sure you include the correct references in
   you <script> and require() statements!

II.a.1  Function list: wsurvey.uploadFiles.js

  The main functions are
     wsurvey.uploadFiles.setup(uploadDataName,optionsArg)
  and
     wsurvey.uploadFiles.textUpload(uploadDataName,astring,mimeType,fileName,comment)

  Viewing and modifying uploadData functions:

     dastuff=wsurvey.uploadFiles.getUploadData(uploadDataName,errmess)
     dastuff=wsurvey.uploadFiles.uploadDataField(uploadDataName,afield)
     aObj= wsurvey.uploadFiles.unpackFileData(dastuff)
     aObjUpdated= wsurvey.uploadFiles.packFileData(aObjChanged)
     wsurvey.uploadFiles.updateFileData(uploadDataName,aObjUpdated)

  Submit functions:
     wsurvey.uploadFiles.submit.upload(uploadDataName,opts,otherInfo);
     wsurvey.uploadFiles.submit.uploadInPieces(uploadDataName,opts,otherInfo)
     wsurvey.uploadFiles.submit.echoback(uploadDataName,opts)
     wsurvey.uploadFiles.submit.clear(uploadDataName,noCallback)


II.a.2 :  Function list: wsurvey.uploadFiles.php

       wsurvey\uploadFiles\retrieve($attachContentName,$unpack )
       wsurvey\uploadFiles\echoBack($whichFile)
       wsurvey\uploadFiles\readSizeLimits($doPrint)
       wsurvey\uploadFiles\checkOverflow($kill)

 Per usual: if you so desire, you can use an alias for the 'wsurvey\uploadFiles' namespace coded into wsurvey.uploadFiles.php

  -----------------

II.b Descriptions of javascript functions:

  For most cases, wsurvey.uploadFiles.setup is the only function that needs to be used!

II.b.1:   wsurvey.uploadFiles.setup and  wsurvey.uploadFiles.textUpload

 wsurvey.uploadFiles.setup is the main function, and often the only one that is needed

       uploadInfo=wsurvey.uploadFiles.setup(uploadDataName,options)    .

  where:  Arguments:
    uploadDataName: a name used to store uploadData information
       Or, use a '1'  to use a default name ('wsurvey_uploadFiles_info').

       In most cases the default ('1') is recommended  -- its easier to remember!
       However, if you want to have different upload choice sets (say, using different drop zones), you can specify
       unique uploadDataNames.

        Technical notes:

          * uploadData information includes a number of jQuery objects, a list of files to be uploaded (including their encoded contents)
            and other information.  The list of files is updated as the user selects additional files.

          * uploadData is stored using $(document).data(uploadDataName).
              Thus: if you specify your own uploadDataName, be sure it does NOT conflict with an existing globals.
              We recommend using names like: 'wsurvey_uploadFiles_info_set1'

     options: optional.  If specified, an associative array that can have a number of fields.
            All of then are optional, though at least one of the "HTML upload elements" options should be specifed,
            as well as one of the "upload" options

            See below for the details
   
 wsurvey.uploadFiles.textUpload(uploadDataName,astring,mimeType,fileName,comment)

     Write a text string to the uploadData list -- the string will be uploaded as if it was a file.

        uploadDataName: must match an uploadDataName specified in setup().  Using the default ('1') makes this easy to remember!
        astring: the string to be saved. It can be text, or binary (such as a gif image)
        mimeType: the mime type. If not specified 'text/plain' is used
        fileName: name to give this file when uploading to server. If not specified, a randomName (with .txt extension) is used.
        comment: optional comment (added to data saved, but not sent to server)

     Note that this can be used to read contents of a dynamically created container, allowing the user to easily save transient results.


II.b.2  :  Functions to view and modify the data to be uploded

  These functions are used to extract, parse, and update the data that is used when uploading files
  (the data used by the .update() and .echoback() functions described below).

  dastuff= wsurvey.uploadFiles.getUploadData(uploadDataName,errmess)

       uploadDataName is a string. As described above, '1' means "use the default of 'wsurvey_uploadFiles_info'

       errmess is optional -- it is displayed if an error occurs (such as no match to uploadDataName)

       dastuff will be the contents of the uploadDataName data structure.
       dastuff will contain a number of fields, including jQuery objects (pointing to buttons, etc).

       Of greatest interest is the 'fileList' field, which contains the contents of the files to be uploaded.

       For an example of the fields in dastuff, see IV.a

       Mostly dastuff is typically used as an input into wsurvey.uploadFiles.unpackFileDat()
       or  wsurvey.uploadFiles.uploadDataField().

  dastuff=wsurvey.uploadFiles.uploadDataField(dastuff,afield)
       dastuff must be the contents of the uploadDataName data structure.
       This is usually  obtained by calling wsurvey.uploadFiles.getUploadData()

      afield is the field to extract. For example: 'fileList'

      afield='*' downloads a summary, including the current size limits (say, as retrieved from the server)

      Note that unpackFileData() is typically used to extract an easier to work with version of 'fileList'
      from dastuff


  fileDataUnpack= wsurvey.uploadFiles.unpackFileData(dastuff)
       Returns the fileList information in a array of objects

       unpackFileData is designed to use the results from calling wsurvey.uploadFiles.getUploadData()

       aList is an array, one row per file to be uploaded.
       Each row is an object with fields:
         'rowId':  this can be used to identify rows (for removal or modification)
         'crc32': a crc32 hash used by the wsurvey.uploadFiles.php functions (to validate integrity)
         'fileName': the file name (possibly random, if derived from a textarea or string)
         'fileType': the mime type
         'fileSize': in bytes (before encoding for safe transmission to the sever)
         'fileDate':  file date (the modification date) in  '2/18/2022 6:44:28 PM'  format
         'fileContent': a string containing the  file content
         'comment' : a comment
         'b64': a 'data' string, meant for internal use

  fileDataPack=wsurvey.uploadFiles.packFileData(fileDataNew)
     Create a fileData object from an "unpacked" -- and possibly modified -- fileData.
     See II.b.2.i for hints on what can be modified.

 wsurvey.uploadFiles.updateFileData(uploadDataName,fileDataPack)

    Save a (possibly updated) fileData to data storage (for the uploadDataName).
    The "uploadDataName data storage area" contains information used to upload files to a server.


 wsurvey.uploadFiles.makeSummary(uploadDataName,fileDataNew)

    If a summary was specified in setup() -- this updates the summary area.
    fileDataNew is usually a modified version of fileDataUnpack

II.b.2.i : Modifying the data to be uploaded.

 The typical useage:

  1) Obtain the full "data to upload" using:
        stuff=wsurvey.uploadFiles.getUploadData(uploadDataName,errmess)
     Typically one uses the default uploadDataName:
             stuff=wsurvey.uploadFiles.getUploadData(1,'getting data')

  2) unpack the fileData
         fileDataUnpack=wsurvey.uploadFiles.unpackFileData(stuff)
     fileData will be an array: one row per "file", each row an object. See above for details
     Note that "stuff" contains the "packed" fileData, and other fields.

  3) Create fileDataNew by changing (or removing) rows in fileDataUnpack.
     For example:
        *  remove rows that you don't want to uplaod
        *  Change the comment   (on one or more of the rows)
        *  Change the fileName or fileDate  (on one or more of the rows)

        Other changes are not recommended, such as changing the fileContent.
           If you change the fileContent, you should also change the 'fileSize' field.
           If you change the 'fileType', you8 should also appropriately change the 'b64' field.

  4) pack this changed fileData
        packed_fileData=wsurvey.uploadFiles.packFileData(fileDataNew)

  5) Save these back to the data storage (for use in uploads)
        wsurvey.uploadFiles.updateFileData(uploadDataName,packed_fileData);

    Note that the 2nd argument is the "packed" file data (not a modified version of the
    fileData).

  6) Optional: update the "summary" container using:
         wsurvey.uploadFiles.updateSummary(uploadDataName,fileDataNew)
      Note that 2nd argument is the possibly changed, but not packed, fileData

II.b.3: Other javascript functions  (submit)

  wsurvey.uploadFiles.submit.upload(uploadDataName,opts,otherInfo)

     Start uploading current selected files.
        uploadDataName: must match an uploadDataName specified in setup().
        Using the default ('1') makes this easy to remember!

        opts: optional options (in an object).  If not specified, values specified in setup() will be used

        otherInfo: other info sent to the callback. This is optional.
        See III. for discussion of callback functions used by upload.

        Valid options are:

            callback: a callback to use. If null, no change
            pathPhp : the selector to the php script that ajax will send the request to. If null, no change
            addFields: an object with other fields to send to the server -- which can be read using $_REQUEST
                       If logical false, or not an object, no other fields are added.
                       Format should be {'fieldName':'fieldVal','fieldName2':'aval2',....}
            delay: delay (in milliseconds) before uploading the files. Default is 0.
                   This is mostly used with wsurvey.uploadFiles.uploadPieces().

  wsurvey.uploadFiles.submit.uploadInPieces(uploadDataName,opts,otherInfo)
  
    Similar to wsurvey.uploadFiles.submit.upload() -- but one file at a time.
    This can get around server limits.
    There are some differences in how the callback is used -- see IV.b  for the details.


  wsurvey.uploadFiles.submit.echoback(uploadDataName,opts)

    Start an "echoback" upload of the  current selected files.
        uploadDataName: must match an uploadDataName specified in setup().  Using the default ('1') makes this easy to remember!

        opts: optional options (in an object).  If not specified, values specified in setup() will be used

        Valid options are:
          'pathPhp' : the selector to the php script that ajax will send the request to.
                   If  not specified, or null, use  the pathPhpEchoback  specified in setup(),

          'whichFile': nth' file to echo (if more than one file).
                 If  not specified, or null,, use the value specified with pathPhpEchoback
                 0 means "return all files in a .zip"

                 Note that if nothing is specified pathPhpEchoback, a value of 0 is used

                 Be aware that 'nth' is somewhat arbitrary (it depends on order of selection , and post selection processing).

          'addFields': an object with other fields to send to the server -- which can be read using $_REQUEST
                       If logical false, or not an object, no other fields are added.
                     Format should be {'fieldName':'fieldVal','fieldName2':'aval2',....}

       Hint: the wsurvey.uploadFile.echoback.php (in the same examples directory) is a simple php script that will echoback
             the files sent by the client.


  wsurvey.uploadFiles.submit.clear(uploadDataName,noCallback)

        uploadDataName: must match an uploadDataName specified in setup().  Using the default ('1') makes this easy to remember!
        noCallback : if false, then do NOT call a callbackClear function (that can be specified in setup()

  -----------------

II.c:  Descriptions of php functions:

 Per usual: if you so desire, you can use an alias for the 'wsurvey\uploadFiles' namespace coded into wsurvey.uploadFiles.php
 Thus, if you start your php program with
         use \wsurvey\uploadFiles as upl
 then you could call these functions as
    upl\funcName(args)
 rather than
   wsurvey\uploadFiles\funcName(args)


  wsurvey\uploadFiles\retrieve($unpack )
     Retrieve stuff uploadec by wsurvey.uploadFile.js functions (such as .upload() and .echoback().

     The default (unpack=1) : an array, one row per file. Each row an object with fields:
        'fileContent' : content of file in a string (binary, if a binary file)
        'fileName': name of file
        'fileType': mime type of file
        'fileDate': modification date of file ('1/21/2020 10:44:44 AM')
        'fileSize': size of files (bytes

     If unpack=0, the raw string (crlf's between files; ' between fields) is returned.

    wsurvey\uploadFiles\checkOverflow($kill)
       Check if for an overflow condition: the size of the request (the content uploaded) exceeds the server limit.
       This can happen if a too large value of post_max_size is used.
       If this happens, the server will see nothing in the content. Which may lead to unexpected results -- such as
       redisplay of the html content, rather than processing of the uploaded files. 
       
       Calling checkOverFlow checks for this condition. If detected, a simple error message is returned to the client.
       Which tends to have fewer bad effects!

       $kill=1 (the default) returns the error message and exits.
       $kill=0 returns a true/false (false if NOT overflow). The caller (say, in the root php program) can then decide
       what to do.
       
       To repeat: if the content is too large, nothing will be available to retrieve (and other functions).
       That is: the content is NOT truncated -- it is empty.
       
       We recommend calling checkOverflow as the FIRST thing the php script does!
       
       Note that if your server limits are correct,  wsurvey.uploadFiles should NEVER try to upload content that is too large.
       But calling checkOverflow is a simple and quick double check!


   wsurvey\uploadFiles\echoBack($whichFile=0)
       Do an echoback using content uploaded from the client.
       The default (whichFile=0) means "make a zip file if more than one file"
       If whichFile>0, get that file.
       If whichFile> # files, get the last file.
       If only one file, whichFile is ignored.

 wsurvey\uploadFiles\readSizeLimits($doPrint=1)
      Return a string that of "javascript var definitions" of the various server side memory limits:
        *  upload_max_filesize: maximum size (in bytes) of any file BEFORE being processed for upload (base64 procssing adds about 30%).
        *  post_max_size: server limits on total bytes to upload (all files combined, plus ancillary information).
        *  memory_limit: server limits on total bytes to upload (all files combined, plus ancillary information).
     doPrint=0 just returns a string containing these javascript var statemetns.
     doPrint=1 also prints them.

     The default (doPrint=1) mode is designed to make it easy to set the memory limits.

        <script type="text/javascript">

         <?php
            \wsurvey\uploadFiles\readSizeLimits(1);
         ?>
         window.onload=init ;

         function init(evt)  { //
            // call wsurvey.uploadFiles.setup()
         }

    This will create the above variables (as javascript globals that .setup() can read), using the server's actual settings.
    Note that these will be created using integer values  -- so a server setting of "8M" becomes 8388608

  -----------------

II.d :  wsurvey.uploadFiles.echoback.php

 wsurvey.uploadFiles.echoback.php is a short file that can be used as a shortcut when echoing back a file (or files).
 To use it, set a 'pathPhp' value, or 'pathPhpEchoback'  (in setup()) to point to its location.
 You might have to change the "require" statement in it to point to wsurvey.uploadFiles.php

 In pathPhpEchoback you can specify which of the files to echoback. The default is "all of them" (in .zip file).
 See description of pathPhpEchoback in section III.


  -----------------

III.: wsurvey.uploadFiles.setup() options

  There are several flavors of options.

    Selecting files (or strings) options.
    The values of these options should be the string id of an html element, or a jQuery or dom object pointing to an html element.

      *   button : an "<input file=""> button -- uses "select from a directory"
      *   drop :  the "drop zone element" (such as a div). Drag and drop files to be uploaed
      *   textarea : uses a textarea to upload a string entered by the user (or saved to it by a javascript function).

    Uploading the contents of the selected files options:
       The values of these options should be the string id of an html element, or a jQuery or dom object pointing to an html element.

      * submit:  the "submit" button - click this to send the chosen files to the server
      * echoback:  the "submit for echoback" button - click this to send the chosen files to the server, to be echoed back.

    Summary and other display options:
       The values of these options should be the string id of an html element, or a jQuery or dom object pointing to an html element.

      *  summary: a  "display currently chosen files" area (such as a <div> placed near the 'button')
               Special value: '1' means "create one and place it next to one of the above"
               As files are selected, a short summary (file name, size, date) is written to this summary area.
               And -- a 'remove this entry" button is also written for each file.
               Thus; the user can remove accidentally chosen files, without having to clear all the files.

      *  clear:  typically a button. When clicked,  clear the summary, reset the select files  HTML elements, and remove all uploadFile data.

   Limit options:

      These specify server limits. If not specified, a global variable may be used. If no global variable, the limit is ignored.
      See below for a note on a recommended method of setting these (using actual server limits)

      *  maxFiles : maximum number of files that can be chosen for upload. Error messages are shown if this exceeeded. 25 is the default
      *  upload_max_filesize: maximum size (in bytes) of any file BEFORE being processed for upload (base64 procssing adds about 30%).
      *  post_max_size: server limits on total bytes to upload (all files combined, plus ancillary information).
      *  memory_limit: server limits on total bytes to upload (all files combined, plus ancillary information).

  Action options:

     *   pathPhp : a selector pointing to the php file that will recieve the uploaded file information (either from upload, textarea, or button)
             Default is '' -- ajax will send the request to the html/php file that is calling .setup()

     *   pathPhpEchoback : a selector pointing to the php file that to use in echoback.
          If not specified, the pathPhp is used.
          If specified, the syntax is:
             pathPhpEchoback : 'phpPath whichFile'
             For example
             Examples:
                   '/wsurvey/wsurvey.lib/examples/wsurvey.uploadFiles.echoback.php 0'
                or
                   '/wsurvey/wsurvey.lib/examples/wsurvey.uploadFiles.echoback.php '
                will echoback all files (as a .zip file)

                   '/wsurvey/wsurvey.lib/examples/wsurvey.uploadFiles.echoback.php 2'
                will echoback the 2nd one.

                Note that if there is only one file uploaded, whichBack is ignored.

             or

     *  pathPhpEchoback : used after a successful ajax request by upload (not used by echoback).
               Default is minimal --  upon recieving a response from the server, write a short "success" message to client.log()

     *  callback: function called after files after completion of a file upload.
        The default is no callback -- though a simple status message will be written toi console.log().
        See below for details.

     *  callbackClear: used after a  setFuncs.clear() -- optional function to call (that could clear custom elements)
                 Will be called with the evt supplied by jQuery evt (due to a click on the 'clear' element)
                 Default is no callback

     *  echoback_auto:  space delimited list of eventElements that cause an auto echoback:
           Values in the list can be: textarea, button, or drop
           If one of these html elements are processed, and it is in the echoback_auto list -- the echoback will occur immediately.
           That is: the submit button does NOT need to be clicked!
           Thus: if echoback_auto='drop', then dropping a file into a drop zone will cause an immediate ajax request to the 'php' script

     * upload_auto:  same as echoback_auto, but contrls auto-upload (using the php and callback specified)


  Notes:

   * If specified, three global parameters are used (if their respective fields are not set in options):
       wsurvey_uploadFiles_upload_max_filesize, wsurvey_uploadFiles_post_max_size, and wsurvey_uploadFiles_memory_limit

      Rather than specifying these (upload_max_filesize, post_max_size, and  memory_limit) in opts, we recommend reading
      these form the server.  See the discussion of wsurvey\uploadFiles\readSizeLimits (in II.c) for the details

  *  While adding files to the uploadData list,
     If any of these limits are violated, a warning message appears that the user must affirm (if not, the select files are not
     added to the uploadData list). Or, if a max_file_size, or maxFiles, is violated -- the summary will note that "this file
     was not included in the list".

III.a   Details on callback

   After uploading files to a server, a specified callback function can be called.
   This callback be specified using the 'callback' option in .setup().
   Or it can be explictily specified  the opts of a .upload(...) call.

   In either case, callback should be a function, or a string name of a function.

   Upon completion of an upload the callback is called as:
      callback(response,stuff0,tstatus,ajx,otherInfo);

   where:
     response : response from server
     stuff0 : the uploadData -- as obtained using stuff0=wsurvey.uploadFiles.getUploadData(upDateName) ;
     tstatus: status variable supplied by ajax (upon return)
     ajx    :  xhr variable supplied by ajax (upon return)
     otherInfo : otherInfo variable.

         otherInfo is false if upload was due to a click on a 'submit' button.
         otherInfo can be anything if wsurvey.uploadFiles.upload(uploadDataName,opts,otherInfo) was used.


   -----------------

IV.  Simple example of useage

  For a more complete example, see wsurvey.uploadFiles_demo.php.

<?php
     require_once('wsurvey.uploadFiles.php');
     $todo=wsurvey\uploadFiles\extractRequestVar('wsurvey_uploadFiles_action','');

        if ($todo=='upload')  {
            $fileList=wsurvey\uploadFiles\retrieve(1);
            print "# of files uploaded=".count($fileList);
            exit;
        }
?>

<!DOCTYPE html>
<html>
 <head><title>Test file upload</title>
   <meta charset="utf-8">

  <script type="text/javascript" src="jquery-3.6.0.min"></script>
  <script type="text/javascript" src="wsurvey.utils1.js"></script>
  <script type="text/javascript" src="wsurvey.uploadFiles.js"></script>

  <script type="text/javascript">
       <?php
          \wsurvey\uploadFiles\readSizeLimits(1);
      ?>
      window.onload=init ;

      function init(evt)  {            // adds event handlers to read submitted files, buttons to upload these files, ...
           let opts={'button':'readFiles',
                  'submit':'uploadNow',
                  'clear':'clearButton',
                  'summary':'1',
                  'callback':myCallback} ;
           wsurvey.uploadFiles.setup(1,opts);
       }
       function myCallback(data,stuff,tstatus,xhr) {  // alert a simple response from the server
           alert('Response from server: ' +data);
       }
   </script>
 </head>
 <body>
   Test of uploadFiles <br>
     <input type="file"    id="readFiles"  multiple="multiple"  title="Chose  files to upload"  >
     <input type="button"  id="uploadNow" value="Upload the file(s)!"  title="Upload the chosen files"  >
     <input type="button"  id="clearButton" value="clear" title="clear uploaded file information   ">
 </body>
</html>

   -----------------

IV.a : Fields in uploadData

The following is an example of the fields in the 'uploadData' object -- that is returned by
wsurvey.uploadFiles.uploadDataField(stuff,'*')

   drop:  string(15): "object  jQuery "
   button:  string(15): "object  jQuery "
   textarea:  string(15): "object  jQuery "
   summary:  string(15): "object  jQuery "
   submit:  string(15): "object  jQuery "
   echoback:  string(15): "object  jQuery "
   clear:  string(15): "object  jQuery "
   uploadDataName:  string(44): "string  24 bytes == wsurvey_uploadFiles_info"
   upload_auto:  string(9): "object   "
   echoback_auto:  string(9): "object   "
   pathPhp:  string(19): "string  0 bytes == "
   pathPhpEchoback:  string(19): "string  0 bytes == "
   pathPhpEchoback_which:  string(8): "number 0"
   callback:  string(9): "function "
   callbackClear:  string(9): "function "
   upload_max_filesize:  string(14): "number 2097152"
   post_max_size:  string(14): "number 8388608"
   memory_limit:  string(17): "number 1342177280"
   maxFiles:  string(9): "number 25"
   nfiles:  string(8): "number 9"
   totBytes:  string(14): "number 3927289"
   fileData:  string(9): "object   "

 Note that 'uploadDataName' contains the location (in $(document).data()) this information is stored.
 While seemingly redundant, it can be useful when calling functions with stuff as an argument --
 it tell the recieving function "where this came from, and where it should be stored".
 
    -----------------

IV.b   Uploading in pieces

  If there are a lot of files, or the size of the files is large, it may be beneficial to upload them
  in several seperate uploads.  wsurvey.uploadFiles.uploadPieces() make this a fairly easy.

  wsurvey.uploadFiles.uploadPieces() is similar to  wsurvey.uploadFiles.upload() -- it should
  be called from  sjavascript function that handles a click (or other event).
  And, it will work with whatever files (or strings) have been selected.

  wsurvey.uploadFiles.submit.uploadInPieces() is called :

     wsurvey.uploadFiles.submit.uploadInPieces(uploadDataName,opts,otherInfo);

  opts can have the same fields as in upload(). In particular:
  
    *  The callback SHOULD point to a function that can handle multiple calls in a row.
       That is: that can display status information as new uploads are completed.
    *  addFields should contain a field that alerts the php that this is a "one-at-a-time" upload.
       Note that .uploadInPieces and .upload send a "action=upload" (that can be ready by $_REQUEST).
    *  You might want to set delay to be a small value (say, 50) -- the default is 100.

  Notes:

     * in the .setup() opts, set maxFiles, post_max_size, and memory_limit to false --
       you do NOT want the various .setFuncs. functions to be performing these "all at once"
       limit tests. However, upload_max_filesize should be the server's maximum.

    * As with .upload, the callback is called as:

            ocallback(response,stuff,tstatus,xhr,otherInfo)

    * There is a a difference: a few fields are few fields are added to otherInfo. 
      The callback can use these to report information (along with the server response):

      The most relevant fields are:
       otherInfo['wsurveyUploadFiles_justDone']-- file just uploaded (starting at 0)
       otherInfo['wsurveyUploadFiles_nTodo']   -- total number to do (the number of files)

       Thus, when nextTodo=nTodo-1, all files have been processed.

IV.b.1 Pausing and stopping

   one-at-atime processing can be paused, resumed, or aborted, using calls to
   wsurvey.uploadFiles.submit.uploadInPieces.
   These are typically done by the 'one-at-a-time' callback.

       wsurvey.uploadFiles.submit.uploadInPieces(action,stuff,otherInfo)

  where action can be:
     'pause' : pause the uploads.
     'stop'  : stop uploads (and reset the uploadData)
     'resume' : resume after a pause.

   For 'pause' and 'stop': stuff and otherInfo are the 2nd and 5th arguments sent to the callback

   For 'resume': stuff should be the uploadDataName (such as '1', if using the default),
   and otherInfo is ignored. For example:
           wsurvey.uploadFiles.submit.uploadInPieces('resume',1);


V. Contact and disclaimer

Contact: Daniel Hellerstein. danielh@crosslink.net.
       http://www.wsurvey.org/distrib, or  https://github.com/dHellerstein

Disclaimer:

    wsurvey.uploadFiles is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    wsurvey.uploadFiles is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    If you did not receive a copy of the GNU General Public License,
    see <http://www.gnu.org/licenses/>.
