The Gravey Framework and RATS RIA

grvUtils.js

Summary

Collection of general utility routines

Version: 2.0

Requires:

Author: Bruce Wallace (PolyGlotInc.com)


Class Summary
grvArgs This function parses ampersand-separated name=value argument pairs from the query string of the URL; It stores the name=value pairs in a static list; adapted from here.

Method Summary
static boolean grvAfter( <String> datestr, <Date> date )
           Determine whether given date is at or before a given datestr (where empty means "future").
static boolean grvAfterNow( <String> datestr )
           Determine whether today is at or before a given date (where empty means "future").
static Object grvAppName(appId)
          
static Object grvArgsToString( args )
          
static Object grvArrayToString( a )
          
static boolean grvBefore( <String> datestr, <Date> date )
           Determine whether a given datestr is explicitly before the given date.
static boolean grvBeforeNow( <String> datestr )
           Determine whether a given date is explicitly before today.
static void grvBusy()
           set the cursor to the hourglass icon
static void grvBusyDo( <String> funcname, <String> funcargs, <int> optDelayMilliSecs )
           generic utility function to queue up for future execution the specified function with the specified arguments after a specified amount of delay.
static void grvClearGlobalVar( <String> varname )
           static routine to dynamically undefine/delete a global variable
static void grvClearGlobalVars()
           static routine to dynamically undefine/delete ALL "...GlobalVars" variables
static void grvClearPersistentVars()
           static routine to dynamically undefine/delete ALL "...PersistentVars" variables
static boolean grvDateKeyFilter( <int> keyCode, <String> valueSoFar )
           is the given character a legal addition to the given dollar string
static String grvDiamond(<boolean> optBlankFlag)
           return the HTML to draw a diamond
static boolean grvDollarKeyFilter( <int> keyCode, <String> valueSoFar )
           is the given character a legal addition to the given dollar string
static Object grvDollarStrFilter(s)
          
static String grvDot()
           return the HTML to draw a biggish dot
static void grvEditElem( e, makeSelected, makeEdited, makeInvalid, optUnselectColor )
          
static void grvEditElemID( ID, makeSelected, makeEdited, makeInvalid )
          
static String grvEpsilon()
           return the HTML to draw a smallish "E"
static Object grvFormatDate( d, f )
          
static String grvFormatDecimal( <anyType> v, <String> currencyPreSymbol, <String> currencyPostSymbol, <String> sepSymbol, <boolean> optZeroAsBlankFlag )
           format given value as -<$>#<,>###.00<%>
static String grvFormatDollar( <anyType> v, <boolean> optZeroAsBlankFlag )
           format given value as $#,###.00
static String grvFormatDollarNot( v )
           like format_dollar except empty string returned for zero
static String grvFormatErrorStr( msg )
           format Server Error Messages
static String grvFormatLpadded( s,len,padChar )
           pad or truncate to be exactly given length
static String grvFormatMultilineStr( s,len )
           convert CRs to
tags
static String grvFormatPaddedStr( s,len )
           blankpad or truncate to be exactly given length
static String grvFormatPercent( <anyType> v, <boolean> optZeroAsBlankFlag )
           format given value as ####.00%
static String grvFormatRpadded( s,len,padChar )
           pad or truncate to be exactly given length
static String grvGenHook( <String> hookID, <String> optInnerHTML )
           generate a piece of HTML, identified by the given ID, that can safely have its innerHTML replaced at runtime.
static Object grvGetArg( argname )
          
static Object grvGetElemVisibility( e )
          
static Object grvGetFormInt( ID )
          
static Object grvGetFormValue( ID )
          
static Object grvGetGlobalVar( <String> varname )
           static routine to return the value of persistent variable with given name
static Object grvGetHook( hookID )
          
static Object grvGetPersistentVar( <String> varname )
           static routine to return the value of the persistent variable with given name
static Object grvGetTodayAsMMDDYYYY()
          
static Object grvGetTodayAsXXDDYYYY(monthNames)
          
static Object grvGlobalVar()
          
static void grvHighlightElem( e, makeSelected, selectColor, optUnselectColor )
          
static Object grvIsChecked( ID )
          
static Object grvIsZeroDollars(v)
          
static boolean grvKeyFilter( <int> keyCode, <String> allowedChars )
           Is the given keyCode in the given list of allowed characters?
static boolean grvNoDuplicates( <String> s, <String> charList )
           Is there no more than one occurance of each character in the given character list in the given string?
static void grvNotBusy()
           set the cursor to the default icon
static Object grvObjectToInitializer( o )
          
static Object grvObjectToShortInitializer( o )
          
static Object grvObjectToString( o )
          
static Object grvPersistentVar()
          
