Feb 2022

wsurvey.getJson .js (and .php) library

These functions -- in wsurvey.getJson.js and wsurvey.getJson.php --  implement an ajax requester for retrieving json'ized arrays
returned by a .php program running on a server. Their main strength is integrated error handling. And a fairly simple interface.

    Basically, this is a front and back end for $.ajax(...)

 The javascript functions are:
     wsurvey.getJson.get :  Make a 'json' request to the server, naming a php program to use -- and specifying a .js callback

     wsurvey.getJson.check. Used by the callback to validate and parse stuff returned from server

     wsurvey.getJson.setErrFunc:  sets a function for displaying error messages. If not specified, alert() is used.

And an optional variable:
    wsurvey.getJson.prePend :  a string to prepend to urls specified in wsurvey.getJson.get. This does NOT have to be set.


 The php functions are:

        wSurvey\getJson\readVar: read a requeat variable 

        wSurvey\getJson\jsonReturn: return an associative array, with various fields, to the requester.
        Which can be examined and validated by  wsurvey.getJson.check().

        wSurvey\getJson\jsonReturnContent: short cut of jsonReturn --
        return an associative array, with 'error' and 'content' field.

        wSurvey\getJson\jsonReturnError: force an "error return", that contain various status messages

   Note that the 'wSurvey\getJson` "php namespace" is hard coded into wsurvey.getJson.php.
   We generally use an alias.  
   For example:  the .php file contains:
                     use wSurvey\getJson as getJs  ;
                  and we use 
                     getJs\jsonReturn(...)

Function description, Javascript:

 wsurvey.getJson.get(aurl,adata,acallback,errMess1)
      where:
        aurl: url to the php program that will form the response.  Or, a [aurl,method] array
        adata: an object. Its fields will be accessible to the .php program using $_REQUEST -- with arrays & objects read  as arrays & objects.
        acallback: function to call when response is recieved from server.  Or a  [acallback,otherArgs] array
                   See the "How is the javascript callback called" section for details.
        errMess1: an optional message displayed if  there is a problem

    Notes:
      *  Despite the name of this function, a "POST" request is sent to the server.
         If you want some other kind of request ("GET", or "HEAD"):  aurl should be a two element array:
              aurl=[aurl,method]
         For example:
              wsurvey.getJson.get(['myServerProg.php','GET'],{'todo':'step1'},doStep1,'the first call')

         Note that aurl will be relative to the calling javascript function

   *   the wsurvey.getJson.prePend variable  will modify the aurl.
       If  wsurvey.getJson.prePend is not '', and the first character in aurl is not ' ', then wsurvey.getJson.prePend is prepended to the url
       By default, wsurvey.getJson.prePend='' -- so no prepending occurs. It can be  directly set anytime after   wsurvey.getJson.js is loaded

       Example:
   	   wsurvey.getJson.prePend='src/';
           wsurvey.getJson.get('myPhpFuncs.php',{'quantity':10},postPhp1,'test call')
       Then wsurvey.getJson.get will make an ajax request to:
          src/myPhpFuncs.php
       To prevent this conversion, start the url with a ' '. Thus:
           wsurvey.getJson.get(' genericPhp.php',{'quantity2':10},postPhp1,'test call2')
        would yield:
             'genericPhp.php'  -- note that spaces have been trimmed.
          
    *   adata can contain indices that are send to the server, but are not used.

        As noted below, all the arguments in adata can be accessed by the callback

    *   acallback should be function reference, or a string pointing to a function. In either case, it MUST exist.

        You can send additional arguments to the callback by using:
             acallback=[acallback,otherArgs]
        For example:
            wsurvey.getJson.get('myServerProg2.php',{'todo':'step1'},[doStep1,{'debugMode':1,'carefulMode':0},'a test call')

        These otherArgs are NOT sent to the server -- but they are available to the callback.
        Thus, they can be long and complex (such as objects containing function references).

   *  errMess1 is an optional string, that will appear in error reports. It can be helpful when debugging.


 reponseObj=wsurvey.getJson.check(aresponse,printOkay,amessage) {

   where
        aresponse : the jsonized array returned by the server to the javascript callback
        printOkay : optional. 0 or 1. If 0 (the default) than any print (or echo) output by the php program is interpreted as an error condition
        amessage : optional. An error message to display (in addition to server generated error information)

    responseObj : the response from the server as a javascript object. Or false if an error occurred

    This is designed to be used by the callback
       *   It can  parse (if necessary) a string (rather than a json'ized object) returned from the server, and create a jquery object
       *   And -- it checks for errors. In particular, errors inserted if jsonReturnError is used (on the .php side)

    If errors are found,
       a) calls a specified funtion (see wsurvey.getJson.setErrFunc below) to diplay an error report
       b) calls console.trace() to print a javascript stack trace (in the browser log)
       c) returns false

    Note: see the "How is the javascript callback called" section for details.

