Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Will Rickards http://willrickards.net/

« Newer Snippets
Older Snippets »
Showing 1-3 of 3 total  RSS 

Javascript LookupControl

A lookup control is a common thing to have on many web pages. In this case we assume a textbox, a command button, and a label of some sort to display a description.

The HTML might look like this
<label for="txtExistingClient">Client</label>
<input id="txtExistingClient" name="txtExistingClient" type="text" size="15" maxlength="14" class="text uppercase" runat="server">
<input id="cmdExistingClientLookup" name="cmdExistingClientLookup" type="button" value=" ? ">
<span id="lblExistingClient"></span>


Here is a javascript function to call in the onload to setup that lookup control. And examples of the functions required.
// ----------------------------------------------------------------------------
// SetupLookupControl
//
// Description : sets up a lookup control by linking it to its 
//    associated controls and hooking up the event handlers
//
// Arguments :
//    strTextBoxID               : input type=text id
//    strLookupButtonID          : input type=button id
//    strLabelID                 : span of div id
//    funcTextBoxOnChange        : function for textbox's onchange and onblur event
//    funcLookupButtonOnClick    : function for lookup button's onclick event
//
// Dependencies : none
//
// History :
// 2006.07.14 - WSR : created
//
function SetupLookupControl( strTextBoxID, strLookupButtonID, strLabelID, funcTextBoxOnChange, funcLookupButtonOnClick )
   {

   // get reference to lookup button
   var ctlLookupButton = document.getElementById(strLookupButtonID);

   // if lookup button was found
   if (ctlLookupButton)
      {

      // hookup event handlers and control references
      ctlLookupButton.onclick = funcLookupButtonOnClick;
      ctlLookupButton.textbox = document.getElementById(strTextBoxID);

      // if textbox was found
      if (ctlLookupButton.textbox)
         {

         // hookup event handlers and control references
         ctlLookupButton.textbox.onchange = funcTextBoxOnChange;
         ctlLookupButton.textbox.onblur = funcTextBoxOnChange;
         ctlLookupButton.textbox.label = document.getElementById(strLabelID);

         // init last value property of textbox
         if ( typeof ctlLookupButton.textbox.lastvalue == 'undefined' )
            ctlLookupButton.textbox.lastvalue = ''; 

         }

      }

   }
//
// SetupLookupControl
// ----------------------------------------------------------------------------

// ----------------------------------------------------------------------------
// cmdTimekeeperLookup_click
// Description: handler for requesting timekeeper selection button click event
// Arguments: none
// Dependencies:
//    TimekeepQuery (lookup.js)
//
function cmdTimekeeperLookup_click()
   {

   // show timekeeper query window
   TimekeepQuery( this.textbox );

   // update timekeeper information
   this.textbox.onchange();

   // process default action
   return true;

   }
//
// cmdTimekeeperLookup_click
// ----------------------------------------------------------------------------


// ----------------------------------------------------------------------------
// txtTimekeeper_change
// Description: event handler for timekeeper textbox change event
// Arguments: none
// Dependencies:
//    window.strTkprMask (masking.js)
//    trim
//    ApplyMask (masking.js)
//    TimekeepLookup (lookup.js)
//    UpdateElementText (shared.js)
//
function txtTimekeeper_change()
   {

   var strTimekeepName = '';
   var objXMLDOM;
   var nodField;
 
   // trim input
   this.value = this.value.trim();
  
   // if there was input
   if ( this.value.length > 0 )
      {

      // apply timekeep mask to textbox input
      ApplyMask( this, window.strTkprMask );

      // if inputted timekeeper is different from current timekeeper
      if ( this.lastvalue != this.value )
         {

         // request timekeeper information
         objXMLDOM = TimekeepLookup( this.value );

         // if XML DOM object returned
         if ( typeof objXMLDOM == 'object' )
            {

            // get field values
            nodField = objXMLDOM.selectSingleNode('//lastname');
            if (nodField != null)
               strTimekeepName = nodField.firstChild.nodeValue;

            nodField = objXMLDOM.selectSingleNode('//firstname');
            if (nodField != null)
               strTimekeepName = strTimekeepName + ', ' + nodField.firstChild.nodeValue;

            // update timekeeper
            this.lastvalue = this.value;

            }
         // if XML DOM object wasn't returned
         else
            {

            // indicate timekeeper was not found
            strTimekeepName = 'Timekeep \'' + this.value + '\' was not found.';

            // update timekeeper
            this.lastvalue = '';

            }

         // update document
         UpdateElementText( this.label, strTimekeepName );

         }

      }
   // if there was no input
   else
      {

      // clear the timekeep and display
      this.lastvalue = '';
      UpdateElementText( this.label, '' );

      }

   // process default action
   return true;

   }