static Object grvPleaseWait( <boolean> enableFlag, <String> msg, appId )
           create and open a window (if enabled) with the specified message
static String grvRightArrow()
           return the HTML to draw a bold right arrow
static void grvSelectElem( e, makeSelected, optUnselectColor )
          
static void grvSelectElemID( ID, makeSelected, optUnselectColor )
          
static void grvSendStatusMessage( <String> msg )
           send a message to the browser status bar
static void grvSetBackgroundColor( ID, color )
          
static void grvSetButtonElemText( button, str )
          
static void grvSetButtonText( buttonId, str )
          
static void grvSetElemBackgroundColor( e, color )
          
static void grvSetElemDisplay( e, visibleFlag )
          
static void grvSetElemText( e, str )
          
static void grvSetElemVisibility( e, visibleFlag )
          
static void grvSetFormValue( ID, theValue )
          
static void grvSetGlobalVar( <String> varname, <Object> value )
           static routine to dynamically define/update a global (to window/page but reloaded with page) variable with the given name and value.
static void grvSetPersistentVar( <String> varname, <Object> value )
           static routine to dynamically define/update a persistent (across page loads) variable with the given name and value.
static void grvSetText( ID, str )
          
static void grvSetVisibility( ID, visibleFlag )
          
static boolean grvStrFilter( s, <String> allowedChars )
           Does the given string consist of only characters in the given list of allowed characters?
static String grvSubitem( isInValid )
           return the HTML to draw a subitem bullet
static Object grvTimestamp()
          
static Object grvTrace(flag,msg)
          
static Object grvTraceEvt(msg)
          
static Object grvTraceMsg(msg)
          
static Object grvTraceMVC(msg)
          
static Object grvTraceObj(msg)
          
static Object grvTraceTODO(msg)
          
static void grvUNWAIT(appId)
           close the "please wait" window if it exists otherwise no effect
static boolean grvUpperKeyFilter( <int> keyCode, <String> valueSoFar )
           convert the given character to uppercase
static String grvURLDecode( <String> encoded )
           This decodes URL-encoded strings because the Javascript function "unescape" only does part of the job; adapted from here.
static void grvWAIT(appId)
           Create an idempotent "wait a minute" window, if one doesn't exist, and squirrel away a reference to it that survives window reloads
static boolean grvWAITING(appId)
           are we in "please wait" mode?
static Object grvWaitWindowName(appId)
          

// This file uses JSDoc-friendly comments [ http://jsdoc.sourceforge.net/ ]

/**
 * @file         grvUtils.js
 * @fileoverview Collection of general utility routines
 * @author       Bruce Wallace  (PolyGlotInc.com)
 * @requires     grvValidate.js
 * @version      2.0
 */

//////////////////////////////////////////////////////////////////
// GRAVEY LEXICAL CODING CONVENTIONS:
// (*) All private variables or functions start with "_"
// (*) All variables and functions start with a lowercase letter
// (*) All Classes start with an uppercase letter
// (*) All Class methods and instance variables start with lowercase
// (*) All Class "static" methods and variables start with uppercase
// (*) All constants start with "k"
// (*) All global variables start with "g"
// (*) All event handler functions start with "on"
//
// (*) All Gravey utility global variables start with "gGrv"
// (*) All Gravey MVC     global variables start with "gMVC"
// (*) All Gravey EDO     global variables start with "gEDO"
// (*) All Gravey utility functions start with "grv"
// (*) All Gravey MVC     functions start with "mvc"
// (*) All Gravey MVC event handler functions start with "onMVC"
// (*) All Gravey EDO event handler functions start with "onEDO"
// (*) All Gravey MVC classes start with "MVC"
// (*) All Gravey EDO classes start with "EDO"
//////////////////////////////////////////////////////////////////


//global debug flags to enable verbose event tracing
var gGrvTraceObj = false;	//OO simulation tracing
var gGrvTraceMVC = false;	//MVC setup tracing
var gGrvTraceEvt = false;	//Event processing tracing
var gGrvTraceMsg = false;	//broadcast message tracing
var gGrvTraceTODO= false;	//"not implemented yet" msgs
function grvTrace(flag,msg){ if (flag) return grvBreak(msg); else return true; }

function grvTraceMVC(msg){ return grvTrace(gGrvTraceMVC,msg); }
function grvTraceObj(msg){ return grvTrace(gGrvTraceObj,msg); }
function grvTraceEvt(msg){ return grvTrace(gGrvTraceEvt,msg); }
function grvTraceMsg(msg){ return grvTrace(gGrvTraceMsg,msg); }

function grvTraceTODO(msg){ return grvTrace(gGrvTraceTODO,"TO DO:"+msg); }

