// Copyright (C) 2007-2010 Bristle Software, Inc.
// 
// This program 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 1, or (at your option)
// any later version.
// 
// This program 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.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc.

/******************************************************************************
* com.bristle.jslib.Enforce.js
*******************************************************************************
* Purpose:
*       This file contains routines that enforce the validation rules of user
*       input controls.
* Usage:
*       - The typical scenario for using this file from an HTML file is:
*         <script language='JavaScript' src='com.bristle.jslib.Enforce.js'></script>
*         Call the various functions that reside here.
* Assumptions:
*       - The file "com.bristle.jslib.Util.js" has already been loaded.
*       - The file "com.bristle.jslib.Validate.js" has already been loaded.
* Effects:
*       - None.
* Anticipated Changes:
* Notes:
* Implementation Notes:
* Portability Issues:
* Revision History:
*   $Log$
******************************************************************************/

// Create the "namespace" to hold the functions in this file.
com.bristle.jslib.Enforce = {};

/******************************************************************************
* Assist in enforcing validation rules.
* If blnTest is true, returns true.  Otherwise, reports the specified 
* message to the user, moves focus back to the specified control, and 
* returns false.
*
* Usage:
*  - The typical scenario for using this class is:
*          <input id='txt1'
*                 type='text'
*                 onchange='return txt1_onChange(this)'
*                 />
*          function txt1_onChange(txtIn)
*          {
*              return com.bristle.jslib.Enforce.enforceValidation
*                     (com.bristle.jslib.Validate.isPositiveInteger
*                              (com.bristle.jslib.Util.trim(txtIn.value))
*                     ,txtIn
*                     ,"Value entered must be a positive integer.\n"
*                      + "Hit Esc to leave the previous value in place."
*                     );
*          }
*    Notice the "return" statements both inside txt1_onChange and on the 
*    call to it.  These are both required to cause the onchange event to
*    be cancelled.  Otherwise the invalid value is accepted.
******************************************************************************/
com.bristle.jslib.Enforce.enforceValidation =
function(blnTest, ctlIn, strMessage)
{
    if (blnTest)
    {
        return true;
    }
    else
    {
        alert(strMessage);
        // Note:  Setting the focus is not usually necessary.  Returning
        //        false to the caller is usually sufficient.  If the 
        //        calling code is written correctly, as shown in the 
        //        "Usage" section above, it will propagate the false
        //        value all the way to the onchange= line of the HTML
        //        which will cancel the onchange event.  This prevents 
        //        the focus from ever leaving the control, and prevents
        //        the newly entered value from being accepted.  If the
        //        user tries again to move the focus, the onchange
        //        event fires again because the invalid value was not 
        //        accepted.  Perfect.  No need to explicitly set the 
        //        focus.  However:
        //        1)  The caller may not propagate the false all the 
        //            way to the HTML.
        //        2)  The focus still moves if the user was trying to 
        //            move it off of the form, not to another control.
        //            For example, when he hits the Tab key from the 
        //            last control in the tabbing sequence of the form, 
        //            focus moves off the form to the URL region of the 
        //            Web Browser.
        //        In both of these cases, it helps to move the focus 
        //        explicitly back to the control.
        // Note:  Given that we want to explicitly move the focus, for
        //        the reasons described above, simply calling:
        //                ctlIn.focus()
        //        may not be sufficient because it sets the focus to
        //        the control immediately.  However, if false was not 
        //        propagated correctly, the onfocus event fires after
        //        the onchange event, moving the focus away from the 
        //        control again.  It is more effective to queue an
        //        event to set the focus, to occur shortly (after all 
        //        previously queued events like the pending onfocus 
        //        event).
        com.bristle.jslib.Event.queueFocusEvent(ctlIn);
        return false;
    }
}

/******************************************************************************
* Interact with the user to force the trimmed value of the specified 
* textbox to be non-empty.
* Returns true if the value was valid; false if interaction with the 
* user was required.
*
* Usage:
*  - See com.bristle.jslib.Enforce.enforceValidation() for typical usage.
******************************************************************************/
com.bristle.jslib.Enforce.textBoxEnforceNonEmpty =
function(txtIn)
{
    return com.bristle.jslib.Enforce.enforceValidation
            ((com.bristle.jslib.Util.trim(txtIn.value) != "")
            ,txtIn
            ,"Value must be specified.\n"
             + "Hit Esc to leave the previous value in place."
            );
}

/******************************************************************************
* Interact with the user to force the trimmed value of the specified 
* textbox to be a positive integer or empty.  
* Returns true if the value was valid; false if interaction with the 
* user was required.
*
* Usage:
*  - See com.bristle.jslib.Enforce.enforceValidation() for typical usage.
******************************************************************************/
com.bristle.jslib.Enforce.textBoxEnforcePositiveIntegerOrEmpty =
function(txtIn)
{
    return com.bristle.jslib.Enforce.enforceValidation
            (com.bristle.jslib.Validate.isPositiveIntegerOrEmpty
                        (com.bristle.jslib.Util.trim(txtIn.value))
            ,txtIn
            ,"Value entered, if any, must be a positive integer.\n"
             + "Hit Esc to leave the previous value in place."
            );
}

/******************************************************************************
* Interact with the user to force the trimmed value of the specified 
* textbox to be a positive integer.  
* Returns true if the value was valid; false if interaction with the 
* user was required.
*
* Usage:
*  - See com.bristle.jslib.Enforce.enforceValidation() for typical usage.
******************************************************************************/
com.bristle.jslib.Enforce.textBoxEnforcePositiveInteger =
function(txtIn)
{
    return com.bristle.jslib.Enforce.enforceValidation
            (com.bristle.jslib.Validate.isPositiveInteger
                (com.bristle.jslib.Util.trim(txtIn.value))
            ,txtIn
            ,"Value entered must be a positive integer.\n"
             + "Hit Esc to leave the previous value in place."
            );
}

/******************************************************************************
* Interact with the user to force the trimmed value of the specified 
* textbox to be a non-zero positive integer or empty.
* Returns true if the value was valid; false if interaction with the 
* user was required.
*
* Usage:
*  - See com.bristle.jslib.Enforce.enforceValidation() for typical usage.
******************************************************************************/
com.bristle.jslib.Enforce.textBoxEnforceNonZeroPositiveIntegerOrEmpty =
function(txtIn)
{
    return com.bristle.jslib.Enforce.enforceValidation
            (com.bristle.jslib.Validate.isNonZeroPositiveIntegerOrEmpty
                (com.bristle.jslib.Util.trim(txtIn.value))
            ,txtIn
            ,"Value entered, if any, must be a positive integer greater"
              + " than 0.\n"
             + "Hit Esc to leave the previous value in place."
            );
}

/******************************************************************************
* Interact with the user to force the trimmed value of the specified 
* textbox to be a non-zero positive integer.  
* Returns true if the value was valid; false if interaction with the 
* user was required.
*
* Usage:
*  - See com.bristle.jslib.Enforce.enforceValidation() for typical usage.
******************************************************************************/
com.bristle.jslib.Enforce.textBoxEnforceNonZeroPositiveInteger =
function(txtIn)
{
    return com.bristle.jslib.Enforce.enforceValidation
            (com.bristle.jslib.Validate.isNonZeroPositiveInteger
                (com.bristle.jslib.Util.trim(txtIn.value))
            ,txtIn
            ,"Value entered must be a positive integer greater than 0.\n"
             + "Hit Esc to leave the previous value in place."
            );
}