//
// txtTimekeeper_change
// ----------------------------------------------------------------------------

Javascript IntegerBoxControl

In input forms on web pages you often have to validate input as an integer or more precisely a positive integer greater than zero. Here is a control implementation of sorts.

// Integer Box Control
// 
// Notes
// To create an integer box control, call the SetupIntegerBoxControl function.
// It should be passed an input element with type of text.
// The onchange event of the input element will invoke the validation function.
// The validation function ensures only positive integer data is entered.
//
// History
// 09/08/2005 - WSR : created based on dateboxcontrol

// hooks functionality up to given textbox
function SetupIntegerBoxControl( ctlIntegerBox )
   {

   // if a valid object was given
   if (ctlIntegerBox)
      {

      // validate current contents
      IntegerBoxControl_Validate( ctlIntegerBox );

      // hook up event handlers
      ctlIntegerBox.onchange = function () { IntegerBoxControl_Validate(this); };
      
      }

   }


// validates the input
function IntegerBoxControl_Validate( ctlIntegerBox )
   {

   // parse the input as an integer
   var intValue = parseInt(ctlIntegerBox.value, 10);

   // if this is not an integer
   if (isNaN(intValue))
      {

      // clear text box
      ctlIntegerBox.value = '';

      }
   // if this is an integer
   else
      {
   
      switch (true)
         {
         case (intValue == 0) :

            // clear text box
            ctlIntegerBox.value = '';

            break;
         case (intValue > 0) :

            // put the parsed integer value in the text box
            ctlIntegerBox.value = intValue.toString();

            break;
         case (intValue < 0) :

            // put the positive parsed integer value in the text box
            ctlIntegerBox.value = (-1 * intValue).toString();

            break;
         }
      
      }

   }


I forgot to mention before how to hook it up in code.
I usually add an attribute bvr-datatype="integer" to the input element. bvr stands for behaviour. I hook up the control in the onload event. Here is a recent example.
// set window load event handler
window.onload = window_load;

// ----------------------------------------------------------------------------
// window_load
// Description: event handler for window load event
// Arguments: none
// Dependencies:
//    SetupDateBoxControl (dateboxcontrol.js)
//    SetupIntegerBoxControl (integerboxcontrol.js)
//    frmSearch_submit
//    cmdRequesting_click
//    txtRequesting_change
//    frmRecent_submit
//
function window_load()
   {

   // get input elements in document
   var arrInputs = document.getElementsByTagName('INPUT');

   // cycle through input elements
   for ( var i = 0; i < arrInputs.length; i++ ) 
      {

      // if this is a datebox control
      if ( 'date' == arrInputs[i].getAttribute('bvr-datatype') && 'text' == arrInputs[i].getAttribute('type') )
         {

         // setup the control
         SetupDateBoxControl( arrInputs[i] );

         }

      // if this is a integerbox control
      if ( 'integer' == arrInputs[i].getAttribute('bvr-datatype') && 'text' == arrInputs[i].getAttribute('type') )
         {

         // setup the control
         SetupIntegerBoxControl( arrInputs[i] );

         }

      }

   // get reference to search form
   var elForm = document.getElementById('frmSearch');
   if (elForm)
      {

      // set submit event handler
      elForm.onsubmit = frmSearch_submit;

      // set cmdTimekeeperLookup click event handler
      var elToWire = document.getElementById('cmdTimekeeperLookup');
      if (elToWire)
         {

         elToWire.onclick = cmdRequesting_click;
         elToWire.textbox = document.getElementById('txtRequestingTimekeeper');

         // set textbox change events
         if (elToWire.textbox)
            {

            elToWire.textbox.onchange = txtRequesting_change;
            elToWire.textbox.onblur = txtRequesting_change;
            elToWire.textbox.label = document.getElementById('lblTimekeeperName');

            if ( typeof window.strRequesting == 'undefined' )
               window.strRequesting = ''; 

            }

         }

      }

   // get reference to recent form
   elForm = document.getElementById('frmRecent');
   if (elForm)
      {

      // set submit event handler
      elForm.onsubmit = frmRecent_submit;

      }

   }