function grvTimestamp(){ return (new Date()).getTime(); }

// ----------------------------------------------------------------------------
// Utility routines for Formatting Data
// ----------------------------------------------------------------------------

/** return the HTML to draw a bold right arrow @type String */
function grvRightArrow(){ return '<font face="Symbol">&#222;</font>'; }

/** return the HTML to draw a biggish dot @type String */
function grvDot       (){ return '<font face="Symbol">&#183;</font>'; }

/** return the HTML to draw a smallish "E" @type String */
function grvEpsilon   (){ return '<font face="Symbol">&#101;</font>'; }


/** return the HTML to draw a diamond
 * @param {boolean} optBlankFlag if true, says generate blanks of same size as 1 diamond
 * @type String
 */
function grvDiamond(optBlankFlag){ return optBlankFlag ? "&nbsp;&nbsp;" : "&diams;"; }

/** return the HTML to draw a subitem bullet @type String */
function grvSubitem( isInValid ){ return isInValid ? grvEpsilon() : grvRightArrow() }

/** Is the given keyCode in the given list of allowed characters?
 * @param {int} keyCode the charCode of the character to validate
 * @param {String} allowedChars the list of characters that are allowed
 * @return true iff keyCode is legal
 * @type boolean
 */
function grvKeyFilter( keyCode, allowedChars ){
	return allowedChars.indexOf(String.fromCharCode(keyCode)) >= 0;
}

/** Does the given string consist of only characters in the given
 * list of allowed characters?
 * @param {int} keyCode the charCode of the character to validate
 * @param {String} allowedChars the list of characters that are allowed
 * @return true iff keyCode is legal
 * @type boolean
 */
function grvStrFilter( s, allowedChars ){
	var q = "";
	for (var i=0; i<s.length; ++i)
	{
	  var c = s.charAt(i);
	  if (allowedChars.indexOf(c) >= 0) q += c;
	}
	return q;
}

/** Is there no more than one occurance of each
 * character in the given character list in the given string?
 * @param {String} s string to check
 * @param {String} charList list of characters that should occur only once
 * @return true if there are no duplicates
 * @type boolean
 */
function grvNoDuplicates( s, charList )
{
	for (var i=0; i<charList.length; ++i)
	{
	  var c = charList.charAt(i);
	  var first = s.indexOf(c);
	  if (first!=-1 && first!=s.lastIndexOf(c)) return false;
	}
	return true;
}

var kDigitChars = "0123456789";
var kFloatChars = "+-.";

/** convert the given character to uppercase
 * @param {int} keyCode the proposed new character
 * @param {String} valueSoFar the value so far
 * @return updated char iff character is legal else null
 * @type boolean
 */
function grvUpperKeyFilter( keyCode, valueSoFar )
{
	if ( keyCode>96 && keyCode<123 ) keyCode -= 32;
	return keyCode;
}

/** is the given character a legal addition to the given dollar string
 * @param {int} keyCode the proposed new character
 * @param {String} valueSoFar the value so far
 * @return updated char iff character is legal else null
 * @type boolean
 */
function grvDateKeyFilter( keyCode, valueSoFar )
{
	if ( grvKeyFilter( keyCode, kDigitChars+"/-" ) ) return keyCode;
	return null;
}

/** is the given character a legal addition to the given dollar string
 * @param {int} keyCode the proposed new character
 * @param {String} valueSoFar the value so far
 * @return updated char iff character is legal else null
 * @type boolean
 */
function grvDollarKeyFilter( keyCode, valueSoFar )
{
	if ( grvKeyFilter( keyCode, kDigitChars+kFloatChars+"$," ) )
//	&& grvNoDuplicates( valueSoFar+String.fromCharCode(keyCode), "$"+kFloatChars );
	  return keyCode;
	return null;
}
function grvDollarStrFilter(s){ return grvStrFilter(s,kDigitChars+kFloatChars); }
function grvIsZeroDollars(v){ return Math.abs(parseFloat(v))<0.01; }


/** format given value as -<$>#<,>###.00<%>
 * @type String
 * @param {anyType} v value to format
 * @param {String} currencyPreSymbol   prefix "currency symbol" to add
 * @param {String} currencyPostSymbol postfix "currency symbol" to add
 * @param {String} sepSymbol thousands "separator" to add
 * @param {boolean} optZeroAsBlankFlag optional flag to make zero format as blank
 * @author Bruce Wallace (PolyGlotInc.com)
 * @version 2.0
 */