acontent=wsurvey.getJson.content(aresponse,printOkay,amessage) 

   This is a front-end to wsurvey.getJson.check. It calls wsurvey.getJson.check, and if no error returns
   the 'content' field of the response. If there is no 'content' field, returns false

wsurvey.getJson.setErrFunc(afunction)

  Supply the name (as a string) of a function to call if there is an error.
  The function will be called with one argument: a string (possibly long) with an error report.

  Note: this must be a function name -- for now, a string containing a method of an object won't work

  For example, if you use wsFloatingContent containers, and a container named "messages" exists

  function myErrorReporter(amess) {
    wsurvey.flContents.show('messages',1,1);
    wsurvey.flContents.contents('messages',amess);
  }
   ...
  wsurvey.getJson.setErrFunc('myErrorReporter');
  ...
  calls to wsurvey.getJson.get()
  ...

  Notes:

    * If wsurvey.getJson.setErrFunc is not used, alert() is used to display messages (not very pretty).

    * wsurvey.getJson.setErrFunc is used in 3 circumstances:
      a ) the jQuery.ajax call (that does the work) generates a failure.
          A short error message is sent, it will contain the 'textstatus' and 'jqXHR' values provided by jQuery.ajax()
      b ) If wsurvey.getJson.check is given a string to process, and JSON.parse fails.
          A simple error messages is written.
      c ) If wsurvey.getJson.check detects errors -- say due to a jsonReturnError call, or because the php output buffer was not empty.
          A relatively long error message, with trace and output buffer, will be displayed.


How is the javascript callback called?

  The  javascript callback is called as:
      acallback(sresponse,origData,otherArgs2,textStatus,jqXHR)

  where:

        sresponse:   data sent back from the server -- typically, using jsonReturn() to return an associative array
                      Technical notes:
                        * 'sresponse' is the 'data' in a standard .ajax() call using (data,textStatus,jqXHR).

        origData : the 'adata' data sent to the server by wsurvey.getJson.get()

        otherArgs2 : the otherArgs specified by wsurvey.getJson.get()
                    If otherArgs are not specified by wsurvey.getJson.get(), otherArgs2={}

        textStatus : the 'textStatus' that  jQuery.ajax() supplies to a .done() function.

        jqXHR : the XHR argument that jQuery.ajax() supplies to a .done() function.

    textStatus and  jqXHR are typically not used -- the goal of wsurvey.getJson is to remove the need to think about these details!

    Either origData or otherArgs can be used to send information from the caller to the callback (without any need for the server to
        do anything). So you don't have to use global data, or internal functions, to pass information to the callback.

        The big difference is that since otherArgs2 is NOT sent to the server, it is safe to make it long and complex -- jQuery's
        ajax call never sees it!