//
// window_load
// ----------------------------------------------------------------------------

JavaScript DateBoxControl

In input forms on web pages you often have to validate dates and users are always entering something off the wall. Simon Incutio came up with a script to parse the dates. I added some stuff and turned it into a control of sorts. It is sort of US centric with date entering but it does accept iso style entries.

// Date Box Control
// 
// based on:
//  'Magic' date parsing, by Simon Willison (6th October 2003)
//   http://simon.incutio.com/archive/2003/10/06/betterDateInput
// 
// Notes
// To create a date box control, call the SetupDateBoxControl function.
// It should be passed an input element with type of text.
// This will first create a div after the input box.
// Then it will associate the div with the input element.
// The div will use the css classes: DateBoxControlMsg, DateBoxControlErrorMsg.
// Then the div is associated with the input element.
// Then the contents are validated so the div will get populated initially.
// The onchange event of the input element will invoke the validation function.
// The validation function populates the div.
// If a successfully parsed date, the div gets a nicely formatted date.
// If an unsuccessfully parse date, the div gets an error message.
//
// History
// 02/03/2005 - WSR : modified for use as datebox control
// 09/09/2005 - WSR : datebox is not required anymore (blank input is valid)
//                  : added style class to datebox itself

// hooks functionality up to given textbox
function SetupDateBoxControl( ctlDateBox )
   {

   // if a valid object was given
   if (ctlDateBox)
      {

      // add div after control for messages
      var divMessage = document.createElement('div');
      divMessage.className = 'DateBoxControlMsg';

      // if there is a next sibling
      if (ctlDateBox.nextSibling)
         {

         // insert before next sibling
		   ctlDateBox.parentNode.insertBefore( divMessage, ctlDateBox.nextSibling );

         }
      // if there is not a next sibling
      else
         {

         // append child to parent
         ctlDateBox.parentNode.appendChild( divMessage );         

         }

      // link message div to textbox for easy script access
      ctlDateBox.message = divMessage;

      // validate current contents
      DateBoxControl_Validate( ctlDateBox );

      // hook up event handlers
      ctlDateBox.onchange = function () { DateBoxControl_Validate(this); };
      
      }

   }

// add indexOf function to Array type
// finds the index of the first occurence of item in the array, or -1 if not found
Array.prototype.indexOf = function(item) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] == item) {
            return i;
        }
    }
    return -1;
};

// add filter function to Array type
// returns an array of items judged true by the passed in test function
Array.prototype.filter = function(test) {
    var matches = [];
    for (var i = 0; i < this.length; i++) {
        if (test(this[i])) {
            matches[matches.length] = this[i];
        }
    }
    return matches;
};

// add right function to String type
// returns the rightmost x characters
String.prototype.right = function( intLength ) {
   if (intLength >= this.length)
      return this;
   else
      return this.substr( this.length - intLength, intLength );
};

// add trim function to String type
// trims leading and trailing whitespace
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/, ''); };

// arrays for month and weekday names
var monthNames = "January February March April May June July August September October November December".split(" ");
var weekdayNames = "Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" ");

/* Takes a string, returns the index of the month matching that string, throws
   an error if 0 or more than 1 matches
*/
function parseMonth(month) {
    var matches = monthNames.filter(function(item) { 
        return new RegExp("^" + month, "i").test(item);
    });
    if (matches.length == 0) {
        throw new Error("Invalid month string");
    }
    if (matches.length < 1) {
        throw new Error("Ambiguous month");
    }
    return monthNames.indexOf(matches[0]);
}

/* Same as parseMonth but for days of the week */
function parseWeekday(weekday) {
    var matches = weekdayNames.filter(function(item) {
        return new RegExp("^" + weekday, "i").test(item);
    });
    if (matches.length == 0) {
        throw new Error("Invalid day string");
    }
    if (matches.length < 1) {
        throw new Error("Ambiguous weekday");
    }
    return weekdayNames.indexOf(matches[0]);
}

function DateInRange( yyyy, mm, dd )
   {

   // if month out of range
   if ( mm < 0 || mm > 11 )
      throw new Error('Invalid month value.  Valid months values are 1 to 12');

   // get last day in month
   var d = (11 == mm) ? new Date(yyyy + 1, 0, 0) : new Date(yyyy, mm + 1, 0);

   // if date out of range
   if ( dd < 1 || dd > d.getDate() )
      throw new Error('Invalid date value.  Valid date values for ' + monthNames[mm] + ' are 1 to ' + d.getDate().toString());

   return true;

   }

