Feb 2022

wsurvey.floatingContent.js library

These functions will create "floating" -- moveable and resizeable -- containers.
   Within one of these 'floatingContent' container there will be a fixed header area (top line of the container).
   And a scrollable content area.

Contents:
I        Introduction
I.a         Basic useage
II.b        What is a floatingContent container
II       Setups
II.a         List of all options
II.b         Header and content options, and more important floatingContent container options.
II.b.1i            Description of options .........
II.c        floatingContent container options.
II.c.1          Description of options .........
III      floatingContent functions, styles, and history
III.a       Functions:  modifying the header and content areas
III.a.1         Quick list (alphabetical order)
III.a.2         Description of functions
III.a.3         Some advanced functions
III.a.4         jQuery extenders
III.b       Functions: modifying the floatingContent container.
III.b.1         Quick list
III.b.2        Description of functions
III.c       Customizing floatingContent default styles
III.d       Working with content history
IV       Displaying tips on using floatingContent containers
V        Contact and legal


        =================================================================

I. Introduction

Using the javascript functions in  wsurvey.floatingContent -- it is straightforward to dynamically alter the
contents of, and read information from, the header and content areas of a 'floatingContent container'.

   In appearance a 'floatingContent container' is something like a simple <iframe>. However, they are
   much easier to modify dynamically, using straightforward javascript/jQuery calls.

testFloatingContent.htm contains a demo of wsurvey.floatingContent

   Note: throughout this documentation we refer to  "element that has been converted to a
   floatingContent container". This means that a DOM element (say, a <div>) has been modified
   by the wsurvey.flContents.create() function in wsurvey.floatingContent.js.
   A modification that gives a DOM element the appearance, and feature set, of a "floatingContent container".


I. Installing

 wsurvey.floatingContent.js uses jQuery.

 Hence, you could use something like:

  <script type="text/javascript" src="/myLibs/jquery-3.6.0.min.js"></script>
  <script type="text/javascript" src="/muLibs/wsurvey.floatingContent.js"></script>

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

I.a: Basic useage

    CAUTION: The html document must start with (on the very first line)
            <!DOCTYPE HTML>
           or similar doctype declaration.
           If this does not exist, various calculations (such as window height) will NOT be correct.

  1) Specify an element (such as a <div>)  which will be converted into a "floatingContent container".
     If no such element exists, one will be created.

  2) Call wsurvey.flContents.create.
     To add various buttons and event listeners -- that "convert" this element into a  moveable & resizeable
     "floatingContent container". One with a "header" and a "content" area that are easy to dynamically update.

  3) If creating a new container, add text and html to the "header" and "content" areas using wsurvey.flContents.content(),
     wsurvey.flContents.header(), and other functions described below.

  Example:

     <div id="myMoveableBox" style="background-color:cyan;border:1px solid red">
        Some html and other stuff here -- which can be updated dynamically!
     </div>

  And in an initialization javascript function:

    wsurvey.flContents.create('myMoveableBox',{optionalSpecs})

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

I.b:  What is a floatingContent container

 A "floatingContent container" (a "flContent") is simply a DOM element (such as <div>) that has a number of features added.
 It will occupy a "box" on the browser screen. A box whose display can be manipulated on the fly!

 A flContent's display features include:
   a) Setting its initial appearance, size, and screen location
   b) Moving location: using drag and drop mouse operations to move the flContent around the browser window.
   c) Resising: using drag and drop mouse operations to resisze the flContent
   d) Hiding and showing
   e) Expanding, and unexpanding, the size (to nearly fill the screen)
   f) Moving to foreground or background

 There are two flavors of floatingContent containers: "simple" and "complete".
    Simple floatingCOntent containers have the display features.
    Complete containers also have  "header" and "content" areas.

 A  "complete" floatingContent container is created with two distinct areas: a "header" and a "content" area
   *  The header area is designed to be small (1 line high), and contain a short descriptive title.
      The header can contain  buttons to scroll the content area, or view a history of prior content.
      It is meant to be always visible.
   *  The content area fills the rest of the flContent "box".
      It is designed to be easily updated -- either by replacing the content, or adding to it.
      And it can be scrolled without changing what is displayed in the header area.

 Note: these features are implented using CSS styling, and input elements with associated event handlers.


        =================================================================

II: Setups

   The quick way to create a "complete" floatingContent container is to uses defaults:

           wsurvey.flContents.create(flContentId)

     where flContentId is a string variable containing the id of an existing element, the id of a <div> element
     to add to the document, or a DOM or jQuery object pointing to an existing element

     Example:   wsurvey.flContents.create('myMoveableBox');

       After this call, the element  (with 'myMoveableBox' id) will be converted into a  "complete" floatingContent container.
       Which will have features such as:
          * a fixed position in the middle of the screen;
          * resize and move buttons in all  4 corners
          * A block of several control buttons in the NE corner:
               tips, reset to original position, move to foreground/background, expand, and hide.
            And a button to toggle view of these control buttons.
         * a light gray background if a background-color was not specified
         * a black border if a border was not specified
         * a "header" and "content" area that can be easily written to

   The quick method has a few limitations. In particular if several floatingContent containers are created --
   they will be on top of each other.

   Hence -- it is recommended that the full syntax be used!

   The full syntax:
         jQobj=wsurvey.flContents.create(flContentId,opts,info)

     where:
       * flContentid is as described above

       * opts is an associative array, with a number of indices. top, left, width, and height are the most commonly used.

       * info is an associative array that can have one index: 'overwrite'. Two other "status" indices are set upon return.

    opts:
       There are two types of options in opts
         * options that control the look and layout of the floatingContent container,
         * options that control the content and header areas.

       These options can be specified using case-insensitive strings. In fact, you can use abbreviations!
         II.b and II.c contain the details.

     info:
       info is used to specify if overwrite is allowed (reset the options of an existing floatingContent container).
       It is also used to return two variables containing status information: 'status' and 'message'
          'status' can be:
              'error'       : an error occurred
              'create'      : a new element was created and made into floatingContent container
              'convert'     : an existing element was converted into a floatingContent container
              'overwrite'   : an existing floatingContent container was reset.
              'failOvewrite' :   an existing floatingContent container was selected, but overwrite not set in status
          'message' will be a html string with a message.

        Note that 'overwrite' only can happen if  'overwrite':1 is set in the info argument.
        If overwrite is not specified, or is anything other than 1, an attempt to convert an existing floatingContent
        container will result in a 'failOverwrite' status. And jQobj will be false.
        Thus, failOverwrite is an error code, that is explicitly identified (use of 'failOverwrite' instead of 'error').

        If there is no third argument, 'overwrite':'0' is assumed.
        And you won't be able to read 'status' information.

    jQobj
         If there is no problems: jQobj is a jQuery object pointing to the element that was converted (or created).
         You don't need to retain it, but it can be used in other wsurvey.flContents calls (instead of the flContentId).

         If there is an error: jQobj will be false

  Note on styling:
     wsurvey.FloatingContent creates and uses a number of CSS style classes.
     Several, but not all, of these can be changed in the opts.
     Ambitious designers can specify their own versions of these defaults --  see III.c for the details

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

II.a:  List of options

  The more important options. Ones preceded by '*'  should be specified. For the others, defaults are usually adequate.

   callFunc         : string specifying a function name. Default= &neArr; to "show contents in new window"
   classContent     : string specifying css class(es) to use in content area. Default='cwsFloatingContent_contentC'
   classHeader      : string specifying css class(es) to use in header area. Default='cwsFloatingContent_headersC'
   classMain       : a string of css class(es) to add to floatingContent container. - may prepend. 1 and .SHADOW are special values. Default= don't add
   contentHistory_enable :  contentHistory enable (show buttons, etc). 0 (disable), 1 (enable). Default=0
   contentHistory_func   :  string specifying function to call when history button clicked. Default=none (do NOT call a function)
   contentHistory_method :  how to save/display contentHitory. 'html' or 'dom'. Default='html'
 * escapeOrder       : what container is closed first on esc (higher values closed first). 'z','n','t', or integer. Default ='t' (time of creation)
   enableOnTop       : enable "move to top" on button click. 0 (no), 1 (content area), 2 (header area), '*' (anywhere), or a selector. Default='*'
   expandBox         : add "expand to nearly all of parent" button. 0 (no)  or 1 (yes). Default=1.
 * height            : height of floatingContent container. px, em, or %. Default is 25%
 * headerPerm        : additional text added to the "permanent" sub-area of the headers area. Default =''
   headerCloser      : add "hide container" button to header area. 0, 1, or a string. Default is '1' (an x button)
 * left              : left edge of floatingContent container. px, em, or %. Default =25%
   priorRetain       : disposition of prior contents.  0 (remove), 1 (retain as content) or 2 (retain as transient header). Default=0
   showScroll        : show "scroll within content area" buttons. 0 (do not show), 1 (show). Default=0
 * top               : top edge of floatingContent container. px, em, or %. Default =25%
 * width             : width of floatingContent container.  px, em, or %. Default =25%
 * zIndex            : the z-index to assign to this floatingContent container. Integer>0. Default=50