function grvFormatDecimal( v, currencyPreSymbol, currencyPostSymbol, sepSymbol, optZeroAsBlankFlag )
{
	if ( v==null || v=="null" ) return grvDot();
	if ( grvIsZeroDollars(v) ) v = 0; //get rid of microcents and negative zeroes
	if ( optZeroAsBlankFlag && v==0 ) return "&nbsp;";

	// Do the equivalent to XSL::format-number($v,'$#,###.00')
	var x = parseFloat(v).toFixed(2);
	var sign = '';
	if (x < 0){ sign = '-'; x = x.substr(1); }
    var C    = x.split("");
    var n    = C.length-4;
    var s    = x.substring(n+1,n+4);

	for (var i=n; i>=0; --i)
	    s = (((C.length-i)%3==0 && i!=0) ? sepSymbol : "") + C[i] + s;

	return sign + currencyPreSymbol + s + currencyPostSymbol;
}

/** format given value as $#,###.00
 * @type String
 * @param {anyType} v value to format
 * @param {boolean} optZeroAsBlankFlag optional flag to make zero format as blank
 * @author Bruce Wallace (PolyGlotInc.com)
 * @version 2.0
 */
function grvFormatDollar ( v, optZeroAsBlankFlag ) {
  return grvFormatDecimal( v, "$", "", ",", optZeroAsBlankFlag );
}

// a global month names array
var kMonthNames = new Array(
		'January',
		'February',
		'March',
		'April',
		'May',
		'June',
		'July',
		'August',
		'September',
		'October',
		'November',
		'December'
	);

// a global day names array
var kDayNames = new Array(
		'Sunday',
		'Monday',
		'Tuesday',
		'Wednesday',
		'Thursday',
		'Friday',
		'Saturday'
	);
	
function grvFormatDate( d, f )
{
    if (!d) return '';
    return f.replace(/(yyyy|mmmm|mmm|mm|dddd|ddd|dd|hh|nn|ss|a\/p)/gi,
        function($1)
        {
            switch ($1.toLowerCase())
            {
            case 'yyyy': return d.getFullYear();
            case 'mmmm': return kMonthNames[d.getMonth()];
            case 'mmm':  return kMonthNames[d.getMonth()].substr(0, 3);
            case 'mm':   return grvFormatLpadded( (d.getMonth()+1), 2, "0" );
            case 'dddd': return kDayNames[d.getDay()];
            case 'ddd':  return kDayNames[d.getDay()].substr(0, 3);
            case 'dd':   return grvFormatLpadded( d.getDate(), 2, "0" );
            case 'hh':   return grvFormatLpadded( ((h=d.getHours()%12)?h:12), 2, "0" );
            case 'nn':   return grvFormatLpadded( d.getMinutes(), 2, "0" );
            case 'ss':   return grvFormatLpadded( d.getSeconds(), 2, "0" );
            case 'a/p':  return d.getHours() < 12 ? 'a' : 'p';
            }
        }
    );
}


/** format given value as ####.00%
 * @type String
 * @param {anyType} v value to format
 * @param {boolean} optZeroAsBlankFlag optional flag to make zero format as blank
 * @author Bruce Wallace (PolyGlotInc.com)
 * @version 2.0
 */
function grvFormatPercent( v, optZeroAsBlankFlag ) {
  return grvFormatDecimal( v, "", "%", "", optZeroAsBlankFlag );
}

/** like format_dollar except empty string returned for zero @type String */
function grvFormatDollarNot( v ){ return grvFormatDollar( v, true ); }


/** pad or truncate to be exactly given length @type String */
function grvFormatRpadded( s,len,padChar ){
	if ( s==null || s=="null" ) return grvDot();
	for (var i=0; i<len; ++i) s += padChar;
	return s.substr(0,len);
}

/** pad or truncate to be exactly given length @type String */
function grvFormatLpadded( s,len,padChar ){
	if ( s==null || s=="null" ) return grvDot();
	for (var i=0; i<len; ++i) s = padChar+s;
	return s.substring(s.length-len);
}

/** blankpad or truncate to be exactly given length @type String */
function grvFormatPaddedStr( s,len ){
	return grvFormatRpadded( s,len,"&nbsp;");
}


/** convert CRs to <br> tags @type String */
function grvFormatMultilineStr( s,len )
{
	if (s==null || s=="null") return grvDot();
	return s.replace( new RegExp( "\\n", "g" ), "<br>" );
}

/** format Server Error Messages @type String */
function grvFormatErrorStr( msg ){
	if (grvIsEmpty(msg)) return "";
	msg = msg.replace( new RegExp( "\\n", "g" ), "<br>" );
	var HTML  = new Array();
		HTML.push( '<table class="grvErrpanel" cellpadding="10" cellspacing="0" width="100%">' );
		HTML.push( '<tr><td>SERVER ERROR: '+msg+'</td></tr>' );
		HTML.push( '</table>' );
 return HTML.join('');
}