Function descriptions, php:

 $aval=readVar(varname,default)

     readVar is an alternative to:  $aval=$_REQUEST['varname'];

     where
        varname : string --  name of a variable provided by wsurvey.getJson.get().
                  Where a "variable" is one of the fields in the adata argument.

        default : value to use if no such varname. Optional: if not specified false is returned


    Feature: varname can be a space (or comma) delimited list. Each "word" in this list is searched, and
    the first match is returned.

    Example: $asize=wsurvey\getJson\readVar('size length',500) ;

 jsonReturn($infos,$printOkay)

   where
      infos: php associative array with fields to return.
      printOkay: 0 or 1. If 0 (the default), any content "printed" (or echoed) is assume to be due to an error.
                 If 1, it is tolerated -- the response is not flagged as an error.

   This is used by the php program to return results to the requester -- the javascript program that used wsurvey.getJson.get().
   Infos can contain any fields that the javascript caller can work with.
   It will be json'ized, and (assuming no errors) will be available to the caller as a javascript object.

   It MUST contain a 'status' field.
       If 'status'='error', then wsurvey.getJson.check will print an error report.
       If there are no errors, status='ok' should be used.

    In any case, jsonReturn adds a 'print' field -- that  contains the output buffer. Which is usually empty (or is a lot of spaces)!

        Thus, only $info is returned to the caller -- the output buffer is flushed, saved to 'print', and discarded.

    Note that in the event of a php error, this may not be true. However, wsurvey.getJson.check will catch most php errors,
    and print it in the error report.

   A 'content' field is also always included, which (by default) is ''. It can be used, but it can be ignored.


   Notes:
     * jsonReturn will exit php -- so nothing is returned
     * The operating assumption is that ALL output should be transfered to the client via the $infos argument to jsonReturn.
        Thus, anything printed is probably the result of an error. Hence is a sign of an error!
        One can $printOkay to override this assumption.

 jsonReturnContent($acontent)
    A shortcut for:
      jsonReturn(['status'=>'ok','content'=>$acontent],0)

    jsonReturnContent checks for anything in the output buffer (from print or echo).
    If anything is in the output buffer, sets status='error' and writes the output buffer to the the 'print' index (of the json'ized object returned)

    $acontent can be an object.

 jsonReturnError($acontent,$otherContent='')

    Force an "error return" -- one that causes wsurvey.getJson.check to write an error report.

        $acontent and $othercontent can be strings, or object. The will be printed in the error report.
        If either is an object, wsurvey.dumpObj() is used (it is similar to php's var_dump).

        In addition, a backtrace of php functions is supplied, and is included in the error report.

        And, if printOkay=0, any stuff in php's output buffer is displayed. That is: anything 'printed' (or 'echoed') by the php program.

        Notes:
          * for this "print output" to work properly, the php program should start with an ob_start().
          * jsonReturnError will exit php -- so nothing is returned



Example:

... javascript ...
   <script type="text/javascript" src="wsurvey.getJson.js"></script>
    ...
   function myErrorReporter(amess) {
     wsurvey.flContents.show('messages',1,1);
     wsurvey.flContents.contents('messages',amess);
   }
   wsurvey.getJson.setErrFunc('myErrorReporter');

   ...
   function doit() {
      let adata={'todo':'action1','forWho':'joe'}
      let odata={'balance':100,'version':'v1'}
      wsurvey.getJson.get('myPhpProg.php',adata,[myCallback,odata],'Testing! ');
    }
    function myCallback(response,origData,otherArgs) {
        var hhUse=wsurvey.getJson.check(response,0) ;
        if (hhUse===false) return 1 ;  // if false, an report was generated
        // do someting with hhUse['content'], otherArgs, etc
    }

.. php ...

   use wSurvey\getJson as getJs  ;
   require_once('wsurvey.getJson.php');
   $whatAction=getJs\jsonVar('todo','go');
   $thePerson=getJs\jsonVar('forWho','1');
   // do something with this
   $infos=['status'=>'ok','content'=>'something using the above'];
   getJs\jsonReturn($infos,0); // jsonReturn will exit

   // or if something odd happenbed and you want to force an error report on the client side
   getJs\jsonReturnError('Something bad happened',$badStuffList);


Contact and legal

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

    wsurvey.getJson  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.getJson  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/>.