Additional "container" options  (details II.b).  Defaults are usually adequate.

   addOverflow     : add an overflow:auto style to container. 0 (do not add), 1 (add). Default=0 (stongly recommended)
   iconFunc        : the button for callFunc. Aa string (such as am htmlEntity). Default='&neArr;'
   iconMove        : string used in move buttons. Typically an html entity. Default='&#9649;' (plus sign). Suggestion:&#9995;' (open hand)
   movers          : where to place move buttons. A list that can contain: 0 * NE SE SW NW TOPBAR. Default='*' (all corners and a a topbar)
   moveTopBarClass : a css class used in the topBar (mover).  0 (no), 1 (default), .FAT, className. Default=1 ('cwsFloatingContent_topBarFat')
   noCloser        : do NOT show small closer button in NE corner. 0 (show), 1 (do NOT show). Default =0
   noHider         : do NOT show small "hide controls" button in NE corner. 0 (show), 1 (do NOT show). Default =0
   noRestoreSize   : do NOT show small "restore original size" button in NE corner. 0 (show), 1 (do NOT show). Default =0
   noTips          : do NOT show small "display some helpful tips" button in NE corner. 0 (show), 1 (do NOT show). Default =0
   noZindexButton  : do NOT show small "move to foreground/background" button in NE corner. 0 (show), 1 (do NOT show). Default =0
   removeClass     : classes to remove from element before conversion. String, or '*' (remove all). Default ='' (don't remove existing classes)
   resizers        : where to place resize buttons. A list that can contain: 0 * NE SE SW NW.  Default='*' (all corners and a a topbar)

Note that some of the "more important options" are available when creating a "simple" floatingContent container. II.a and II.b describe
what options are specified where.

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

II.b:  Header and content options, and more important  floatingContent container options.

  wsurvey.flContents.create() creates a "complete floatingContent container". The following describes
  the options that specify its features.

        Several of these features (such as 'top' and 'height') specify a "simple floatingContent container" that a
        "complete" one is built on.  These are more fully described in II.b.

        Note: you should NOT call wsurvey.flContents.container.create() before calling wsurvey.flContents.create()!
              wsurvey.flContents.create() will take care of that step.

 Note that while using the full option name is recommended, most of the options have acceptable abbreviations
 and alternate names. These are noted in the option descriptions.
 And for all options, a case insensitive match is used.


II.b.1: Description of options .........

   'callFunc' : a string specifying a function name  (details in II.b)
      Specify a custom function that be called using a 'control button'.
      By default, a "show this content in an external window" function is used
      callFunc=0 will suppress this default.
      See II.b for the details -- including options to send an additional argument to the function,
      and to change the icon used to call this custom function.

    *  synonyms (case insensitive abbreviation match works): 'callF' and 'funcC'

   'classContent': a string specifying css class(es)

       This class is used in the content area of a floatingContent container.

         0 : no class is used. This is not recommended, but may be necessary if if you want to customize apperarance.
             If 0 is used, do NOT have anything after it. If so, 0 is ignored.
         1 : (the default). A shorthand for cwsFloatingContent_contentC
         classNames :  add these class(es).  If more than one, use  a space delimited list.
                       Note to use the default and these classes, use something like '1 myClass ...'
         There is a shorthand classname: .THIN. It stands for cwsFloatingContent_contentThin, with a style of:
                   {scrollbar-width:thin !important ,scrollbar-color:dark !important}
            This is best used along with '1'.

          *  synonyms (case insensitive abbreviation match works): 'contentClass' and 'classCo'

      Examples: ' 1 '
               '1 .THIN '
               'myContentClass'
               '1 myContentClass0'

   'classHeader': a string specifying css class(es)  .

       This class is used in the header area of a floatingContent container.

         0 : no class is used. This is not recommended, but may be necessary if you want to customize apperarance.
         1 : (the default). cwsFloatingContent_headersC is used
         classNames :  in addition to  cwsFloatingContent_headerC, add these classes.
                       If more than one,in a space delimited list.

          *  synonyms (case insensitive abbreviation match works): 'headerClass' and 'classHe'

    'contentHistory_enable': 0 (the default) or 1
        0 : do NOT enable contentHistory for this container (the default)
        1 : enable contentHistory. Two buttons (prior and next) will be displayed in the header area.

        The contentHistory buttons allow the user to view prior stuff (html and text), for this floatingContent container's
        content area.

        The list of prior stuff is added to whenever content is changed with wsurvey.flContent.content()

        Notes:
          * By clicking on the "prior" or "next" buttons, one can go back and forth in the history list.
          * These buttons are displayed in the left edge of the header.
          * showHistory_func and showHistory_method options modify how this 'prior content' is displayed.
          * See III.d for further discussion on working with contentHistory (which can be quirky).

          *  synonyms (case insensitive abbreviation match works): 'showHis'  and 'contentHistory_en'

   'contentHistory_func': function name, or '' (the default), or 0, or 1
         '' or 0 : do not call a function when history buttons are used.
         '1' : use wsurvey.flContents.historyFuncDefault -- writes some status info to console.log()
         Otherwise: should be a string, with the name of an existing custom function

      If specified (and exists) this function is called after the entry from the history is displayed in 
      the content area.

      The function is called as:
         window[callFuncHistory](e1,idire)
                where:
         * e1 is a jQuery object of the floatingContent container (that the "history" button is in)
         * idire=1 means a forward (next) , idire=0 means a backward (prior),  button was clicked

     Notes:
        * This is ignored if showHistory=0 (or '')
        * The function is called AFTER the previous (or next) content is (re) displayed.
        * The default (of '') is to NOT call any such function.
        * This can be used to update event handlers, if contentHistory_method='html'
        * See III.d for further discussion on working with contentHistory (which can be quirky).

        * synonyms (case insensitive abbreviation match works): 'contentHistory_fu'

   'contentHistory_method': either 'html' (the default) or 'dom'
       How to save the content area's html.

          * 'html' (the default). The html is saved. This "locks" the appearance, but assigned event managers are NOT retained
          ' 'dom'  : Assigned event managers ARE retained. But if the content area is being changed by non floatingContent
            functions, the history might be inappropriately updated.

     Notes:
        * This is ignored if showHistory=0 (or '')
        * See III.d for further discussion on working with contentHistory (which can be quirky).

        * synonyms (case insensitive abbreviation match works): 'contentHistory_me'
                               historyFunc historyMethod

    'enableOnTop' :   selector string. Or 0, or * (or 1, or 2)

          This enables "click on the floatingContent container to bring it to the foreground"

          The default is '*' -- any element in the container, when clicked on, will move this container to the
          foreground. '1' is a synonym for '*'
          Special values:
                  1 : the content area of a complete floating content container (same as '.cwsFloatingContent_contentC')
                  2 : the header area of a complete floating content container (same as '.cwsFloatingContent_headersC')
          Hint: to limit enableOnTop to header areas of a 'complete' floatingContent container, use
                enableOnTop:'cwsFloatingContent_headersC'. Or use '2' as a shortcut.

         There is an exception: clicking a control button will NOT move the element to the foreground.

         Use of something other than the default ('*') may be necessary if there are complicated click
         handlers in the content. That may not work nicely with this click-to-move-to-foreground handler
         that is assigned to the floatingContent container.

         For example, you could specify 'enableOnTop':'.safeToUse' - only elements with a safeToUse class
         will cause a move to foreground.

         *  synonyms (case insensitive abbreviation match works): 'enableOn'


  'escapeOrder':  integer value    (details in II.b)
       Higher integer values are hidden first when esc key hit.
       See description in section II.b -- including notes on how to disable wsFloatingContent's
       key handler.

   'height' : Height of floatingContent container  (details in II.b)
      Height is measured down screen from the top. In px, em, or %.
         See description in section II.b
         Notes:
         * if wsurvey.flContents.create is called on an existing floatingContent container, this is ignored
         * 'width' and 'height', given a 'left' and 'top' define the SE corner of the container.

   'headerPerm :  Default of ''.  Additional text added to the "permanent" sub-area of the headers area.
      Can be any text or html -- but  should be fairly short
      The header area contains two sub-areas: this permanent portion, and a transient sub-area.
      Both are displayed when a floatingContent container is visible
      Notes:
         * The "permanent" portion of the headers area can NOT be readily changed.
         * The text (html okay) used should be fairly short -- unless you are okay with a header that
           covers more than one line.
         * The headerCloser button, and the contentHistory buttons, appear before this permanent header text.
         * It is often useful to specify other buttons within the permanent header area.
         * The transient header area can be changed by .show(), or .header().
           By default, the transient header area is empty!

         *  synonyms (case insensitive abbreviation match works): 'headerP'  and 'permH'

   'headerCloser': 0, 1, or a string. Default is '1'
        If '0', do NOT show a "close" button at the left edge of the header area.
        If '1',  show an extra "close" button (in upper left corner).
        string:  Insted of using '0', you can specify some options in a CSV string, using:
                  'value,class,title '
        Where:
           value: the displayed button,
                    class:  css class to use. It can NOT contain commas
                    title: its mouseover title. It can contain commas
           title and class are optional.
             If title is not specified: title='close'
             If class is not specified: cwsFloatingContent_headerCloser is used, which has a style of:
                          cursor:pointer;margin:0px;padding:0px;font-size:100%;
           Notes:
             * 'headerCloser':1 is the same as 'headerCloser':'x,Close this,cwsFloatingContent_headerCloser'
             * Be aweare that the "noCloser" option controls the "close" button in the floatingContent container.
               Since this is small and out of the way, headerCloser allows one to add a more visible closer button.
               See section II.b. for details
             * Do NOT HTML, or embedded quotes, in the 'title' portion of a 'string' specification

             *  synonyms (case insensitive abbreviation match works): 'headerCl'  and 'extraC'

   'left' : left edge of floatingContent container  (details in II.b)
       Location of top edge of floatingContent container. In px, em, or %.
       See description in section II.b
       Notes:
         * if wsurvey.flContents.create is called on an existing floatingContent container, this is ignored
         * 'left' and 'top' define the NW corner of the container.

   'priorRetain': a  0,1 or 2.
      What to do with content in an existing element that is being converted to a floatingContent container.

      0 : the default. Remove existing content from the element bieng converted
      CONTENT, or 1: retain it, and add it to the content. An append is used,  so existing event handlers will be retained
      HEADER : retain it, and save to the  header's "transient" header area.

      This is only used if the anid is an existing element
      Is is irrelavant if a new container is being  created.

      If just want to convert  an existing element into a floatingContainer, and have no intention
      of using the content and header area manipulation functions -- it makes sense to use
      wsurvey.flContents.container.create() instad of wsurvey.flContents.create().
      See section II.b for the details.

      Notes:
        *  priorRetain is ignored if a floatingContent container is being "ovewritten".
           The current area will be retained; and the header area will be rewritten.
        *  we do NOT recommend retaining HEADER. The display may include extra lines.
           And it will not be retained if you  overWrite the floatingContent container.

        * synonyms (case insensitive abbreviation match works): 'priorR' or 'priorC'



    'showScroll': 0 (the default) or 1.
         0: do not show "scroll in contents" buttons (the  default)
         1 : do show these buttons.
     
       When enabled,  4 buttons are displayed toward the right end of the headers row.
       An up, right, down, and left arrow.
          * clicking one of them scrolls the content container 10px (about one row, or one space)
          * RMB click scrolls to top/right border/ bottom/ left border
          * A double click (2 clicks within a 1/4 second) scrolls 150 px
        Since these are conveniences that might take up valuable space, the default is 0 (do not show)

        *  synonyms (case insensitive abbreviation match works): 'showS'

   'top' : top edge of floatingContent container.  (details in II.b)
       In px, em, or %.
       See description in section II.b
       Notes:
         * if wsurvey.flContents.create is called on an existing floatingContent container, this is ignored
         * 'left' and 'top' define the NW corner of the container.

   'width' : Width of floatingContent container  (details in II.b)
        In px, em, or %.
        Width is to the right from the left.
        See description in section II.b
        Notes:
         * if wsurvey.flContents.create is called on an existing floatingContent container, this is ignored
         * 'width' and 'height', given a 'left' and 'top' define the SE corner of the container.

    'zIndex': The z-index to assign to this floatingContent container.
        If not specified, a value of "50" is used. Higher values are displayed on top of lower values.

        To not specify (and use whatever z-index was specified in the element, or to use default (50),
        use '' (do not use 0).

        Notes:
          *  the zindexButton option (see II.b) can be used to display a "bring forward/ bring back" button
             (to change the z-index of a floatingContent container on-the-fly).
          *  the onTop option of .show() can be used to "bring forward/bring back" a showContent container
          *  this overrides whatever z-index may already be specified for an existing element.

          *  synonyms (case insensitive abbreviation match works): 'z-index'

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

II.c:  floatingContent container options.

    This section specifies the options recognized by wsurvey.flContents.container.create()
     -- options that are passed to wsurvey.flContents.container.create by wsurvey.flContents.create

   wsurvey.flContents.create() has two major components:
      (i)  convert an existing element into a "simple" floatingContent container, or create a new element
      (ii) Create "header" and "content" areas within this converted, or new, floatingContent container

    The first is done by the wsurvey.flContents.container.create() function.

        Basically:  wsurvey.flContents.container.create() creates a "simple floatingContent container".
                    wsurvey.flContents.create() upgrades  a "simple floatingContent container"
                    to a "complete floatingContent container".

     Thus: if you just want to convert an existing element into a "simple" floatingContent container --
           you can  call wsurvey.flContents.container.create() directly.
            The header and content areas will not be available; but  move, resize, and other features will be.

            In this case (just creating a "simple" floatingContent conatner), useage is:

                  eJquery=wsurvey.flContents.container.create(anid,opts,info)

             where the anid, opts, and info are as described in II. and II.a.


    Note that several of the more important ones are also briefly described in section II.a.
    For all the options defaults are used if they are not specified. So you can safely specify a subset of options.

    The most important are top,left,height, and width. For the other options, the defaults are often adequate.

II.c.1: Description of options .........

    'addOverflow':  0 (the default) or 1
        If 1, and if the box being converted into a floatingContent container has a 'visible' overflow,
        convert to 'auto' overflow.
        This is NOT recommended -- the buttons will move as you scroll. As in "move out of view"!

        Use of the header and content areas, within a floatingContent container, are the recommended methods
        of displaying content.   And the content area is always scrollable.


    'callFunc': afunctionName (as a string). '' is the default
        If callFunc is specified (and not ''), an icon is included in the upper right corner of the floatingContent container --
        clicking it calls the specified function!

       The function will be called with, with 1 argument -- the jQuery object of the floatingContent  container.

       Or, you can specify additional items: an argument to be sent to this function, and a title to be displayed on mouseover
       Syntax:
              'function : other info ,title ':
       Careful, the ':' is in the "value", not the ':' in the associative array specification!

       Before the : -- the function name.
       The next two are optional:
          After the : and before a , -- argument sent (as is) to the function. It can not contain commas!
          After the , -- a title to display (which can contain commas) when mouseOver the call this function  button.

        Examples:
          'callFunc':'myCallBack1'
            This would call: myCallBack1(eFlContent)  -- eFlContent the jQuery object of the floatingContent container

         'callFunc':'showInNewWindowNow : ver=1 , show content in a new window, or tab '
             This would call: showInNewWindow(eFlContent,' ver=1');
             showInNewWindow could find something in eFlContent, and use "ver=1" to determine additional content.
            'show content in a new window, or tab' would be displayed when the mouse was over the call function icon.

         Notes:
           * if the simpler form is used a 2nd argument is NOT send to the callFunc.
           * by default, the call this function button will be a small button with &neArr; character (a double
             arrow pointing NE). You can customize this with iconFunc
           * synonyms (case insensitive abbreviation match works): 'callf'  and 'funcC';

   'classMain': a string specifying css class(es). Or 0  or 1 or 2. May have a minus prepended.
       This class is added to the floatingContent container.

       1  : use   "cwsFloatingContent_mainC",
       a class name: one, or several in a space delimited list, of your own classes.
                   Be sure these do not attempt to set 'position'.
       There is a special built-in classes that can be used via a shorthand:
        .SHADOW : is short for cwsFloatingContent_mainShadow, which has a style of:
                 {box-shadow: 20px 20px 30px 20px tan ;background-color:#f3f3f3;}

     If the first character i "-", then existing classes will be removed (and retained for later reassignment).

     The default is '- 1 '  -- remove existing classes and add  cwsFloatingContent_mainC

     Examples: '- 1 .SHADOW ' is a shorthand for   "- cwsFloatingContent_mainC cwsFloatingContent_mainShadow"
                  It means "remove existing classes, use cwsFloatingContent_mainC and cwsFloatingContent_shadowClass
               'myBigClass ' means 'add myBigClass to whatever may be in the original element.

      Notes:
         * If removeClass is specified, a starting "-" is ignored.
           Basically: for finer control of pre-existing classes, use removeClass (rather than starting with a -)
         * Example:  '-1' is the same as  "-cwsFloatingContent_mainC"
         * For newly created containers, the - is ignored (there are no classes to remove)
         * Do NOT include trailing "." in the classnames. Thus "myFunClass" is okay, but not ".myFunClass"

      *  synonyms (case insensitive abbreviation match works): 'mainClass' and 'classMa'

      Using 0 is interesting --  it there is no background defined in the target element,
      the background color will be transparent. So the text, etc underneath the floatingContent container will be
      visible as it is moved and resized. This may have it uses, but it makes reading the content of a
      floatingContent container not-so-easy!

      Note that  during conversion to a floatingContent container several styles are added.
      These are meant to prevent the control buttons from impinging on content.
      You can override these by specifying CSS in the classMain -- using an !important modifier.
      The styles set are (using .css()):
          *  border: 1px solid black  (this is not done if a preexisting border is detected
          *  padding-bottom: 14px   (this is not done if a pre-existing padding-bottom is detected)
          *  padding-top: 14px   (this is not done if a pre-existing padding-top is detected)
          *  overflow:auto   (this is only done if addOverflow=1, and the existing overflow is visible)



    'escapeOrder':  integer value. Higher integer values are hidden first when esc key hit.
         This is useful if more than one floatingContent container is created.
         If not specified, time of creation is used (so last created is hidden first)

         This value is used as the "escIndex" attribute for the floatingContent container -- for use with the
         ws_escHandler function.  Note that higher values mean "close this first".
         The default values (current timestamp) are likely to be always the highest values of escIndex!

         It may be better to use the ws_escHandler function, epecially if other elements (that are not
         floatingContent containers) may be subject to keyup events.

         Special values;
            't'  : current time (at time of  call to .create). This is the default.
            'z'  : use the current z-index (at time of esc key hit). If all your floatingContent containers
                  have this, then the first hidden is the one on top
            'n'  : do NOT hide this on escape.
                   If all floatingContent containers have 'n', then the escapeHandler function will NOT be
                   assigned to the document. This is a way to avoid possible conflicts with other
                   key handlers.
                             164 286 052 002 2
         Note: if you mix modes ('z' for some, explicit values for others, 't' for others) the results may be odd.
               't' will always close first (unless you assign 14 digit values)!
                If the explicit values are high (say, in the 100s), they will close first,
                but maybe not if there has been a lot of moving elements to the foreground and background!

           * synonyms (case insensitive abbreviation match works): 'escape'  and 'escorr';

    'expandBox': 0 or 1 (default).
          0 : do NOT include this button
          1 :include a "expand to nearly all of parent" button (typically, the parent is the full browser window). Default is 1.
          See wsurvey.flContents.container.doExpand for more details

         *  synonyms (case insensitive abbreviation match works): 'expandB' or 'expandBoxButton'

    'height':  height of box (% or px or em). % is of entire screen (the browser viewport).

    'iconFunc': a string (such as am htmlEntity)
        Used as the button to "callFunc".
        If not specified, or 0, a &neArr; (double arrow pointing to the NE) is used.
        Any HTML will be removed!

        * synonyms (case insensitive abbreviation match works): 'iconF'

    'iconMove' : a string (such as an html entity'). The icon to use for the "move the floatingContent container box"
       If not specified, &#9649 (a plus sign) is used.
         Example: 'iconMove':'&#9995;'   (an open hand)

       Note: iconMove can NOT contain html!

       *  synonyms (case insensitive abbreviation match works): 'moveIcon'  and 'iconM';

    'left' : left of box (% or px or em)

    'movers' : a space delimited list that containe the following (case insensitive)
          *  : put the moverIcon in all 4 corners, and create the topBar.
          NE: put a iconMove in the NE corner (along with other control buttons)
          SE: put a iconMove in the SE corner (perhaps with a resize button)
          SW: put a iconMove in the SW corner (perhaps with a resize button)
          NW: put a iconMove in the NW corner (perhaps with a resize button)
          TOPBAR: create a low opacity bar along the top of the floatingContent container

       To suppress iconMove display: use '0' (with nothing else)

       Using * makes the others unneccessary, but it won't cause problems if these others are included along with a *

       These iconMoves (or topBar) are used to move the container. Clicking, holding down the mouse,
       and moving will cause the container to move.

       Notes:
        * If one uses "top bar only" -- sometimes the top of the box can move off the screen, and you won't be
           able to access the move button!
        * A topbar will be float above the top of the floatingContent container. While this will reduce interference
          with content, it isn't perfect. Hence it maybe useful to specify one (or all 4) corners,
          but not the topbar.
        * You can tweak the display of the topBar using the moveTopBarClass option
        *  synonyms (case insensitive abbreviation match works): 'moveIcon'  and 'iconM';

     'moveTopBarClass': a class name.
        This class is used to display the topBar  -- used to move the floatingContent container
        If not specified, or 1, a built in class is used (cwsFloatingContent_topBar).
        If 0, no class is added. This is NOT recommended!

        If '.FAT' (be sure to include the ".") a built in class is used (cwsFloatingContent_topBarFat)

        When specifying a moveTopBarClass -- do NOT include periods (you can include more than one class)

        cwsFloatingContent_topBar is a 9px high, low opacity, slightly orange bar that covers the top 90%
        of the the width of the container. It is placed at the top (actually, a bit above the top)
        of the container. And it has a low z-index, hence the control buttons are not obscured.

        cwsFloatingContent_topBarFat is similar, but is 18px high.

        *  synonyms (case insensitive abbreviation match works): 'moveTop'

     'noCloser' : 0 or 1 (0 is the default)
         If 0 (the default) show a "closer" button.
         If 1, do NOT show it.

         The closer button is a small x in the NE corner.
         When clicked, the floatingContent container (that this button is inside of) is hidden.

         Note: headerCloser is another method of adding a closer. Or you can make your own (see description of
         wsurvey.flContents.container.close)

        *  synonyms (case insensitive abbreviation match works): 'noCl'

   'noHider': 0 or 1 (0 is the default)
         If 0 (the default) show a "hide control buttons" button.
         If 1, do NOT show it.

         The hider button is a small . in the NE corner.
         When clicked, this  hides all the other control buttons in the NE corner..
         It remains (displayed in the NE corner) --   and when clicked again redisplays the other buttons.

      *  synonyms (case insensitive abbreviation match works): 'noHi'

    'noRestoreSize' : 0 or 1 (0 is the default)
                   If 0  (the default) show  a restore to original size button .
                   If 1, the restore to original size button is NOT shown

                   Clicking on this button will reset the size of the floatingContent container to its original size
                   (as specified in wsurvey.flContents.create).

      *  synonyms (case insensitive abbreviation match works): 'noRe'

    'noTips' :  0 or 1 (0 is the default).
        If 0 (the default) the tips button will be displayed.
        If 1, the show tips button is NOT shown

        Clicking on this button will toggle display of a descripton floatingContent containers,
        with some details on the various control buttons.
        Clicking it again will hide this description.

        The description is displayed in a small <div> at the top of the floatingContent container
        For details, see wsurvey.flContents.container.desc() in II.b.

      *  synonyms (case insensitive abbreviation match works): 'noTi'

    'noZindexButton': 0 (the default) or 1.
        If 1, include a button to put this floatingContent container box above all others --
        give it a higher-zindex (hence move to foreground).
        Or, if right mouse button hit, give it a lower z-index (move to background)

        To prevent problems (of floatingContent containers being behind the background),
        the minimum z-index is 0. Thus, RMB to move a box "back" will fail when   the "smallest" z-index
        (of all floatingContent containers) is 0.

        enableOnTop is a somewhat more natural means of moving to the foreground, but zindexButton  allows for
        move to background. And, it is somewhat less intrusive -- enableOnTop sets a listener on the
        entire container. If other click handlers are listening, there may be conflicts.

       Note that if no z-index is specified (in a element being converted into a floatingContent container),
       a value of 1 is assigned to the container.

       *  synonyms (case insensitive abbreviation match works): 'noZi' and 'noOnTopB'

    'removeClass' : a space delimited list of classes
                  These classes are removed from the element before converting it into a floatingContent container
                  '*' means "remove all classes".
                  If specified, the list of classes removed is retained (as an oldClass) attribute, and these classes are
                  restored if you use wsurvey.flContents.container.remove.

                  This is useful if the element being converted to a  floatingContent container had any kind of
                  css styling that might not work well once the element becomes "floating". Such as an elaborate shadowing.

                  Thus: it is best to use classes when specifying css formatting of an existing element.

      *  synonyms (case insensitive abbreviation match works): 'remove'

    'resizers' : a space delimited list that may contain  the following (case insensitive)
          *  : put the resizer icons  in all 4 corners .
          NE: put a resizer icon in the NE corner (along with other control buttons)
          SE: put a resizer icon in the SE corner (perhaps with a mover button)
          SW: put a resizer icon in the SW corner (perhaps with a mover button)
          NW: put a resizer icon in the NW corner (perhaps with a mover button)

       To suppress resizer button display: use '0' (with nothing else)

       Using * makes the others unneccessary, but it won't cause problems if these others are included along with a *

       These resizer buttons resize the container. Clicking, holding down the mouse,
       and moving will cause that corner of the  container to move.

       The icons displayed are diagonal double arrows, that are appropriate for the corner the are placed in.
       And the cursor changes to a similar diagonal double-arrow when over one of these icons.

      *  synonyms (case insensitive abbreviation match works): 'resize'

    'top' : top of box (% or px or em). % is percent of screen

    'width':  width of box (% or px or em). % is percent of screen


    -- end of  (floatingContainer) options ---

  Example:  show NO buttons, use default size and location.

      wsurvey.flContents.container.create('v3',{'expandBox':0,'callFunc':0,'zindexButton':0,'movers':'0','resizers':'0',
                              'noCloser':1,'noHider':1,'noRestoreSize':1,'noTips':1});

  Notes:
     * See section III.b for details on functions that modify floatingContent containers
     * an element converted into a floatingContent container will have a wsFloatingContent class added to it.

        =================================================================

III:  Functions: working with floatingContent containers, adding and modifying content, and more

A primarily rationale for using floatingContent containers is the ease with which they can be manipulated using
straightforward javascript. No need for convoluted event listeners!

A suite of functions are provided to facilitate this manipulation. They are divided into two parts
   III.a   Functions that manipulate header and content areas.
   III.b   Functions that manipulate the floatingContent area

Most of the time the III.a functions are all you will need. Though if you created a "simple" floatingContent area,
the III.a functions will not work!

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

III.a:  Functions: modifying the header and content areas

  These functions control the header and content area of a "complete" floatingContent container.
  Some of them are used to manipulate the floatingContent container -- replicating some of the functions in III.b.

               ----------------
III.a.1  Quick list (alphabetical order). The  * functions are most commonly used, + less frequently,  - even less

   -  wsurvey.flContents.checkOverflow(ebox,tol,afull)   : check if content area requires scroll bars to display
   +  wsurvey.flContents.closest(athis,selfOnly)          : find floatingContent container an element is in
   -  wsurvey.flContents.current(ebox)  : returns size, location, visibilityi, and zindex "current info"
   +  wsurvey.flContents.dom(ebox,which)  : return pointers to main, header, and content area of a floatingContent container
   -  wsurvey.flContents.find(ebox,sel,siblingOk)  : return pointers to main, header, and content area of a floatingContent container
   +  wsurvey.flContents.header(ebox,content,doappend) : read or  modify contents of the transientHeader area
   -  wsurvey.flContents.headerView(ebox,which) : toggles view of the header area
   *  wsurvey.flContents.hide(ebox,speed)  : hide (do not display) a floatingContent container
   +  wsurvey.flContents.onTop(ebox,which)  : move to foreground
   *  wsurvey.flContents.show(ebox,speed)  : show (display) a floatingContent container
   +  wsurvey.flContents.toggle(ebox)  : toggle between show and hide
   -  wsurvey.flContents.visible(ebox) : return visiblity status

   Notes:
     * in all the following, "ebox" can be a string containing the id of an element (it can, but does not have to,
         begin with a "#"). Or it can be a dom or jQuery element.
         If ebox does not match with an element, or the element is not a floatingContent container:
            * false is returned.
            * a note is written using console.log().

     * For most of these functions, a jQuery extended version is available. These are :
       .wsFlContents, .wsFlContents,  .wsFlCurrent, .wsFlFind, .wsFlHeader, .wsFlHide, .wsFlOnTop, .wsFlShow,
       .wsFlToggle, and .wsFlVisible

    *  wsurvey.flContents.content is a synonym for wsurvey.flContents.contents, and
       wsurvey.flContents.headers is a synonym for wsurvey.flContents.header

III.a.2  Description of functions

 wsurvey.flContents.closest(anid,selfOnly) :

    Return jquery object of the closest floatingContent container.
    This might the element pointed to by anid, or a parent of the anid element.

    anid can be a string id of an element, or it can be a jQuery or DOM object.
    Or it can be an argument provided by an event handler (either inline or assigned via .on('xxx',..))

        Thus, wsurvey.flContents.closest can be used for buttons inside of the content (or header)
        of a complete floatingContent container -- that invoke functions that do something to the entire container.

    If no floatingPoint container is found, a false is returned.

    selfOnly is optional
      0 (the default) -- checks if anid is a floatingContent container. If not, then looks in parents if necessary
      1   -- only looks at self
      2   --  returns the "type" of floatingContent element (of anid -- or anid's parent)
              false : not a floatingContent container
              'simple' : a simple floatingContent container (no content or header area)
              'complete' : a complete floatingContent container (with a  content and header area)
             Thus: a string (or false) reporting the  "type of container", and NOT a jQuery object, is returned.

    You can also use the jQuery extender: $(anid).wsFlClosest(0)

 wsurvey.flContents.checkOverflow(ebox,tol,afull)

   Check  if the contents of a floatingContent container  are "overflowing" -- are scroll bars (either horizontal
   or vertical) needed to view its content.

   Returns true if they are, false if not.

     ebox: string id, or a jQuery or dom object, pointint to a floatingContent container.
     tol:  toleranace. Optional. Used to deal with round up or other errors -- it is the # of pixels
           of overlap that are tolerable. Using less than 1 is NOT recommended (1 is the default)
     full: optional. If specified and 1, then instead of true or false, return an associative array with:
            ['status':false or true,'scrollWidth':scrollWidth,'scrollHeight':scrollHeight,
                                     'innerWidth':innerWidth,innerHeight':innerHeight]

  Notes:
    *   false occurs if scrollWidth > innerWidth + tol,  or scrolHeight>innerHeight+tol
        You can use full=1 to quickly find these basic features of the content portion of a ws_showBox container!

    *  If an error (such as anid doesn't point to jquery object), returns ['status':'error','content':erroMessage]
       If full not specified, errors cause a return of false (no error message)

    * Note that given a container with some content in it:
         * scroll height and width:  how big the container would have to be to display this without scroll bars
         * inner height and width : the max sizesa this container can display without scroll bars
         These are somewhat imprecise -- paddings and scrollbar width & height are abstracted from


wsurvey.flContents.contents(ebox,newContent,extras)  :

   Read or set the content area.

   ebox is a jQuery or dom object, or a string id, pointing to a floatingContent container.

   newContent is the new content to use. It can be text or html.
     Or it can be a dom or jQuery element: in which case the contents of the newContent element are written to the content area.

     If newContent is not specified (only one argument), the current contents of ebox are returned as a html string.
     See the Special feature  for what happens if newContent={}

   extras is optional.
     An object with several options.

     Shortcut: if extras is a number or string, it is converted to {'append':extras}

        'append': 0 or 1.
           Sets the "append" option
              0           newContent replaces existing content (the default),
              1 (or 'a')  append newContent to existing content
           Note the shortcut above -- if extras is not an object, its value is used as the append option.
           Thus:
              extras=1
           is the same as
              extras={'append':1}

        'show' : 0 or 1.
               0 (or 'h') : hide the container after writing newContent
               1 (or 's') : show the container after writing newContent
               'n'        : no change
            If you do NOT specify 'show', the default is 1 (show)
            If you DO specify 'show', but do not specify 0, h, 1, or s: the default is no change

        'onTop': 0 or 1
             0 : do NOT change z-index
             1 : move to top (foreground).
           The default is to move to top

        'header': '' or a string
            If specified and not '', a string to use as a transient header.
            If not specified, or '', the transient header is not changed
               Hint: to effectively erase current transient header, you can use '&nbsp;'

        'noHistory': 0 or 1
           This is ignored if contentHistory has NOT been enabled (using the contentHistory_enable options)
              0  : save contentArea to history list. This is the default
              1  : do NOT save
           If specified, this only applies to the current call to wsurvey.flContents.contents.

           Note that entries are saved to the contentHistory list AFTER wsurvey.flContents.contents has replaced
           (or appended) newContent. So specifying noHistory ONLY affects whether this call is added to the history list.

         'addEvents': an array of event specifications.
            The default is [] -- do NOT add event handlers.

            If specified, an array of event handler instructions. Each element in the array is a 3 element array:
                [0] : the event. i.e.; 'mousedown'
                [1] : jQuery selector string. The entire floatingContent container (not just the contentArea) will
                      be searched within. Example: '.addMyEventHere';
                [2]  : function to call. Must exist: false is returned if it doesn't (with console.log() message).

              Basically, this calls
                 ee=$(thisContainer).find(aSelector).on(anEvent,aFunc) is called
               However: each element is ee is checked,i
                        and if aFunc is already an handler for anEvent, it is skipped.
                        Thus, no multiple instances of the same event handler!


   If the content area does not exist (but ebox is a floatingContent container), null is returned.
   If success, and not a "read contents", a 1 is returned.

   If newContent is NOT specified -- the current stuff in the contentArea is returned as a string (using .html()).

   Special feature: to return the stuff in the contentArea as a jQuery collection, newContent should be an empty object.
         example : thoseElems=wsurvey.flContents.contents(ebox,{});
         thoseElems will contain all the direct children of 'newStuff' -- including  text nodes (.content() is used).
         Note that for this to work newContent must  be {} -- the object MUST be empty!

   Notes:
     * The default value for extras is essentially:

          {'append':0,'show':1,'onTop':1,'noHistory':0,'header':'','addEvents':[] }

     * if newContent is a dom or jquery object, replacing (or appending) it to the contentArea will preserve
       any event handlers already assigned to the object..

     * wsurvey.flContents.content() is a synonym.

     * you can also use the jQuery extender: isVis=ebox.wsFlContents(newContent,extras),
       or  daContent==ebox.wsFlContents() to read the content into a string.



wsurvey.flContents.current(ebox)
  ebox is string, or jQuery or dom object, pointing to a floatingContent container

  Returns size, location, and zindex  in an object
  The objects' fields are:
    'left', 'top', 'width', 'height', and 'zIndex', 'visible','foreGround'
    And, 0 = same as 'width', 1= same as 'height'

   Notes:
     visible:    0 (not visible), or 1 (visible)
     foreGround: 0 (might be behind), 1 (would be in front of) -- all other floatingContent containers
               foreGround does not tell if a container is beind (or in front) of any other floatingContent container,
               only whether it could be (if the containers were moved around appropriately)

  This extends:
     specInfo=wsurvey.flContents.container.doResize(ebox,'C');

  You can also use the jQuery extender: specInfo=ebox.wsFlCurrent() ;


wsurvey.flContents.dom(ebox,which)  :

  Return pointers to the various components of a floatingContent container

     ebox:  string id, or jQuery or dom object, of a floatingContent container (simple or complete)
     'which' is optional: it can be 'm','c','h,' or 't'. Or '*' (the default)

  By default, an object is returned:
     {'main':jqm,'header':jqh,'transientHeader':jqt,'content':jqc}
  where each "jqx" is a jQuery object pointing to that section.

  If 'which' is specified,
    'm' : return jQuery object of main floatingContent container
    'h' : return jQuery object of header area (null if ebox is simple floatingContent container)
    't' : return jQuery object of transient header area (null if ebox is simple floatingContent container)
    'c' : return jQuery object of content area (null if ebox is simple floatingContent container)
    '*'  : return the object with all 4 of these

  Notes:
     * "header" contains both the permanent header, history and scrolling buttons, and the transient headers.
     * "transientHeader" refers to the transient headers subarea, that is within 'header'.
     *  wsurvey.flContents.header changes the transientHeader subarea.
        There is no built in method for changing the permanent headers!

  If there are issues with ebox -- it doesn't point to an element, or the element is not a floatingContent area,
  a false is returned (and a note is written using console.log()).

  If ebox is a floatingContent container, but does not have header and content areas, jqm will contain a jQuery
  object pointing to the floatingContent container. The other three will be null.
  This can happen if  wsurvey.flContent.container.create() was used, (instead of  wsurvey.flContent.create().

  Hint:  .dom can be used to facilitate searching for elements within a floatingContent container.

     For example: if two floatingContent containers -- say  'menu1' and 'menu2'-- both contain:
       <input type="text" name="yourChoice" size="30">
     and you want to extract the "yourChoice" from floating 'menu2'

      let edom=wsurvey.flContents.dom('menu2');  // skip error checking for brevity's sake
      let edomC=edom['contents'];               // or use edomC=wsurvey.flContents.dom('menu2','c')
      let einput=edomC.find('[name="yourChoice"]');
      alert('You chose: '+einput.val());

      Or, you could use
         einput= $('#menu2').wsFl.find(('[name="yourChoice"]');


wsurvey.flContents.find(ebox,sel,siblingOk)

   Find element(s) in ebox's content area; using sel as jQuery selector string.
   
   If siblingOk =1 , then first check if ebox is a main floatingContent container.
   If not, then wsurvey.flContents.closest() is used to the ebox's parent floatingContent container.
   A find is then done within this parent.

   If siblingOk=0 (the default), the ebox MUST be the id of the floatingContent container.

   You can also use the jQuery extension of ebox.wsFlFind(sel)

   Example:
     einput= $('#menu2').wsFl.find(('[name="yourChoice"]');
   or
      einput=wsurvey.flContents.find($('#menu2'),'[name="yourChoice"]');

   Example: assuming a button  inside of a floatingContent container:

        <input type="button"  value="show them!" onClick="showMyBrothers(this)" >

     function  showMyBrothers(athis) {
       let ethis=$(athis);
       let eBrothers=wsurvey.flContents.find(ethis,'[name="brothers"]',1);
       eBrothers.show();
     }

wsurvey.flContents.header(ebox,newHeader,doappend)  :

   Read or set the transient header area.

   The syntax (including the special feature) is the same as that used in wsurvey.flContents.contents.

   Note that wsurvey.flContents.headers() is a synonym.

   You can also use the jQuery extender: isVis=ebox.wsFlHeader(newHeader,doappend), or daHeader=ebox.wsFlHeader()


wsurvey.flContents.headerView(ebox,which) :

   Hide, display, or toggle view of the permanent header area.
   This can free up space in the floatingContent container, making the content area bigger.
   But it does mean the permanent and transient headers are hidden, as well as the control buttons.

   ebox is a string id, or a jQuery or dom object.
   If ebox does not resolve to  jQuery object, false is returned.
   If ebox, or a parent (.closest()) of ebox is not a floatingContent container, false is returned.

   'which' can be: 'hide', 'show', or 'toggle'.

   ebox does NOT have to be the floatingContent container. It can be any element within a floating content --
   the "header" area of the parent floatingContent container will be hidden/shown/toggled.

   Thus:  you can specify wsurvey.flContents.headerView as an event handler.
   In this case (where no 2nd argument can be specified), include a data-which attribute in the
   input (or whatever) element.
   Or specify 'headerView' as a data element -- if using something like .on('click',dataObj,wsurvey.flContents.headerView)

   In all cases: which should have 'hide','show', or 'toggle' as a value!
   If none of these 3 methods of determining which works 'hide' is used.

   Hint:
     A button calling this could be in the permanent headers, but that would make it difficult to
     undo the action -- since the button will be hidden when the header area is hidden!


wsurvey.flContents.hide(ebox,speed)
   Hide (do not display) the ebox floatingContent container.
   speed is optional -- if specified it shoudl be milliseconds.
   If greater than 0, the element will fade out using speed as the  duration of the fadeout.
   If 0, or not specified, the element is instantly hidden.

   Note: since one might be forgetful, you can call this using wsurvey.flContents.hide(speed,ebox) --   speed MUST BE A NUMBER !

  You can also use  the jQuery extender:   specInfo=ebox.wsFlHide(speed) ;


wsurvey.flContents.onTop(ebox,which) :
  Move ebox to the foreground or background.
     which=1 : to foreground (on top of all other floatingContent containers.
     which=0 (or -1)  : to background (below all other floatingContent containers).
  If which is not specified, which=1 is used.

  wsurvey.flContents.onTop is bascially a synonym for wsurvey.flContents.container.setZindex.
  See its description (in III.b) for a more complete discsusonn of the capablities and limitations
  of moving floatingContent containers to the foreground.

  You can also use  the jQuery extender: ebox.wsFlOnTop(which) ;


wsurvey.flContents.show(ebox,speed,onTop)
   Show (do display) the ebox floatingContent container.

   The speed argument is the same as described for wsurvey.flContents.hide -- for a fade in.
   onTop is optional. If specified, and 1, ebox is moved to the foreground (onTop of all other floatingContent containers)

   Note: since one might be forgetful, you can call this using wsurvey.flContents.show(speed,ebox) --  speed MUST BE A NUMBER!

   You can also use  the jQuery extender: ebox.wsFlShow(speed) ;


wsurvey.flContents.toggle(ebox)
   Toggle the display of ebox between show and hide.
   Note that this is instantaneous (there is no speed option).


wsurvey.flContents.visible(ebox)
   Return the current visiblity status of ebox.
     0: not visible (hidden)
     1: visisble (shown)

    Careful: false is returned if ebox is not a proper floatingContent container.
    Thus, strict operators (===0 or ===false) should be used!

   You can also use the jQuery extender: isVis=ebox.wsFlVisible(speed) ;

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

III.a.3: Some advanced functions

 wsurvey.flContents.checkOverflow(anid,tol,afull)

   Check  if the contents of a floatingConteint container  are "overflowing" -- are scroll bars (either horizontal
   or vertical) needed to view its content.

   Returns true if they are, false if not.

     anid: string id of floatingContent container. Or its jquery object.
     tol:  toleranace. Optional. Used to deal with round up or other errors -- it is the # of pixels
           of overlap that are tolerable. Using less than 1 is NOT recommended (1 is the default)
     full: optional. If specified and 1, then instead of true or false, return an associative array with:
            ['status':false or true,'scrollWidth':scrollWidth,'scrollHeight':scrollHeight,
                                     'innerWidth':innerWidth,innerHeight':innerHeight]

  Notes:
    *   false occurs if scrollWidth > innerWidth + tol,  or scrolHeight>innerHeight+tol
        You can use full=1 to quickly find these basic features of the content portion of a ws_showBox container!

    *  If an error (such as anid doesn't point to jquery object), returns ['status':'error','content':erroMessage]
       If full not specified, errors cause a return of false (no error message)

    * Note that given a container with some content in it:
         * scroll height and width:  how big the container would have to be to display this without scroll bars
         * inner height and width : the max sizesa this container can display without scroll bars
         These are somewhat imprecise -- paddings and scrollbar width & height are abstracted from

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


wsurvey.flContents.container.doEsc(evt,findMe) 

 esc handler for wsFloatingContent -- close a floatingContent container when esc key is hit.

 The one argument form is used as the  esc handler for wsFloatingContent -- close "most recently created" boxes first.
 Which  ONLY considers wsFloatingContent containers! The one argument mode is for internal use!

 Of interest is the 2 argument form -- which does NOT close anything.
 It  will return the next floatingContent container that WOULD be closed on an esc. Or the last one that would be closed

     jqObj=wsurvey.flContents.container.doEsc(0,findMe)

 where
   findme:  0: the last container that would be closed,  1: the next one (the default)
   jqObj  : the jQuery object of the next (or last) floatingContent container that esc would close.
            or false if no floatingContent containers are visible

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

III.a.4:  jQuery extenders

  Most of the modifying the header and content areas can also be invoked as "extended" methods of jQuery.

  That is, instead of calling:

     let jq=$(anid);
     wsurvey.flContents.funcx(jq,otherArgs);

  you would use something like

     let jq=$(anid);
     jq.wsFlFuncx(otherArgs)

   where, as described below, 'Funcx' could be 'Contents', etc.

  The supported functions : and  their jQuery extender versions.

     wsurvey.flContents.contents(jq,newContent,append) :  jq.wsFlContents(newContent,append)
     wsurvey.flContents.current :  jq.wsFlCurrent()
     wsurvey.flContents.find(ebox,sel)     :  ebox.wsFlFind(sel)
     wsurvey.flContents.header(jq,newContent,append)   :  jq.wsFlHeader(newContent,append),
     wsurvey.flContents.hide(jq,speed)      :  jq.wsFlHide(speed), or jq.wsFlHide()
     wsurvey.flContents.show(jq,speed,onTop)      :  jq.wsFlShow(speed), or jq.wsFlShow()
     wsurvey.flContents.onTop(jq,direction) :  jq.wsFlOnTop(direction), or jq.wsFlOnTop()
     wsurvey.flContents.toggle(jq,speed)    :  jq.wsFlToggle()
     wsurvey.flContents.visible(jq)         :  jq.wsFlVisible( )

   Note: .wsFlContent and wsFlHeaders can be used as synoymns (for .wsFlContents and wsFlHeader)

 Advanced users note:

   The "wsFl" prefix can be changed.

     In your code, BEFORE loading wsurvey.FloatingContent.js, set the wsurvey_flContents_extendPrefix variable.
     And use that prefix instead of wsFl

  Example:
      <script type="text/javascript">
         window['wsurvey_flContents_extendPrefix']='w_';
      </script>
      <script type="text/javascript" src="/generalLibs/jquery-3.6.0.min.js"></script>
      <script type="text/javascript" src="/otherLibs/wsurvey.FloatingContent.js"></script>

     Which means one would use : jq.w_Contents(), instead of jq.wsFlContents(),
     and similarly for the other wsurvey.flContents extended jQuery functions.

     Note that, you can't change the 'Content' to something else! Maybe in a later release?

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

III.b:  Functions: modifying the floatingContent container.

These functions directly control the "floatingContent" container. Some of them replicate functions specified in III.a.
  However: if you are just creating a floatingContent container (you use wsurvey.flContents.container.create() directly,
           the functions in III.a. may not work, or may not be available.

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

III.b.1:  Quick list

    +  wsurvey.flContents.container.close(athis) : close (hide) a container. Designed to be used as an event handler
    +  wsurvey.flContents.container.create(aid,opts) : create a floating content container
    +  wsurvey.flContents.container.desc(iconMove) :  tips on using the floatingContent container
    +  wsurvey.flContents.container.doExpand(ebox,todo) : toggle size of a  floatingContent container
    +  wsurvey.flContents.container.doResize(ebox,specs,itest) : change size and position of a floatingContent container
    +  wsurvey.flContents.container.list(showComplete)    : return list of floatingContent containers
    +  wsurvey.flContents.container.remove(ebox) :remove floatingContent container attributes from an element
    +  wsurvey.flContents.container.setZindex(ebox,idire) : move a floatingContent container to foreground or background
    +  wsurvey.toPx(aa,asize0,bodyFontSize)  : convert size/location measures to pixels


III.b.2: Description of functions


wsurvey.flContents.container.close(ebox,anaction)

  Close (or hide) a floatingContent container. Or open, or return visiblity flag

  This has two uses: as a onClick event handler, or as a explcit  function call.
  If an onClick event, only the first argument is used.
  When called, will automatically close the floatingContent container containing the element that was
  clicked on. For example:
     <input type="button" value="x" onClick="wsurvey.flContents.container.close(this)">
        or

     <input type="button" value="x" id="closerTwo">
          ...
     $('#closerTwo').on('click',wsurvey.flContents.container.close)

    What does this mean?
        you can create additional closer buttons (within the content or header sections
        of a floatingContent container) by specifying wsurvey.flContents.container.close as the 'click' handler.

 The rest of this section describes the 2 argument form -- the form used in explicit function calls

     ebox : a string containing the id of the floatingContent container, or the jquery object of the floatingContent container.
           IOW: unlike the event handler version, the "closest parent"  floatingContent container is NOT looked for.
                Thus: if ebox is NOT a floatingContent container, an error message is written using console.log()

    anaction: an action:
        'open' or 'show' or '1' : open (display) the floatingContent container
        'hide or '0'  : hide the floatingContent container-- retains the state of the "hide buttons" and "expand"
        'close'   : resets (buttons are shown, full-screen expansion it toggled off). Then a hide occurs
        'toggle':  toggles state. Return state AFTER toggling (0=hidden, 1=visible)
        'visible': returns 0 if e2 is visible, 0 if not.

    Only the first (case-insensitive letter) matters. If a unrecognized action is requested, false is returned
    (check with  ===false)

wsurvey.flContents.container.create(aid,opts)

  This is called by wsurvey.flContents.create -- it setups the floatingContent container.
  The aid and opts are as described in the floatingContent container options section above

  You could use this -- instead of wsurvey.flContents.create -- if you just want to convert an existing element into
  a floatingContent container, and do NOT want to add header and content areas.

  If this is the intended use, be sure that the contents of the element (being converted into a floatingContent container)
  are small enough to fit in the specified height and width. Or contains a sub-element with all the contend, and is scrollable.

  Otherwise, when the content in the existing element is scrolled, the control buttons are also scrolled.
  They will disappear!


wsurvey.flContents.container.desc(iconMove)

  Return a string with tips on using the floatingContent container

    iconMove is optional. If specified, should be a string that is used to display the "iconMove".
   For example:  '&#9995;' (a yellow palm).
   If not specified, the default is '&#9769;' (a cross).

   Note that this function is used to create the "info"  button (if noTips=0).

   Or, if called with evt is a pointer to an jQuery or DOM element ...
        wsurvey.flContents.container.desc(evt)
   such as accomplished with an inline, or assigned, click event.

   The tips will be displayed at the top of the floatingContent container.

   Note that clicking such a button again will remove these tips.


wsurvey.flContents.container.doExpand(ebox,todo)

   Toggle size of a  floatingContent container : either  "near-full", or at current size (before set to near-full)


      e2 : jquery object of the floatingContent container  (or string id )
      todo : 0 -- set to original size
             1 -- expand to "near full screen"
             2 -- toggle between these

wsurvey.flContents.container.doResize(ebox,specs,itest)

  Resize or move a  floatingContent container.
  Nothing else changes (content stays the same, visiblity stays the same)

 ebox : a string ,or jQuery or DOM object, pointing to a floatingContent container.
        If not a floatingContent container, return false and use console.log() to display an error message

  specs is an object with fields. You can specify one or more of them. Anything unspecified is not changed.
            'top' : top of box (% or px, or em).
            'left' : left of box (% or px, or em)
            'width':  width of box (% of px, or em)
            'height':  height of box (% of px, or em)
            'latest': 0,1, or 2. 0 is the default

                    0, use the "original" position and size when doing relative changes.
                    1, use the "latest" position and size when doing relative changes.
                    2, reset the "latest" position to be the "original" position

                     The 'latest' position is NOT affected by moves done using the mover and resier control buttons.
                     It is only seen by wsurvey.flContents.container.doResize

     doResize can also be used to read current and original location info about a floatingContent container --
     by using specs='O' (capital 'o') or specs='C'. Or reset the size by using 'R'

     See III.e for a full description of doResize


 wsurvey.flContents.container.list(complete)

   Return a collection (of jQuery objects) of all currently specifiedf floatingContent containers.
   Doesn't matter if they are visible or not
   
   Complete is optional. It can be:
      0 (or 'a') : all floatingContent containers  (the default)
      1 (or 'c') : only complete floatingContent containers
      2 (or 's') : only simple floatingContent containers

wsurvey.flContents.container.remove(ebox)

   Remove floatingContent container attributes from an element was converted to  floatingContent container.

    ebox : a string ,or jQuery or DOM object, pointing to a floatingContent container.
        If not a floatingContent container, return false and use console.log() to display an error message

     All floatingContentattributes and content (such as the various expansion arrows and move icons) are removed.
     If a "removeClass" was specified, all removed classes are restored.

     One use of  wsurvey.flContents.container.remove is to tinker with the control buttons of an existing floatingContent
     container.
        a)   call wsurvey.flContents.container.remove with ebox pointing to an existing floatingContent container
             element
        b)  then call wsurvey.flContents.create, using this ebox (and whatever options you want the reCreated
             floatingContent container to have.

wsurvey.flContents.container.setZindex(e,idire)

   Set the z-index of a floatingContent container -- to on top, or behind, all other floatingContent containers.
      e: jQuery object pointing to a floatingContent container.
          Or a string containing the id of a floatingContent conatiner (does not need to start with a #)
      idire: 1: move to on "top" of all floatingContent containers,
             0 (or any other number): move to "behind" all floatingContent containers

   Note that this only acts in relationship to other floatingContent containers.
   Other elements, with their own z-index, are ignored.
   Thus, it is somewhat indeterminate if (after a z-index change )   the floatingContent container will be behind,
   or in front of, non-floatingContent elements.

   Setting the zIndex of all floatingContent contaiers to a relatively high value will tend to ensure that the
   floatingContent containers are always on top.

  Caution: the css z-index attribute only works with containers that have the same parent.
    In particular: when comparing containers that have different parent, the z-index of a child can never be greater than
    its parent. That means that a floatingContent container, that is within another element,
    would have an effective Z-index of this parent element.

    What does this mean? It is safest  for all floatingContent containers to be direct children of the document!
    Othwerwise, wsurvey.flContents.container.setZindex might not work as expected.

    Details:  https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context

wsurvey.toPx(aa,asize0,bodyFontSize)

 This is used internally, but could be useful.
 Nowadays, this information is also supplied via wsurvey.flContents.container.doResize with itest=1

   Convert a string containing a "size" into pixels.

   aa: string. Can be (case insensitive): 'mmPx', 'mmEM', or 'mm%' (mm an integer or a decimal)
       Or just a number, in which case integer conversion is done.
   asize: the "document" size: used in % measures. Either a height or width
          We recommend using $(window).height(); and $(window).width().
          IOW: if you are looking to convert top/height and left/width measures, you SHOULD specify the appropriate size.
          Shortcut: if asize='width' or asize='height', the appropriate $(window). measure will be used.
                    So you don't have to remember the exact syntax.

                    CAUTION: as noted above, for this to work properly, the html document SHOULD start with a <!DOCTYPE HTML>

          If not specified, an average of these two is used.

   bodyFontSize: The pixel size of a character. It is used for em measures.
                 If not specified bodyFontSize=$("body").css('font-size') is used.
                 This default is probably adequate for most needs.

   If asize is not specified: the average of the document height and width is use
   If bodyFontSize is not specified, the default font size is  used ($("body").css('font-size'))

   Returns an integer representing the px size of aa

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

III.c:   Customizing wsurvey.FloatingContent default styles

  wsurvey.FloatingContent creates and uses a number of styles.  Several of these can be changed with
  the various options -- but not all of them. Ambitious designers can substitute their own versions of these --
  by creating a stylesheet with a name of wsurvey.FloatingContent_defaults
  For example:
    <style type="text/css" name="wsurvey.FloatingContent_defaults"> .... </style>

  It is advised that you pay close attention to how the defaults are specified -- the appearance of floatingContent
  containers may be flawed if the some of the attributes in some of the styles are not specified.

  To extract the current version of the stylesheet, you can use something like:
      let defStyles=$('[name="wsurvey.FloatingContent_defaults"]');
      let defStylesText=defStyles.prop('outerHTML'));
  .. and then display defStylesText somewhere


  Note:
    Floating content containers contain two special classes -- these are classed added to the element that
    was "converted". These classes flag that this element is a floatingContent container. By default, no
    CSS styling is associated with these classes.
      * wsFloatingContent -- assigned to an element by wsurvey.flContent.container.create().
      * wsFloatingContent_main -- assigned to an element by wsurvey.flContent.create().
    Thus: if wsFloatingContent exists but wsFloatingContent_main does not, than this is a simple floatingContent 
          container. One that does NOT have a "header" or "content" area.
  
    While not necessarily recommened, one could create css styles with these names; to apply css formatting
    to all floatingContent containers (perhaps different styles depending on whether they are simple of
    complete floatingContent containers
          that does

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

III.d:  Working with content history

If contentHistor_enable  is enabled, everytime new material is written to a content area (or appended to one), the  material
in the content area is saved in an entry in a floatingContent container specific "history list".
One can then re-display these entries by using the prior and next buttons.
Thus: one can go  back and forth through what has been displayed, reviewing prior material.
And you can do this in any order, with any amount of repetition.

   Saving to history ONLY occurs when wsurvey.flContent.content(), is used -- either to replace, or append to,
   a complete floatingContent container's "content area".
   On the fly changes to elements within the content area, that other javascript functions may cause, do NOT effect
   the material saved in history list entries.
      There is an exception to this, which is complicates matters -- see below for more details.

While a convenience, there are a few limitations to content history.  These limitations depend on the choice
of  "content history method" (the contentHistory_method option).

a) method='html'. This is the default if contentHistory is enabled (using the contentHistory_enable option)
   After wsurvey.flContent.content() replaces, or appends, material to the contentArea -- the html of the content
   area is copied to the history list.
      Limitation: the html and text is copied, but event handlers are NOT.
                  Thus, any event handler assigned to elements in the content area are NOT available when
                  one views an entry from the history list.
                     These could be event handlers assigned after use of wsurvey.flContent.content().
                     Or they could be event handlers already assigned when an existing element is moved to a
                     content area.
                  Note: if one views prior entries, and then goes back to the most recent -- the event handlers
                        are lost.
       Strengths: the displayed material, in each history list entry, does not change
       Workarounds:  inline event handlers will work.
                     Or, you can use a contentHistory function to reassign event handlers whenever a history entry
                     is displayed.
       Technical note:  .html() is used to read the "html of the content area".

b) method='dom'
   After  wsurvey.flContent.content() replaces, or appends, material -- a collection of the dom elements in the
   content area is copied  to the  history list.
       A collection consists of an array of pointers to dom objects, that may or may not be actively displayed. 
       In this case, an entry in the history lists contains a collection of the dom objects in the content area
       just after wsurvey.flContent.content() does a replacement or an append.

       Limitations:  if some other javascript function modifies a dom object that is in the content area,
                     and this object is also in a history list entry -- when this history list entry is displayed,
                     the changed dom object will be displayed. 
                     That is: NOT the state of the dom object at the time it (actually, a pointer to it) was saved to the history list!
                     That means the history may not be accurate -- when displayed it may reflect recent changes.
                     This can happen when material is appended in succession -- so that a portion of the dom elements
                     are the same across several history entries, and are in the current content area.
       Strenghs: event handlers are NOT lost. Thus, when displaying an history entry -- clicking on buttons
                 will invoke the assigned event handler.
       Workaround: Avoid changing content area elements with other javascript functions.
                  Or, avoid using append if such changes will occur.
       Technical note:  .contents() is used to read the "dom elements of the content area" (therefore text nodes
                        are also part of a collection).

 Notes:
  * More memory is required for html (string) storage than dom (collection) storage.
  * Unfortunately, the lack of good memory statistics (available via javascript function calls) means
    refined management of the history list is impratical. But collections take very little space, and modern
    browsers seem to store html content very efficiently.
    Hence, on modern devices  memory issues are unlikely.
  * But to avoid extreme cases, a limit of 1000 entries are allowed for each floatingContent container.
    If that limit is hit, older entries are dropped.
  * If you are really concerned, use the 'dom' method!
  * javascript (or jQuery) does not have a reliable method for retreiving current event handlers. 
    Which is why auto reassignment of event handlers is not available in the 'html' method. 
    Use contentHistory_function can overcome this, if you know what event handlers should be assigned to what elements.

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

III.e. Descpription of wsurvey.flContents.container.doResize()

  Resize or move a floatingContent container. Nothing else changes (content stays the same, visiblity stays the same).
  Or, just return information.

       specInfo=wsurvey.flContents.container.doResize(e2,specs,itest)

   where:
     specs  : an object with new location and size specifications. Or a special case instruction
     e2     : the jquery object of the floatingContent container.  Or a string with its id (a '#' is prepended if necessary)
               If e2 does not point to a wsFloatingContent classed object, return 0 (nothing is done)
    itest   : if specified, and 1 -- do NOT do the move. Just compute what the move would be, and return the results.

  specs is typically an object with fields. You can specify one or more of them. Anything unspecified is not changed.

     'top' : top of box (% or px, or em). Location in the browser window.
     'left' : left of box (% or px, or em). Location in the browser window.
     'width':  width of box (% of px, or em)
     'height':  height of box (% of px, or em)
     'latest': 0,1, or 2. 0 is the default

         0, use the "original" position and size when doing relative changes.
         1, use the "latest" position and size when doing relative changes.
         2, reset the "latest" position to be the "original" position

       The 'latest' position is NOT affected by moves done using the mover and resier control buttons.
       It is only seen & used by wsurvey.flContents.container.doResize

   Note: em, and %, are converted into pixels using the document's default font-size, and current document width and height

  Specifying relative changes:
      precede with a + or  - to increase or decrease by this much of the ORIGINAL (creation) size,
      Or:  if 'latest':1  changes are applied to the  latest size and position specifications
      (after most recent call to wsurvey.flContents.container.doResize that used 'latest=1')

      In the first case (latest=0): if creation width was 100 px,
               'width':'200px'   : width becomes 200px
               'width':'+200px': : width becomes 300px
               'width':'-20%'    : width becomes 80px
               'width':'150%'    : width becomes 150px

      By default (with latest=0) after this kind of "relative" change, the "creation" (original) width is
      NOT reset to these values. Hence, consecutive calls to wsurvey.flContents.container.doResize works with
      the ORIGINAL size & position.

      To make cumulative changes, use 'latest':1 (perhaps with 'latest':2 used in a first call, to ensure that the first value of
      the "latest" position is the "original" position)


 What is returned?

    Typically (with specs and e2 specified) ...

    a) the box is moved & resized
    b) An object with old and new positions is returned
       4  fields (top,left, height, and width), each of them a 2 element array of: [basePosition,newPosition]
       (in pixels). basePosition is either the "original" or "latest"

   If itest=1, step a is NOT done! The object returned is where the box WOULD be IF the move had hapened

 Special cases (case insensitive)

    * specs='O' (capital o)  or specs={}
      return the original position  as:  {'left':origLeft,'top':origTop,'height':origHeight,'width':origWidth}

      example: origSpecs=wsurvey.flContents.container.doResize('O','#myFlContent')


    * specs='0' (zero) or specs='C'
       return the current position as:  {'left':currentLeft,'top':currentTop,'height':currentHeight,'width':currentWidth}

      Or: use wsurvey.flContents.current(ebox) -- or ebox.wsFlCurrent();

   * specs='L':

      Does nothing, returns latest position
      return the original position  as:  {'left':latestLeft,'top':latestTop,'height':latestHeight,'width':latestWidth}
      Note:, if no 'latest=1' call ever made, returns original position

    * specs='R', or specs='B', or specs={'left':'+0'}

       Moves box to the original position and size! Returns {'left':[origLeft,origLeft] ... (similar for top,width, and height)
       Specs B will also reset the 'latest' position & sizes back to the original.

       example: backToOrig=wsurvey.flContents.container.doResize({'left':'+0'},'#myFlContent')


   Notes:

     * when a floatingContent container is created, a data-wsfloatingcontent_positionoriginal attribute is added to the element
       (that is being 'converted'   into a  floatingContent container).
       This contains the "original" size and position. It is NEVER changed.
       Thus, relative changes (when latest=0) are ALWAYS relative to these original specifications.
       Example:  data-wsfloatingcontent_positionoriginal="position=fixed,top=43px,left=1248px,height=363px,width=634px"

     * floatingContent containers es are created with, and should ALWAYS have,  "position:fixed".
       If not (if somehow it was changed), wsurvey.flContents  may not behave properly!

       =================================================================

IV:  Displaying tips on how to use floatingContent containers

Something like this is returned (as a string) when wsurvey.flContents.container.desc() is called.

<em>floatingContent containers</em> are used to display a variety of content.
  These <tt>display containers</tt> can be manipulated by you, the end user,
    in a number of ways -- by clicking (or clicking and dragging) on buttons displayed in the corners!

<ul >
  <li><span style="cursor:move;border:1px solid black">&#9769;</span> &nbsp; move the box... click, hold the mouse button down, move, and release.
For some floatingContent containeers, you can also click-hold-move on the <span  style="cursor: move;background-color:#dbdbab;border:1px dotted gray">top border</span>
  <li><span style="cursor: pointer;" >&#9195; </span> move the box to the foreground. Or right-mouse-click to move to the background.

  <li><span style="cursor: pointer;" >&#128307; </span>  expand the box to cover most of the window. Click again to restore to prior size. This is not available on all floatingContent containers!

  <li><span style="cursor: pointer;border:1px solid black"> &neArr;  </span>&nbsp;  display the contents of the box in a new window
  <li><span style="cursor: pointer;border:1px solid black"> &Chi;  </span>&nbsp;  hide the box
  <li><span style="cursor: ne-resize;border:1px solid black"> &nearr; </span>&nbsp;  expand the box .. click, hold the mouse button down, move (to resize in that direction), and release
<br> the &searr;, &swarr;, and &nwarr; buttons can be used in similar fashion.
  <li>If you hit the <tt>Esc</tt> key, these boxes will be hidden one-at-a-time.
</ul>
</div>

        =================================================================

V: Contact and legal

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

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