/** generate a piece of HTML, identified by the given ID,
 * that can safely have its innerHTML replaced at runtime.
 * @param {String} hookID name of the HTML to be generated
 * @param {String} optInnerHTML optional HTML to be inserted
 * into the generated HTML
 * @return generated HTML
 * @type String
 * @see #grvGetHook
 * @author Bruce Wallace (PolyGlotInc.com)
 * @version 2.0
 */
function grvGenHook( hookID, optInnerHTML ){
	return '<span id="'+hookID+'">'
	     + (optInnerHTML?optInnerHTML:"")
	     + '</span>';
}
function grvGetHook( hookID ){
	//special case: document.body
	if (hookID=="document.body"){
	 var e = document.body;
	 grvTraceMVC("document body is:["+e+"]");
	 return e;
	}

	var e = document.getElementById( hookID );
	if (e==null) grvTraceMVC("cant find hook["+hookID+"]");
	return e;
}

function grvSetElemBackgroundColor( e, color ){
    if (!e) {grvBreak("null setElemBackgroundColor!"); return;}
	e.style.backgroundColor = color;
}
function grvSetBackgroundColor( ID, color ){
	grvSetElemBackgroundColor( document.getElementById(ID), color );
}
function grvSetElemText( e, str ){
    if (!e) {grvBreak("null setElemText!"); return;}
	e.innerHTML = str;
}
function grvSetText( ID, str ){
	grvSetElemText( grvGetHook(ID), str );
}
/** @see http://www.permadi.com/tutorial/jsInnerHTMLDOM/ */
function grvSetButtonElemText( button, str )
{
	if (!button) {grvBreak("null setButtonText!"); return;}
	if (button.childNodes[0]) button.childNodes[0].nodeValue = str; else
	if (button.value)         button.value = str;                   else
  /*if (button.innerHTML)*/   button.innerHTML = str;
}
function grvSetButtonText( buttonId, str ){
	grvSetButtonElemText( grvGetHook(buttonId), str );
}


//TODO implement these via CSS instead
var kColorTeal       = '#6eaba1';
var kColorTealLight  = '#99CCCC';
var kColorCornstarch = '#FFFAF0';
var kColorWhitePepper= '#F0F0CC';
var kColorDaffodil   = '#FFFACA';
var kColorNavy       = '#000066';
var kColorDarkSilver = '#COCOCO';
var kColorLime       = '#66FF66';
var kColorLightMoney = '#CCFFCC';
var kColorMatteSilver= '#CCCCCC';
var kColorLemonCream = '#FFFFCC';
var kColorPeriwinkle = '#9CA9C5';
var kColorBanana     = '#FFFF66';
var kColorTurqoise   = '#66CCCC';
var kColorPumpkin    = '#FFCC33';
var kColorPumpkinGrey= '#DDBB08';
var kColorDustyRose  = '#FFE0E0';
var kColorDustierRose= '#EEAAAA';
var kColorRoseGrey   = '#DAABAB';
var kColorLipstick   = '#FF6666';
var kColorYellow     = '#FFFF00';


var      kInValidColor = '#FF9900';
var       kEditedColor = kColorTealLight;//'#FFCC99';
var     kSelectedColor = kColorLemonCream;
var   kUnSelectedColor = kColorCornstarch;//kColorDaffodil;
var kROUnselectedColor = kColorMatteSilver;

function grvHighlightElem( e, makeSelected, selectColor, optUnselectColor ){
	if ( grvIsUndefined(optUnselectColor) ) optUnselectColor = kUnSelectedColor;
	grvSetElemBackgroundColor( e, makeSelected?selectColor:optUnselectColor );
}
/*ALTERNATE COLOR SCHEME...
//set the background color of the given element based on
//whether it is selected, dirty, and valid.
function grvEditElem( e, makeSelected, makeEdited, makeInvalid ){
	var useColor = makeSelected || makeEdited || makeInvalid;
	grvHighlightElem( e, useColor, makeInvalid ? kInValidColor :
	                               makeEdited  ? kEditedColor  :
	                                             kSelectedColor );
}
*/
//set the background color of the given element based on
//whether it is selected, dirty, and valid.
function grvEditElem( e, makeSelected, makeEdited, makeInvalid, optUnselectColor ){
	var useColor = makeSelected || makeEdited;
	grvHighlightElem( e, useColor, makeEdited ? kEditedColor  :
	                                          kSelectedColor, optUnselectColor );
}
function grvEditElemID( ID, makeSelected, makeEdited, makeInvalid ){
	grvEditElem( grvGetHook(ID), makeSelected, makeEdited, makeInvalid );
}
function grvSelectElem( e, makeSelected, optUnselectColor ){
	grvHighlightElem( e, makeSelected, kSelectedColor, optUnselectColor );
}
function grvSelectElemID( ID, makeSelected, optUnselectColor ){
	grvSelectElem( grvGetHook(ID), makeSelected, optUnselectColor );
}