/* Array of objects, each has 're', a regular expression and 'handler', a 
   function for creating a date from something that matches the regular 
   expression. Handlers may throw errors if string is unparseable. 
*/
var dateParsePatterns = [
    // Today
    {   re: /^today/i,
        handler: function() { 
            return new Date();
        } 
    },
    // Tomorrow
    {   re: /^tomorrow/i,
        handler: function() {
            var d = new Date(); 
            d.setDate(d.getDate() + 1); 
            return d;
        }
    },
    // Yesterday
    {   re: /^yesterday/i,
        handler: function() {
            var d = new Date();
            d.setDate(d.getDate() - 1);
            return d;
        }
    },
    // mmddyyyy (American style)
    {   re: /(\d{2})(\d{2})(\d{4})/,
        handler: function(bits) {

            var yyyy = parseInt(bits[3], 10);
            var dd = parseInt(bits[2], 10);
            var mm = parseInt(bits[1], 10) - 1;

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // mmddyy (American style) short year
    {   re: /(\d{2})(\d{2})(\d{2})/,
        handler: function(bits) {

            var d = new Date();
            var yyyy = d.getFullYear() - (d.getFullYear() % 100) + parseInt(bits[3], 10);
            var dd = parseInt(bits[2], 10);
            var mm = parseInt(bits[1], 10) - 1;

            if ( DateInRange(yyyy, mm, dd) )
               return new Date(yyyy, mm, dd);

        }
    },
    // 4th
    {   re: /^(\d{1,2})(st|nd|rd|th)?$/i, 
        handler: function(bits) {

            var d = new Date();
            var yyyy = d.getFullYear();
            var dd = parseInt(bits[1], 10);
            var mm = d.getMonth();

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // 4th Jan
    {   re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+)$/i, 
        handler: function(bits) {

            var d = new Date();
            var yyyy = d.getFullYear();
            var dd = parseInt(bits[1], 10);
            var mm = parseMonth(bits[2]);

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // 4th Jan 2003
    {   re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+),? (\d{4})$/i,
        handler: function(bits) {

            var yyyy = parseInt(bits[3], 10);
            var dd = parseInt(bits[1], 10);
            var mm = parseMonth(bits[2]);

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // Jan 4th
    {   re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?$/i, 
        handler: function(bits) {

            var d = new Date();
            var yyyy = d.getFullYear(); 
            var dd = parseInt(bits[2], 10);
            var mm = parseMonth(bits[1]);

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // Jan 4th 2003
    {   re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?,? (\d{4})$/i,
        handler: function(bits) {

            var yyyy = parseInt(bits[3], 10); 
            var dd = parseInt(bits[2], 10);
            var mm = parseMonth(bits[1]);

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // next Tuesday - this is suspect due to weird meaning of "next"
    {   re: /^next (\w+)$/i,
        handler: function(bits) {

            var d = new Date();
            var day = d.getDay();
            var newDay = parseWeekday(bits[1]);
            var addDays = newDay - day;
            if (newDay <= day) {
                addDays += 7;
            }
            d.setDate(d.getDate() + addDays);
            return d;

        }
    },
    // last Tuesday
    {   re: /^last (\w+)$/i,
        handler: function(bits) {

            var d = new Date();
            var wd = d.getDay();
            var nwd = parseWeekday(bits[1]);
         
            // determine the number of days to subtract to get last weekday
            // calculates 0 if weekdays are the same so we have to change this to 7
            var addDays = (wd == nwd) ? -7 : (-1 * (wd + 7 - nwd)) % 7;
            
            // adjust date and return
            d.setDate(d.getDate() + addDays);
            return d;

        }
    },
    // Tuesday
    {   re: /^(\w+)$/i,
        handler: function(bits) {

            var d = new Date();
            var wd = d.getDay();
            var nwd = parseWeekday(bits[1]);
         
            // if same weekday, return date         
            if (nwd == wd)
               return d;

            // if new weekday is before current weekday
            if (nwd < wd )
               {
 
               // calculate last weekday
               d.setDate(d.getDate() + ((wd == nwd) ? -7 : (-1 * (wd + 7 - nwd)) %