function grvSetElemVisibility( e, visibleFlag )
{
    if (!e) {if (grvTraceMVC("null setElemVisibility!")) return;}
	e.style.visibility = visibleFlag ? "visible"  : "hidden";
	e.style.position   = visibleFlag ? "relative" : "absolute";
}
function grvGetElemVisibility( e )
{
    if (!e) {if (grvTraceMVC("null getElemVisibility!")) return false;}
	return e.style.visibility == "visible";
}

function grvSetElemDisplay( e, visibleFlag )
{
    if (!e) {if (grvTraceMVC("null setElemDisplay!")) return;}
	e.style.display = visibleFlag ? "inline" : "none";
}
function grvSetVisibility( ID, visibleFlag ){
  grvSetElemVisibility( grvGetHook(ID), visibleFlag );
}

function grvGetFormInt( ID ){
	return parseInt( grvGetFormValue(ID) );
}
function grvGetFormValue( ID ){
	return document.getElementById(ID).value;
}
function grvSetFormValue( ID, theValue ){
	document.getElementById(ID).value = theValue;
}


var kMonthNames = new Array(
				"January","February","March","April","May","June","July",
				"August","September","October","November","December");
var kMonthNums = new Array(
				"01","02","03","04","05","06","07",
				"08","09","10","11","12");

function grvGetTodayAsXXDDYYYY(monthNames)
{
	var now = new Date();
	return monthNames[ now.getMonth() ]
	     + "/" + now.getDate()
	     + "/" + now.getFullYear();
}
function grvGetTodayAsMMDDYYYY(){
  return grvGetTodayAsXXDDYYYY( kMonthNums );
}


/**
 * Determine whether a given datestr is explicitly before the given date.
 * @param {String} datestr string rendition of date in Date.parse format
 * @param {Date} date date object to compare to
 * @return true if given date is not empty and before given date
 * @type boolean
 * @author Bruce Wallace (PolyGlotInc.com)
 * @version 2.0
 */
function grvBefore( datestr, date ){
	return datestr && datestr.length>0 && ( date > Date.parse(datestr) );
}

/**
 * Determine whether given date is at or before a given datestr (where empty means "future").
 * @param {String} datestr string rendition of date in Date.parse format
 * @param {Date} date date object to compare to
 * @return true if given date is empty or after today's date
 * @type boolean
 * @author Bruce Wallace (PolyGlotInc.com)
 * @version 2.0
 */
function grvAfter( datestr, date ){
	return( (datestr && datestr.length>0) ? (date < Date.parse(datestr)) : true	);
}

/**
 * Determine whether a given date is explicitly before today.
 * @param {String} datestr string rendition of date in Date.parse format
 * @return true if given date is not empty and before today's date
 * @type boolean
 * @author Bruce Wallace (PolyGlotInc.com)
 * @version 2.0
 */
function grvBeforeNow( datestr ){ return grvBefore( datestr, new Date() ); }

/**
 * Determine whether today is at or before a given date (where empty means "future").
 * @param {String} datestr string rendition of date in Date.parse format
 * @return true if given date is empty or after today's date
 * @type boolean
 * @author Bruce Wallace (PolyGlotInc.com)
 * @version 2.0
 */
function grvAfterNow( datestr ){ return grvAfter( datestr, new Date() ); }

// ----------------------------------------------------------------------------
// Utility routines for "please wait" indicators
// ----------------------------------------------------------------------------

function grvAppName(appId){
	return appId ? appId : (kAppName?kAppName:"");
}
function grvWaitWindowName(appId){
	return "_gGrvWaitWindow" + grvAppName(appId);
}
/** Create an idempotent "wait a minute" window, if one doesn't exist,
 * and squirrel away a reference to it that survives window reloads
 */
function grvWAIT(appId)
{
	// HACK! windows get goofed up if we dont suppress
	// the "please wait" window on launch...
	if (_gGrvHackStartupInhibitWait) return;

	var winName = grvWaitWindowName(appId);
	if (navigator[ winName ]==null)
		navigator[ winName ]= grvPleaseWait( true, "Loading data.", appId );
}
/** close the "please wait" window if it exists otherwise no effect */
function grvUNWAIT(appId) {
	var winName = grvWaitWindowName(appId);
	if (navigator[ winName ]==null) return;
	    navigator[ winName ].close();
	    navigator[ winName ] = null;
}

/** are we in "please wait" mode? @type boolean */
function grvWAITING(appId){ return navigator[ grvWaitWindowName(appId) ]; }

/** create and open a window (if enabled) with the specified message
 * @param {boolean} enableFlag iff true then create window
 * @param {String} msg message to place in window
 * @return the created window or null if not enabled
 * @type Object
 */
function grvPleaseWait( enableFlag, msg, appId )
{
	var theWindow = null;
	if ( enableFlag )
	{
	 var xMax = screen.width, yMax = screen.height;
     var xOffset = (xMax - 220)/2, yOffset = (yMax - 100)/2;
     theWindow = window.open("", 'grvPleaseWait', 'width=250 height=100 toolbar=no scrollbars=no menubar=no resizable=yes top='+yOffset+' left='+xOffset+'');
     theWindow.document.write("<BODY BGCOLOR="+kColorTeal+">");
     theWindow.document.write("<TITLE>" +grvAppName(appId)+ " Processing...</TITLE>");
     theWindow.document.write('<FONT FACE="Arial" SIZE=2><layer id="c"><left><B>'+msg+'<br/>Please Wait.</left></layer></font><br>');
	}
	return theWindow;
}

/** set the cursor to the hourglass icon */
function grvBusy() {
  document.body.style.cursor='wait';
}
/** set the cursor to the default icon */
function grvNotBusy() {
  document.body.style.cursor='default';
}

/**
 * generic utility function to queue up for future execution the specified
 * function with the specified arguments after a specified amount of delay.
 * THIS function returns immediately, and the specified function will execute
 * later (in potentially a different thread). If this is called with the same
 * function specified as was specified earlier, and that function has not
 * executed yet, then the scheduled execute time is updated, rather than the
 * function being executed twice.
 * @param {String} funcname the name of the function to call
 * @param {String} funcargs a string image of the parameters to be passed
 * @param {int} optDelayMilliSecs optional delay amount (default 5 milliSeconds)
 * @author Bruce Wallace  (PolyGlotInc.com)
 * @version 2.0
 */
function grvBusyDo( funcname, funcargs, optDelayMilliSecs )
{
	var timedelay = optDelayMilliSecs || 5;
//	grvBusy();
	var globalVarName = "_gGrvTimeout"+funcname;
	if (navigator[ globalVarName ]==null) navigator[globalVarName] = null;
	if (navigator[ globalVarName ]!=null) clearTimeout( navigator[globalVarName] );
	    navigator[ globalVarName ] = setTimeout( funcname+funcargs, timedelay );
}

// ----------------------------------------------------------------------------
// Utility routines for URL Handling
// ----------------------------------------------------------------------------

/** This decodes URL-encoded strings because the Javascript
 * function "unescape" only does part of the job; adapted from
 * <a target="_blank" href="http://www.albionresearch.com/misc/urlencode.php">here.</a>
 * @param {String} encoded the URL-encoded string to translate
 * @return decoded version of given encoded string
 * @type String
 * @author Bruce Wallace (PolyGlotInc.com)
 * @version 2.0
 */
function grvURLDecode( encoded )
{
   // Replace + with space
   // Replace %xx with equivalent character
   // Put [ERROR] in output if %xx is invalid.
   var HEXCHARS = "0123456789ABCDEFabcdef"; 
   var plaintext = "";
   var i = 0;
   while (i < encoded.length) {
       var ch = encoded.charAt(i);
	   if (ch == "+") {
	       plaintext += " ";
		   i++;
	   } else if (ch == "%") {
			if (i < (encoded.length-2) 
					&& HEXCHARS.indexOf(encoded.charAt(i+1)) != -1 
					&& HEXCHARS.indexOf(encoded.charAt(i+2)) != -1 )
			{
				plaintext += unescape( encoded.substr(i,3) );
				i += 3;
			} else {
				throw 'Bad escape combination near ...' + encoded.substr(i);
				i++;
			}
		} else {
		   plaintext += ch;
		   i++;
		}
	}
   return plaintext;
}

/**
 * @class This function parses ampersand-separated name=value
 * argument pairs from the query string of the URL; It stores the
 * name=value pairs in a static list; adapted from
 * <a target="_blank" href="http://www.oreilly.com/catalog/jscript3/chapter/ch13.html#ch13_08.htm">here.</a>
 * @author Bruce Wallace (PolyGlotInc.com)
 * @version 2.0
 */
function grvArgs( anArgName )
{
	if ( grvIsUndefined(grvArgs.ARGS) )
	{
		grvArgs.ARGS = new Object(); //private singleton

	    var query = location.search.substring(1);  // Get query string.
	    var pairs = query.split("&");              // Break at ampersand.

	    for (var i=0; i<pairs.length; ++i)
	    {
		  var pos = pairs[i].indexOf('=');            // Look for "name=value".
		  if (pos == -1) continue;                    // If not found, skip.
		  var argname   = pairs[i].substring(0,pos);  // Extract the name.
		  var value     = pairs[i].substring(pos+1);  // Extract the value.
		  grvArgs.ARGS[argname] = grvURLDecode(value);// Store in LIST.
	    }
	}

    return grvArgs.ARGS[ anArgName ];	// Return the specified argument
}

function grvGetArg( argname ) {
	return grvArgs( argname );
}

function grvIsChecked( ID )
{
  var checkbox = document.getElementById( ID );
  return checkbox.checked;
}

/** send a message to the browser status bar
 * @param {String} msg the message to send.
 */
function grvSendStatusMessage( msg )
{
    window.status = msg; grvTraceMsg(msg);
    window.status = "";
}

// ----------------------------------------------------------------------------
// Utility routines to convert entities into strings
// ----------------------------------------------------------------------------

function grvObjectToString( o )
{
	var s = "";
	for (var property in o)// iterate over all properties  
    	s += "Property [" + property + "] is [" +  o[property] +"]\n";
    return s;
}
function grvObjectToInitializer( o )
{
	var s = "{\n";
	for (var property in o)// iterate over all properties
	{
	  var q = (o[property] instanceof Function) ? '' : '"';
	  s += property + ':'+q + o[property] +q+',\n';
    }
    return s.substring(0,s.length-2)+"\n}";//get rid of dangling comma
}
function grvObjectToShortInitializer( o )
{
	var s = "{\n";
	for (var property in o)// iterate over all properties
	{
	  var P = o[ property ];
	  if (!(P instanceof Function))
	       s += property + ':"' + P + '",\n';
//	  else s += property + ': function,\n';
    }
    return s.substring(0,s.length-2)+"\n}";//get rid of dangling comma
}
function grvArrayToString( a )
{
	var s = "";
	for (var i in a)// iterate over all array items  
    	s += "["+ i +"] is ["+  a[i] +"]\n";
    return s;
}
function grvArgsToString( args )
{
     var s = "";
     for (var i=0; i<args.length; ++i)// iterate over all function args
    	s += "["+ i +"] is ["+  args[i] +"]\n";
     return s;
}

///// GLOBAL-PERSISTENCE VARIABLES ROUTINES /////

function grvPersistentVar()
{
	if (navigator._gGrvGlobalMap==null) navigator._gGrvGlobalMap = new Object();
	return navigator._gGrvGlobalMap;
}

/** static routine to dynamically define/update a persistent (across page loads)
 * variable with the given name and value.
 * @param {String} varname name of "persistent" variable
 * @param {Object} value value to set variable to
 */
function grvSetPersistentVar( varname, value ) //persisted across page loads
{
	grvPersistentVar()[varname] = value;
}

/** static routine to return the value of the persistent variable with given name
 * @param {String} varname name of "persistent" variable
 * @return {Object} value of variable (empty object if not previously defined)
 * @type Object
 */
function grvGetPersistentVar( varname )
{
	return grvPersistentVar()[varname];
}

/** static routine to dynamically undefine/delete ALL "...PersistentVars" variables  */
function grvClearPersistentVars(){ grvPersistentVar() = null; }


function grvGlobalVar()
{
	if (window._gGrvGlobalMap==null) window._gGrvGlobalMap = new Object();
	return window._gGrvGlobalMap;
}

/** static routine to dynamically define/update a global (to window/page
 * but reloaded with page) variable with the given name and value.
 * @param {String} varname name of "persistent" variable
 * @param {Object} value value to set variable to
 */
function grvSetGlobalVar( varname, value )
{
	grvGlobalVar()[ varname ] = value;
}

/** static routine to return the value of persistent variable with given name
 * @param {String} varname name of "global" i.e. "static" variable
 * @return {Object} value of variable (empty object if not previously defined)
 * @type Object
 */
function grvGetGlobalVar( varname )
{
	return grvGlobalVar()[ varname ];
}

/** static routine to dynamically undefine/delete ALL "...GlobalVars" variables */
function grvClearGlobalVars(){ grvGlobalVar() = null; }

/** static routine to dynamically undefine/delete a global variable
 * @param {String} varname name of "persistent" variable
 */
function grvClearGlobalVar( varname ){ delete grvGlobalVar()[ varname ]; }


The Gravey Framework and RATS RIA

Documentation generated by JSDoc on Sat Dec 8 21:52:02 2007