
// Crunch Insert -  Fri Nov 6 16:54:45 EST 2009

/*
  This file changes the default document_domain if a meta tag named 'document_domain_change' is set to true
  or
  If the search param fixDomain is set to true
*/
var original_document_domain = document.domain;
document_domain_changed = false;
if(typeof document.getElementsByName('document_domain_change')[0] != 'undefined' && typeof document.getElementsByName('document_domain_change')[0].content != 'undefined' || document.location.search.indexOf('fixDomain=true') != -1 ){
  var wlhs = window.location.hostname.split('.');
  document.domain = wlhs[wlhs.length-2] +'.'+wlhs[wlhs.length-1];
  document_domain_changed = true;
}

// Crunch Insert -  Fri Nov 6 16:54:45 EST 2009

/**
 * @Overview  This is a library designed to simplify and standardize many of the common ways of doing things. This library was written using OOP methodology borrowing from the JavaBean specification combined with Gang-of-Four (GoF) patterns.
 * @name common.js
*/



// Turn off the jQuery '$' to not conflict with prototype
jQuery.noConflict();

// Used to scope global things.  Currently only used for eval
var global = this;


// Defining namespaces for functions and classes
cnp = {};

cnp.util = {};
cnp.dom = {};
cnp.dom.toggleClass = {};
cnp.number = {};
cnp.dependencyLoader = {};
cnp.widget = {};
cnp.widget.rte = {};
cnp.widget.popup = {};
cnp.archetype = {};

cnp.stats = {};
cnp.ad = {};
cnp.message = {};


/********************************************
** common archetype definitions
*********************************************/

/**
 * singleton - contains the methods used by singletons
*/
cnp.archetype.Singleton = {
  getInstance: function() {
    if(typeof(this._instance) == 'undefined') {
      this._instance = new this;
      if(this._instance.init) {
        this._instance.init();
      }	
    }
    return this._instance;
  }
}


/**
 *	Class - used to create class hierarchies using .beget() to have a super/sub class relationship  
 */
cnp.archetype.Class={
   beget:function(args){
      var F=function(self){return function(){
         this.Super=self;
      }}(this);
      F.prototype=this;
return new F();
}};

/**
 * Observable - contains methods used for observable objects
 */
cnp.archetype.Observable = function() {
  var observers = new cnp.util.Array();
  
  this.addObserver = function(func) {
    observers.add(func);
  }
  
  this.notify = function(obj, evt) {
    var it = observers.getIterator();
    while(it.hasNext()) {
      var func = it.next();
      func(obj, evt);
    }
  }
}




/**********************************************************************
** General purpose Classes
***********************************************************************/

/**
 *  @desc parse Query String 
 *  @returns {cnp.util.Map} Map containing parameters in key/value pairs
 *  @param {String} queryString the query string to parse.
 */
cnp.util.parseQueryString = function(str) {
  paramMap = new cnp.util.Map().setUniqueKey(false);
  str = str ? str : location.search;
  var query = str.charAt(0) == '?' ? str.substring(1) : str;
  if (query) {
    var fields = query.split('&');
    for (var f = 0; f < fields.length; f++) {
      var field = fields[f].split('=');
	if (field[1]){
      		paramMap.add(unescape(field[0].replace(/\+/g, ' ')),unescape(field[1].replace(/\+/g, ' ')));
	}
    }
  }
  return paramMap;
}


cnp.util.buildUrl = function(args) {
  var uri = args.uri;
  var parameterMap = args.parameterMap;
  var seperator = args.seperator ? args.seperator : '&';
  
  var joiner = uri.indexOf("?") == -1 ? '?' : seperator;
  joiner = uri ? joiner : '';
  
  var retString = uri + (!parameterMap.isEmpty() ? joiner : '');
  var it = parameterMap.asArray().getIterator();
  while(it.hasNext()) {
    var key = it.next();
    var value = it.next();
    retString += key+'='+value;
    retString += it.hasNext() ? seperator : '';
  }
  return retString;
}

/**
 * @desc General purpose iterator
 * @Constructor
 * @param {Array} backingArray An array to iterate through
 * 
 */
cnp.util.Iterator = function(backingArray) {
  var pointer = 0;
  
    /**
    * @desc Check to see if there are more elements in the array
    * @returns {boolean} true if array has more elements 
    */   
  this.hasNext = function() {
    return (pointer <= backingArray.length-1)
  }
  
    /**
    * @desc Return next object in the array
    * @returns {Object} next object in the array
    */
  this.next = function() {
    if (pointer > backingArray.length-1) {
      return false;
    }
    var ret = backingArray[pointer];
    pointer++;
    return ret;
  }    
  
}


/**
* @desc General purpose array
* @constructor
* @example
* var myArray = new cnp.util.Array();
* var button = new Button("press me");
* myArray.add(button);
* var it = myArray.getIterator();
* while(it.hasNext) {
*     alert(it.next());
* }
*/
cnp.util.Array = function() {
  var backingArray = new Array();
  var index = false;
  var unique = false;
  
    /**
    *  @desc Add a new element to the array
    *  @param {Object} element New element to add
    *  @returns {boolean} success or failure of add.  Will fail if array is unique and attempt to add a duplicate object.
    */
  this.add = function(element, index) {
    if(index) {
      backingArray[index] = element;
    }    
    
    if(unique) {
      if(this.contains(element)) {
        return false;
      }
    }
    index = backingArray.length;
    backingArray.push(element);
    return true;
  }
  
  
  this.getIndex = function() {
    return index;
  }
  
  this.setUnique = function(set_unique) {
    unique = set_unique;
    return this;
  }
  
    /**
    *  @desc check to see if array contains this element
    *  @param {Object} object to check against.  Object must impliment a .equals(Object) method.
    *  @returns {boolean} true if object matches an element in the array
    */
  this.contains = function(element) {
    return (this.get(element) != null);
  }
  
    /**
    *  @desc Get an element from the array
    *  @param {Object or int} object If object is a integer, gets indexed element from array.  If object is an Object, retrieves a matching element using the .equals(object) method.  If object does not have a .equals method, compares by natural equality. 
    *  @returns {Object} element from the array
    */
  this.get = function(object) {
    if(object.equals) {
      return getByEqualsMethod(object);
      } else {
      return getByNaturalEquality(object);
    }
    return null;
  }
  
  
  this.getByIndex = function(i) {
    index = i;
    return backingArray[index];
  }
  
  function getByEqualsMethod(object) {
    for(index=0; index<backingArray.length; index++) {
      if(backingArray[index].equals) {        // I don't like this hack, but it will protect us from objects that don't have equals in the array
        if(backingArray[index].equals(object)) {
          return backingArray[index];
        }
      }    
    }
    return null;        
  }
  
  function getByNaturalEquality(object) {
    for(index=0; index < backingArray.length; index++) {
      if(backingArray[index] == object) {
        return backingArray[index];
      }
    }
    return null;
  }
  
    /**
    *  @desc Get the size of an array
    *  @returns {int} size of the array
    */
  this.size = function() {
    return backingArray.length;
  }    
  
  this.isEmpty = function() {
    return (this.size() == 0);
  }
  
    /**
    *  @desc Get the backing array.  This can be used to retrieve the backing array to perform functions directly on the array (last resort)
    *  @returns {Array} the backing array  
    */
  this.getBackingArray  = function() {
    return backingArray;
  }
  
    /**
    * @desc Get a cnp.util.Iterator for this array
    * @returns {cnp.util.Iterator} a cnp.util.Iterator for this array
    */
  this.getIterator = function() {
    return new cnp.util.Iterator(backingArray);
  }
}





/**
 * @constructor
 * @desc General purpose map of key/value pairs
 */
cnp.util.Map = function() {
  var keyArray = new cnp.util.Array().setUnique(true);
  var valueArray = new cnp.util.Array();
  
  this.setUniqueKey = function(set_unique) {
    keyArray.setUnique(set_unique);
    return this;
  }
  
  this.isEmpty = function() {
    return keyArray.isEmpty();
  }    
  
  this.add = function(key, value) {
        // keyArray will return false if unique is set when adding a duplicate.
    if(keyArray.add(key)) {
      valueArray.add(value);
      return this;
    }
        // We can use the keyArray index here since add above called Array.contains which calls Array.get which sets the index.
    valueArray.add(value, keyArray.getIndex());
    return this;
  }
  
  this.get = function(key) {
    return keyArray.get(key) && valueArray.getByIndex(keyArray.getIndex());
  }
  
  this.contains = function(key) {
    return keyArray.contains(key);
  }
  
  this.getIterator = function() {
    return keyArray.getIterator();
  }
  
  this.size = function() {
    return keyArray.size();
  }
  
  this.asArray = function() {
    var array = new cnp.util.Array();
    for(var i=0; i < keyArray.size(); i++) {
      array.add(keyArray.getByIndex(i));
      array.add(valueArray.getByIndex(i));
    }
    return array;
  }
  
  this.getValues = function() {
    return valueArray;
  }
}



cnp.util.browser = new function() {
  
  this.isIe = function() {
    return jQuery.browser.msie;
  }
  
  this.isSafari = function() {
    return jQuery.browser.safari;
  }
  
  this.isFirefox = function() {
    return jQuery.browser.mozilla;
  }
  
  this.isOpera = function() {
    return jQuery.browser.opera;
  }
  
}

	/******************************************************
	 ** This group sets the value of a element
	 ******************************************************/
	 /** 
	  * @desc  Set the value on a collection of elements according to jQuery selector
	  * @returns {boolean} false if no elements found otherwise true
	  * @param {String} selector  A jQuery selector string to identify the collection of elements
	  * @param {String} value  The value to set on the elements
	  */
cnp.dom.setValueBySelector = function(selector, value) {
  el = jQuery(selector);
  if(el.size() > 0) {
    el.val(value);
    return true;
  }
  return false;
}	

	 /** 
	  * @desc   Set the value on a collection of elements using the name attribute
	  * @returns {boolean} false if no elements found otherwise true
	  * @param {String} name  The name attribute of the elements
	  * @param {String} value  The value to set on the elements
	  */
cnp.dom.setValueByName = function(name, value) {
  return cnp.dom.setValueBySelector("*[@name="+name+"]", value);
}	

	 /** 
	  * @desc    Set the value on a collection of elements by id
	  * @returns {boolean} false if no elements found otherwise true
	  * @param {String} id  The id of the element
	  * @param {String} value  The value to set on the element
	  */	
cnp.dom.setValueById = function (id, value) {
  return cnp.dom.setValueBySelector("#"+id, value);
}

	 /** 
	  * @desc     Set the value on a collection of elements by name and then by id if fails to find elements by name
	  * @returns {boolean} false if no elements found otherwise true
	  * @param {String} name  The name attribute of the elements
	  * @param {String} value The value to set on the elements
	  */	
cnp.dom.setValue = function(name, value) {
  return (cnp.dom.setValueByName(name, value) || cnp.dom.setValueById(name, value));
}



	/***************************************************
	 ** This group sets the inner html of a element 
	 ***************************************************/	
	 /** 
	  * @desc   Set the value on a collection of elements according to jQuery selector
	  * @returns {boolean} false if no elements found otherwise true
	  * @param {String} selector  The jQuery selector to identify the collection of elements
	  * @param {String} html  The inner html for the elements
	  */		 
cnp.dom.setInnerHtmlBySelector = function(selector, html) {
  j = jQuery(selector);
  if(j.size() > 0) {
    j.html(html);
    return true;
  }
  return false;
}

   /** 
    * @desc    Set the inner html on a collection of elements using the name attribute
    * @returns {boolean} false if no elements found otherwise true
    * @param {String} name  The name of the elements to modify
    * @param {String} html  The html for each of the elements
    */  
cnp.dom.setInnerHtmlByName = function(name, html) {
  return cnp.dom.setInnerHtmlBySelector("*[@name="+name+"]", html);
}

   /** 
    * @desc     Set the inner html on a collection of elements by id
    * @returns {boolean} false if no elements found otherwise true
    */  
cnp.dom.setInnerHtmlById = function (id, html) {
  return cnp.dom.setInnerHtmlBySelector("#"+id, html);
}

   /** 
    * @desc      Set the inner html on a collection of elements by name and then by id if fails to find elements by name
    * @returns {boolean} false if no elements found otherwise true
    */    
cnp.dom.setInnerHtml = function(name, html) {
  return (cnp.dom.setInnerHtmlByName(name, html) || cnp.dom.setInnerHtmlById(name, html)); 
} 

  /**
   * @desc Add a function to either execute on window onload (IE) or on document ready (Everyone else).
   *    This is due to bugs with IE and document ready.
   * @returns {none} 
   * @param {function} f  The callback function to be called when the event occurs
   */
cnp.util.doWhenReady = function(f) {
  if(jQuery.browser.msie) {
    var prev=window.onload;
    window.onload=function(){ if(prev)prev(); f(); } 
    } else {
    jQuery(document).ready(f);
  }
}

   /**
   * @desc Generate a random number
   * @param {int} min minimum value of returned number
   * @param {int} max maximum value of returned number
   * @returns {int} random number
   */
cnp.number.randomNumber = function(min, max) {
  return Math.floor(Math.random()*(max-min))+min;
  
}

/**
*  @constructor
*  @desc class describing a single dependency
*  @example
*  jqModalDep = new cnp.dependencyLoader.Dependency()
*                .setName("jqModal")
*                .setLocation("/js/3rdparty/jqModal.js")
*                .setPostProcessor(new cnp.dependencyLoader.JavascriptPostProcessor());
*/
cnp.dependencyLoader.Dependency = function() {
  
  this.STATE_NOT_LOADED = 1;
  this.STATE_LOADING = 2;
  this.STATE_PROCESSING = 3;
  this.STATE_PROCESSED = 4;
  
  var name;
  var state = this.STATE_NOT_LOADED;
  var me = this;
  var location;
  var dependencies = new cnp.util.Array();
  var postProcessor;
  var data;
  var depreciated;
  
    /**
    *  @desc get the name associated with this dependency - name is used to decouple the dependency with the location of that dependency
    *  @returns {String} the name associated with this dependency
    */
  this.getName = function() {
    return name;
  }
  
    /**
    *  @desc set the name associated with this dependency - name is used to decouple the dependency with the location of that dependency
    *  @returns {cnp.dependencyLoader.Dependency} set_name The name to set for this dependency
    */
  this.setName = function(set_name) {
    name = set_name;
    return this;
  }    
  
  this.getLocation = function() {
    return location;
  }    
  
  this.setLocation = function(set_location) {
    location = set_location;
    return this;
  }    
  
  this.getState = function() {
    return state;
  }
  
  this.setState = function(set_state) {
    state = set_state;
  }
  
  this.setPostProcessor = function(set_postProcessor) {
    postProcessor = set_postProcessor;
    return this;
  }
  
  this.getData = function() {
    return data;
  }
  
  this.setDepreciated = function(set_depreciated) {
    depreciated = set_depreciated;
    return this;
  }
  
  this.equals = function(dependency) {
    return (name == dependency.getName());
  }
  
  this.getDependencyCount = function() {
    return dependencies.size();
  }
  
  this.addDependency = function(dependency) {
    (dependencies.contains(dependency) || dependencies.add(dependency));
    return me;
  }
  
  function loadDependencies() {
    var ret = true;
    var it = dependencies.getIterator();
    while(it.hasNext()) {
      var dep = it.next();
      ret = (dep.load() & ret);
    }
    return ret;
  }
  
  this.load = function() {
        // First, if I am loaded, don't continue just return true
    if(state != this.STATE_NOT_LOADED) {
      return true;
    }
    loadDependencies();
    
            // If this is a non OO library use depreciated loading
    if(depreciated) {
      postProcessor.loadDepreciated(me);
      } else {            
      state = this.STATE_LOADING;                
      data = jQuery.ajax({
        url : location,
        ifModified : true,
        async: false
      }).responseText;
      
      postProcessor.process(me);
    }    
    
    return true; 
  }
  
  
  
  
  return me;
}


/** @Constructor
*   @Desc DependencyLoader Singleton - used to load dependencies of objects
*/ 
cnp.dependencyLoader.Loader = new function() {
  var me = this;
  var dependencies = new cnp.util.Array();
  
  this.addDependency = function(dependency) {
    (dependencies.contains(dependency) || dependencies.add(dependency));
    return me;
  }
  
  this.getDependencyByName = function(name) {
    return dependencies.get(new cnp.dependencyLoader.Dependency().setName(name));
  }
  
  this.loadDependency = function(name) {
    dep = this.getDependencyByName(name);
    return(dep && dep.load());
  }
}


cnp.dependencyLoader.JavascriptPostProcessor = function() {
  var me = this;
  
  this.process = function(dependency) {
    dependency.setState(cnp.dependencyLoader.Dependency.STATE_PROCESSING);
    global.eval(dependency.getData());
    dependency.setState(cnp.dependencyLoader.Dependency.STATE_PROCESSED);
  }
  
  this.loadDepreciated = function(dependency) {
    var head = document.getElementsByTagName('head')[0];
    
            // Check for duplicate before adding this script  
    for(var i=0; i<head.childNodes.length; i++) {
      if(head.childNodes[i].nodeName == "SCRIPT") {
        if(head.childNodes[i].src.indexOf(dependency.getLocation()) > -1) {
          dependency.setState(dependency.STATE_PROCESSED);
          return;
        }
      }
    }
    if(dependency.getState() == dependency.STATE_NOT_LOADED) {
      dependency.setState(dependency.STATE_LOADING);
      var script = document.createElement('script');
      script.onload = new function() {dependency.setState(this.STATE_PROCESSED);}
      script.setAttribute('type', 'text/javascript');
      script.setAttribute('language', 'text/javascript');
      script.setAttribute('src', dependency.getLocation());
      head.appendChild(script);
      dependency.setState(this.STATE_PROCESSING);
    }        
    
  }        
  
}


cnp.dependencyLoader.CssPostProcessor = function() {
  this.process = function(dependency) {
    dependency.setState(cnp.dependencyLoader.Dependency.STATE_PROCESSING);
    jQuery("body").prepend("<style>"+dependency.getData()+"</style>");
    dependency.setState(cnp.dependencyLoader.Dependency.STATE_PROCESSED);  
  }
  
  this.loadDepreciated = function(dependency) {
    alert("depreciated mode should not be used for CSS dependencies!!!!");
  } 
}



/************************************************
** Dependency map used by the dependency loader
*************************************************/
jqModalDep = new cnp.dependencyLoader.Dependency()
.setName("jqModal")
.setLocation("/js/3rdparty/jqModal.js")
.setPostProcessor(new cnp.dependencyLoader.JavascriptPostProcessor());
cnp.dependencyLoader.Loader.addDependency(jqModalDep);


tinyMceDep = new cnp.dependencyLoader.Dependency()
.setName("tinyMce")
.setDepreciated(true)
.setLocation("/tinymce/jscripts/tiny_mce/tiny_mce.js")
.setPostProcessor(new cnp.dependencyLoader.JavascriptPostProcessor());
cnp.dependencyLoader.Loader.addDependency(tinyMceDep);

autoSave = new cnp.dependencyLoader.Dependency()
.setName("autoSave")
.setDepreciated(true)
.setLocation("/js/weddingwebsite/saveform.js")
.setPostProcessor(new cnp.dependencyLoader.JavascriptPostProcessor());
cnp.dependencyLoader.Loader.addDependency(autoSave);   

rteEditorCss = new cnp.dependencyLoader.Dependency()
.setName("rteEditorCss")
.setLocation("/css/cnp/dependencies/rte_editor.css")
.setPostProcessor(new cnp.dependencyLoader.CssPostProcessor());
cnp.dependencyLoader.Loader.addDependency(rteEditorCss);    

rteEditor = new cnp.dependencyLoader.Dependency()
.setName("rteEditor")
.setLocation("/js/cnp/dependencies/rte_editor.js")
.setPostProcessor(new cnp.dependencyLoader.JavascriptPostProcessor())
.addDependency(rteEditorCss);
cnp.dependencyLoader.Loader.addDependency(rteEditor);

jqFormsPlugin = new cnp.dependencyLoader.Dependency()
.setName("jqFormsPlugin")
.setLocation("/js/3rdparty/jquery.form.js")
.setPostProcessor(new cnp.dependencyLoader.JavascriptPostProcessor());
cnp.dependencyLoader.Loader.addDependency(jqFormsPlugin);


/**@constructor
 * @desc Provides a standard popup dialog box in the page 
 *
 * @example
 * imagePopup = new cnp.widget.Popup(). 
 *     setText("This is the text that will go inside of the popup").draw(); 

 * function doSomething() { 
 *   imagePopup.popup(); 
 * }
 */ 
 
cnp.widget.Carousel = function() {

	contentBlock = jQuery("#topicIntroBlock .introBlockContent");
	photoBar = jQuery("#topicIntroBlock .photoBar");
	photoBarHeight = photoBar.height();
	pbCarouselFrame = jQuery("#topicIntroBlock .photoBarWindow ul");
	pbCarousel = jQuery("#topicIntroBlock .photoBarWindow ul li");
	pbCarouselUnitWidth = pbCarousel.width(); // Assuming that all thumbs are of identical width...
	pbCarouselCount = pbCarousel.size();
	prevButton = jQuery(".photoBarPrev span");
	nextButton = jQuery(".photoBarNext span");
	pbWindowWidth = jQuery("#topicIntroBlock .photoBarWindow").width();
	pbWindowFitCount = Math.floor(pbWindowWidth / pbCarouselUnitWidth);
	pbFrameWidth = pbCarouselFrame.width();
	pbOffscreenWidth = pbFrameWidth - pbWindowWidth;
	pbFrameShift = 0; // this value represents the amount that the photobar has shifted left or right. Only needed for non-carousel mode.
	amountToSlide = pbCarouselUnitWidth;
	animSpeed = 300; // This multiplier determines rougly how many milliseconds it takes to slide a distance of one unit. Higher numbers are slower.


function disable(obj) { obj.addClass('disabled') };
function enable(obj) { obj.removeClass('disabled') };

function manageCarouselStatus() {
	if (parseInt(pbCarouselFrame.css("left")) >= 0) {
		disable(prevButton);
	} else {
		enable(prevButton);
	}
	if (-1*parseInt(pbCarouselFrame.css("left")) >= pbOffscreenWidth) {
		disable(nextButton);
	} else {
		enable(nextButton);
	}	
}


if (pbOffscreenWidth > 0) { // bind hover states for the previous and next buttons if the carousel is wider than the viewing window, or hide them entirely.
nextButton.hover(
	function () {
		enable(prevButton);
		unitsRemaining = Math.ceil((pbOffscreenWidth + parseInt(pbCarouselFrame.css("left"))) / pbCarouselUnitWidth); // calculate how many units are offscreen
		pbCarouselFrame.animate({ left: -1*pbOffscreenWidth + "px" }, unitsRemaining*animSpeed, manageCarouselStatus )
	}, 
	function () {
		pbCarouselFrame.stop();
		manageCarouselStatus();
	}
);

prevButton.hover(
	function () {
		enable(nextButton);
		unitsRemaining = Math.ceil(-1*parseInt(pbCarouselFrame.css("left")) / pbCarouselUnitWidth); // calculate how many units are offscreen
		pbCarouselFrame.animate({ left: 0 + "px" }, unitsRemaining*animSpeed, manageCarouselStatus )
	}, 
	function () {
		pbCarouselFrame.stop();
		manageCarouselStatus();
	}
);
} else {
	prevButton.css({ visibility: "hidden" });
	nextButton.css({ visibility: "hidden" });
}


jQuery(".photoBarToggleOn").click(function(){
	manageCarouselStatus();
	contentBlock.height("auto");
	contentBlockHeight = contentBlock.height() + parseInt(contentBlock.css("padding-top")) + parseInt(contentBlock.css("padding-bottom")); // This gets queried on each event, in case the user has resized the page in some way.
	
	contentBlock.toggleClass("toggleState0");
	contentBlock.toggleClass("toggleState1");
	contentBlock.height(contentBlock.height() + "px");
	jQuery("#topicIntroBlock .introBlockContentCopyTree").animate({ top: contentBlockHeight + "px" }, 600 );
	jQuery("#mostViewedPhotos").animate({ top: (contentBlockHeight - photoBarHeight) / 2 + "px" }, 600 );
});
	
jQuery(".photoBarToggleOff").click(function(){
	
	
	contentBlock.toggleClass("toggleState0");
	contentBlock.toggleClass("toggleState1");
	
	jQuery("#mostViewedPhotos").animate({ top: -1*photoBarHeight + "px" }, 600 );
	jQuery("#topicIntroBlock .introBlockContentCopyTree").animate({ top: "0px" }, 600, function(){
		if (!jQuery.browser.msie) { // there's no reason that setting height to 'auto' should break anything in IE6, and yet it does!
			contentBlock.height("auto"); 
		}
	} );
});

/* END PHOTOBAR CODE */
	


}



/**@constructor
 * @desc Provides a standard popup dialog box in the page 
 *
 * @example
 * imagePopup = new cnp.widget.Popup(). 
 *     setText("This is the text that will go inside of the popup").draw(); 

 * function doSomething() { 
 *   imagePopup.popup(); 
 * }
 */ 
cnp.widget.Popup = function() {
  cnp.dependencyLoader.Loader.loadDependency("jqModal");
  var id = cnp.util.UniqueIdGenerator.getInstance().getUniqueId("popup");
  var text = "";
  var buttons = new Array();
  var me = this;
  var closeAction = 'cnp.widget.Popup().close(\''+id+'\')';
  var onDraw;
  
  // This is only to preload the images for IE which does not reliably load images for the box
  new Image().src="/i/weddingwebsite/popup_right-round.gif";
  new Image().src="/i/weddingwebsite/popup_left-round.gif";
  new Image().src="/i/weddingwebsite/popup_middle.gif";
/*  new Image().src="/i/weddingwebsite/popup_background.gif";
  new Image().src="/i/loading_ring.gif";*/
  
  
  
  cnp.util.doWhenReady(function() {
    jQuery("body").prepend('<div class="popup redirectLoggerExclusion" id="'+id+'"> \
    <div> \
    <a href="#" onclick="'+closeAction+'"/> \
    <img src="/i/weddingwebsite/popup_right-round.gif" class="right"/> \
    </a> \
    <img src="/i/weddingwebsite/popup_left-round.gif" class="left"/> \
    <div class="middle"></div> \
    </div>  \
    <div class="lower"> \
    <p id="popupBody'+id+'" class="text"> \
    </p> \
    <div id="popupButtonDiv'+id+'" class="buttonBar"></div> \
    </div> \
    </div>');           
    jQuery("#"+id).jqm({modal:true});
    
    
  });   
  
  
  /** @desc Change the action to be performed if someone hits the corner "close" button */
  this.setCloseAction = function(set_closeAction) {
    closeAction = set_closeAction;
  }
  
  
  this.setOnDraw = function(set_OnDraw) {
    onDraw = set_OnDraw;
  }
  
  /** @desc  Get text that will be displayed in this popup box 
   *  @returns {String} Text displayed in the popup box
     */
  this.getText = function() {
    return text;
  } 
  
  this.addButton = function(button) {
    buttons.push(button);
    return this;
  }
  
  this.removeButtons = function() {
    buttons = new Array();
    return this;
  }
  
  /** @desc Set text that will be displayed in this popup box 
   * @returns {cnp.widget.Popup} returns this cnp.widget.Popup object
   * @param {String}  set_text The text to put inside the popup box
   */
  this.setText = function(set_text) {
    text = set_text;
    return this;
  }
  
  /** @desc  Popup the popup box 
   * @returns {cnp.widget.Popup} returns this cnp.widget.Popup object
  */
  this.popup = function() {
    if(navigator.appName.indexOf("Explorer") > -1) {
      var popup = document.getElementById(id);
      objh = popup.offsetHeight/2;
      objw = popup.offsetWidth/2;
      popup.style.position="absolute";
      popup.style.top = Math.floor(Math.round((document.documentElement.offsetHeight/2)+document.documentElement.scrollTop)-objh)+'px';
      popup.style.left = Math.floor(Math.round((document.documentElement.offsetWidth/2)+document.documentElement.scrollLeft)-objw)+'px';      
    }		
    
    var popup = document.getElementById(id);
    popup.style.display = "block";    
    jQuery("#"+id).jqm().jqmShow();
    
    return this;
  }
  
  this.popdown = function() {
    jQuery("#"+id).jqm().jqmHide();
    return this;
  }
  
     /** @desc Static method to close a box by ID without relying on having it's object */
  this.close = function(id) {
    jQuery("#"+id).jqm().jqmHide();
    return false;
  }  
  
  /** @desc Render the box in the dom
   *  @returns {cnp.widget.Popup} returns this cnp.widget.Popup object
   */
  this.draw = function() {
    cnp.util.doWhenReady(function() {
      cnp.dom.setInnerHtmlById("popupBody"+id, text);
      
      cnp.dom.setInnerHtmlById("popupButtonDiv"+id, "");
      for(var i=0;i<buttons.length;i++) {
        buttons[i].draw("#popupButtonDiv"+id);
      }
      (onDraw && onDraw());
    });
    return this;
  }
  return this;
  
}

/** @Constructor */
cnp.widget.Button = function(set_buttonType) {
  var id = cnp.util.UniqueIdGenerator.getInstance().getUniqueId("button");
  var name;
  var value;
  var onclick;
  var me = this;
  var buttonType = set_buttonType;
  
  this.getId = function() {
    return id;
  }    
  
  this.setName = function(set_name) {
    name = set_name;
    return this;
  }
  
  this.getName = function() {
    return name;
  }
  
  this.setValue = function(set_value) {
    value = set_value;
    return this;
  }
  
  this.getValue = function() {
    return value;
  }
  
  this.onclick = function(func) {
    onclick = func;
    return this;
  }
  
  this.click = function() {
    onclick(me);
  }
  
  this.draw  = function(parentSelector) {
    buttonType.draw(parentSelector, me);
    return this;
  }
  
  return this;
}


/** @constructor */
cnp.widget.ImageButton = function(set_image) {
  var image = set_image;
  new Image().src=set_image;    
  
  
  this.draw = function(parentSelector, button) {
    if(jQuery.browser.msie) {
      jQuery(parentSelector).append('<a id="'+button.getId()+'"href="#"><img src="'+image+'" class="button" /></a>');
      } else {
      jQuery(parentSelector).append('<a id="'+button.getId()+'"href="javascript:void(0)"><img src="'+image+'" class="button" /></a>');
    }        
    jQuery("#"+button.getId()).click(button.click);
  }
  return this;
}

cnp.widget.popup.newPopup = function(args) {
  return new cnp.widget.Popup();
}

cnp.widget.popup.deletePhotoPopup = function(args) {
  var deletePhotoPopup = new cnp.widget.Popup();
  
  if(!args.noAction) {
    args.noAction = function() {deletePhotoPopup.popdown();}
  }
  
  return deletePhotoPopup
  .setText("Are you sure you wish to delete photo?")
  .addButton(new cnp.widget.Button(new cnp.widget.ImageButton("/i/production/BTN_yes.gif")).onclick(args.yesAction))
  .addButton(new cnp.widget.Button(new cnp.widget.ImageButton("/i/production/BTN_no.gif")).onclick(args.noAction));
}

cnp.widget.popup.photoUploadPopup = function(args) {
  imagePopup = cnp.widget.popup.newPopup()
  .setText("Your photo is uploading now. Please note that newly uploaded images may not appear immediately.");
  return imagePopup;
}


/** @constructor 
 *  @desc sets a collection of columns to an equal height
 *  
 *  @example
 * cnp.dom.equalElements(".stretchBracket .stretchable");
 *
 * .stretchBracket = outercontainer class for the collection
 * .stretchable = class added to each stretchable column
 *
 */

cnp.dom.equalElements = function(elements) {  
  var elements = jQuery(elements);
  var maxHeight;
  elements.each(function(i, n){
    var elem = jQuery(elements[i]);
    if (!maxHeight || elem.height() > maxHeight) maxHeight = elem.height();
  });  
  jQuery(elements).css("height", maxHeight);    
}


/** @constructor 
 *  @desc Toggles the inclusion of a class determined by it's id between one or two states.
 *  This allows multiple behaviors for a block on a page dependent on the class of the wrapper.
 *  
 *  @example
 * ed = new cnp.dom.ToggleClass().setId("idOfThingToToggle").setOnClass("closed").setOffClass("open");
 *
 * function toggleIt() {
 *    ed.toggle();
 * }
 */
cnp.dom.ToggleClass = function() {
  var id = null;
  var onClass = null;
  var offClass = null;
  
  
  
    /** @desc  Toggle between the off class and the on class
     *  @returns {cnp.dom.ToggleClass}  Returns this cnp.dom.ToggleClass
     */        
  this.toggle = function() {
    if(onClass) {
      jQuery("#"+id).toggleClass(onClass);
    }
    
    if(offClass) {
      jQuery("#"+id).toggleClass(offClass);
    }
    return this;
  }
  
  
    /** @desc  Get Id of object that will be acted upon 
     *  @returns {String}
     */ 
  this.getId = function() {
    return id;
  }    
  
    /** @desc  Set Id of element to be acted upon
     *  @returns {cnp.dom.ToggleClass} this cnp.dom.ToggleClass
     *  @param {String} The id of the element
     */
  this.setId = function(set_id) {
    id = set_id;
    return this;
  }
  
    /** @desc  Get the class to be set when toggle is 'on'
     *  @returns {String} 
     */        
  this.getOnClass = function() {
    return onClass;
  }    
  
    /** @desc  Set the class to be used when the toggle is 'on'
     *  @returns {cnp.dom.ToggleClass} this cnp.dom.ToggleClass
     *  @param {String}   set_onClass The class to set in the class list for the element given by set_id during on state
     */
  this.setOnClass = function(set_onClass) {
    onClass = set_onClass;
    return this;
  }
  
    /** @desc  Get the class to be set when toggle is 'off'
     *  @returns {String}
     */ 
  this.getOffClass = function() {
    return offClass();
  }
  
    /** @desc   Set the class to be used when the toggle is 'off'
     *  @returns {cnp.dom.ToggleClass} this cnp.dom.ToggleClass
     *  @param {String}  set_offClass The class to set in the class list for the element given by set_id during off state
     */
  this.setOffClass = function(set_offClass) {
    offClass = set_offClass;
    return this;
  }
  return this;
}

cnp.dom.toggleClass.hiddenToggleClass = function(args)  {
  if(!args.onClass) {
    args.onClass = "toggleOpen";
  }
  
  if(!args.offClass) {
    args.offClass = "toggleClose";
  }
  
  return new cnp.dom.ToggleClass().setId(args.id).setOnClass(args.onClass).setOffClass(args.offClass);
}



/** @constructor 
 *  @desc   Prevents searches on pre-defined array of 'useless/disallowed' search terms; assign to onsubmit for search forms
 *  @returns {true/false} depending on whether search string is one of disallowed variety 
 */
 cnp.util.searchSubmitStringTest = function(form) {
   var disallowed = ["\"\"","\"","'","''","?"," ",".",",","Search","search",""];
   var valid = true;
   var str = form.search_string.value;
   str = jQuery.trim(str);
   for (i=0 ; i < disallowed.length ; i++) {
     if (str == disallowed[i]) {
       valid = false;
     }
   }
   //alert(form.search_string.value, " valid: " + valid);
   return valid;
 }


/** @constructor
 *  @desc Generates and maintains a list of unique ids
 */
cnp.util.UniqueIdGenerator = function() {
  var ids = new cnp.util.Array();
  var count = 1000;
  
  this.getUniqueId = function(prefix) {
    var id;
    do {
      id = new String(prefix+"-unique-"+count);
      count++;
    } while(ids.contains(id));
    ids.add(id);
    return id;   
  }
}
cnp.util.UniqueIdGenerator.getInstance = cnp.archetype.Singleton.getInstance;


/** @constructor 
 *  @desc   Inner class defining a decorator to be used by setTheme()
 *  @returns {EditorTheme1}
 */     
cnp.widget.rte.TinyMCEEditor = function() {
  /** @ignore */
  this.init = function() {
    tinyMCE.init({
      mode : "none",
      theme_advanced_layout_manager : "SimpleLayout",
      theme_advanced_buttons1 : "bold,italic,underline,justifyleft,justifycenter,justifyright,justifyfull,bullist,numlist",
      theme_advanced_buttons2 : "",
      theme_advanced_buttons3 : "",
      theme_advanced_toolbar_location : "top",
      onchange_callback : "cnp.widget.RichTextSingleton.executeOnChangeCallbackChain"
    });
  }
  
  this.apply = function(args) {
    
    for(var i=0;i<elements.length;i++) {
      tinyMCE.execCommand('mceAddControl',true,elements[i]);
    }
  }
}

cnp.widget.rte.StandardTheme = function() {
  cnp.dependencyLoader.Loader.loadDependency("rteEditor");    
  
  this.apply = function(editor) {
        // Can not run this editor on Safari
    if(cnp.util.browser.isSafari()) {
      return;
    }
    onChangeCallback = editor.getOnChangeCallback();
    jQuery('#'+editor.getId()).rte({onChangeCallback: onChangeCallback});
  }        
}

cnp.widget.rte.newEditor = function(args) {
  var id = args.id;
  var theme = args.theme;
  
  var editor = new cnp.widget.rte.RichTextEditor().setId(id);
  if(!theme) {
    editor.setTheme(new cnp.widget.rte.StandardTheme());
  }
  return editor;    
}

cnp.widget.rte.RichTextEditor = function() {
  var me = this;
  var id;
  var theme;
  var onChangeCallback = function() {};
  
  this.getId = function()                                   {return id;}
  this.setId = function(set_id)                             {id = set_id; return this;}
  this.setTheme = function(set_theme)                       {theme = set_theme; return this;}
  this.getOnChangeCallback = function()                     {return onChangeCallback;}
  this.setOnChangeCallback = function(set_onChangeCallback) {onChangeCallback = set_onChangeCallback; return this;}
  this.apply = function() {
    theme.apply(me);
  }
}

/**@constructor
 * @desc Given an active group {String} quizpoll drops a toolkit quizpoll on a page -- pass the constructor the div id you wish to drop the quizpoll in.
 *
 * @example
 * cnp.util.doWhenReady(function() {  
 * var b = new cnp.quizpoll('div_id_for_quiz').loadQuizpoll();
 * });
 * 
 */
cnp.quizpoll = function(quiz_name) {
  cnp.dependencyLoader.Loader.loadDependency("jqFormsPlugin");
  var me = this;
  var quizID = quiz_name;
  var quizUrl = "/ajax/uncached/poll/" + quizID;
  
  this.setQuizResponse = function() {
    //balert("...inside setQuizResponse...");
    var quizForm = "#" + quizID + " form";
    // assumes the only form in the quizpoll is the one we want

    var responseUrl = quizUrl + "/" + jQuery("form input#activePollName").attr("value");
    jQuery(quizForm).ajaxForm( { target: ("#" + quizID), url: responseUrl, type:'POST', success: me.setQuizResponse } ); 
    // hi-jacks submission of the form to post to the url given originally
  }
  
  this.loadQuizpoll = function() {
    jQuery("#"+quizID).load(quizUrl, this.setQuizResponse);           
  }
  
  

}












cnp.stats.Writer = function() {
  output = '';
  this.setOutput = function(set_output) { output = set_output; return this;}
  this.getOutput = function() {return output;}
  
}


cnp.stats.AjaxWriter = function() {
  this.write = function() {
    jQuery.ajax({
      url : this.getOutput(),
      ifModified : true,
      async: false,
      timeout: 500
    });
    return true;
  }            
}
cnp.stats.AjaxWriter.prototype = new cnp.stats.Writer();





cnp.stats.ScriptWriter = function() {
  this.write = function() {
    var head = document.getElementsByTagName('head').item(0)
    var scriptTag = document.getElementById('loadScript');
    if(scriptTag) head.removeChild(scriptTag);
    script = document.createElement('script');
    script.src = this.getOutput();
    script.type = 'text/javascript';
    script.id = 'loadScript';
    head.appendChild(script);     
    return true; 
  }
  
}
cnp.stats.ScriptWriter.prototype = new cnp.stats.Writer();



/**
 * @constructor
 * @desc Stats singleton
 */
cnp.stats.Stats = function() {
  var me = this;
  var writer;
  
  var parameters = new cnp.util.Map();
  
  var uri = document.location.href;
  var userData;
  
  jQuery("meta").each(function(index) {
    if(this.name.indexOf("stats_") != -1) {
      parameters.add(this.name.substring(6), this.content);
    }       
  });    
  
  
  this.getParameter = function(paramKey) {
    return parameters.get(paramKey);
  }    
  
  this.addParameter = function(key, value) {
    parameters.add(key,value);
    return this;
  }
  
  this.getParameters = function() {
    return parameters;
  }
  
  this.getUri = function() {
    return uri;
  }
  
  this.setUri = function(set_uri) {
    if(set_uri.match(/\:\/\//)) {
      uri = set_uri
      } else {            
      uri = document.location.protocol + '//' + document.location.host + set_uri;
    }    
  }
  
  this.getUserData = function() {
    return userData;
  }
  
  this.setUserData = function(set_userData) {
    userData = set_userData;
  }
  
  this.getWriter = function() {
    return writer;
  }
  
  this.setWriter = function(set_writer) {
    writer = set_writer;
  }
}
cnp.stats.Stats.getInstance = cnp.archetype.Singleton.getInstance;


/**
 *  @constructor
 *  @desc defaultLogger 
 */
cnp.stats.DefaultLogger = function() {
  
  this.log = function() {
    var stats = cnp.stats.Stats;
    var output = ""; // default
    var re = /.*www\.brides\.com|video\.brides\.com/;
    var curHost = document.location.host;
        // console.debug("server name is " + curHost);
    output = curHost.match(re) ? "http://stats.brides.com" : ''; // if in prod
    output += '/js/stats/zag.js?Log=1';
    
    // pduey: if sending email to vendor from the vendor listing results page,
    // the vendor listing ID is not part of the URI. Lead reporting depends on that.
    // Rather than redo the vendor reporting data transformation, which is a big
    // stupid ugly mess, I'll just continue in the hacking tradition and fake it here.
    var vendorListingId = cnp.stats.Stats.getParameter("vendorListingId");
    if (vendorListingId) {
      var re = /\/local.*results\/\d+.*/;
      var curUrl = document.location.href;
      if ( ! curUrl.match(re)) {
        stats.setUri(stats.getUri().replace(/results/g, 'results/' + vendorListingId));
              // console.debug("added vendor listing id to outputURI: " + outputURI);
      }
    }
    
    
        // dwells: feedroom will provide FRsection and FRtopic url encoded we collect them 
        // and stuff them into the url for tracking
    
    if(document.location.href.indexOf("video.brides") != -1) {
      stats.setUri(document.location.href.replace(/video./g, 'www.'));
      var leadToken = '/videos/';
      if(stats.getUri().substring(test.length-1, test.length) == '/') {
        leadToken = 'videos/';
      } 
      var FRsection = stats.getParameter("FRsection");
      var FRtopic = stats.getParameter("FRtopic");
      if(FRsection) {
        stats.setUri(stats.getUri() + leadToken + FRsection);
      }
      if(FRtopic){
        stats.setUri(stats.getUri() + '/' + FRtopic);
      }      
    }
    
    
        /* keep these grouped as URL, REFERRER, screenres */  
    output += '&URL=' + cnp.util.buildUrl({ uri: stats.getUri(), parameterMap: stats.getParameters() });
    output += '&REFERRER=' + (document.referrer);
    output += '&screenres='+ screen.availWidth + "x" + screen.availHeight;
        /* keep these grouped as URL, REFERRER, screenres */
    
        // sburch - Leave this for now for backward compatibility
    if(stats.getUserData()) {
      output += '&email='+stats.getUserData().email;
    }
    
    output += '&cachedefeat=' + (new Date()).getTime();
    
    return stats.getWriter().setOutput(output).write();
  }  
}

cnp.stats.newDefaultLogger = function() {
  cnp.stats.Stats.setWriter(new cnp.stats.AjaxWriter());
  return new cnp.stats.DefaultLogger();
}

cnp.stats.newFastLogger = function() {
  cnp.stats.Stats.setWriter(new cnp.stats.ScriptWriter());
  return new cnp.stats.DefaultLogger();
}    







/**********************************************************************
** Ad related objects
***********************************************************************/



local = { 
  load:function(adType, targetDiv) {
    //console.log('local.load: '+ adType + ' : ' + targetDiv);
    localUnit = cnp.ad.getNewLocalAdUnit({placement: adType, target: targetDiv});
    localUnit.load();
  }
}




cnp.ad.getNewDartAdUnit = function(args) {
  var dartAdUnit = new cnp.ad.DartAdUnit();
  var tileCount = cnp.ad.property.dartProperties.getTileCounter();
  if(tileCount == 1){dartAdUnit.setFirst(true);}
  dartAdUnit.setTileNumber(tileCount);
  dartAdUnit.setSize(args.size);
  dartAdUnit.setPlacement(args.placement);
  dartAdUnit.setName('dartAdUnit_'+args.size.replace(/,/g, '_') +'_'+dartAdUnit.getPlacement());
  dartAdUnit.setInstanceName(args.instanceName);
  dartAdUnit.setTableAdProps(args.tableTagProps);
  dartAdUnit.setAdditionalKWValues(args.additionalKWvalues);
  cnp.ad.property.addAdUnit(dartAdUnit);
  return dartAdUnit;
}



cnp.ad.getNewLocalAdUnit = function(args) {
  var localAdUnit = new cnp.ad.LocalAdUnit();
  localAdUnit.setPlacementType(args.placement);
  localAdUnit.setTargetDiv(args.target);
  localAdUnit.setName('localAdUnit_'+localAdUnit.getPlacementType()+'_'+localAdUnit.getTargetDiv());
  cnp.ad.property.addAdUnit(localAdUnit);
  return localAdUnit;
}


/**
 * @desc Global Ads object - stores dart settings. This object is initilized as a singleton. There can be only one!
 * @Constructor
 * @param {Array} backingArray An array to iterate through
 * 
 */
cnp.ad.property = new function() {
  var me = this;
  
  var environment;                    // global application environment      
  var adUnits = new cnp.util.Map();   // register ads here
  var ord; randomizeOrd();            // set and randomize ord;
  
  
  this.dartProperties = {
    site: "",
    zone: "",
    url: "",
    section: "",
    keywords: new cnp.util.Map(),
    facets: new cnp.util.Map(),
    tileCount: 0,
    hackRegEx: new RegExp('1x1|140x300|148x166|446x154|110x165|125x300|140x310|224x200|88x165'),
    /* 
      HACK: ad size details
      1x1     text link
      140x300 local ad failover
      148x166 travel partner ad upper 
      446x154 travel partner ad lower
      110x165 gallery landing promo
      125x300 registry topplaces adrail unit
      140x310 shop online main promo
      224x200 Added by sburch per jason v. ad in fashion/dresses/gallery/vendor/designer/davidsbridal
    */
    
    getSite:         function()             { return this.site;},
    setSite:         function(set_site)      { this.site = set_site; return me;},
    getZone:         function()              { return this.zone; },
    setZone:         function(set_zone)      { this.zone = set_zone; return me;},
    getUrl:          function()              { return this.url; },
    setUrl:          function(set_url)       { this.url = set_url; return me;},
    getSection:      function()              { return this.section; },
    setSection:      function(set_section)   { this.section = set_section; return me;},
    getKeywords:     function()              { return this.keywords; },
    getKeyword:      function(key)           { return this.keywords.get(key); },
    addKeyword:      function(key, value)    { this.keywords.add(key, value); return me; },
    getFacets:       function()              { return this.facets; },
    getFacet:        function(key)           { return this.facets.get(key); },
    addFacet:        function(key, value)    { this.facets.add(key, value); return me; },
    getTileCounter:  function()              { return ++this.tileCount;},
    getHackRegEx:    function()              { return this.hackRegEx;},
    isDomainChanged: function()              { return document_domain_changed; } // this is set in 100_document_domain_fix.js
    
  }
  
  this.localProperties = {
    getSite:          function()              {return me.dartProperties.getSite();},
    getZone:          function()              {return me.dartProperties.getZone();}
  }
  
  
  function randomizeOrd() {
    ord = cnp.number.randomNumber(10000000000000000, 99999999999999999);
  }
  
  this.getAdUnits = function() {
    return adUnits;
  }
  
  this.addAdUnit = function(adUnit) {
    adUnits.add(adUnit.getName(), adUnit); 
  }
  
  this.getAdUnit = function(name) {
    return adUnits.get(name);
  }
  
  this.reloadAds = function() {
    randomizeOrd();
    //console.log("ORD: "+this.getOrd())
    var it = adUnits.getIterator();
    while(it.hasNext()) {
      var theAd = it.next();
      me.getAdUnit(theAd).load();
    }
  }
  
  this.getOrd = function() {
    return ord;
  }
  
  
  /** @desc  Sets the dart environment value (DEV,STAG,..,PROD)
   *  @example cnp.ad.property.setEnvironment('DEV'); 
   */
  this.setEnvironment = function(set_environment) {
    environment = set_environment;
    return this;
  }
  /** @desc  Gets the dart environment value
   *  @example cnp.ad.property.getEnvironment();
   *  @returns String: environment value 
   */
  this.getEnvironment = function() {
    return environment;
  }
}

/**
 * @desc Shared Ad utilities stored in this object.
 * @Constructor
 * 
 */

cnp.ad.DartAdUnit = function() {
  var me = this;
  var name;
  var instanceName;
  var size;
  var placement;
  var target;
  var first = false;
  var tileNumber;
  var tableAdProps;
  var additionalKWvalues = '';
  var runCounter = 0;
  
  
  this.getName = function() {return name;}      
  this.setName = function(set_name) {name = set_name; return this;}
  this.getInstanceName = function() {return instanceName;}
  this.setInstanceName = function(set_instanceName) {instanceName = set_instanceName; return this;}
  this.getSize = function() { return size;}
  this.setSize = function(set_size) { size = set_size; return this;}
  this.getPlacement = function() { return placement; }
  this.setPlacement = function(set_placement){ placement = set_placement; return this;}
  this.getTarget = function() { return target; }
  this.setTarget = function(set_target) { target = set_target; return this;}
  this.isFirst = function() { return first; }
  this.setFirst = function(set_first)  { first = set_first; return this;}
  this.getTileNumber = function()            { return tileNumber; }
  this.setTileNumber = function(set_tileNumber){ tileNumber = set_tileNumber; return this; }
  this.setTableAdProps = function(table_ad_props){tableAdProps = table_ad_props; return this;}
  this.getTableAdProps = function(){return tableAdProps;}
  this.setAdditionalKWValues = function(x){additionalKWvalues = x; return this;}
  this.getAdditionalKWValues = function(){return additionalKWvalues;}

  
  function refererCheck(pqs) {
    var RefererCheck = 'okay';
    ref = document.referrer;
    if (ref.indexOf('google') != '-1' || ref.indexOf('yahoo') != '-1') {RefererCheck = ''; }
    if (pqs.contains('nav')) {RefererCheck = '';}
    return RefererCheck;
  }
  
  this.load = function() {
    var pqs = cnp.util.parseQueryString();
    var dartURL = '';
    
    var dartLoaderMap = new cnp.util.Map()
    .setUniqueKey(false)
    .add("req", cnp.ad.property.dartProperties.getUrl()+cnp.ad.property.dartProperties.getSite()+'/'+cnp.ad.property.dartProperties.getZone())
    .add("pos", placement);
    
    if(parseInt(tableAdProps.numberOfAds) >= 0){
         if(tableAdProps.horzORvert == 'v') {
           var adsPerColumn = Math.round(tableAdProps.numberOfAds / tableAdProps.numberOfColumns);
           for (var i=0; i < tableAdProps.numberOfColumns; i++) {
             dartLoaderMap.add('tn', adsPerColumn); // number of ads per column/row 
           }
         } else {
           dartLoaderMap.add('tn', tableAdProps.numberOfAds); // number of ads per column/row 
         }
    
      dartLoaderMap
        .add('tr', tableAdProps.numberOfColumns) // Specifies that the Table will have to Rows/Columns 
        .add('to', tableAdProps.horzORvert)
        .add('te', tableAdProps.targetedAdsOnly)
        .add('tcs', tableAdProps.cellSpacing)
        .add('tp', '1');
    }
    
    if (additionalKWvalues != '' && additionalKWvalues != null ) {
      var akwv = additionalKWvalues.split(',');
      for (var i=0; i < akwv.length; i++) {
        dartLoaderMap.add('kw', akwv[i]);
      };
    }
    
    dartLoaderMap
    .add("kw", refererCheck(pqs)) /* referer check for google and popups see John P. or Dan with Questions */
    .add("section", cnp.ad.property.dartProperties.getSection())
    .add("printfriendly", pqs.contains('printable') ? true : false)
    .add("env", cnp.ad.property.getEnvironment())
    .add("search_string", escape(pqs.get('search_string')))
    .add("market", pqs.get('market'))
    .add("forumID", pqs.get('forumID'));

     
    var it = pqs.asArray().getIterator();
    while(it.hasNext()) {
      var key = it.next();
      var value = it.next();
      if(key == 'f') {
        var dump = value.split(':');
        dump0 = dump[0].replace(/\+/g, '-').replace(/ /g, '-').replace(/%20/g, '-');
        dump1 = dump[1].replace(/\+/g, '-').replace(/ /g, '-').replace(/%20/g, '-');
        dartLoaderMap.add(dump0, dump1);
      }
    }
    
    if (typeof microsite != 'undefined') {
      dartLoaderMap.add("microsite", microsite);
    }
    
    if (first){ dartLoaderMap.add("dcopt", 'ist') } // yeah, that is ist...
    dartLoaderMap
    .add("sz", size)
    .add("tile", tileNumber)
    .add("ord", '99999');   /* cnp.ad.property.getOrd()); */
    // sysparams()
    
    
    dartURL = cnp.util.buildUrl({ uri: '/dart/adbody.html', parameterMap: dartLoaderMap, seperator: ';' });
    if(cnp.ad.property.dartProperties.isDomainChanged()) {
      dartURL += '&fixDomain=true'
    }
    //console.log('hi from load, whsh you were here.'+adUnit.getName());
    //set IFrame URL  
    /* this .location.replace() = code style is used to avoid messing with IE browser back history DON"T MESS WITH IT! */
       if (cnp.util.browser.isSafari() && (navigator.userAgent.indexOf("419") > -1 || navigator.userAgent.indexOf("418") > -1)) { 
         // Safari 2.0.4 hack: wait until dom/iframes are ready and time out this is a really stupid hack. BUT IT WORKS 
         jQuery(function() { setTimeout(function() {me.getIframeDocument().location.replace(dartURL)},0) });
       } else {
         me.getIframeDocument().location.replace(dartURL);
       }
    //console.log("changed source");
    /* this .location.replace() = code style is used to avoid messing with IE browser back history DON"T MESS WITH IT! */
    }
    
  this.resizeMe = function() {
    var iframe = me.getIframe();
    var iframeDocument = me.getIframeDocument();
      //console.log("Resize: "+me.getInstanceName());
      var swapLocation = name.replace(/dartAdUnit/g, 'dartTarget');
      var hiddenIframe = false;
      iframe.height = "1px";
      iframe.width = "1px";


      var newwidth = iframeDocument.body.scrollWidth;
      /* HACK: if the ad unit is a text unit 1x1 or Integrated Vendor Unit
      failing over to dart then use the old iframe copy method to place 
      it on the page. */
      //HACK: begin
      //console.log("###############" + name);
      if (name.match(cnp.ad.property.dartProperties.getHackRegEx()) != null ) {
        hiddenIframe = true;
        var swp = document.getElementById(swapLocation);
        //alert(id +" source: "+getIFrameHTML(iframe));
        swp.innerHTML = getIFrameHTML();
        iframe.width = '0px';
        iframe.height= '0px';
        iframe.style.position = 'absolute';
        //HACK: End
      } else { 
        iframe.width = (newwidth) + "px";
      }
      var newheight = iframeDocument.body.scrollHeight;
      // HACK: This is a correction for improved IE height handling
      if (iframeDocument.getElementById('bottom_div')) {
        newheight = iframeDocument.getElementById('bottom_div').offsetTop;
      }
      if (hiddenIframe) { 
        //HACK: text links and local do nothing if above swapping hack has been run.
      } else {
        iframe.height = (newheight) + "px";
      }
  }
    
  // Iframe code can be rewritten into one request that returns 3 objects?
  
  this.getIframe = function() {
    var iframe = document.getElementById(me.getName());
    return iframe; 
  }
  
  this.getIframeDocument = function() {
    var doc = (me.getIframe().contentDocument // For NS6
    || me.getIframe().contentWindow.document // For IE5.5 and IE6
    || me.getIframe().document); // For IE5 et al
    return doc;
  }
  
  function getIFrameHTML() {
    return me.getIframeDocument().documentElement.innerHTML;
  }
  
  // if you need a callback after this unit has been resized then use .processAdUnit('callBackFn');
  // callbacks can be defined on page render in the tiles:insert tag
  this.processAdUnit = function(callback) {
    if(runCounter == 0 || (me.getIframeDocument().location.pathname.indexOf('empty') != -1)) {
      runCounter++;
      me.load();
      return true;
    } else {
      me.resizeMe();
      if( (typeof callback != undefined) ) {new Function(callback)();}
      return true;
    }
  }  
  
}


cnp.ad.LocalAdUnit = function() {
  var me = this;
  var name;                    // name of localAdUnit
  var placementType;           // name of ad placement (feature_1, fourthrail_1, etc.)
  var placementString;         // combination of dart placement values and location
  var targetDiv;               // target Div for ad output
  var localAdsArray;           // the array that contains all the ad unit ids for a given placement
  var ajaxLoadAdIds;           // loading action ajax url
  var ajaxLoadAdUnit;          // placing action ajax url
  var localParams;             // extra parameters for the ajax request
  var localAdRegion;           // your localized location or the pageRegion value.
  var landingPage = false;     // true only in the local section!? needs evaluation.
  var localParamsMap = new cnp.util.Map() // stuff everything in here when working on ajax localparams
  
  this.getName = function() {return name;}      
  this.setName = function(set_name) {name = set_name; return this;}
  this.getPlacementType = function() {return placementType;}
  this.setPlacementType = function(set_type) {placementType = set_type; return this;}
  this.getPlacementString = function() {return placementString;}
  this.setPlacementString = function(set_placementString) {placementString = set_placementString; return this;}
  this.getAjaxLoadAdIds = function() {return ajaxLoadAdIds;}
  this.setAjaxLoadAdIds = function(set_ajaxLoadAdIds) {ajaxLoadAdIds = set_ajaxLoadAdIds; return this;}
  this.getAjaxLoadAdUnit = function() {return ajaxLoadAdUnit;}
  this.setAjaxLoadAdUnit = function(set_ajaxLoadAdUnit) {ajaxLoadAdUnit = set_ajaxLoadAdUnit; return this;}
  this.getLocalAdsArray = function() {return localAdsArray;}
  this.setLocalAdsArray = function(set_localAdsArray) {localAdsArray = set_localAdsArray; return this;}
  this.getLocalParams = function() {return localParams;}
  this.setLocalParams = function(set_localParams) {localParams = set_localParams; return this;}  
  this.getTargetDiv = function() {return targetDiv;}
  this.setTargetDiv = function(set_targetDiv) {targetDiv = set_targetDiv; return this;}
  this.getLocalAdRegion = function() {return localAdRegion;}
  this.setLocalAdRegion = function(set_localAdRegion) {localAdRegion = set_localAdRegion; return this;}
  this.getLandingPage = function() {return landingPage;}
  this.setLandingPage = function(set_landingPage) {landingPage = set_landingPage; return this;}
  
  function constructPlacementString() {
    var site = cnp.ad.property.localProperties.getSite();
    var zone = cnp.ad.property.localProperties.getZone();
    me.setLocalAdRegion(link_location);
    if (typeof pageRegion != 'undefined') { // set in the local secton
      me.setLocalAdRegion(pageRegion);
      me.setLandingPage(true);
      } else {
      me.setLocalAdRegion(link_location);
      me.setLandingPage(false);
    }
    
    if (typeof pageRegion != 'undefined' && document.location.href.indexOf('local')) {
      me.setPlacementString('brides.local.' + me.getLocalAdRegion()); // pageRegion is set on the page itself in the /local section.
      } else {
      if(zone) {
        me.setPlacementString(site+'.'+me.getLocalAdRegion());
        } else {
        if(zone.indexOf('gallery') || zone.indexOf('feature')) {
          splits = zone.split('.');
          var the_string = site + '.' + splits[0];
          me.setPlacementString(the_string + '.' + me.getLocalAdRegion());
          } else {
          var the_string = site + '.' + zone;
          me.setPlacementString(the_string + '.' + me.getLocalAdRegion());
        }
      }
    }
  } // END: this.setPlacementString();
  
  this.load = function() {
    constructPlacementString();
    
    this.setAjaxLoadAdIds('/ajax/cached/local/' + this.getPlacementType() + '/' + this.getTargetDiv() + '/' + this.getPlacementString());
    localParamsMap
    .add('landing', this.getLandingPage())
    .add('placementRegion', this.getLocalAdRegion())
    .add('adUnitName', this.getName())
    .add('dartSite', cnp.ad.property.localProperties.getSite())
    .add('dartZone', cnp.ad.property.localProperties.getZone())
    
    this.setLocalParams(cnp.util.buildUrl({uri: '', parameterMap: localParamsMap }));
    
     // console.log('placement type: '+this.getPlacementType());
     // console.log('AjaxURL: '+this.getAjaxLoadAdIds());
     // console.log('parameters: '+this.getLocalParams());
    
    if (this.getPlacementType() != 'category_listing') { 
      	
		jQuery.ajax({
			url: this.getAjaxLoadAdIds(), 
		 	dataType: "script",
		 	data: this.getLocalParams(),
			cache: true
		});
    }
    
  }
  
  this.place = function() {
     // if we're in local and localAdsArray = dartFailOver, hide the header and targetDiv
     // the class noContentDisplay adds display: none; to the object.
	var oFeatVendHdr = jQuery('#featVendHdr').eq(0);
	var oTargetDiv = jQuery('#'+this.getTargetDiv());
	var isDartFailOver = this.getLocalAdsArray()[0] == 'dartFailOver';
	
    if (document.location.href.indexOf('local') > -1 && oFeatVendHdr.is('div') && isDartFailOver && this.getPlacementType() == 'feature_1') {
      oFeatVendHdr.addClass('noContentDisplay');
      oTargetDiv.addClass('noContentDisplay');
    }
    
    
    if (isDartFailOver) {
		oTargetDiv.html(jQuery.ajax({ 
		 url: '/ajax/cached/local/' + this.getPlacementType() + '/0/' + this.getTargetDiv(), 
		 async: true, 
		 dataType: "html",
		 data: this.getLocalParams()
		}).responseText);
      } else {
      
      oTargetDiv.html('');
      var showValue = this.getLocalAdsArray().shift();
      this.getLocalAdsArray().sort( function () { return Math.round(Math.random()) - 0.5; } );
      if (this.getLocalAdsArray().length < 0) {
        oTargetDiv.addClass = this.getPlacementType();
      }
      var objWrapper = document.createElement('div');
      objWrapper.className = "columnWrapper clearFix";
      oTargetDiv.append(objWrapper);
      localParamsMap.add('placementName', this.getPlacementType())
      .add('showTitle', true)
      .add('colCount', '1of1');
      var VPids = ''; // empty var creation. LOCAL EVENT TRACKING
      for (j = 0; j < this.getLocalAdsArray().length && j < showValue; j++) {
        if (j != 0 ) {
          localParamsMap.add('showTitle', false);
        }
        localParamsMap.add('colCount', (j + 1));
        VPids += '&'+this.getLocalAdsArray()[j]; //LOCAL EVENT TRACKING
        this.setLocalParams(cnp.util.buildUrl({uri: '', parameterMap: localParamsMap }));
        jQuery.ajax({ 
		 url: '/ajax/cached/local/' + this.getPlacementType() +'/' + this.getLocalAdsArray()[j] + '/' + this.getTargetDiv(), 
		 async: true, 
		 dataType: "html",
		 data: this.getLocalParams(),
		 success: function(data, text) {jQuery("#"+me.getTargetDiv()+" .columnWrapper").append(data);}
		});
      }//for
      searchResultImpressionEvent(VPids,'lc_ot_imp'); //LOCAL EVENT TRACKING
      //console.log('VPids is : '+VPids);
    }
  } // this.place 
  
} // END cnp.ad.LocalAdUnit()




/**
 *  MessageBusSingleton - central message buss 
 */
cnp.message.MessageBusSingleton = function() {
  var me = this;
  var observers = new cnp.util.Map();
  
  this.addObserver = function(mesg, func) {
    if(observers.get(mesg) == null)  {
      observers.add(mesg, new cnp.archetype.Observable());
    }
    observers.get(mesg).addObserver(func);
    return this;
  }
  
  this.notify = function(obj, mesg) {
    observers.get(mesg) != null &&	observers.get(mesg).notify(obj, mesg);
		// Notify registrants of ALL
    observers.get(cnp.message.ALL) != null && observers.get(cnp.message.ALL).notify(obj, mesg);
    return me;
  }
}
cnp.message.MessageBusSingleton.getInstance = cnp.archetype.Singleton.getInstance;



cnp.message.ALL = "ALL";



// Crunch Insert -  Fri Nov 6 16:54:45 EST 2009

//*** This code is copyright 2002-2003 by Gavin Kistner and Refinery Inc.; www.refinery.com
//*** It is covered under the license viewable at http://phrogz.net/JS/_ReuseLicense.txt


// Find the x,y location in pixels for a relatively positioned object
// returns an object with .x and .y properties.
function FindXY(obj){
	var x=0,y=0;
	while (obj!=null){
		x+=obj.offsetLeft-obj.scrollLeft;
		y+=obj.offsetTop-obj.scrollTop;
		obj=obj.offsetParent;
	}
	return {x:x,y:y};
}

// Find the x,y location in pixels for a relatively positioned object
// returns an object with .x, .y, .w (width) and .h (height) properties.
function FindXYWH(obj){
	var objXY = FindXY(obj);
	return objXY?{ x:objXY.x, y:objXY.y, w:obj.offsetWidth, h:obj.offsetHeight }:{ x:0, y:0, w:0, h:0 };
}

//*** End copyrighted code


function findPosX(obj) {
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

function findPosY(obj) {
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

// fadeDirection is a global variable used to minimize visual stuttering during fadeIn/fadeOut loops.
fadeDirection = 1;
balloonOpacity = 0;
itemOpacity = 0;


balloonCopyArray = new Array (
"Someday, information will be in me.",
"This item is very much like the first one, but is lower down on the page. Moreover, the contents of this balloon contain considerably more text than the other one."
)

function showBalloon(invokerId) {
	invokerNum = parseInt(invokerId.split('_')[1]);
	theBalloon = document.getElementById('balloon');
	theBalloonCopy = document.getElementById('balloonCopy');
	theBalloonCopy.innerHTML = balloonCopyArray[invokerNum];
	showItem('balloon',invokerId,'topright');
}


function showBalloonHelp(invokerId, helpText) {
	invokerNum = parseInt(invokerId.split('_')[1]);
	theBalloon = document.getElementById('balloon');
	theBalloonCopy = document.getElementById('balloonCopy');
	theBalloonCopy.innerHTML = helpText;
	showItem('balloon',invokerId,'topright');
}

function showPriceRange(invokerId, priceRangeType) {
	invokerNum = invokerId.split("_")[1];
	
	theBalloon = document.getElementById("balloon");
	theBalloonCopy = document.getElementById("balloonCopy");
	
	var copyString = (priceRangeType == "Bride_Price") ?
		"Price Range: " + showPriceRange._priceBride["_" + invokerNum] :
		"Price Range: " + showPriceRange._priceOther["_" + invokerNum] ;
		
	if (copyString.indexOf("undefined") == -1) {

		theBalloonCopy.innerHTML = copyString;
		
		showItem("balloon", invokerId, "topright");

	} else {
	/* This empty array prevents later functions from trying to un-hide page elements that were never hidden to begin with. */
		tempHidden["balloon"] = new Array();

	}
	
}
showPriceRange._priceBride = {
	"_$" : "$500 and under",
	"_$$" : "$501 - $1000",
	"_$$$" : "$1001 - $1500",
	"_$$$$" : "$1501 - $3000",
	"_$$$$$" : "$3001 and up"
}
showPriceRange._priceOther = {
	"_$" : "$80 and under",
	"_$$" : "$81 - $150",
	"_$$$" : "$151 - $250",
	"_$$$$" : "$251 - $300",
	"_$$$$$" : "$301 and up"
}


function findXYPos(el){
	for (var lx=0,ly=0;el!=null;
		lx+=el.offsetLeft,ly+=el.offsetTop,el=el.offsetParent);
	return {x:lx,y:ly}
}

function setOpacity(obj, opacity) {
  opacity = (opacity == 100)?99.999:opacity;
  
  // IE/Win
  obj.style.filter = "alpha(opacity:"+opacity+")";
  
  // Safari<1.2, Konqueror
  obj.style.KHTMLOpacity = opacity/100;
  
  // Older Mozilla and Firefox
  obj.style.MozOpacity = opacity/100;
  
  // Safari 1.2, newer Firefox and Mozilla, CSS3
  obj.style.opacity = opacity/100;
}

// global object for tracking elements which need to be invisibled during a DHTML popup (Flash containers, SELECTs in IE, etc.)
// members are named after item ID's, and are Arrays of objects that need to be hidden for that ID
var tempHidden = new Object;

function showItem(faderId,invokerId,positionVH,offsetX,offsetY) {
	// The 'positionVH' argument currently accepts one of five values:
	// 'topleft', 'topright', 'bottomleft', 'bottomright', or null.
	if (undefined == offsetX) { offsetX = 0; }
	if (undefined == offsetY) { offsetY = 0; }
	theFader = FindXYWH(document.getElementById(faderId));
	theInvoker = FindXYWH(document.getElementById(invokerId));
	invokerElement = document.getElementById(invokerId);
	faderWidth = theFader.w;
	faderHeight = theFader.h;
	invokerWidth = theInvoker.w;
	invokerHeight = theInvoker.h;
	invokerPosX = findPosX(invokerElement);
	invokerPosY = findPosY(invokerElement);
	// If no position is specified, put the fader in the center of the screen.
	if (undefined == positionVH) {
		document.getElementById(faderId).style.left = document.body.offsetWidth/2 - faderWidth/2 + 'px';
		document.getElementById(faderId).style.top = document.body.offsetHeight/2 - faderHeight/2 + 'px';
	} else {
		//...Otherwise set default position as 'center'/'middle'
		newFaderPosX = invokerPosX + invokerWidth/2 - faderWidth/2;
		newFaderPosY = invokerPosY + invokerHeight/2 - faderHeight/2;
		//...And then check to see if a specific alignment has been requested.
		if (positionVH.indexOf('top') != -1) { newFaderPosY = invokerPosY - faderHeight; }
		if (positionVH.indexOf('bottom') != -1) { newFaderPosY = invokerPosY + invokerHeight; }
		if (positionVH.indexOf('left') != -1) {	newFaderPosX = invokerPosX - faderWidth; }
		if (positionVH.indexOf('right') != -1) {	newFaderPosX = invokerPosX + invokerWidth; }
		document.getElementById(faderId).style.left = newFaderPosX + offsetX +'px';
		document.getElementById(faderId).style.top = newFaderPosY + offsetY + 'px';
	}

	tempHidden[faderId] = new Array();
	
	// any not-already-hidden SELECT elements outside the item to be shown will need to be hidden in IE6
	if(navigator.userAgent.indexOf('MSIE') != -1) {
		var allSelects = document.getElementsByTagName("select");
		var excludeSelects = document.getElementById(faderId).getElementsByTagName("select");
		for (var i=0; i < allSelects.length; i++) {
			var exclude = false;
			for (var j=0; j < excludeSelects.length; j++) {
				if (allSelects[i] == excludeSelects[j]) {
					exclude = true;
					break;
				}
			}
			
			// if select is not viewable, or is descendant of such an element, exclude it
			var j=allSelects[i];
			do {
				if (j.style.visibility == 'hidden' || j.style.display == 'none') {
					exclude = true;
					break;
				}
			} while (j = j.parentElement);
		
			if (!exclude) tempHidden[faderId].push(allSelects[i]);
		}
	}
	
	// Flash containers will need to be hidden in all browsers
	var allFlash = getElementsByRegex('class', 'flashContainer');
	for (var i=0; i < allFlash.length; i++) {
		tempHidden[faderId].push(allFlash[i]);
	}
	
	// hide what needs to be hidden
	for (var i=0; i < tempHidden[faderId].length; i++) {
		if (tempHidden[faderId][i].style) {
			tempHidden[faderId][i].style.visibility = 'hidden';
		}
	}
	
	fadeDirection = 1;
	fadeIn(faderId);
	if(faderId != 'balloon' && faderId != 'dateballoon'){page.reloadAssets();} // reload all ads and stats based on user interaction with the page.
}

function hideItem(faderId) {
	fadeDirection = -1;
	fadeOut(faderId);
	
	// restore anything we had to temporarily hide
	var obj;
	while (obj = tempHidden[faderId].pop()) {
		if (obj.style) {
			obj.style.visibility = 'visible';
		}
	}
	delete tempHidden[faderId];
	if(faderId != 'balloon' && faderId != 'dateballoon'){page.reloadAssets();} //reload all ads and stats based on user interaction with the page.
}

function fadeIn(objId) {
  if (itemOpacity < 0) { itemOpacity = 0; }
  if (fadeDirection == 1) {
    obj = document.getElementById(objId);
	obj.style.visibility = 'visible';
    if (itemOpacity <= 100) {
      setOpacity(obj, itemOpacity);
      itemOpacity += 10;
      window.setTimeout("fadeIn('"+objId+"')", 30);
    }
  }
}

function fadeOut(objId) {
  if (itemOpacity > 100) { itemOpacity = 100; }
  if (fadeDirection == -1) {
    obj = document.getElementById(objId);
    if (itemOpacity >= 0) {
      setOpacity(obj, itemOpacity);
      itemOpacity += -10;
      window.setTimeout("fadeOut('"+objId+"')", 15);
    } else { 
    	obj.style.visibility = 'hidden'; 
    }
  }
}

//page 2

function toggleLine(num) {
// NB: For the sake of brevity, this function assumes that the 'selected' class
// will only be applied to DIVs that already have an existing class.
	//var numberExp = /[0-9]+/g;
	//if ( numberExp.test(num) ) 
	if (typeof num == "number")
	{
		var thisDivId = "line" + num;
		prevClassname = document.getElementById(thisDivId).className;
		if (prevClassname.indexOf('selected') != -1) {
		 newClassname = prevClassname.substring(0,(prevClassname.indexOf('selected') - 1));
		 document.getElementById(thisDivId).getElementsByTagName('span')[0].innerHTML = '&#9658;';
		} else {
		 newClassname = prevClassname + ' selected';
		 document.getElementById(thisDivId).getElementsByTagName('span')[0].innerHTML = '&#9660;';
		}
		document.getElementById(thisDivId).className = newClassname;
	} // close if num equals number
	else if ( num == "showAll" || num == "hideAll" )
	{
			// collect all of the <div>s as an array
			var divArray = document.getElementsByTagName('div');
			// loop through the array
			 for (var i=0; i < divArray.length; i++) 
			 {
			   // check for divs with line IDs assigned to them
			   if(divArray[i].id.indexOf('line') != -1)
				{ 
					var thisDivId = divArray[i].id;
					var prevClassname = document.getElementById(thisDivId).className;
					var spanArray = document.getElementById(thisDivId).getElementsByTagName('span');
					if (num == 'showAll')
					{
						var newClassname = prevClassname + ' selected';
				 		for (var j=0; j < spanArray.length; j++)
						{
					
								if ( spanArray[j].className == 'r0') 
								{
									spanArray[j].innerHTML = '&#9660;';
								}
						}
						document.getElementById(thisDivId).className = newClassname;
					}
					if (num == 'hideAll')
					{
						if (prevClassname.indexOf('selected') != -1) 
						{
							newClassname = prevClassname.substring(0,(prevClassname.indexOf('selected') - 1));
							for (var j=0; j < spanArray.length; j++)
							{
								if ( spanArray[j].className == 'r0') 
								{
									spanArray[j].innerHTML = '&#9658;';
								}
							}
							document.getElementById(thisDivId).className = newClassname;
						}
					}
				} // close if statement
			 } // close for loop
	} // close else if num equals showAll or hideAll
	page.reloadAssets(); // reload all ads and stats based on user interaction with the page.
} // close toggleLine function

// Parse URL string for variables
function parseQueryString (str) {
  str = str ? str : location.search;
  var query = str.charAt(0) == '?' ? str.substring(1) : str;
  var args = new Object();
  if (query) {
	var fields = query.split('&');
	for (var f = 0; f < fields.length; f++) {
	  var field = fields[f].split('=');
	  args[unescape(field[0].replace(/\+/g, ' '))] = unescape(field[1].replace(/\+/g, ' '));
	}
  }
  return args;
}
// usage: var args = parseQueryString (); args['c'] would equal URL variable 'c'

/******************************************

var pqs = new ParsedQueryString();

pqs.param( name )
  Returns the string value associated with name (name is case sensitive). If
  name was not defined in the query string, returns undefined. If multiple
  values were associated with name, returns the first value from the order it
  occurs in the query string.
  
  e.g., QUERY-STRING: "hello=world&hello=hi&foo=bar"
  pqs.param('hello') returns "world"
  pqs.param('foo') returns "bar"
  pqs.param('not there') returns undefined

pqs.params( [ name ] )
  Returns an array for all values associated with name (name is case
  sensitive). If name was not defined in the query string, returns null. If
  name is omitted, returns an array of every name in the query string.
  
  e.g., QUERY-STRING: "hello=world&hello=hi&foo=bar"
  pqs.params('hello') returns ["world", "hi"]
  pqs.params('foo') returns ["bar"]
  pqs.params('not there') returns null
  pqs.params() returns ["hello", "foo"]

*****************************/

String.prototype.decodeURL = function() {
    return unescape(this.replace(/\+/g, " "));
}

function ParsedQueryString() {
    var parameters = {};
    
    parse();
    function parse() {
        var parts = window.location.search.substr(1).split(/[&;]/);
        for (var i = 0; i < parts.length; ++i) {
            var pair = parts[i].split(/=/);
            var name = pair[0].decodeURL();
            var value = pair[1] != undefined ? pair[1].decodeURL() : undefined;
            if (parameters[name] == undefined)
                parameters[name] = [value];
            else
                parameters[name].push(value);
        }
    }
    
    this.param = function(name) {
        return parameters[name] != undefined ? parameters[name][0] : undefined;
    }
    
    this.params = function(name) {
        if (arguments.length)
            return parameters[name] != undefined ? parameters[name] : null;
        else {
            var pnames = [];
            for (var p in parameters)
                pnames.push(p);
            return pnames;
        }
    }
}

dateballoonOpacity = 0;



function showdateballoon_lrm(invokerId) {
	theBalloon = document.getElementById('dateballoon');
	newInvokerId = "info" + invokerId;
	showItem('dateballoon',newInvokerId,'topleft');
}

function showdateballoon(invokerId) {
//	invokerNum = parseInt(invokerId.split('_')[1]);
	theBalloon = document.getElementById('dateballoon');
	newInvokerId = "info" + invokerId;
//	theBalloonCopy = document.getElementById('dateballoonCopy');
//	theBalloonCopy.innerHTML = balloonCopyArray[invokerNum];
	showItem('dateballoon',newInvokerId,'topright');
}

function hidedateballoon() {
	fadeDirection = -1;
	// IE BUG-FIX show form SELECT when DIV is hidden
	var selNodes = document.getElementsByTagName('select')
	var i=0;
	if (!selNodes.item(0)){
		return false;
	} else {
		do {
			selNodes.item(i).style.visibility = 'visible';}
		while (++i < selNodes.length);
	}	
	fadeOut('dateballoon')
}


// Calendar functionality
function KW_cal_class(m,d,y,d1,d2,mn,c) { // v1.3.0
	this.o="";this.dsp="";this.m=m;this.d=d;this.y=y;this.d1=d1;this.d2=d2;
	this.mn=mn,this.sy=((y%100)<10)?"0"+(y%100):(y%100);this.mm=(m<10)?"0"+m:m;this.c=c
	this.dd=(d<10)?"0"+d:d;	iD=new Date(y,(m-1),d);eD=new Date();eD.setMilliseconds(0)
	eD.setHours(0);eD.setMinutes(0);eD.setSeconds(0);this.ofs=parseInt((eD-iD)/86400000)
	this.gC=function(){iD=new Date(this.y,(this.m-1),this.d);sD=this.dsp.toString()
	retVal="on";if (sD.indexOf("<a")!=0)retVal="off";if (iD.getDay()==0||iD.getDay()==6)
	if (sD.indexOf("<a")!=0)retVal="wkendoff";else retVal="wkendon";if (this.c==0)
	if (sD.indexOf("<a")!=0)retVal="ntmoff";else retVal="ntmon";if (this.ofs==0) 
	retVal="today";	if (this.spc()==true)retVal="special";return "kw_cal_"+retVal;}
	this.spc=function(){var retVal=false;dc=document;if (dc.kw_sp){ for (var i=0;i<dc.kw_sp.length;i++){
	if (this.m==dc.kw_sp[i].m&&(this.y==dc.kw_sp[i].y||dc.kw_sp[i].y=="*")&&this.d==dc.kw_sp[i].d)
	retVal=true;}} return retVal;}
}

function KW_setThisDisplay(f,n,d,o,a1,a2,a3,a4,w,l,sd){ // v1.4.0
	var rV="<a href=\"javascript:window.opener.KW_setCalendar('"+f+"',"+n+",'"+l+"');hidedateballoon(); window.close();\">"+d+"</a>";
	if ((a1==1&&o>0)||(a1==-1&&o<1)||(a1==2&&o>=0)) rV=d;if (a2>0) {if (o<=-a2) rV=d;} 
	else if (a2<0) {if (o>=-a2) rV=d;}if (a3!=-1) {ss=a3.split("|");if (ss[w]==1) rV=d} 
	if (a4>0) {if (o>=-a4 && o<0) rV=d;} if (a4<0) {if (o<=-a4 && o>0) rV=d; } if (sd) {
	rV=d} return rV;
}

function KW_date_class(m,d,y) {this.m=m;this.d=d;this.y=y;}

function KW_setCalendar(obj,n,l) { // v1.3.0
	dc=document;dO=dc.tMh[n];if (obj.indexOf("|")==-1)MM_findObj(obj).value=dO.o;
	else {oS=obj.split("|");tV= new Array(dO.m,dO.d,dO.y);for(var i=0;i<3;i++) {
	tO=MM_findObj(oS[i]);dc.KW_calYear=dO.y;for (var j=0;j<tO.options.length;j++)
	if (tO.options[j].value==tV[i]) tO.selectedIndex=j;}}dc.KW_calMonth=dO.m-1;
	if (l!=''){o=MM_findObj(l);v="hide";if (o.style){o=o.style; v='hidden'} o.visibility=v}
}

function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

function KW_setDel(val) { // v1.3.1
	return (val.match(/\.gif$|\.png$|\.jpg$|\.jpeg$/i))?"<img src=\""+val+"\" class=\"kw_img\">":val
}

function KW_expertCalendar(){ // v1.4.1 
	var dc=document,a=KW_expertCalendar.arguments,d=new Date();d.setDate(1); if (a[29]!=-1) 
	d.setMonth(a[29]);else if (dc.KW_calMonth) d.setMonth(dc.KW_calMonth);cMn= d.getMonth(); 
	pMt=((cMn-1)<0)?11:cMn-1;nMh=((cMn+1)>11)?0:cMn+1;if (a[30]!=-1) d.setFullYear(a[30]);
	else if (dc.KW_calYear) d.setYear(dc.KW_calYear);cYr=d.getFullYear();pYr=(pMt==11)?cYr-1:cYr;
	nYr=(nMh==0)?cYr+1:cYr;wdy=d.getDay();dc.tMh=new Array();if (a[25]==1) wdy=((--wdy)<0)?6:wdy;
	tpM=new Date(d.getFullYear(),d.getMonth(),d.getDate()-wdy);for (var i=0;i<wdy;i++) {
	n=dc.tMh.length;dc.tMh[n]= new KW_cal_class((tpM.getMonth()+1),tpM.getDate(),tpM.getFullYear(),
	a[21],a[23],a[tpM.getMonth()],0);dc.tMh[n].o=eval("dc.tMh["+n+"]."+a[20])+dc.tMh[n].d1+
	eval("dc.tMh["+n+"]."+a[22])+dc.tMh[n].d2+eval("dc.tMh["+n+"]."+a[24]);	dc.tMh[n].dsp=
	(a[31]==1)?"&nbsp;":KW_setThisDisplay(a[19],n,tpM.getDate(),dc.tMh[n].ofs,a[26],a[27],
	a[28],a[42],tpM.getDay(),a[41],(dc.tMh[n].spc() && a[45]==1));tpM.setDate(tpM.getDate()+1)}EOM=false;for (var i=1;!EOM;i++) {
	n=dc.tMh.length;dc.tMh[n]=new KW_cal_class((d.getMonth()+1),d.getDate(),d.getFullYear(),
	a[21],a[23],a[d.getMonth()],1);;dc.tMh[n].o=eval("dc.tMh["+n+"]."+a[20])+dc.tMh[n].d1+
	eval("dc.tMh["+n+"]."+a[22])+dc.tMh[n].d2+eval("dc.tMh["+n+"]."+a[24]);
	dc.tMh[n].dsp=KW_setThisDisplay(a[19],n,d.getDate(),dc.tMh[n].ofs,a[26],a[27],a[28],a[42],
	d.getDay(),a[41],(dc.tMh[n].spc() && a[45]==1));d.setDate(d.getDate()+1);if (d.getDate()==1) EOM=true;} wdy=d.getDay();
	if (a[25]==1) wdy=((--wdy)<0)?6:wdy;for (var i=wdy;i<7;i++) {n=dc.tMh.length;
	dc.tMh[n]= new KW_cal_class((d.getMonth()+1),d.getDate(),d.getFullYear(),a[21],a[23],
	a[d.getMonth()],0);dc.tMh[n].o=eval("dc.tMh["+n+"]."+a[20])+dc.tMh[n].d1+
	eval("dc.tMh["+n+"]."+a[22])+dc.tMh[n].d2+eval("dc.tMh["+n+"]."+a[24]);
	dc.tMh[n].dsp=(a[31]==1)?"&nbsp;":KW_setThisDisplay(a[19],n,d.getDate(),dc.tMh[n].ofs,
	a[26],a[27],a[28],a[42],d.getDay(),a[41],(dc.tMh[n].spc() && a[45]==1));d.setDate(d.getDate()+1);} 
	ns4 =(dc.layers)?true:false;px=(ns4||window.opera)?'':'px';s=a[32];if (a[33]==-1) 
	{ww=window;d="document.getElementById('"+a[32].name+"')";k=1;x=0;y=0;xpos=0;ypos=0;
	iM=(navigator.appVersion.indexOf("Mac")==-1);p=".offsetParent";if (dc.getElementById) {
	if (!eval(d)) {d=d.replace(/.getElementById/,".getElementsByName")}
	while (eval(d+p)) {	x+=parseInt(eval(d+p+".offsetLeft"));
	y+=parseInt(eval(d+p+".offsetTop"));p+=".offsetParent";}ox=parseInt(s.offsetLeft);
	oy=parseInt(s.offsetTop);} else {x=parseInt(screen.height/2-75);ox=0;oy=0;
	y=parseInt(screen.width/2-75);}xp=parseInt(x+ox),yp=parseInt(y+oy+20);
	winW=(ns4)?window.innerWidth-16:dc.body.offsetWidth-20;
	winH=(ns4)?window.innerHeight:dc.body.offsetHeight;if (dc.all && iM) winH+=dc.body.scrollTop
	if ((xp+a[35])>winW) xp=winW-a[35]; if ((yp+a[36])>winH) yp=winH-a[36];	
	if (a[41]=='') {if (isNaN(ww.screenX)) {xp=xp-dc.body.scrollLeft+ww.screenLeft;
	yp=yp-dc.body.scrollTop+ww.screenTop;}else {xp=xp+ww.screenX+
	(ww.outerWidth-ww.innerWidth)-ww.pageXOffset;yp=yp+ww.screenY+
	(ww.outerHeight-24-ww.innerHeight)-ww.pageYOffset;	}if (!iM && dc.all)
	{ xp=xp-dc.body.scrollLeft;yp=yp-dc.body.scrollTop}}a[33]=xp;a[34]=yp}
	str="<html><head><title>"+a[cMn]+" "+cYr; accs="<a class=\"kw_cal_a\" ";
	str+="</title></head><link href=\""+a[43]+"\" rel=\"stylesheet\" type=\"text/css\" />"
	str+="<body style=\"margin:0; background-color:"+a[44]+";\">";if (a[41]!='' && !ns4) str="";
	str+="<table class=\"kw_cal_tbl2\" border=0 cellspacing=0 cellpadding=2><tr><td colspan=\"7\">"
	str+="<table width=\""+(a[35]-10)+"\" border=0 cellspacing=0 cellpadding=2 class=\"kw_cal_tbl2\">";
	endStr="','"+a[31]+"',0";for(ix=33;ix<37;ix++)endStr+=","+a[ix];for(ix=37;ix<46;ix++)
	endStr+=",'"+a[ix]+"'";bStr="";for (var j=0;j<29;j++) bStr+="'"+a[j]+"',";
	aStr1=bStr+"'"+pMt+"','"+pYr+endStr;aStr2=bStr+"'"+nMh+"','"+nYr+endStr;str+="<tr><td "
	str+="class=\"kw_cal_mnth\">"+accs+"href=\"javascript:window.opener.KW_expertCalendar("+aStr1;
	str+=")\">"+KW_setDel(a[37])+"</a>"+a[cMn]+accs+"href=\"javascript:window.opener.KW_expertCalendar("
	str+=aStr2+")\">"+KW_setDel(a[38])+"</a></td>";aStr1=bStr+"'"+cMn+"','"+(cYr-1)+endStr;
	aStr2=bStr+"'"+cMn+"','"+(cYr+1)+endStr;str+="<td class=\"kw_cal_yr\">"+accs
	str+="href=\"javascript:window.opener.KW_expertCalendar("+aStr1+")\">"+KW_setDel(a[39])+"</a>"
	str+=cYr+accs+"href=\"javascript:window.opener.KW_expertCalendar("+aStr2+")\">"
	str+=KW_setDel(a[40])+"</a></td></tr></table></td></tr><tr>"
	for (var i=(a[25]==1)?13:12;i<19;i++) str+="<td class=\"kw_cal_wktitle\">"+a[i]+"</td>";
	if (a[25]==1) str+="<td class=\"kw_cal_wktitle\">"+a[12]+"</td>";str+="</tr>";
	for (var i=0;i<dc.tMh.length;i++) {if ((i)/7==parseInt((i)/7)) str+="<tr>"; 
	tdClass=dc.tMh[i].gC();temp=dc.tMh[i].dsp.toString();tdActive=(temp.indexOf("<a")!=-1)?"id='kwon'":"";
	str+="<td class=\""+tdClass+"\" "+tdActive+">"+dc.tMh[i].dsp+"</td>"
	if ((i+1)/7==parseInt((i+1)/7))str+="</tr>";}str+=(a[41]==''&&!ns4)?"</table></body></html>":"</table>";
	if (a[41]!='' && !ns4) {t=MM_findObj(a[41]);v="show";if (t.style) { t=t.style; v='visible'}
	t.visibility=v;	t.left=xp+px;t.top=yp+px;while (str.indexOf('window.opener.')!=-1)
	str=str.replace('window.opener.','');p1=str.indexOf(" window.close();"); while (p1!=-1) {
	str=str.substring(0,p1)+str.substring(p1+16);p1=str.indexOf(" window.close();")}
	MM_findObj(a[41]).innerHTML=str;} else {var nnx=(ns4)?1.25:1;var look='width='+(a[35]*nnx)
	look+=',height='+(a[36]*nnx)+',left='+a[33]+',top='+a[34];
	popwin=window.open('','calendar',look);	with(popwin.document){open();write(str);close();}}
}

function getEl(id) {
    if (document.layers) { return document.layers[id]; }
    else if (document.all) { return document.all[id]; }
    else if (document.getElementById) { return document.getElementById(id); }
}
function openWin(url) {
    var win = window.open(url,'newWindow','width=450,height=400,menubar=yes,location=no,statusbar=yes,personalbar=no,scrollbars=yes,resize=yes');
}
function openWinVSize(url,width,height) {
    var win = window.open(url,'newWindow','width='+width+',height='+height+',menubar=no,location=no,statusbar=no,personalbar=no,scrollbars=yes,resize=yes');
}

function replaceSpan(ht,hd,hs){						

	var newSpan = document.createElement("span");

	if (ht) {

		var newText = document.createTextNode(ht);

	} else {

		// Default text for headline

		var newText = document.createTextNode("Contact Brides.com");

	}

	newSpan.appendChild(newText);						

	var para = document.getElementById(hd);

	var spanElm = document.getElementById(hs);

	var replaced = para.replaceChild(newSpan,spanElm);

}


function getElementsByRegex (attr, regex) {
	if (attr == 'class') attr = 'className';
	var myRegex = new RegExp('\\b' + regex + '\\b');
	var allTags = document.getElementsByTagName('*');
	var matches = new Array();
	for (i=0; i<allTags.length; i++) {
		if ( myRegex.test( eval('allTags[i].' + attr) ) ) {
			matches.push(allTags[i]);
		}
	}
	return matches;
}

function addClass(obj, classValue) {
	if (obj && obj.className) {
		var alreadyThere = false;
		var classArr = new Array;
		classArr = obj.className.split(' ');
		for (var i=0; i<classArr.length; i++) {
			if (classArr[i] == classValue) {
				alreadyThere = true;
			}
		}
		if (! alreadyThere) {
			classArr.push(classValue);
			var newClassName = classArr.join(' ');
			obj.className = newClassName;
		}
	} else if (obj) {
		obj.className = classValue;
	}
}

function removeClass(obj, classValue) {
  if (obj && obj.className) {
    var wasThere = false;
    var classArr = new Array;
    classArr = obj.className.split(' ');
    for (var i=0; i<classArr.length; i++) {
      if (classArr[i] == classValue) {
        classArr.splice(i, 1);
        wasThere = true;
        break;
      }
    }
    if (wasThere) {
      var newClassName = classArr.join(' ');
      obj.className = newClassName;
    }
  }
}


//this function is a wrapper used to reload ads and stats. don't remove it - dan
// to use this call page.reloadAssets(); 
page={
 reloadAssets:function(args) {
  GetStatsData(undefined, true); //HACK: "undefined" are you kidding me... bad idea!
  CN.stats.omniture.trackAjaxPage();
  cnp.ad.property.reloadAds()
 },
 trackFlash:function(altURI) { // this is used in a JCPenney flash promotion that needs to track flash activity as pageviews 
	CN.stats.omniture.trackAjaxPage();
   page.trackLocation(altURI);
 },  
 trackLocation:function(altURI) { // this is used to track page activity as pageviews 
    if(altURI == undefined) { altURI = document.location.pathname;}
    GetStatsData(altURI, true);
	CN.stats.omniture.trackAjaxPage();
		
 },
 trackLocationWithAdRefresh:function(altURI) { // this is used to track page activity as pageviews 
    if(altURI == undefined) { altURI = document.location.pathname;}
    GetStatsData(altURI, true);
    cnp.ad.property.reloadAds();
    CN.stats.omniture.trackAjaxPage();
  }
}

isSafari = cnp.util.browser.isSafari(); // HACK fix gallery detail js code

/* 
 * Dan Holly Wells / Adam Fahy
 * this function used to store events until the userData object is returned by the DWR call the function
 * userDataEventRegistry.run is called header.jsp by the userData.load callback function. 
 */  
userDataEventRegistry={
 	list:[],
	add:function(item) {
		 if(typeof userData === "object" && userData != null) {
			new Function(item)();
		} else {
			userDataEventRegistry.list.push(item);
		}
	},
	run:function() {
		if (userDataEventRegistry.list.length != 0){
		  for (var i = userDataEventRegistry.list.length - 1; i >= 0; i--){
		    new Function(userDataEventRegistry.list[i])();
		    userDataEventRegistry.list.pop[i];
		  }
		}
	}
}


//onload page queue function.
function WindowOnload(f) {
    var prev=window.onload;
    window.onload=function(){ if(prev)prev(); f(); }
  }
  
  
//this is for the local link in the header.  it will redirect users to the local landing page they are localized as.
//the href action should be /local the onClick action should be this function
function localizedLocal() {
 if(link_location != 'national') {
  window.location = '/local/'+link_location;
 } else {
  window.location = '/local/';
 }
}

// To compensate for the unexpected behavior of the "infinite height" layout method,
// this function scrolls the page to an object with the specified ID.
function scroll2Anchor(divName) {
	if (obj = document.getElementById(divName)) {
		yAmount = findPosY(obj);
		self.scrollTo(0, yAmount);
	}
}

/* populate search box if the user has preformed a search */
function populateSearchString() {
var pqs = new ParsedQueryString();
 if (typeof pqs.param('search_string') != 'undefined') {
	jQuery('#searchField').eq(0).attr("value", pqs.param('search_string'));
 }
}
WindowOnload(populateSearchString);

function clearSelect(selectId) {
  var selectObj = document.getElementById(selectId);
  if (selectObj) {
    for (var i=0; i<selectObj.options.length; i++) {
      selectObj.options[i].selected = false;
    }
  }
}

/* returns string in format MM/DD/YYYY given a date object such as userData.weddingDate
* used in contact a vendor popup */ 
function formatMMDDYYYY(dateObj) { 
	var dateStr = "";
	if (dateObj !== null && typeof dateObj === "object") {
		var dateArr = ["", "", String(dateObj.getFullYear())];		
		var monthNum = dateObj.getMonth() + 1;
		var dateNum = dateObj.getDate();
		
		dateArr[0] = String(monthNum);
		dateArr[1] = String(dateNum);
		
		if (monthNum < 10) {
			dateArr[0] = "0" + dateArr[0];	
		}
		if (dateNum < 10) {
			dateArr[1] = "0" + dateArr[1];
		}
		dateStr = dateArr.join("/");			
	} 
	return dateStr;
}



// Crunch Insert -  Fri Nov 6 16:54:45 EST 2009

/**
 * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */
if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;

// Crunch Insert -  Fri Nov 6 16:54:45 EST 2009

// This is the definition for a collection of JavaScript objects
function EventList(divId) {
    this.divId = divId;
    this.maxURLLength = 2000;
    this.cacheBusterLength = 20;
    this.baseUrl = "/";
    this.imageUrl = "images/event.gif";
    this.jsUrl = "js/event.js";
    this.eventList = new Array();

    this.addEvent = function (event) {
        this.eventList.push(event);
    };

    this.setBaseUrl = function (baseUrl) {
        this.baseUrl = baseUrl;
    };

    this.setImageUrl = function (imageUrl) {
        this.imageUrl = imageUrl;
    };

    this.setJsUrl = function (jsUrl) {
        this.jsUrl = jsUrl;
    };

    this.writeImageTags = function () {
        this.clearOldTags();
        this.writeTags(this.imageUrl, this.writeIndividualImageTag);
    };

    this.writeJavaScriptTags = function () {
        this.clearOldTags();
        this.writeTags(this.jsUrl, this.writeIndividualJavaScriptTag);
    };

    this.clearOldTags = function () {
        var eventTagHolder = document.getElementById(divId);
        while (eventTagHolder.firstChild) {
            eventTagHolder.removeChild(eventTagHolder.firstChild);
        }
    };

    this.writeTags = function (tagUrl, tagFunc) {
        if (this.eventList.length == 0) {
            return;
        }
        var fullUrl = this.baseUrl + tagUrl + "?" + this.eventList[0].getQueryString("e0_");
        for (var i = 1; i < this.eventList.length; ++i) {
            var eventQueryString = this.eventList[i].getQueryString("e" + i + "_");
            var tmpFullUrl = fullUrl + eventQueryString;
            if (tmpFullUrl.length + this.cacheBusterLength < this.maxURLLength) {
                // Tack it on to the current url
                fullUrl = tmpFullUrl;
            } else {
                // Overflow.  Write out what we have and start a new URL.
                tagFunc(fullUrl);
                fullUrl = this.baseUrl + tagUrl + "?" + eventQueryString;
            }
        }
        // Flush whatever we have
        tagFunc(fullUrl);
    };

    this.writeIndividualImageTag = function (url) {
        if (url.length + this.cacheBusterLength > this.maxURLLength) {
            throw ("URL for event is longer than max URL length of " + this.maxURLLength);
        }
        url = url + "rnd=" + Math.random() * 10000000000000000; // Append a cache buster
        var node = document.createElement("img");
        node.src = url;
        document.getElementById(divId).appendChild(node);
    };

    this.writeIndividualJavaScriptTag = function (url) {
        if (url.length + this.cacheBusterLength > this.maxURLLength) {
            throw ("URL for event is longer than max URL length of " + this.maxURLLength);
        }
        url = url + "rnd=" + Math.random() * 10000000000000000; // Append a cache buster
        var node = document.createElement("script");
        node.type = "text/javascript";
        node.src = url;
        document.getElementById(divId).appendChild(node);
    };
}

// This is the definition for a JavaScript object to capture events.
// The three globally required parameters -- site code, event code, and content id -- are included.
function EventObject(siteCode, eventCode) {
    // prototype.js keeps you from using Array() as a hash.  Use Object for associative arrays.
    this.properties = new Object();
    this.properties["sc"] = siteCode;
    this.properties["ec"] = eventCode;

    // Generic set property function (can also be used to add properties beyond the standard set)
    this.setProperty = function (name, value) {
        this.properties[name] = value;
    };

    // Generic get property function
    this.getProperty = function (name) {
        return this.properties[name];
    };

    // Set environment
    this.setEnvironment = function (environment) {
        this.setProperty("env", environment);
    };

    // Set action code
    this.setActionCode = function (actionCode) {
        this.setProperty("ac", actionCode);
    };

    // Set content id (most viewed)
    this.setContentId = function (contentId) {
        this.properties["id"] = contentId;
    };

    // Set content type (most viewed)
    this.setContentType = function (contentType) {
        this.setProperty("ct", contentType);
    };

    // Set full URL (most viewed)
    this.setFullUrl = function (fullUrl) {
        this.setProperty("url", fullUrl);
    };

    // Set content title (most viewed)
    this.setContentTitle = function (contentTitle) {
        this.setProperty("tit", contentTitle);
    };

    // Set location (brides affiliate)
    this.setLocation = function (location) {
        this.setProperty("loc", location);
    };

    // Set search results count (brides affiliate)
    this.setSearchResultCount = function (searchResultCount) {
        this.setProperty("rc", searchResultCount);
    };

    // Set asset ID (flip affiliate)
    this.setAssetId = function (assetId) {
        this.setProperty("asid", assetId);
    };

    // Set application ID (application tracking)
    this.setApplicationId = function (applicationId) {
        this.setProperty("apid", applicationId);
    };

    // Override user ID (overrides whatever is set by the amg user cookie
    this.overrideUserId = function (userId) {
        this.setProperty("uid", userId);
    };

    // Returns a query string containing all of the properties of the event
    this.getQueryString = function (paramPrefix) {
        var queryString = "";
        for (var p in this.properties) {
            queryString += paramPrefix + p + "=" + encodeURIComponent(this.getProperty(p)) + "&";
        }
        return queryString;
    };
}




// Crunch Insert -  Fri Nov 6 16:54:45 EST 2009

function sendEvent(vendorPlacementId,event_code) {
	var eventList = new EventList("eventListHolder");
 	var event = new EventObject("BRI", event_code);
  	event.setProperty("vendorPlacementId",vendorPlacementId);
  	eventList.addEvent(event);
        
  	var re = /www\.brides\.com|.*\.advancepubs\.net/;
  	var curHost = document.location.host;
  	var eventHost = curHost.match(re) ? "http://event.brides.com/" : "http://samgdeac12:8300/";
 	eventList.setBaseUrl(eventHost);

	eventList.writeJavaScriptTags();
	//console.debug("server name is " + curHost+ "event host is : "+ eventHost);
	//console.debug('in sendEvent' );
}

function processImpressionSO(impVpids, soIds){
        //console.debug('in searchResultImpressionEvent' );
        var eventListx = new EventList("eventListHolder");
        var splitResults = impVpids.split("&");
        for (var i=0;i<splitResults.length;i++){
            if(splitResults[i]!=""){
                var event = new EventObject("BRI", "lc_sr_imp");
                event.setProperty("vendorPlacementId",splitResults[i]);
                eventListx.addEvent(event);
            }
        }

        var splitSo = soIds.split("^");
        for (var i=0;i<splitSo.length;i++){
                if(splitSo[i]!=""){
                  var twoIds=splitSo[i].split("*");
                  var event = new EventObject("BRI", "lc_so_sr_ipsn");
                  event.setProperty("vendorPlacementId",twoIds[0]);
                  event.setProperty("secondId",twoIds[1]);
                  eventListx.addEvent(event);
                }
        }

        var re = /www\.brides\.com|.*\.advancepubs\.net/;
        var curHost = document.location.host;
        var eventHost = curHost.match(re) ? "http://event.brides.com/" : "http://samgdeac12:8300/";
        //console.debug("server name is " + curHost+ "event host is : "+ eventHost);
        eventListx.setBaseUrl(eventHost);
        eventListx.writeImageTags();
}


function searchResultImpressionEvent(vendorPlacementIds, event_code){
	//console.debug('in searchResultImpressionEvent' );
	var eventList = new EventList("eventListHolder");
	var splitResults = vendorPlacementIds.split("&");
	for (var i=0;i<splitResults.length;i++){ 
            if(splitResults[i]!=""){	
	        var event = new EventObject("BRI", event_code);
		event.setProperty("vendorPlacementId",splitResults[i]);
        	eventList.addEvent(event);
	    }
	}
	
	var re = /www\.brides\.com|.*\.advancepubs\.net/;
  	var curHost = document.location.host;
  	var eventHost = curHost.match(re) ? "http://event.brides.com/" : "http://samgdeac12:8300/";
  	//console.debug("server name is " + curHost+ "event host is : "+ eventHost);
  	eventList.setBaseUrl(eventHost);
  	eventList.writeImageTags();
}

function sendEmailEvent(from, to, vpid) {
	//console.debug('in sendEmailEvent' );
        var eventList = new EventList("eventListHolder");
        var event = new EventObject("BRI", "lc_ev");
        event.setProperty("vendorPlacementId",vpid);
	event.setProperty("fromEmail",from);
	event.setProperty("toEmail",to);
        eventList.addEvent(event);

	var re = /www\.brides\.com|.*\.advancepubs\.net/;
  	var curHost = document.location.host;
  	var eventHost = curHost.match(re) ? "http://event.brides.com/" : "http://samgdeac12:8300/";
  	//console.debug("server name is " + curHost+ "event host is : "+ eventHost);
  	eventList.setBaseUrl(eventHost);
  	eventList.writeJavaScriptTags();
}

function sendEventsWithSecondId(slidesIds,event_code){
        var eventList = new EventList("eventListHolder");
	var splitResults = slidesIds.split("^");
	for (var i=0;i<splitResults.length;i++){
		if(splitResults[i]!=""){
		  var twoIds=splitResults[i].split("*");
        	  var event = new EventObject("BRI", event_code);
        	  event.setProperty("vendorPlacementId",twoIds[0]);
        	  event.setProperty("secondId",twoIds[1]);
        	  eventList.addEvent(event);
		}
	}

	var re = /www\.brides\.com|.*\.advancepubs\.net/;
  	var curHost = document.location.host;
  	var eventHost = curHost.match(re) ? "http://event.brides.com/" : "http://samgdeac12:8300/";
  	//console.debug("server name is " + curHost+ "event host is : "+ eventHost);
  	eventList.setBaseUrl(eventHost);
  
	eventList.writeJavaScriptTags();
	//console.debug('in sendEventsWithSecondId'+ event_code +" secondIds is :" +slidesIds );
}

function sendThreeEvents(vendorPlacementId,slidesIds,soVpIds){
        var eventLista = new EventList("eventListHolder");
        var event = new EventObject("BRI", "lc_vd_imp_*");
	event.setProperty("vendorPlacementId",vendorPlacementId);
        eventLista.addEvent(event);

        var splitResults = slidesIds.split("^");
        for (var i=0;i<splitResults.length;i++){
                if(splitResults[i]!=""){
                  var twoIds=splitResults[i].split("*");
                  var event = new EventObject("BRI", "lc_img_imp");
                  event.setProperty("vendorPlacementId",twoIds[0]);
                  event.setProperty("secondId",twoIds[1]);
                  eventLista.addEvent(event);
                }
        }

        var soResults = soVpIds.split("^");
        for (var i=0;i<soResults.length;i++){
                if(soResults[i]!=""){
                  var twoIds=soResults[i].split("*");
                  var event = new EventObject("BRI", "lc_so_vd_ipsn");
                  event.setProperty("vendorPlacementId",twoIds[0]);
                  event.setProperty("secondId",twoIds[1]);
                  eventLista.addEvent(event);
                }
        }

        var re = /www\.brides\.com|.*\.advancepubs\.net/;
        var curHost = document.location.host;
        var eventHost = curHost.match(re) ? "http://event.brides.com/" : "http://samgdeac12:8300/";
        //console.debug("server name is " + curHost+ "event host is : "+ eventHost);
        eventLista.setBaseUrl(eventHost);

        eventLista.writeImageTags();
        //console.debug('in sendEventsWithSecondId'+ event_code +" secondIds is :" +slidesIds );
}


function sendClickEvent(vendorPlacementId,event_code) {
    var output = "http://event.brides.com/";
    output += '/images/event.gif?e0_sc=BRI';
    output += '&e0_ec=' + event_code;
    output += '&e0_vendorPlacementId=' + vendorPlacementId;
    output += '&REFERRER=' + (document.referrer);
    jQuery.ajax({url : output, ifModified : true, async : false, timeout : 250 });
}


// Crunch Insert -  Fri Nov 6 16:54:45 EST 2009

function DWREngine() { }

DWREngine.setErrorHandler = function(handler) {
DWREngine._errorHandler = handler;
};


DWREngine.setWarningHandler = function(handler) {
DWREngine._warningHandler = handler;
};





DWREngine.setTimeout = function(timeout) {
DWREngine._timeout = timeout;
};





DWREngine.setPreHook = function(handler) {
DWREngine._preHook = handler;
};





DWREngine.setPostHook = function(handler) {
DWREngine._postHook = handler;
};


DWREngine.XMLHttpRequest = 1;


DWREngine.IFrame = 2;






DWREngine.setMethod = function(newmethod) {
if (newmethod != DWREngine.XMLHttpRequest && newmethod != DWREngine.IFrame) {
DWREngine._handleError("Remoting method must be one of DWREngine.XMLHttpRequest or DWREngine.IFrame");
return;
}
DWREngine._method = newmethod;
};





DWREngine.setVerb = function(verb) {
if (verb != "GET" && verb != "POST") {
DWREngine._handleError("Remoting verb must be one of GET or POST");
return;
}
DWREngine._verb = verb;
};





DWREngine.setOrdered = function(ordered) {
DWREngine._ordered = ordered;
};





DWREngine.setAsync = function(async) {
DWREngine._async = async;
};





DWREngine.defaultMessageHandler = function(message) {
if (typeof message == "object" && message.name == "Error" && message.description) {
//alert("Error: " + message.description);
}
else {
//alert(message);
}
};





DWREngine.beginBatch = function() {
if (DWREngine._batch) {
DWREngine._handleError("Batch already started.");
return;
}

DWREngine._batch = {};
DWREngine._batch.map = {};
DWREngine._batch.paramCount = 0;
DWREngine._batch.map.callCount = 0;
DWREngine._batch.ids = [];
DWREngine._batch.preHooks = [];
DWREngine._batch.postHooks = [];
};





DWREngine.endBatch = function(options) {
var batch = DWREngine._batch;
if (batch == null) {
DWREngine._handleError("No batch in progress.");
return;
}

if (options && options.preHook) batch.preHooks.unshift(options.preHook);
if (options && options.postHook) batch.postHooks.push(options.postHook);
if (DWREngine._preHook) batch.preHooks.unshift(DWREngine._preHook);
if (DWREngine._postHook) batch.postHooks.push(DWREngine._postHook);

if (batch.method == null) batch.method = DWREngine._method;
if (batch.verb == null) batch.verb = DWREngine._verb;
if (batch.async == null) batch.async = DWREngine._async;
if (batch.timeout == null) batch.timeout = DWREngine._timeout;

batch.completed = false;


DWREngine._batch = null;



if (!DWREngine._ordered) {
DWREngine._sendData(batch);
DWREngine._batches[DWREngine._batches.length] = batch;
}
else {
if (DWREngine._batches.length == 0) {

DWREngine._sendData(batch);
DWREngine._batches[DWREngine._batches.length] = batch;
}
else {

DWREngine._batchQueue[DWREngine._batchQueue.length] = batch;
}
}
};






DWREngine._errorHandler = DWREngine.defaultMessageHandler;


DWREngine._warningHandler = DWREngine.defaultMessageHandler;


DWREngine._preHook = null;


DWREngine._postHook = null;


DWREngine._batches = [];


DWREngine._batchQueue = [];


DWREngine._handlersMap = {};


DWREngine._method = DWREngine.XMLHttpRequest;


DWREngine._verb = "POST";


DWREngine._ordered = false;


DWREngine._async = true;


DWREngine._batch = null;


DWREngine._timeout = 0;


DWREngine._DOMDocument = ["Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"];


DWREngine._XMLHTTP = ["Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];










DWREngine._execute = function(path, scriptName, methodName, vararg_params) {
var singleShot = false;
if (DWREngine._batch == null) {
DWREngine.beginBatch();
singleShot = true;
}

var args = [];
for (var i = 0; i < arguments.length - 3; i++) {
args[i] = arguments[i + 3];
}

if (DWREngine._batch.path == null) {
DWREngine._batch.path = path;
}
else {
if (DWREngine._batch.path != path) {
DWREngine._handleError("Can't batch requests to multiple DWR Servlets.");
return;
}
}


var params;
var callData;
var firstArg = args[0];
var lastArg = args[args.length - 1];

if (typeof firstArg == "function") {
callData = { callback:args.shift() };
params = args;
}
else if (typeof lastArg == "function") {
callData = { callback:args.pop() };
params = args;
}
else if (typeof lastArg == "object" && lastArg.callback != null && typeof lastArg.callback == "function") {
callData = args.pop();
params = args;
}
else if (firstArg == null) {



if (lastArg == null && args.length > 2) {
if (DWREngine._warningHandler) {
DWREngine._warningHandler("Ambiguous nulls at start and end of parameter list. Which is the callback function?");
}
}
callData = { callback:args.shift() };
params = args;
}
else if (lastArg == null) {
callData = { callback:args.pop() };
params = args;
}
else {
if (DWREngine._warningHandler) {
DWREngine._warningHandler("Missing callback function or metadata object.");
}
return;
}


var random = Math.floor(Math.random() * 10001);
var id = (random + "_" + new Date().getTime()).toString();
var prefix = "c" + DWREngine._batch.map.callCount + "-";
DWREngine._batch.ids.push(id);


if (callData.method != null) {
DWREngine._batch.method = callData.method;
delete callData.method;
}
if (callData.verb != null) {
DWREngine._batch.verb = callData.verb;
delete callData.verb;
}
if (callData.async != null) {
DWREngine._batch.async = callData.async;
delete callData.async;
}
if (callData.timeout != null) {
DWREngine._batch.timeout = callData.timeout;
delete callData.timeout;
}


if (callData.preHook != null) {
DWREngine._batch.preHooks.unshift(callData.preHook);
delete callData.preHook;
}
if (callData.postHook != null) {
DWREngine._batch.postHooks.push(callData.postHook);
delete callData.postHook;
}


if (callData.errorHandler == null) callData.errorHandler = DWREngine._errorHandler;
if (callData.warningHandler == null) callData.warningHandler = DWREngine._warningHandler;


DWREngine._handlersMap[id] = callData;

DWREngine._batch.map[prefix + "scriptName"] = scriptName;
DWREngine._batch.map[prefix + "methodName"] = methodName;
DWREngine._batch.map[prefix + "id"] = id;


DWREngine._addSerializeFunctions();
for (i = 0; i < params.length; i++) {
DWREngine._serializeAll(DWREngine._batch, [], params[i], prefix + "param" + i);
}
DWREngine._removeSerializeFunctions();


DWREngine._batch.map.callCount++;
if (singleShot) {
DWREngine.endBatch();
}
};




DWREngine._sendData = function(batch) {

if (batch.map.callCount == 0) return;

for (var i = 0; i < batch.preHooks.length; i++) {
batch.preHooks[i]();
}
batch.preHooks = null;

if (batch.timeout && batch.timeout != 0) {
batch.interval = setInterval(function() {
clearInterval(batch.interval);
DWREngine._abortRequest(batch);
}, batch.timeout);
}

var statsInfo;
if (batch.map.callCount == 1) {
statsInfo = batch.map["c0-scriptName"] + "." + batch.map["c0-methodName"] + ".dwr";
}
else {
statsInfo = "Multiple." + batch.map.callCount + ".dwr";
}


if (batch.method == DWREngine.XMLHttpRequest) {
if (window.XMLHttpRequest) {
batch.req = new XMLHttpRequest();
}

else if (window.ActiveXObject && !(navigator.userAgent.indexOf('Mac') >= 0 && navigator.userAgent.indexOf("MSIE") >= 0)) {
batch.req = DWREngine._newActiveXObject(DWREngine._XMLHTTP);
}
}

var query = "";
var prop;
if (batch.req) {
batch.map.xml = "true";

if (batch.async) {
batch.req.onreadystatechange = function() {
DWREngine._stateChange(batch);
};
}

var indexSafari = navigator.userAgent.indexOf('Safari/');
if (indexSafari >= 0) {

var version = navigator.userAgent.substring(indexSafari + 7);
var verNum = parseInt(version, 10);
if (verNum < 400) {
batch.verb == "GET";
}



}
if (batch.verb == "GET") {



batch.map.callCount = "" + batch.map.callCount;

for (prop in batch.map) {
var qkey = encodeURIComponent(prop);
var qval = encodeURIComponent(batch.map[prop]);
if (qval == "") {
if (DWREngine._warningHandler) {
DWREngine._warningHandler("Found empty qval for qkey=" + qkey);
}
}
query += qkey + "=" + qval + "&";
}
query = query.substring(0, query.length - 1);

try {
batch.req.open("GET", batch.path + "/exec/" + statsInfo + "?" + query, batch.async);
batch.req.send(null);
if (!batch.async) {
DWREngine._stateChange(batch);
}
}
catch (ex) {
DWREngine._handleMetaDataError(null, ex);
}
}
else {
for (prop in batch.map) {
if (typeof batch.map[prop] != "function") {
query += prop + "=" + batch.map[prop] + "\n";
}
}

try {




batch.req.open("POST", batch.path + "/exec/" + statsInfo, batch.async);
batch.req.setRequestHeader('Content-Type', 'text/plain');
batch.req.send(query);
if (!batch.async) {
DWREngine._stateChange(batch);
}
}
catch (ex) {
DWREngine._handleMetaDataError(null, ex);
}
}
}
else {
batch.map.xml = "false";
var idname = "dwr-if-" + batch.map["c0-id"];

batch.div = document.createElement('div');
batch.div.innerHTML = "<iframe frameborder='0' width='0' height='0' id='" + idname + "' name='" + idname + "'></iframe>";
document.body.appendChild(batch.div);
batch.iframe = document.getElementById(idname);
batch.iframe.setAttribute('style', 'width:0px; height:0px; border:0px;');

if (batch.verb == "GET") {
for (prop in batch.map) {
if (typeof batch.map[prop] != "function") {
query += encodeURIComponent(prop) + "=" + encodeURIComponent(batch.map[prop]) + "&";
}
}
query = query.substring(0, query.length - 1);

batch.iframe.setAttribute('src', batch.path + "/exec/" + statsInfo + "?" + query);
document.body.appendChild(batch.iframe);
}
else {
batch.form = document.createElement('form');
batch.form.setAttribute('id', 'dwr-form');
batch.form.setAttribute('action', batch.path + "/exec" + statsInfo);
batch.form.setAttribute('target', idname);
batch.form.target = idname;
batch.form.setAttribute('method', 'post');
for (prop in batch.map) {
var formInput = document.createElement('input');
formInput.setAttribute('type', 'hidden');
formInput.setAttribute('name', prop);
formInput.setAttribute('value', batch.map[prop]);
batch.form.appendChild(formInput);
}

document.body.appendChild(batch.form);
batch.form.submit();
}
}
};




DWREngine._stateChange = function(batch) {
if (!batch.completed && batch.req.readyState == 4) {
try {
var reply = batch.req.responseText;
var status = batch.req.status;

if (reply == null || reply == "") {
DWREngine._handleMetaDataError(null, "No data received from server");
return;
}


if (reply.search("DWREngine._handle") == -1) {
DWREngine._handleMetaDataError(null, "Invalid reply from server");
return;
}

if (status != 200) {
if (reply == null) reply = "Unknown error occured";
DWREngine._handleMetaDataError(null, reply);
return;
}

eval(reply);


DWREngine._clearUp(batch);
}
catch (ex) {
if (ex == null) ex = "Unknown error occured";
DWREngine._handleMetaDataError(null, ex);
}
finally {



if (DWREngine._batchQueue.length != 0) {
var sendbatch = DWREngine._batchQueue.shift();
DWREngine._sendData(sendbatch);
DWREngine._batches[DWREngine._batches.length] = sendbatch;
}
}
}
};






DWREngine._handleResponse = function(id, reply) {

var handlers = DWREngine._handlersMap[id];
DWREngine._handlersMap[id] = null;

if (handlers) {


try {
if (handlers.callback) handlers.callback(reply);
}
catch (ex) {
DWREngine._handleMetaDataError(handlers, ex);
}
}


if (DWREngine._method == DWREngine.IFrame) {
var responseBatch = DWREngine._batches[DWREngine._batches.length-1];

if (responseBatch.map["c"+(responseBatch.map.callCount-1)+"-id"] == id) {
DWREngine._clearUp(responseBatch);
}
}
};




DWREngine._handleServerError = function(id, error) {

var handlers = DWREngine._handlersMap[id];
DWREngine._handlersMap[id] = null;
if (error.message) {
DWREngine._handleMetaDataError(handlers, error.message, error);
}
else {
DWREngine._handleMetaDataError(handlers, error);
}
};




DWREngine._abortRequest = function(batch) {
if (batch && batch.metadata != null && !batch.completed) {
DWREngine._clearUp(batch);
if (batch.req) batch.req.abort();

var handlers;
var id;
for (var i = 0; i < batch.ids.length; i++) {
id = batch.ids[i];
handlers = DWREngine._handlersMap[id];
DWREngine._handleMetaDataError(handlers, "Timeout");
}
}
};




DWREngine._clearUp = function(batch) {
if (batch.completed) {
alert("double complete");
return;
}


if (batch.div) batch.div.parentNode.removeChild(batch.div);
if (batch.iframe) batch.iframe.parentNode.removeChild(batch.iframe);
if (batch.form) batch.form.parentNode.removeChild(batch.form);


if (batch.req) delete batch.req;

for (var i = 0; i < batch.postHooks.length; i++) {
batch.postHooks[i]();
}
batch.postHooks = null;


for (var i = 0; i < DWREngine._batches.length; i++) {
if (DWREngine._batches[i] == batch) {
DWREngine._batches.splice(i, 1);
break;
}
}

batch.completed = true;
};




DWREngine._handleError = function(reason, ex) {
if (DWREngine._errorHandler) {
DWREngine._errorHandler(reason, ex);
}
};




DWREngine._handleMetaDataError = function(handlers, reason, ex) {
if (handlers && typeof handlers.errorHandler == "function") {
handlers.errorHandler(reason, ex);
}
else {
DWREngine._handleError(reason, ex);
}
};




DWREngine._addSerializeFunctions = function() {
Object.prototype.dwrSerialize = DWREngine._serializeObject;
Array.prototype.dwrSerialize = DWREngine._serializeArray;
Boolean.prototype.dwrSerialize = DWREngine._serializeBoolean;
Number.prototype.dwrSerialize = DWREngine._serializeNumber;
String.prototype.dwrSerialize = DWREngine._serializeString;
Date.prototype.dwrSerialize = DWREngine._serializeDate;
};




DWREngine._removeSerializeFunctions = function() {
delete Object.prototype.dwrSerialize;
delete Array.prototype.dwrSerialize;
delete Boolean.prototype.dwrSerialize;
delete Number.prototype.dwrSerialize;
delete String.prototype.dwrSerialize;
delete Date.prototype.dwrSerialize;
};








DWREngine._serializeAll = function(batch, referto, data, name) {
if (data == null) {
batch.map[name] = "null:null";
return;
}

switch (typeof data) {
case "boolean":
batch.map[name] = "boolean:" + data;
break;

case "number":
batch.map[name] = "number:" + data;
break;

case "string":
batch.map[name] = "string:" + encodeURIComponent(data);
break;

case "object":
if (data.dwrSerialize) {
batch.map[name] = data.dwrSerialize(batch, referto, data, name);
}
else if (data.nodeName) {
batch.map[name] = DWREngine._serializeXml(batch, referto, data, name);
}
else {
if (DWREngine._warningHandler) {
DWREngine._warningHandler("Object without dwrSerialize: " + typeof data + ", attempting default converter.");
}
batch.map[name] = "default:" + data;
}
break;

case "function":

break;

default:
if (DWREngine._warningHandler) {
DWREngine._warningHandler("Unexpected type: " + typeof data + ", attempting default converter.");
}
batch.map[name] = "default:" + data;
break;
}
};


DWREngine._lookup = function(referto, data, name) {
var lookup;

for (var i = 0; i < referto.length; i++) {
if (referto[i].data == data) {
lookup = referto[i];
break;
}
}
if (lookup) {
return "reference:" + lookup.name;
}
referto.push({ data:data, name:name });
return null;
};


DWREngine._serializeObject = function(batch, referto, data, name) {
var ref = DWREngine._lookup(referto, this, name);
if (ref) return ref;

if (data.nodeName) {
return DWREngine._serializeXml(batch, referto, data, name);
}


var reply = "Object:{";
var element;
for (element in this)  {
if (element != "dwrSerialize") {
batch.paramCount++;
var childName = "c" + DWREngine._batch.map.callCount + "-e" + batch.paramCount;
DWREngine._serializeAll(batch, referto, this[element], childName);

reply += encodeURIComponent(element);
reply += ":reference:";
reply += childName;
reply += ", ";
}
}

if (reply.substring(reply.length - 2) == ", ") {
reply = reply.substring(0, reply.length - 2);
}
reply += "}";

return reply;
};


DWREngine._serializeXml = function(batch, referto, data, name) {
var ref = DWREngine._lookup(referto, this, name);
if (ref) {
return ref;
}
var output;
if (window.XMLSerializer) {
var serializer = new XMLSerializer();
output = serializer.serializeToString(data);
}
else {
output = data.toXml;
}
return "XML:" + encodeURIComponent(output);
};


DWREngine._serializeArray = function(batch, referto, data, name) {
var ref = DWREngine._lookup(referto, this, name);
if (ref) return ref;

var reply = "Array:[";
for (var i = 0; i < this.length; i++) {
if (i != 0) {
reply += ",";
}

batch.paramCount++;
var childName = "c" + DWREngine._batch.map.callCount + "-e" + batch.paramCount;
DWREngine._serializeAll(batch, referto, this[i], childName);
reply += "reference:";
reply += childName;
}
reply += "]";

return reply;
};


DWREngine._serializeBoolean = function(batch, referto, data, name) {
return "Boolean:" + this;
};


DWREngine._serializeNumber = function(batch, referto, data, name) {
return "Number:" + this;
};


DWREngine._serializeString = function(batch, referto, data, name) {
return "String:" + encodeURIComponent(this);
};


DWREngine._serializeDate = function(batch, referto, data, name) {
return "Date:" + this.getTime();
};


DWREngine._unserializeDocument = function(xml) {
var dom;
if (window.DOMParser) {
var parser = new DOMParser();
dom = parser.parseFromString(xml, "text/xml");
if (!dom.documentElement || dom.documentElement.tagName == "parsererror") {
var message = dom.documentElement.firstChild.data;
message += "\n" + dom.documentElement.firstChild.nextSibling.firstChild.data;
throw message;
}
return dom;
}
else if (window.ActiveXObject) {
dom = DWREngine._newActiveXObject(DWREngine._DOMDocument);
dom.loadXML(xml);

return dom;
}








else {
var div = document.createElement('div');
div.innerHTML = xml;
return div;
}
};





DWREngine._newActiveXObject = function(axarray) {
var returnValue;
for (var i = 0; i < axarray.length; i++) {
try {
returnValue = new ActiveXObject(axarray[i]);
break;
}
catch (ex) {
}
}
return returnValue;
};


if (typeof window.encodeURIComponent === 'undefined') {
DWREngine._utf8 = function(wide) {
wide = "" + wide;
var c;
var s;
var enc = "";
var i = 0;
while (i < wide.length) {
c = wide.charCodeAt(i++);

if (c >= 0xDC00 && c < 0xE000) continue;
if (c >= 0xD800 && c < 0xDC00) {
if (i >= wide.length) continue;
s = wide.charCodeAt(i++);
if (s < 0xDC00 || c >= 0xDE00) continue;
c = ((c - 0xD800) << 10) + (s - 0xDC00) + 0x10000;
}

if (c < 0x80) {
enc += String.fromCharCode(c);
}
else if (c < 0x800) {
enc += String.fromCharCode(0xC0 + (c >> 6), 0x80 + (c & 0x3F));
}
else if (c < 0x10000) {
enc += String.fromCharCode(0xE0 + (c >> 12), 0x80 + (c >> 6 & 0x3F), 0x80 + (c & 0x3F));
}
else {
enc += String.fromCharCode(0xF0 + (c >> 18), 0x80 + (c >> 12 & 0x3F), 0x80 + (c >> 6 & 0x3F), 0x80 + (c & 0x3F));
}
}
return enc;
}

DWREngine._hexchars = "0123456789ABCDEF";

DWREngine._toHex = function(n) {
return DWREngine._hexchars.charAt(n >> 4) + DWREngine._hexchars.charAt(n & 0xF);
}

DWREngine._okURIchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";

window.encodeURIComponent = function(s)  {
s = DWREngine._utf8(s);
var c;
var enc = "";
for (var i= 0; i<s.length; i++) {
if (DWREngine._okURIchars.indexOf(s.charAt(i)) == -1) {
enc += "%" + DWREngine._toHex(s.charCodeAt(i));
}
else {
enc += s.charAt(i);
}
}
return enc;
}
}


if (typeof Array.prototype.splice === 'undefined') {
Array.prototype.splice = function(ind, cnt)
{
if (arguments.length == 0) {
return ind;
}
if (typeof ind != "number") {
ind = 0;
}
if (ind < 0) {
ind = Math.max(0,this.length + ind);
}
if (ind > this.length) {
if (arguments.length > 2) {
ind = this.length;
}
else {
return [];
}
}
if (arguments.length < 2) {
cnt = this.length-ind;
}

cnt = (typeof cnt == "number") ? Math.max(0, cnt) : 0;
removeArray = this.slice(ind, ind + cnt);
endArray = this.slice(ind + cnt);
this.length = ind;

for (var i = 2; i < arguments.length; i++) {
this[this.length] = arguments[i];
}
for (i = 0; i < endArray.length; i++) {
this[this.length] = endArray[i];
}

return removeArray;
}
}


if (typeof Array.prototype.shift === 'undefined') {
Array.prototype.shift = function(str) {
var val = this[0];
for (var i = 1; i < this.length; ++i) {
this[i - 1] = this[i];
}
this.length--;
return val;
}
}


if (typeof Array.prototype.unshift === 'undefined') {
Array.prototype.unshift = function() {
var i = unshift.arguments.length;
for (var j = this.length - 1; j >= 0; --j) {
this[j + i] = this[j];
}
for (j = 0; j < i; ++j) {
this[j] = unshift.arguments[j];
}
}
}


if (typeof Array.prototype.push === 'undefined') {
Array.prototype.push = function() {
var sub = this.length;
for (var i = 0; i < push.arguments.length; ++i) {
this[sub] = push.arguments[i];
sub++;
}
}
}


if (typeof Array.prototype.pop === 'undefined') {
Array.prototype.pop = function() {
var lastElement = this[this.length - 1];
this.length--;
return lastElement;
}
}


// Crunch Insert -  Fri Nov 6 16:54:45 EST 2009

function DWRUtil() { }





DWRUtil.onReturn = function(event, action) {
if (!event) {
event = window.event;
}
if (event && event.keyCode && event.keyCode == 13) {
action();
}
};





DWRUtil.selectRange = function(ele, start, end) {
var orig = ele;
ele = $(ele);
if (ele == null) {
DWRUtil.debug("selectRange() can't find an element with id: " + orig + ".");
return;
}
if (ele.setSelectionRange) {
ele.setSelectionRange(start, end);
}
else if (ele.createTextRange) {
var range = ele.createTextRange();
range.moveStart("character", start);
range.moveEnd("character", end - ele.value.length);
range.select();
}
ele.focus();
};




DWRUtil._getSelection = function(ele) {
var orig = ele;
ele = $(ele);
if (ele == null) {
DWRUtil.debug("selectRange() can't find an element with id: " + orig + ".");
return;
}
return ele.value.substring(ele.selectionStart, ele.selectionEnd);





}





var $;
if (!$ && document.getElementById) {
$ = function() {
var elements = new Array();
for (var i = 0; i < arguments.length; i++) {
var element = arguments[i];
if (typeof element == 'string') {
element = document.getElementById(element);
}
if (arguments.length == 1) {
return element;
}
elements.push(element);
}
return elements;
}
}
else if (!$ && document.all) {
$ = function() {
var elements = new Array();
for (var i = 0; i < arguments.length; i++) {
var element = arguments[i];
if (typeof element == 'string') {
element = document.all[element];
}
if (arguments.length == 1) {
return element;
}
elements.push(element);
}
return elements;
}
}





DWRUtil.toDescriptiveString = function(data, level, depth) {
var reply = "";
var i = 0;
var value;
var obj;
if (level == null) level = 0;
if (depth == null) depth = 0;
if (data == null) return "null";
if (DWRUtil._isArray(data)) {
if (data.length == 0) reply += "[]";
else {
if (level != 0) reply += "[\n";
else reply = "[";
for (i = 0; i < data.length; i++) {
try {
obj = data[i];
if (obj == null || typeof obj == "function") {
continue;
}
else if (typeof obj == "object") {
if (level > 0) value = DWRUtil.toDescriptiveString(obj, level - 1, depth + 1);
else value = DWRUtil._detailedTypeOf(obj);
}
else {
value = "" + obj;
value = value.replace(/\/n/g, "\\n");
value = value.replace(/\/t/g, "\\t");
}
}
catch (ex) {
value = "" + ex;
}
if (level != 0)  {
reply += DWRUtil._indent(level, depth + 2) + value + ", \n";
}
else {
if (value.length > 13) value = value.substring(0, 10) + "...";
reply += value + ", ";
if (i > 5) {
reply += "...";
break;
}
}
}
if (level != 0) reply += DWRUtil._indent(level, depth) + "]";
else reply += "]";
}
return reply;
}
if (typeof data == "string" || typeof data == "number" || DWRUtil._isDate(data)) {
return data.toString();
}
if (typeof data == "object") {
var typename = DWRUtil._detailedTypeOf(data);
if (typename != "Object")  reply = typename + " ";
if (level != 0) reply += "{\n";
else reply = "{";
var isHtml = DWRUtil._isHTMLElement(data);
for (var prop in data) {
if (isHtml) {

if (prop.toUpperCase() == prop || prop == "title" ||
prop == "lang" || prop == "dir" || prop == "className" ||
prop == "form" || prop == "name" || prop == "prefix" ||
prop == "namespaceURI" || prop == "nodeType" ||
prop == "firstChild" || prop == "lastChild" ||
prop.match(/^offset/)) {
continue;
}
}
value = "";
try {
obj = data[prop];
if (obj == null || typeof obj == "function") {
continue;
}
else if (typeof obj == "object") {
if (level > 0) {
value = "\n";
value += DWRUtil._indent(level, depth + 2);
value = DWRUtil.toDescriptiveString(obj, level - 1, depth + 1);
}
else {
value = DWRUtil._detailedTypeOf(obj);
}
}
else {
value = "" + obj;
value = value.replace(/\/n/g, "\\n");
value = value.replace(/\/t/g, "\\t");
}
}
catch (ex) {
value = "" + ex;
}
if (level == 0 && value.length > 13) value = value.substring(0, 10) + "...";
var propStr = prop;
if (propStr.length > 30) propStr = propStr.substring(0, 27) + "...";
if (level != 0) reply += DWRUtil._indent(level, depth + 1);
reply += prop + ":" + value + ", ";
if (level != 0) reply += "\n";
i++;
if (level == 0 && i > 5) {
reply += "...";
break;
}
}
reply += DWRUtil._indent(level, depth);
reply += "}";
return reply;
}
return data.toString();
};




DWRUtil._indent = function(level, depth) {
var reply = "";
if (level != 0) {
for (var j = 0; j < depth; j++) {
reply += "\u00A0\u00A0";
}
reply += " ";
}
return reply;
};





DWRUtil.useLoadingMessage = function(message) {
var loadingMessage;
if (message) loadingMessage = message;
else loadingMessage = "Loading";
DWREngine.setPreHook(function() {
var disabledZone = $('disabledZone');
if (!disabledZone) {
disabledZone = document.createElement('div');
disabledZone.setAttribute('id', 'disabledZone');
disabledZone.style.position = "absolute";
disabledZone.style.zIndex = "1000";
disabledZone.style.left = "0px";
disabledZone.style.top = "0px";
disabledZone.style.width = "100%";
disabledZone.style.height = "100%";
document.body.appendChild(disabledZone);
var messageZone = document.createElement('div');
messageZone.setAttribute('id', 'messageZone');
messageZone.style.position = "absolute";
messageZone.style.top = "0px";
messageZone.style.right = "0px";
messageZone.style.background = "red";
messageZone.style.color = "white";
messageZone.style.fontFamily = "Arial,Helvetica,sans-serif";
messageZone.style.padding = "4px";
disabledZone.appendChild(messageZone);
var text = document.createTextNode(loadingMessage);
messageZone.appendChild(text);
}
else {
$('messageZone').innerHTML = loadingMessage;
disabledZone.style.visibility = 'visible';
}
});
DWREngine.setPostHook(function() {
$('disabledZone').style.visibility = 'hidden';
});
}





DWRUtil.setValue = function(ele, val, options) {
if (val == null) val = "";
if (options != null) {
if (options.escapeHtml) {
val = val.replace(/&/, "&amp;");
val = val.replace(/'/, "&apos;");
val = val.replace(/</, "&lt;");
val = val.replace(/>/, "&gt;");
}
}

var orig = ele;
var nodes, node, i;

ele = $(ele);

if (ele == null) {
nodes = document.getElementsByName(orig);
if (nodes.length >= 1) {
ele = nodes.item(0);
}
}
if (ele == null) {
DWRUtil.debug("setValue() can't find an element with id/name: " + orig + ".");
return;
}

if (DWRUtil._isHTMLElement(ele, "select")) {
if (ele.type == "select-multiple" && DWRUtil._isArray(val)) {
DWRUtil._selectListItems(ele, val);
}
else {
DWRUtil._selectListItem(ele, val);
}
return;
}

if (DWRUtil._isHTMLElement(ele, "input")) {
if (ele.type == "radio") {

if (nodes == null) nodes = document.getElementsByName(orig);
if (nodes != null && nodes.length > 1) {
for (i = 0; i < nodes.length; i++) {
node = nodes.item(i);
if (node.type == "radio") {
node.checked = (node.value == val);
}
}
}
else {
ele.checked = (val == true);
}
}
else if (ele.type == "checkbox") {
ele.checked = val;
}
else {
ele.value = val;
}
return;
}

if (DWRUtil._isHTMLElement(ele, "textarea")) {
ele.value = val;
return;
}



if (val.nodeType) {
if (val.nodeType == 9  ) {
val = val.documentElement;
}

val = DWRUtil._importNode(ele.ownerDocument, val, true);
ele.appendChild(val);
return;
}


ele.innerHTML = val;
};






DWRUtil._selectListItems = function(ele, val) {


var found  = false;
var i;
var j;
for (i = 0; i < ele.options.length; i++) {
ele.options[i].selected = false;
for (j = 0; j < val.length; j++) {
if (ele.options[i].value == val[j]) {
ele.options[i].selected = true;
}
}
}

if (found) return;

for (i = 0; i < ele.options.length; i++) {
for (j = 0; j < val.length; j++) {
if (ele.options[i].text == val[j]) {
ele.options[i].selected = true;
}
}
}
};






DWRUtil._selectListItem = function(ele, val) {


var found  = false;
var i;
for (i = 0; i < ele.options.length; i++) {
if (ele.options[i].value == val) {
ele.options[i].selected = true;
found = true;
}
else {
ele.options[i].selected = false;
}
}


if (found) return;

for (i = 0; i < ele.options.length; i++) {
if (ele.options[i].text == val) {
ele.options[i].selected = true;
}
else {
ele.options[i].selected = false;
}
}
}





DWRUtil.getValue = function(ele, options) {
if (options == null) {
options = {};
}
var orig = ele;
ele = $(ele);


var nodes = document.getElementsByName(orig);
if (ele == null && nodes.length >= 1) {
ele = nodes.item(0);
}
if (ele == null) {
DWRUtil.debug("getValue() can't find an element with id/name: " + orig + ".");
return "";
}

if (DWRUtil._isHTMLElement(ele, "select")) {


var sel = ele.selectedIndex;
if (sel != -1) {
var reply = ele.options[sel].value;
if (reply == null || reply == "") {
reply = ele.options[sel].text;
}

return reply;
}
else {
return "";
}
}

if (DWRUtil._isHTMLElement(ele, "input")) {
if (ele.type == "radio") {
var node;
for (i = 0; i < nodes.length; i++) {
node = nodes.item(i);
if (node.type == "radio") {
if (node.checked) {
if (nodes.length > 1) return node.value;
else return true;
}
}
}
}
switch (ele.type) {
case "checkbox":
case "check-box":
case "radio":
return ele.checked;
default:
return ele.value;
}
}

if (DWRUtil._isHTMLElement(ele, "textarea")) {
return ele.value;
}

if (options.textContent) {
if (ele.textContent) return ele.textContent;
else if (ele.innerText) return ele.innerText;
}
return ele.innerHTML;
};





DWRUtil.getText = function(ele) {
var orig = ele;
ele = $(ele);
if (ele == null) {
DWRUtil.debug("getText() can't find an element with id: " + orig + ".");
return "";
}

if (!DWRUtil._isHTMLElement(ele, "select")) {
DWRUtil.debug("getText() can only be used with select elements. Attempt to use: " + DWRUtil._detailedTypeOf(ele) + " from  id: " + orig + ".");
return "";
}



var sel = ele.selectedIndex;
if (sel != -1) {
return ele.options[sel].text;
}
else {
return "";
}
};





DWRUtil.setValues = function(map) {
for (var property in map) {

if ($(property) != null || document.getElementsByName(property).length >= 1) {
DWRUtil.setValue(property, map[property]);
}
}
};






DWRUtil.getValues = function(data) {
var ele;
if (typeof data == "string") ele = $(data);
if (DWRUtil._isHTMLElement(data)) ele = data;
if (ele != null) {
if (ele.elements == null) {
alert("getValues() requires an object or reference to a form element.");
return null;
}
var reply = {};
var value;
for (var i = 0; i < ele.elements.length; i++) {
if (ele[i].id != null) value = ele[i].id;
else if (ele[i].value != null) value = ele[i].value;
else value = "element" + i;
reply[value] = DWRUtil.getValue(ele[i]);
}
return reply;
}
else {
for (var property in data) {

if ($(property) != null || document.getElementsByName(property).length >= 1) {
data[property] = DWRUtil.getValue(property);
}
}
return data;
}
};





DWRUtil.addOptions = function(ele, data) {
var orig = ele;
ele = $(ele);
if (ele == null) {
DWRUtil.debug("addOptions() can't find an element with id: " + orig + ".");
return;
}
var useOptions = DWRUtil._isHTMLElement(ele, "select");
var useLi = DWRUtil._isHTMLElement(ele, ["ul", "ol"]);
if (!useOptions && !useLi) {
DWRUtil.debug("addOptions() can only be used with select/ul/ol elements. Attempt to use: " + DWRUtil._detailedTypeOf(ele));
return;
}
if (data == null) return;

var text;
var value;
var opt;
var li;
if (DWRUtil._isArray(data)) {

for (var i = 0; i < data.length; i++) {
if (useOptions) {
if (arguments[2] != null) {
if (arguments[3] != null) {
text = DWRUtil._getValueFrom(data[i], arguments[3]);
value = DWRUtil._getValueFrom(data[i], arguments[2]);
}
else {
value = DWRUtil._getValueFrom(data[i], arguments[2]);
text = value;
}
}
else
{
text = DWRUtil._getValueFrom(data[i], arguments[3]);
value = text;
}
if (text || value) {
opt = new Option(text, value);
ele.options[ele.options.length] = opt;
}
}
else {
li = document.createElement("li");
value = DWRUtil._getValueFrom(data[i], arguments[2]);
if (value != null) {
li.innerHTML = value;
ele.appendChild(li);
}
}
}
}
else if (arguments[3] != null) {
for (var prop in data) {
if (!useOptions) {
alert("DWRUtil.addOptions can only create select lists from objects.");
return;
}
value = DWRUtil._getValueFrom(data[prop], arguments[2]);
text = DWRUtil._getValueFrom(data[prop], arguments[3]);
if (text || value) {
opt = new Option(text, value);
ele.options[ele.options.length] = opt;
}
}
}
else {
for (var prop in data) {
if (!useOptions) {
DWRUtil.debug("DWRUtil.addOptions can only create select lists from objects.");
return;
}
if (typeof data[prop] == "function") {

text = null;
value = null;
}
else if (arguments[2]) {
text = prop;
value = data[prop];
}
else {
text = data[prop];
value = prop;
}
if (text || value) {
opt = new Option(text, value);
ele.options[ele.options.length] = opt;
}
}
}
};




DWRUtil._getValueFrom = function(data, method) {
if (method == null) return data;
else if (typeof method == 'function') return method(data);
else return data[method];
}





DWRUtil.removeAllOptions = function(ele) {
var orig = ele;
ele = $(ele);
if (ele == null) {
DWRUtil.debug("removeAllOptions() can't find an element with id: " + orig + ".");
return;
}
var useOptions = DWRUtil._isHTMLElement(ele, "select");
var useLi = DWRUtil._isHTMLElement(ele, ["ul", "ol"]);
if (!useOptions && !useLi) {
DWRUtil.debug("removeAllOptions() can only be used with select, ol and ul elements. Attempt to use: " + DWRUtil._detailedTypeOf(ele));
return;
}
if (useOptions) {
ele.options.length = 0;
}
else {
while (ele.childNodes.length > 0) {
ele.removeChild(ele.firstChild);
}
}
};





DWRUtil.addRows = function(ele, data, cellFuncs, options) {
var orig = ele;
ele = $(ele);
if (ele == null) {
DWRUtil.debug("addRows() can't find an element with id: " + orig + ".");
return;
}
if (!DWRUtil._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"])) {
DWRUtil.debug("addRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + DWRUtil._detailedTypeOf(ele));
return;
}
if (!options) options = {};
if (!options.rowCreator) options.rowCreator = DWRUtil._defaultRowCreator;
if (!options.cellCreator) options.cellCreator = DWRUtil._defaultCellCreator;
var tr, rowNum;
if (DWRUtil._isArray(data)) {
for (rowNum = 0; rowNum < data.length; rowNum++) {
options.rowData = data[rowNum];
options.rowIndex = rowNum;
options.rowNum = rowNum;
options.data = null;
options.cellNum = -1;
tr = DWRUtil._addRowInner(cellFuncs, options);
if (tr != null) ele.appendChild(tr);
}
}
else if (typeof data == "object") {
rowNum = 0;
for (var rowIndex in data) {
options.rowData = data[rowIndex];
options.rowIndex = rowIndex;
options.rowNum = rowNum;
options.data = null;
options.cellNum = -1;
tr = DWRUtil._addRowInner(cellFuncs, options);
if (tr != null) ele.appendChild(tr);
rowNum++;
}
}
};




DWRUtil._addRowInner = function(cellFuncs, options) {
var tr = options.rowCreator(options);
if (tr == null) return null;
for (var cellNum = 0; cellNum < cellFuncs.length; cellNum++) {
var func = cellFuncs[cellNum];
var reply = func(options.rowData, options);
options.data = reply;
options.cellNum = cellNum;
var td = options.cellCreator(options);
if (td != null) {
if (reply != null) {
if (DWRUtil._isHTMLElement(reply)) td.appendChild(reply);
else td.innerHTML = reply;
}
tr.appendChild(td);
}
}
return tr;
};




DWRUtil._defaultRowCreator = function(options) {
return document.createElement("tr");
};




DWRUtil._defaultCellCreator = function(options) {
return document.createElement("td");
};





DWRUtil.removeAllRows = function(ele) {
var orig = ele;
ele = $(ele);
if (ele == null) {
DWRUtil.debug("removeAllRows() can't find an element with id: " + orig + ".");
return;
}
if (!DWRUtil._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"])) {
DWRUtil.debug("removeAllRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + DWRUtil._detailedTypeOf(ele));
return;
}
while (ele.childNodes.length > 0) {
ele.removeChild(ele.firstChild);
}
};







DWRUtil._isHTMLElement = function(ele, nodeName) {
if (ele == null || typeof ele != "object" || ele.nodeName == null) {
return false;
}

if (nodeName != null) {
var test = ele.nodeName.toLowerCase();

if (typeof nodeName == "string") {
return test == nodeName.toLowerCase();
}

if (DWRUtil._isArray(nodeName)) {
var match = false;
for (var i = 0; i < nodeName.length && !match; i++) {
if (test == nodeName[i].toLowerCase()) {
match =  true;
}
}
return match;
}

DWRUtil.debug("DWRUtil._isHTMLElement was passed test node name that is neither a string or array of strings");
return false;
}

return true;
};




DWRUtil._detailedTypeOf = function(x) {
var reply = typeof x;
if (reply == "object") {
reply = Object.prototype.toString.apply(x);
reply = reply.substring(8, reply.length-1);
}
return reply;
};




DWRUtil._isArray = function(data) {
return (data && data.join) ? true : false;
};




DWRUtil._isDate = function(data) {
return (data && data.toUTCString) ? true : false;
};




DWRUtil._importNode = function(doc, importedNode, deep) {
var newNode;

if (importedNode.nodeType == 1  ) {
newNode = doc.createElement(importedNode.nodeName);

for (var i = 0; i < importedNode.attributes.length; i++) {
var attr = importedNode.attributes[i];
if (attr.nodeValue != null && attr.nodeValue != '') {
newNode.setAttribute(attr.name, attr.nodeValue);
}
}

if (typeof importedNode.style != "undefined") {
newNode.style.cssText = importedNode.style.cssText;
}
}
else if (importedNode.nodeType == 3  ) {
newNode = doc.createTextNode(importedNode.nodeValue);
}

if (deep && importedNode.hasChildNodes()) {
for (i = 0; i < importedNode.childNodes.length; i++) {
newNode.appendChild(DWRUtil._importNode(doc, importedNode.childNodes[i], true));
}
}

return newNode;
}




DWRUtil.debug = function(message) {
alert(message);
}


// Crunch Insert -  Fri Nov 6 16:54:45 EST 2009

/*
    http://www.JSON.org/json2.js
    2008-11-19

    Public Domain.

    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

    See http://www.JSON.org/js.html

    This file creates a global JSON object containing two methods: stringify
    and parse.

        JSON.stringify(value, replacer, space)
            value       any JavaScript value, usually an object or array.

            replacer    an optional parameter that determines how object
                        values are stringified for objects. It can be a
                        function or an array of strings.

            space       an optional parameter that specifies the indentation
                        of nested structures. If it is omitted, the text will
                        be packed without extra whitespace. If it is a number,
                        it will specify the number of spaces to indent at each
                        level. If it is a string (such as '\t' or '&nbsp;'),
                        it contains the characters used to indent at each level.

            This method produces a JSON text from a JavaScript value.

            When an object value is found, if the object contains a toJSON
            method, its toJSON method will be called and the result will be
            stringified. A toJSON method does not serialize: it returns the
            value represented by the name/value pair that should be serialized,
            or undefined if nothing should be serialized. The toJSON method
            will be passed the key associated with the value, and this will be
            bound to the object holding the key.

            For example, this would serialize Dates as ISO strings.

                Date.prototype.toJSON = function (key) {
                    function f(n) {
                        // Format integers to have at least two digits.
                        return n < 10 ? '0' + n : n;
                    }

                    return this.getUTCFullYear()   + '-' +
                         f(this.getUTCMonth() + 1) + '-' +
                         f(this.getUTCDate())      + 'T' +
                         f(this.getUTCHours())     + ':' +
                         f(this.getUTCMinutes())   + ':' +
                         f(this.getUTCSeconds())   + 'Z';
                };

            You can provide an optional replacer method. It will be passed the
            key and value of each member, with this bound to the containing
            object. The value that is returned from your method will be
            serialized. If your method returns undefined, then the member will
            be excluded from the serialization.

            If the replacer parameter is an array of strings, then it will be
            used to select the members to be serialized. It filters the results
            such that only members with keys listed in the replacer array are
            stringified.

            Values that do not have JSON representations, such as undefined or
            functions, will not be serialized. Such values in objects will be
            dropped; in arrays they will be replaced with null. You can use
            a replacer function to replace those with JSON values.
            JSON.stringify(undefined) returns undefined.

            The optional space parameter produces a stringification of the
            value that is filled with line breaks and indentation to make it
            easier to read.

            If the space parameter is a non-empty string, then that string will
            be used for indentation. If the space parameter is a number, then
            the indentation will be that many spaces.

            Example:

            text = JSON.stringify(['e', {pluribus: 'unum'}]);
            // text is '["e",{"pluribus":"unum"}]'


            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'

            text = JSON.stringify([new Date()], function (key, value) {
                return this[key] instanceof Date ?
                    'Date(' + this[key] + ')' : value;
            });
            // text is '["Date(---current time---)"]'


        JSON.parse(text, reviver)
            This method parses a JSON text to produce an object or array.
            It can throw a SyntaxError exception.

            The optional reviver parameter is a function that can filter and
            transform the results. It receives each of the keys and values,
            and its return value is used instead of the original value.
            If it returns what it received, then the structure is not modified.
            If it returns undefined then the member is deleted.

            Example:

            // Parse the text. Values that look like ISO date strings will
            // be converted to Date objects.

            myData = JSON.parse(text, function (key, value) {
                var a;
                if (typeof value === 'string') {
                    a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
                    if (a) {
                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
                            +a[5], +a[6]));
                    }
                }
                return value;
            });

            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
                var d;
                if (typeof value === 'string' &&
                        value.slice(0, 5) === 'Date(' &&
                        value.slice(-1) === ')') {
                    d = new Date(value.slice(5, -1));
                    if (d) {
                        return d;
                    }
                }
                return value;
            });


    This is a reference implementation. You are free to copy, modify, or
    redistribute.

    This code should be minified before deployment.
    See http://javascript.crockford.com/jsmin.html

    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    NOT CONTROL.
*/

/*jslint evil: true */

/*global JSON */

/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/

// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

if (!this.JSON) {
    JSON = {};
}
(function () {

    function f(n) {
        // Format integers to have at least two digits.
        return n < 10 ? '0' + n : n;
    }

    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function (key) {

            return this.toUTCString();
        };

        String.prototype.toJSON =
        Number.prototype.toJSON =
        Boolean.prototype.toJSON = function (key) {
            return this.valueOf();
        };
    }

    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        gap,
        indent,
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        rep;


    function quote(string) {

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.

        escapable.lastIndex = 0;
        return escapable.test(string) ?
            '"' + string.replace(escapable, function (a) {
                var c = meta[a];
                return typeof c === 'string' ? c :
                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            }) + '"' :
            '"' + string + '"';
    }


    function str(key, holder) {

// Produce a string from holder[key].

        var i,          // The loop counter.
            k,          // The member key.
            v,          // The member value.
            length,
            mind = gap,
            partial,
            value = holder[key];

// If the value has a toJSON method, call it to obtain a replacement value.

        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }

// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.

        if (typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }

// What happens next depends on the value's type.

        switch (typeof value) {
        case 'string':
            return quote(value);

        case 'number':

// JSON numbers must be finite. Encode non-finite numbers as null.

            return isFinite(value) ? String(value) : 'null';

        case 'boolean':
        case 'null':

// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.

            return String(value);

// If the type is 'object', we might be dealing with an object or an array or
// null.

        case 'object':

// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.

            if (!value) {
                return 'null';
            }

// Make an array to hold the partial results of stringifying this object value.

            gap += indent;
            partial = [];

// Is the value an array?

            if (Object.prototype.toString.apply(value) === '[object Array]') {

// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.

                length = value.length;
                for (i = 0; i < length; i += 1) {
                    partial[i] = str(i, value) || 'null';
                }

// Join all of the elements together, separated with commas, and wrap them in
// brackets.

                v = partial.length === 0 ? '[]' :
                    gap ? '[\n' + gap +
                            partial.join(',\n' + gap) + '\n' +
                                mind + ']' :
                          '[' + partial.join(',') + ']';
                gap = mind;
                return v;
            }

// If the replacer is an array, use it to select the members to be stringified.

            if (rep && typeof rep === 'object') {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    k = rep[i];
                    if (typeof k === 'string') {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            } else {

// Otherwise, iterate through all of the keys in the object.

                for (k in value) {
                    if (Object.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            }

// Join all of the member texts together, separated with commas,
// and wrap them in braces.

            v = partial.length === 0 ? '{}' :
                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
                        mind + '}' : '{' + partial.join(',') + '}';
            gap = mind;
            return v;
        }
    }

// If the JSON object does not yet have a stringify method, give it one.

    if (typeof JSON.stringify !== 'function') {
        JSON.stringify = function (value, replacer, space) {

// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.

            var i;
            gap = '';
            indent = '';

// If the space parameter is a number, make an indent string containing that
// many spaces.

            if (typeof space === 'number') {
                for (i = 0; i < space; i += 1) {
                    indent += ' ';
                }

// If the space parameter is a string, it will be used as the indent string.

            } else if (typeof space === 'string') {
                indent = space;
            }

// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.

            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                     typeof replacer.length !== 'number')) {
                throw new Error('JSON.stringify');
            }

// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.

            return str('', {'': value});
        };
    }


// If the JSON object does not yet have a parse method, give it one.

    if (typeof JSON.parse !== 'function') {
        JSON.parse = function (text, reviver) {

// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.

            var j;

            function walk(holder, key) {

// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.

                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }


// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.

            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' +
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.

// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

            if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

                j = eval('(' + text + ')');

// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.

                return typeof reviver === 'function' ?
                    walk({'': j}, '') : j;
            }

// If the text is not JSON parseable, then a SyntaxError is thrown.

            throw new SyntaxError('JSON.parse');
        };
    }
})();


// Crunch Insert -  Fri Nov 6 16:54:45 EST 2009

//
// Copyright (c) 2008, 2009 Paul Duncan (paul@pablotron.org)
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

/**
 * Persist - top-level namespace for Persist library.
 * @namespace
 */
Persist = (function() {
  var VERSION = '0.2.0', P, B, esc, init, empty, ec;

  // wrapper for Array.prototype.indexOf, since IE doesn't have it
  var index_of = (function() {
    if (Array.prototype.indexOf)
      return function(ary, val) { 
        return Array.prototype.indexOf.call(ary, val);
      };
    else
      return function(ary, val) {
        var i, l;

        for (i = 0, l = ary.length; i < l; i++)
          if (ary[i] == val)
            return i;

        return -1;
      };
  })();


  // empty function
  empty = function() { };

  /**
   * Escape spaces and underscores in name.  Used to generate a "safe"
   * key from a name.
   *
   * @private
   */
  esc = function(str) {
    return 'PS' + str.replace(/_/g, '__').replace(/ /g, '_s');
  };

  C = {
    /* 
     * Backend search order.
     * 
     * Note that the search order is significant; the backends are
     * listed in order of capacity, and many browsers
     * support multiple backends, so changing the search order could
     * result in a browser choosing a less capable backend.
     */ 
    search_order: [
      // TODO: air
      'localstorage',
      'whatwg_db', 
      'globalstorage', 
      'ie', 
      'flash'
    ],

    // valid name regular expression
    name_re: /^[a-z][a-z0-9_ -]+$/i,

    // list of backend methods
    methods: [
      'init', 
      'get', 
      'set', 
      'remove', 
      'load', 
      'save'
      // TODO: clear method?
    ],

    // sql for db backends (gears and db)
    sql: {
      version:  '1', // db schema version

      // XXX: the "IF NOT EXISTS" is a sqlite-ism; fortunately all the 
      // known DB implementations (safari and gears) use sqlite
      create:   "CREATE TABLE IF NOT EXISTS persist_data (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)",
      get:      "SELECT v FROM persist_data WHERE k = ?",
      set:      "INSERT INTO persist_data(k, v) VALUES (?, ?)",
      remove:   "DELETE FROM persist_data WHERE k = ?" 
    },

    // default flash configuration
    flash: {
      // ID of wrapper element
      div_id:   '_persist_flash_wrap',

      // id of flash object/embed
      id:       '_persist_flash',

      // default path to flash object
      path: 'persist.swf',
      size: { w:1, h:1 },

      // arguments passed to flash object
      args: {
        autostart: true
      }
    } 
  };

  // built-in backends
  B = {
    // whatwg db backend (webkit, Safari 3.1+)
    // (src: whatwg and http://webkit.org/misc/DatabaseExample.html)
    whatwg_db: {
      // size based on DatabaseExample from above (should I increase
      // this?)
      size:   200 * 1024,

      test: function() {
        var name = 'PersistJS Test', 
            desc = 'Persistent database test.';

        // test for openDatabase
        if (!window.openDatabase)
          return false;

        // make sure openDatabase works
        // XXX: will this leak a db handle and/or waste space?
        if (!window.openDatabase(name, C.sql.version, desc, B.whatwg_db.size))
          return false;

        // return true
        return true;
      },

      methods: {
        transaction: function(fn) {
          // lazy create database table;
          // this is done here because there is no way to
          // prevent a race condition if the table is created in init()
          if (!this.db_created) {
            this.db.transaction(function(t) {
              // create table
              t.executeSql(C.sql.create, [], function() {
                this.db_created = true;
              });
            }, empty); // trap exception
          } 

          // execute transaction
          this.db.transaction(fn);
        },

        init: function() {
          // create database handle
          this.db = openDatabase(
            this.name, 
            C.sql.version, 
            this.o.about || ("Persistent storage for " + this.name),
            this.o.size || B.whatwg_db.size 
          );
        },

        get: function(key, fn, scope) {
          var sql = C.sql.get;

          // if callback isn't defined, then return
          if (!fn)
            return;

          // get callback scope
          scope = scope || this;

          // begin transaction
          this.transaction(function (t) {
            t.executeSql(sql, [key], function(t, r) {
              if (r.rows.length > 0)
                fn.call(scope, true, r.rows.item(0)['v']);
              else
                fn.call(scope, false, null);
            });
          });
        },

        set: function(key, val, fn, scope) {
          var rm_sql = C.sql.remove,
              sql    = C.sql.set;

          // begin set transaction
          this.transaction(function(t) {
            // exec remove query
            t.executeSql(rm_sql, [key], function() {
              // exec set query
              t.executeSql(sql, [key, val], function(t, r) {
                // run callback
                if (fn)
                  fn.call(scope || this, true, val);
              });
            });
          });

          return val;
        },

        // begin remove transaction
        remove: function(key, fn, scope) {
          var get_sql = C.sql.get;
              sql = C.sql.remove;

          this.transaction(function(t) {
            // if a callback was defined, then get the old
            // value before removing it
            if (fn) {
              // exec get query
              t.executeSql(get_sql, [key], function(t, r) {
                if (r.rows.length > 0) {
                  // key exists, get value 
                  var val = r.rows.item(0)['v'];

                  // exec remove query
                  t.executeSql(sql, [key], function(t, r) {
                    // exec callback
                    fn.call(scope || this, true, val);
                  });
                } else {
                  // key does not exist, exec callback
                  fn.call(scope || this, false, null);
                }
              });
            } else {
              // no callback was defined, so just remove the
              // data without checking the old value

              // exec remove query
              t.executeSql(sql, [key]);
            }
          });
        } 
      }
    }, 
    
    // globalstorage backend (globalStorage, FF2+, IE8+)
    // (src: http://developer.mozilla.org/en/docs/DOM:Storage#globalStorage)
    // https://developer.mozilla.org/En/DOM/Storage
    //
    // TODO: test to see if IE8 uses object literal semantics or
    // getItem/setItem/removeItem semantics
    globalstorage: {
      // (5 meg limit, src: http://ejohn.org/blog/dom-storage-answers/)
      size: 5 * 1024 * 1024,

      test: function() {
        return window.globalStorage ? true : false;
      },

      methods: {
        key: function(key) {
          return esc(this.name) + esc(key);
        },

        init: function() {
          //alert('domain = ' + this.o.domain);
          this.store = globalStorage[this.o.domain];
        },

        get: function(key, fn, scope) {
          // expand key
          key = this.key(key);

          if (fn)
            fn.call(scope || this, true, this.store.getItem(key));
        },

        set: function(key, val, fn, scope) {
          // expand key
          key = this.key(key);

          // set value
          this.store.setItem(key, val);

          if (fn)
            fn.call(scope || this, true, val);
        },

        remove: function(key, fn, scope) {
          var val;

          // expand key
          key = this.key(key);

          // get value
          val = this.store[key];

          // delete value
          this.store.removeItem(key);

          if (fn)
            fn.call(scope || this, (val !== null), val);
        } 
      }
    }, 
    
    // localstorage backend (globalStorage, FF2+, IE8+)
    // (src: http://www.whatwg.org/specs/web-apps/current-work/#the-localstorage)
    // also http://msdn.microsoft.com/en-us/library/cc197062(VS.85).aspx#_global
    localstorage: {
      // (unknown?)
      // ie has the remainingSpace property, see:
      // http://msdn.microsoft.com/en-us/library/cc197016(VS.85).aspx
      size: -1,

      test: function() {
        return window.localStorage ? true : false;
      },

      methods: {
        key: function(key) {
          return esc(this.name) + esc(key);
        },

        init: function() {
          this.store = localStorage;
        },

        get: function(key, fn, scope) {
          // expand key
          key = this.key(key);

          if (fn)
            fn.call(scope || this, true, this.store.getItem(key));
        },

        set: function(key, val, fn, scope) {
          // expand key
          key = this.key(key);

          // set value
          this.store.setItem(key, val);

          if (fn)
            fn.call(scope || this, true, val);
        },

        remove: function(key, fn, scope) {
          var val;

          // expand key
          key = this.key(key);

          // get value
          val = this.getItem(key);

          // delete value
          this.store.removeItem(key);

          if (fn)
            fn.call(scope || this, (val !== null), val);
        } 
      }
    }, 
    
    // IE backend
    ie: {
      prefix:   '_persist_data-',
      // style:    'display:none; behavior:url(#default#userdata);',

      // 64k limit
      size:     64 * 1024,

      test: function() {
        // make sure we're dealing with IE
        // (src: http://javariet.dk/shared/browser_dom.htm)
        return window.ActiveXObject ? true : false;
      },

      make_userdata: function(id) {
        var el = document.createElement('div');

        // set element properties
        // http://msdn.microsoft.com/en-us/library/ms531424(VS.85).aspx 
        // http://www.webreference.com/js/column24/userdata.html
        el.id = id;
        el.style.display = 'none';
        el.addBehavior('#default#userdata');

        // append element to body
        document.body.appendChild(el);

        // return element
        return el;
      },

      methods: {
        init: function() {
          var id = B.ie.prefix + esc(this.name);

          // save element
          this.el = B.ie.make_userdata(id);

          // load data
          if (this.o.defer)
            this.load();
        },

        get: function(key, fn, scope) {
          var val;

          // expand key
          key = esc(key);

          // load data
          if (!this.o.defer)
            this.load();

          // get value
          val = this.el.getAttribute(key);

          // call fn
          if (fn)
            fn.call(scope || this, val ? true : false, val);
        },

        set: function(key, val, fn, scope) {
          // expand key
          key = esc(key);
          
          // set attribute
          this.el.setAttribute(key, val);

          // save data
          if (!this.o.defer)
            this.save();

          // call fn
          if (fn)
            fn.call(scope || this, true, val);
        },

        remove: function(key, fn, scope) {
          var val;

          // expand key
          key = esc(key);

          // load data
          if (!this.o.defer)
            this.load();

          // get old value and remove attribute
          val = this.el.getAttribute(key);
          this.el.removeAttribute(key);

          // save data
          if (!this.o.defer)
            this.save();

          // call fn
          if (fn)
            fn.call(scope || this, val ? true : false, val);
        },

        load: function() {
          this.el.load(esc(this.name));
        },

        save: function() {
          this.el.save(esc(this.name));
        }
      }
    },
    
    // flash backend (requires flash 8 or newer)
    // http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_16194&sliceId=1
    // http://livedocs.adobe.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002200.html
    flash: {
      test: function() {
        // TODO: better flash detection
        if (!deconcept || !deconcept.SWFObjectUtil)
          return false;

        // get the major version
        var major = deconcept.SWFObjectUtil.getPlayerVersion().major;

        // check flash version (require 8.0 or newer)
        return (major >= 8) ? true : false;
      },

      methods: {
        init: function() {
          if (!B.flash.el) {
            var o, key, el, cfg = C.flash;

            // create wrapper element
            el = document.createElement('div');
            el.id = cfg.div_id;

            // FIXME: hide flash element
            // el.style.display = 'none';

            // append element to body
            document.body.appendChild(el);

            // create new swf object
            o = new deconcept.SWFObject(this.o.swf_path || cfg.path, cfg.id, cfg.size.w, cfg.size.h, '8');

            // set parameters
            for (key in cfg.args)
              o.addVariable(key, cfg.args[key]);

            // write flash object
            o.write(el);

            // save flash element
            B.flash.el = document.getElementById(cfg.id);
          }

          // use singleton flash element
          this.el = B.flash.el;
        },

        get: function(key, fn, scope) {
          var val;

          // escape key
          key = esc(key);

          // get value
          val = this.el.get(this.name, key);

          // call handler
          if (fn)
            fn.call(scope || this, val !== null, val);
        },

        set: function(key, val, fn, scope) {
          var old_val;

          // escape key
          key = esc(key);

          // set value
          old_val = this.el.set(this.name, key, val);

          // call handler
          if (fn)
            fn.call(scope || this, true, val);
        },

        remove: function(key, fn, scope) {
          var val;

          // get key
          key = esc(key);

          // remove old value
          val = this.el.remove(this.name, key);

          // call handler
          if (fn)
            fn.call(scope || this, true, val);
        }
      }
    }
  };

  /**
   * Test for available backends and pick the best one.
   * @private
   */
  var init = function() {
    var i, l, b, key, fns = C.methods, keys = C.search_order;

    // set all functions to the empty function
    for (i = 0, l = fns.length; i < l; i++) 
      P.Store.prototype[fns[i]] = empty;

    // clear type and size
    P.type = null;
    P.size = -1;

    // loop over all backends and test for each one
    for (i = 0, l = keys.length; !P.type && i < l; i++) {
      b = B[keys[i]];
      
      try {
          // test for backend
          if (b.test()) {
            // found backend, save type and size
            P.type = keys[i];
            P.size = b.size;

            // extend store prototype with backend methods
            for (key in b.methods)
              P.Store.prototype[key] = b.methods[key];
          }
        } catch (e) {
            //Protect us from any exceptions while testing
        }
    }

    // mark library as initialized
    P._init = true;
  };

  // create top-level namespace
  P = {
    // version of persist library
    VERSION: VERSION,

    // backend type and size limit
    type: null,
    size: 0,

    // XXX: expose init function?
    // init: init,

    add: function(o) {
      // add to backend hash
      B[o.id] = o;

      // add backend to front of search order
      C.search_order = [o.id].concat(C.search_order);

      // re-initialize library
      init();
    },

    remove: function(id) {
      var ofs = index_of(C.search_order, id);
      if (ofs < 0)
        return;

      // remove from search order
      C.search_order.splice(ofs, 1);

      // delete from lut
      delete B[id];

      // re-initialize library
      init();
    },

    // store API
    Store: function(name, o) {
      // verify name
      if (!C.name_re.exec(name))
        throw new Error("Invalid name");

      // XXX: should we lazy-load type?
      // if (!P._init)
      //   init();

      if (!P.type)
        throw new Error("No suitable storage found");

      o = o || {};
      this.name = name;

      // get domain (XXX: does this localdomain fix work?)
      o.domain = o.domain || location.host || 'localhost';
      
      // strip port from domain (XXX: will this break ipv6?)
      o.domain = o.domain.replace(/:\d+$/, '')

      // append localdomain to domains w/o '."
      // (see https://bugzilla.mozilla.org/show_bug.cgi?id=357323)
      // (file://localhost/ works, see: 
      // https://bugzilla.mozilla.org/show_bug.cgi?id=469192)
/* 
 *       if (!o.domain.match(/\./))
 *         o.domain += '.localdomain';
 */ 

      this.o = o;

      // expires in 2 years
      o.expires = o.expires || 365 * 2;

      // set path to root
      o.path = o.path || '/';

      // call init function
      this.init();
    } 
  };

  // init persist
  init();

  // return top-level namespace
  return P;
})();


// Crunch Insert -  Fri Nov 6 16:54:45 EST 2009

/* HACK: Below Code for nav hover used in IE6 only. IE5.5 and under users are screwed possibly */
if(jQuery.browser.msie && parseInt(jQuery.browser.version) == 6) {
  jQuery(function() { 
    jQuery("#navBar li.navItem")
        .hover(function(event) { jQuery(this).addClass('sfhover');}, 
          function(event) { jQuery(this).removeClass('sfhover');}
        )
  });
}
/* HACK: Above Code for nav hover used in IE6 only. IE5.5 and under users are screwed possibly */

// Crunch Insert -  Fri Nov 6 16:54:45 EST 2009

/*
 * jQuery validation plug-in v1.2.1
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
 * http://docs.jquery.com/Plugins/Validation
 *
 * Copyright (c) 2006 - 2008 Jörn Zaefferer
 *
 * $Id: jquery.validate.js 4708 2008-02-10 16:04:08Z joern.zaefferer $
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

jQuery.extend(jQuery.fn, {
	// http://docs.jquery.com/Plugins/Validation/validate
	validate: function( options ) {
		
		// if nothing is selected, return nothing; can't chain anyway
		if (!this.length) {
			options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
			return;
		}
		
		// check if a validator for this form was already created
		var validator = jQuery.data(this[0], 'validator');
		if ( validator ) {
			return validator;
		}
		
		validator = new jQuery.validator( options, this[0] );
		jQuery.data(this[0], 'validator', validator); 
		
		if ( validator.settings.onsubmit ) {
		
			// allow suppresing validation by adding a cancel class to the submit button
			this.find("input.cancel:submit").click(function() {
				validator.cancelSubmit = true;
			});
		
			// validate the form on submit
			this.submit( function( event ) {
				if ( validator.settings.debug )
					// prevent form submit to be able to see console output
					event.preventDefault();
					
				function handle() {
					if ( validator.settings.submitHandler ) {
						validator.settings.submitHandler.call( validator, validator.currentForm );
						return false;
					}
					return true;
				}
					
				// prevent submit for invalid forms or custom submit handlers
				if ( validator.cancelSubmit ) {
					validator.cancelSubmit = false;
					return handle();
				}
				if ( validator.form() ) {
					if ( validator.pendingRequest ) {
						validator.formSubmitted = true;
						return false;
					}
					return handle();
				} else {
					validator.focusInvalid();
					return false;
				}
			});
		}
		
		return validator;
	},
	// http://docs.jquery.com/Plugins/Validation/valid
	valid: function() {
        if ( jQuery(this[0]).is('form')) {
            return this.validate().form();
        } else {
            var valid = true;
            var validator = jQuery(this[0].form).validate();
            this.each(function() {
                valid = validator.element(this) && valid;
            });
            return valid;
        }
    },
	// http://docs.jquery.com/Plugins/Validation/rules
	rules: function() {
		var element = this[0];
		var data = jQuery.validator.normalizeRules(
		jQuery.extend(
			{},
			jQuery.validator.metadataRules(element),
			jQuery.validator.classRules(element),
			jQuery.validator.attributeRules(element),
			jQuery.validator.staticRules(element)
		), element);
	
		// convert from object to array
		var rules = [];
		// make sure required is at front
		if (data.required) {
			rules.push({method:'required', parameters: data.required});
			delete data.required;
		}
		jQuery.each(data, function(method, value) {
			rules.push({
				method: method,
				parameters: value
			});
		});
		return rules;
	},
	// destructive add
	push: function( t ) {
		return this.setArray( this.add(t).get() );
	}
});

// Custom selectors
jQuery.extend(jQuery.expr[":"], {
	// http://docs.jquery.com/Plugins/Validation/blank
	blank: "!jQuery.trim(a.value)",
	// http://docs.jquery.com/Plugins/Validation/filled
	filled: "!!jQuery.trim(a.value)",
	// http://docs.jquery.com/Plugins/Validation/unchecked
	unchecked: "!a.checked"
});

jQuery.format = function(source, params) {
	if ( arguments.length == 1 ) 
		return function() {
			var args = jQuery.makeArray(arguments);
			args.unshift(source);
			return jQuery.format.apply( this, args );
		};
	if ( arguments.length > 2 && params.constructor != Array  ) {
		params = jQuery.makeArray(arguments).slice(1);
	}
	if ( params.constructor != Array ) {
		params = [ params ];
	}
	jQuery.each(params, function(i, n) {
		source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
	});
	return source;
};

// constructor for validator
jQuery.validator = function( options, form ) {
	this.settings = jQuery.extend( {}, jQuery.validator.defaults, options );
	this.currentForm = form;
	this.init();
};

jQuery.extend(jQuery.validator, {

	defaults: {
		messages: {},
		errorClass: "error",
		errorElement: "label",
		focusInvalid: true,
		errorContainer: jQuery( [] ),
		errorLabelContainer: jQuery( [] ),
		onsubmit: true,
		ignore: [],
		onfocusin: function(element) {
			this.lastActive = element;
				
			// hide error label and remove error class on focus if enabled
			if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
				this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass );
				this.errorsFor(element).hide();
			}
		},
		onfocusout: function(element) {
			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
				this.element(element);
			}
		},
		onkeyup: function(element) {
			if ( element.name in this.submitted || element == this.lastElement ) {
				this.element(element);
			}
		},
		onclick: function(element) {
			if ( element.name in this.submitted )
				this.element(element);
		},
		highlight: function( element, errorClass ) {
			jQuery( element ).addClass( errorClass );
		},
		unhighlight: function( element, errorClass ) {
			jQuery( element ).removeClass( errorClass );
		}
	},

	// http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
	setDefaults: function(settings) {
		jQuery.extend( jQuery.validator.defaults, settings );
	},

	messages: {
		required: "This field is required.",
		remote: "Please fix this field.",
		email: "Please enter a valid email address.",
		url: "Please enter a valid URL.",
		date: "Please enter a valid date.",
		dateISO: "Please enter a valid date (ISO).",
		dateDE: "Bitte geben Sie ein gültiges Datum ein.",
		number: "Please enter a valid number.",
		numberDE: "Bitte geben Sie eine Nummer ein.",
		digits: "Please enter only digits",
		creditcard: "Please enter a valid credit card.",
		equalTo: "Please enter the same value again.",
		accept: "Please enter a value with a valid extension.",
		maxlength: jQuery.format("Please enter no more than {0} characters."),
		maxLength: jQuery.format("Please enter no more than {0} characters."),
		minlength: jQuery.format("Please enter at least {0} characters."),
		minLength: jQuery.format("Please enter at least {0} characters."),
		rangelength: jQuery.format("Please enter a value between {0} and {1} characters long."),
		rangeLength: jQuery.format("Please enter a value between {0} and {1} characters long."),
		rangeValue: jQuery.format("Please enter a value between {0} and {1}."),
		range: jQuery.format("Please enter a value between {0} and {1}."),
		maxValue: jQuery.format("Please enter a value less than or equal to {0}."),
		max: jQuery.format("Please enter a value less than or equal to {0}."),
		minValue: jQuery.format("Please enter a value greater than or equal to {0}."),
		min: jQuery.format("Please enter a value greater than or equal to {0}.")
	},
	
	autoCreateRanges: false,
	
	prototype: {
		
		init: function() {
			this.labelContainer = jQuery(this.settings.errorLabelContainer);
			this.errorContext = this.labelContainer.length && this.labelContainer || jQuery(this.currentForm);
			this.containers = jQuery(this.settings.errorContainer).add( this.settings.errorLabelContainer );
			this.submitted = {};
			this.valueCache = {};
			this.pendingRequest = 0;
			this.pending = {};
			this.invalid = {};
			this.reset();
			
			function delegate(event) {
				var validator = jQuery.data(this[0].form, "validator");
				validator.settings["on" + event.type] && validator.settings["on" + event.type].call(validator, this[0] );
			}
			jQuery(this.currentForm)
				.delegate("focusin focusout keyup", ":text, :password, :file, select, textarea", delegate)
				.delegate("click", ":radio, :checkbox", delegate);
		},

		// http://docs.jquery.com/Plugins/Validation/Validator/form
		form: function() {
			this.prepareForm();
			var elements = this.elements();
			for ( var i = 0; elements[i]; i++ ) {
				this.check( elements[i] );
			}
			jQuery.extend(this.submitted, this.errorMap);
			this.invalid = jQuery.extend({}, this.errorMap);
			jQuery(this.currentForm).triggerHandler("invalid-form.validate", [this]);
			this.showErrors();
			return this.valid();
		},
		
		// http://docs.jquery.com/Plugins/Validation/Validator/element
		element: function( element ) {
			element = this.clean( element );
			this.lastElement = element;
			this.prepareElement( element );
			var result = this.check( element );
			if ( result ) {
				delete this.invalid[element.name];
			} else {
				this.invalid[element.name] = true;
			}
			if ( !this.numberOfInvalids() ) {
				// Hide error containers on last error
				this.toHide.push( this.containers );
			}
			this.showErrors();
			return result;
		},

		// http://docs.jquery.com/Plugins/Validation/Validator/showErrors
		showErrors: function(errors) {
			if(errors) {
				// add items to error list and map
				jQuery.extend( this.errorMap, errors );
				this.errorList = [];
				for ( var name in errors ) {
					this.errorList.push({
						message: errors[name],
						element: this.findByName(name)[0]
					});
				}
				// remove items from success list
				this.successList = jQuery.grep( this.successList, function(element) {
					return !(element.name in errors);
				});
			}
			this.settings.showErrors
				? this.settings.showErrors.call( this, this.errorMap, this.errorList )
				: this.defaultShowErrors();
		},
		
		// http://docs.jquery.com/Plugins/Validation/Validator/resetForm
		resetForm: function() {
			if ( jQuery.fn.resetForm )
				jQuery( this.currentForm ).resetForm();
			this.prepareForm();
			this.hideErrors();
			this.elements().removeClass( this.settings.errorClass );
		},
		
		numberOfInvalids: function() {
			var count = 0;
			for ( var i in this.invalid )
				count++;
			return count;
		},
		
		hideErrors: function() {
			this.addWrapper( this.toHide ).hide();
		},
		
		valid: function() {
			return this.size() == 0;
		},
		
		size: function() {
			return this.errorList.length;
		},
		
		focusInvalid: function() {
			if( this.settings.focusInvalid ) {
				try {
					jQuery(this.findLastActive() || this.errorList.length && this.errorList[0].element || []).filter(":visible").focus();
				} catch(e) { /* ignore IE throwing errors when focusing hidden elements */ }
			}
		},
		
		findLastActive: function() {
			var lastActive = this.lastActive;
			return lastActive && jQuery.grep(this.errorList, function(n) {
				return n.element.name == lastActive.name;
			}).length == 1 && lastActive;
		},
		
		elements: function() {
			var validator = this;
			
			
			var rulesCache = {};
			
			// select all valid inputs inside the form (no submit or reset buttons)
			// workaround with jQuery([]).add until http://dev.jquery.com/ticket/2114 is solved
			return jQuery([]).add(this.currentForm.elements)
			.filter("input, select, textarea")
			.not(":submit, :reset, [disabled]")
			.not( this.settings.ignore )
			.filter(function() {
				!this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
			
				// select only the first element for each name, and only those with rules specified
				if ( this.name in rulesCache || !jQuery(this).rules().length )
					return false;
				
				rulesCache[this.name] = true;
				return true;
			});
		},
		
		clean: function( selector ) {
			return jQuery( selector )[0];
		},
		
		errors: function() {
			return jQuery( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
		},
		
		reset: function() {
			this.successList = [];
			this.errorList = [];
			this.errorMap = {};
			this.toShow = jQuery( [] );
			this.toHide = jQuery( [] );
			this.formSubmitted = false;
		},
		
		prepareForm: function() {
			this.reset();
			this.toHide = this.errors().push( this.containers );
		},
		
		prepareElement: function( element ) {
			this.reset();
			this.toHide = this.errorsFor( this.clean(element) );
		},
	
		check: function( element ) {
			element = this.clean( element );
			this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass );
			var rules = jQuery(element).rules();
			for( var i = 0; rules[i]; i++) {
				var rule = rules[i];
				try {
					var result = jQuery.validator.methods[rule.method].call( this, jQuery.trim(element.value), element, rule.parameters );
					if ( result == "dependency-mismatch" )
						return;
					if ( result == "pending" ) {
						this.toHide = this.toHide.not( this.errorsFor(element) );
						return;
					}
					if( !result ) {
						this.formatAndAdd( element, rule );
						return false;
					}
				} catch(e) {
					this.settings.debug && window.console && console.warn("exception occured when checking element " + element.id
						 + ", check the '" + rule.method + "' method");
					throw e;
				}
			}
			if ( rules.length )
				this.successList.push(element);
			return true;
		},
		
		// return the custom message for the given element name and validation method
		customMessage: function( name, method ) {
			var m = this.settings.messages[name];
			return m && (m.constructor == String
				? m
				: m[method]);
		},
		
		// return the first defined argument, allowing empty strings
		findDefined: function() {
			for(var i = 0; i < arguments.length; i++) {
				if (arguments[i] !== undefined)
					return arguments[i];
			}
			return undefined;
		},
		
		defaultMessage: function( element, method) {
			return this.findDefined(
				this.customMessage( element.name, method ),
				// title is never undefined, so handle empty string as undefined
				element.title || undefined,
				jQuery.validator.messages[method],
				"<strong>Warning: No message defined for " + element.name + "</strong>"
			);
		},
		
		formatAndAdd: function( element, rule ) {
			var message = this.defaultMessage( element, rule.method );
			if ( typeof message == "function" ) 
				message = message.call(this, rule.parameters, element);
			this.errorList.push({
				message: message,
				element: element
			});
			this.errorMap[element.name] = message;
			this.submitted[element.name] = message;
		},
		
		addWrapper: function(toToggle) {
			if ( this.settings.wrapper )
				toToggle.push( toToggle.parents( this.settings.wrapper ) );
			return toToggle;
		},
		
		defaultShowErrors: function() {
			for ( var i = 0; this.errorList[i]; i++ ) {
				var error = this.errorList[i];
				this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass );
				this.showLabel( error.element, error.message );
			}
			if( this.errorList.length ) {
				this.toShow.push( this.containers );
			}
			if (this.settings.success) {
				for ( var i = 0; this.successList[i]; i++ ) {
					this.showLabel( this.successList[i] );
				}
			}
			this.toHide = this.toHide.not( this.toShow );
			this.hideErrors();
			this.addWrapper( this.toShow ).show();
		},
		
		showLabel: function(element, message) {
			var label = this.errorsFor( element );
			if ( label.length ) {
				// refresh error/success class
				label.removeClass().addClass( this.settings.errorClass );
			
				// check if we have a generated label, replace the message then
				label.attr("generated") && label.html(message);
			} else {
				// create label
				label = jQuery("<" + this.settings.errorElement + "/>")
					.attr({"for":  this.idOrName(element), generated: true})
					.addClass(this.settings.errorClass)
					.html(message || "");
				if ( this.settings.wrapper ) {
					// make sure the element is visible, even in IE
					// actually showing the wrapped element is handled elsewhere
					label = label.hide().show().wrap("<" + this.settings.wrapper + ">").parent();
				}
				if ( !this.labelContainer.append(label).length )
					this.settings.errorPlacement
						? this.settings.errorPlacement(label, jQuery(element) )
						: label.insertAfter(element);
			}
			if ( !message && this.settings.success ) {
				label.text("");
				typeof this.settings.success == "string"
					? label.addClass( this.settings.success )
					: this.settings.success( label );
			}
			this.toShow.push(label);
		},
		
		errorsFor: function(element) {
			return this.errors().filter("[@for='" + this.idOrName(element) + "']");
		},
		
		idOrName: function(element) {
			return this.checkable(element) ? element.name : element.id || element.name;
		},

		rules: function( element ) {
			return jQuery(element).rules();
		},

		checkable: function( element ) {
			return /radio|checkbox/i.test(element.type);
		},
		
		findByName: function( name ) {
			// select by name and filter by form for performance over form.find("[name=...]")
			var form = this.currentForm;
			return jQuery(document.getElementsByName(name)).map(function(index, element) {
				return element.form == form && element || null;
				//  && element.name == name
			});
		},
		
		getLength: function(value, element) {
			switch( element.nodeName.toLowerCase() ) {
			case 'select':
				return jQuery("option:selected", element).length;
			case 'input':
				if( this.checkable( element) )
					return this.findByName(element.name).filter(':checked').length;
			}
			return value.length;
		},
	
		depend: function(param, element) {
			return this.dependTypes[typeof param]
				? this.dependTypes[typeof param](param, element)
				: true;
		},
	
		dependTypes: {
			"boolean": function(param, element) {
				return param;
			},
			"string": function(param, element) {
				return !!jQuery(param, element.form).length;
			},
			"function": function(param, element) {
				return param(element);
			}
		},
		
		optional: function(element) {
			return !jQuery.validator.methods.required.call(this, jQuery.trim(element.value), element) && "dependency-mismatch";
		},
		
		startRequest: function(element) {
			if (!this.pending[element.name]) {
				this.pendingRequest++;
				this.pending[element.name] = true;
			}
		},
		
		stopRequest: function(element, valid) {
			this.pendingRequest--;
			// sometimes synchronization fails, make pendingRequest is never < 0
			if (this.pendingRequest < 0)
				this.pendingRequest = 0;
			delete this.pending[element.name];
			if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
				jQuery(this.currentForm).submit();
			}
		},
		
		previousValue: function(element) {
			return jQuery.data(element, "previousValue") || jQuery.data(element, "previousValue", previous = {
				old: null,
				valid: true,
				message: this.defaultMessage( element, "remote" )
			});
		}
		
	},
	
	classRuleSettings: {
		required: {required: true},
		email: {email: true},
		url: {url: true},
		date: {date: true},
		dateISO: {dateISO: true},
		dateDE: {dateDE: true},
		number: {number: true},
		numberDE: {numberDE: true},
		digits: {digits: true},
		creditcard: {creditcard: true}
	},
	
	addClassRules: function(className, rules) {
		className.constructor == String ?
			this.classRuleSettings[className] = rules :
			jQuery.extend(this.classRuleSettings, className);
	},
	
	classRules: function(element) {
		var rules = {};
		var classes = jQuery(element).attr('class');
		classes && jQuery.each(classes.split(' '), function() {
			if (this in jQuery.validator.classRuleSettings) {
				jQuery.extend(rules, jQuery.validator.classRuleSettings[this]);
			}
		});
		return rules;
	},
	
	attributeRules: function(element) {
		var rules = {};
		var $element = jQuery(element);
		
		for (method in jQuery.validator.methods) {
			var value = $element.attr(method);
			// allow 0 but neither undefined nor empty string
			if (value !== undefined && value !== '') {
				rules[method] = value;
			}
		}
		
		// maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
		if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
			delete rules.maxlength;
			// deprecated
			delete rules.maxLength;
		}
		
		return rules;
	},
	
	metadataRules: function(element) {
		if (!jQuery.metadata) return {};
		
		var meta = jQuery.data(element.form, 'validator').settings.meta;
		return meta ?
			jQuery(element).metadata()[meta] :
			jQuery(element).metadata();
	},
	
	staticRules: function(element) {
		var rules = {};
		var validator = jQuery.data(element.form, 'validator');
		if (validator.settings.rules) {
			rules = jQuery.validator.normalizeRule(validator.settings.rules[element.name]) || {};
		}
		return rules;
	},
	
	normalizeRules: function(rules, element) {
		// convert deprecated rules
		jQuery.each({
			minLength: 'minlength',
			maxLength: 'maxlength',
			rangeLength: 'rangelength',
			minValue: 'min',
			maxValue: 'max',
			rangeValue: 'range'
		}, function(dep, curr) {
			if (rules[dep]) {
				rules[curr] = rules[dep];
				delete rules[dep];
			}
		});
		
		// evaluate parameters
		jQuery.each(rules, function(rule, parameter) {
			rules[rule] = jQuery.isFunction(parameter) ? parameter(element) : parameter;
		});
		
		// clean number parameters
		jQuery.each(['minlength', 'maxlength', 'min', 'max'], function() {
			if (rules[this]) {
				rules[this] = Number(rules[this]);
			}
		});
		jQuery.each(['rangelength', 'range'], function() {
			if (rules[this]) {
				rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
			}
		});
		
		if (jQuery.validator.autoCreateRanges) {
			// auto-create ranges
			if (rules.min && rules.max) {
				rules.range = [rules.min, rules.max];
				delete rules.min;
				delete rules.max;
			}
			if (rules.minlength && rules.maxlength) {
				rules.rangelength = [rules.minlength, rules.maxlength];
				delete rules.minlength;
				delete rules.maxlength;
			}
		}
		
		return rules;
	},
	
	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
	normalizeRule: function(data) {
		if( typeof data == "string" ) {
			var transformed = {};
			transformed[data] = true;
			data = transformed;
		}
		return data;
	},
	
	// http://docs.jquery.com/Plugins/Validation/Validator/addMethod
	addMethod: function(name, method, message) {
		jQuery.validator.methods[name] = method;
		jQuery.validator.messages[name] = message;
		if (method.length < 3) {
			jQuery.validator.addClassRules(name, jQuery.validator.normalizeRule(name));
		}
	},

	methods: {

		// http://docs.jquery.com/Plugins/Validation/Methods/required
		required: function(value, element, param) {
			// check if dependency is met
			if ( !this.depend(param, element) )
				return "dependency-mismatch";
			switch( element.nodeName.toLowerCase() ) {
			case 'select':
				var options = jQuery("option:selected", element);
				return options.length > 0 && ( element.type == "select-multiple" || (jQuery.browser.msie && !(options[0].attributes['value'].specified) ? options[0].text : options[0].value).length > 0);
			case 'input':
				if ( this.checkable(element) )
					return this.getLength(value, element) > 0;
			default:
				return value.length > 0;
			}
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/remote
		remote: function(value, element, param) {
			if ( this.optional(element) )
				return "dependency-mismatch";
			
			var previous = this.previousValue(element);
			
			if (!this.settings.messages[element.name] )
				this.settings.messages[element.name] = {};
			this.settings.messages[element.name].remote = typeof previous.message == "function" ? previous.message(value) : previous.message;
			
			if ( previous.old !== value ) {
				previous.old = value;
				var validator = this;
				this.startRequest(element);
				var data = {};
				data[element.name] = value;
				jQuery.ajax({
					url: param,
					mode: "abort",
					port: "validate" + element.name,
					dataType: "json",
					data: data,
					success: function(response) {
						if ( !response ) {
							var errors = {};
							errors[element.name] =  response || validator.defaultMessage( element, "remote" );
							validator.showErrors(errors);
						} else {
							var submitted = validator.formSubmitted;
							validator.prepareElement(element);
							validator.formSubmitted = submitted;
							validator.successList.push(element);
							validator.showErrors();
						}
						previous.valid = response;
						validator.stopRequest(element, response);
					}
				});
				return "pending";
			} else if( this.pending[element.name] ) {
				return "pending";
			}
			return previous.valid;
		},

		// http://docs.jquery.com/Plugins/Validation/Methods/minlength
		minlength: function(value, element, param) {
			return this.optional(element) || this.getLength(value, element) >= param;
		},
		
		// deprecated, to be removed in 1.3
		minLength: function(value, element, param) {
			return jQuery.validator.methods.minlength.apply(this, arguments);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/maxlength
		maxlength: function(value, element, param) {
			return this.optional(element) || this.getLength(value, element) <= param;
		},
		
		// deprecated, to be removed in 1.3
		maxLength: function(value, element, param) {
			return jQuery.validator.methods.maxlength.apply(this, arguments);
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/rangelength
		rangelength: function(value, element, param) {
			var length = this.getLength(value, element);
			return this.optional(element) || ( length >= param[0] && length <= param[1] );
		},
		
		// deprecated, to be removed in 1.3
		rangeLength: function(value, element, param) {
			return jQuery.validator.methods.rangelength.apply(this, arguments);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/min
		min: function( value, element, param ) {
			return this.optional(element) || value >= param;
		},
		
		// deprecated, to be removed in 1.3
		minValue: function() {
			return jQuery.validator.methods.min.apply(this, arguments);
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/max
		max: function( value, element, param ) {
			return this.optional(element) || value <= param;
		},
		
		// deprecated, to be removed in 1.3
		maxValue: function() {
			return jQuery.validator.methods.max.apply(this, arguments);
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/range
		range: function( value, element, param ) {
			return this.optional(element) || ( value >= param[0] && value <= param[1] );
		},
		
		// deprecated, to be removed in 1.3
		rangeValue: function() {
			return jQuery.validator.methods.range.apply(this, arguments);
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/email
		email: function(value, element) {
			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
			return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/url
		url: function(value, element) {
			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
			return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);
		},
        
		// http://docs.jquery.com/Plugins/Validation/Methods/date
		date: function(value, element) {
			return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/dateISO
		dateISO: function(value, element) {
			return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/dateDE
		dateDE: function(value, element) {
			return this.optional(element) || /^\d\d?\.\d\d?\.\d\d\d?\d?$/.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/number
		number: function(value, element) {
			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
		},
	
		// http://docs.jquery.com/Plugins/Validation/Methods/numberDE
		numberDE: function(value, element) {
			return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(value);
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/digits
		digits: function(value, element) {
			return this.optional(element) || /^\d+$/.test(value);
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/creditcard
		// based on http://en.wikipedia.org/wiki/Luhn
		creditcard: function(value, element) {
			if ( this.optional(element) )
				return "dependency-mismatch";
			var nCheck = 0,
				nDigit = 0,
				bEven = false;

			value = value.replace(/\D/g, "");

			for (n = value.length - 1; n >= 0; n--) {
				var cDigit = value.charAt(n);
				var nDigit = parseInt(cDigit, 10);
				if (bEven) {
					if ((nDigit *= 2) > 9)
						nDigit -= 9;
				}
				nCheck += nDigit;
				bEven = !bEven;
			}

			return (nCheck % 10) == 0;
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/accept
		accept: function(value, element, param) {
			param = typeof param == "string" ? param : "png|jpe?g|gif";
			return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 
		},
		
		// http://docs.jquery.com/Plugins/Validation/Methods/equalTo
		equalTo: function(value, element, param) {
			return value == jQuery(param).val();
		}
		
	}
	
});

// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 
;(function($) {
	var ajax = $.ajax;
	var pendingRequests = {};
	$.ajax = function(settings) {
		// create settings for compatibility with ajaxSetup
		settings = jQuery.extend(settings, jQuery.extend({}, jQuery.ajaxSettings, settings));
		var port = settings.port;
		if (settings.mode == "abort") {
			if ( pendingRequests[port] ) {
				pendingRequests[port].abort();
			}
			return pendingRequests[port] = ajax.apply(this, arguments);
		}
		return ajax.apply(this, arguments);
	};
})(jQuery);

// provides cross-browser focusin and focusout events
// IE has native support, in other browsers, use event caputuring (neither bubbles)

// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
// handler is only called when $(event.target).is(delegate), in the scope of the jQuery-object for event.target 

// provides triggerEvent(type: String, target: Element) to trigger delegated events
;(function($) {
	$.extend($.event.special, {
		focusin: {
			setup: function() {
				if ($.browser.msie)
					return false;
				this.addEventListener("focus", $.event.special.focusin.handler, true);
			},
			teardown: function() {
				if ($.browser.msie)
					return false;
				this.removeEventListener("focus", $.event.special.focusin.handler, true);
			},
			handler: function(event) {
				var args = Array.prototype.slice.call( arguments, 1 );
				args.unshift($.extend($.event.fix(event), { type: "focusin" }));
				return $.event.handle.apply(this, args);
			}
		},
		focusout: {
			setup: function() {
				if ($.browser.msie)
					return false;
				this.addEventListener("blur", $.event.special.focusout.handler, true);
			},
			teardown: function() {
				if ($.browser.msie)
					return false;
				this.removeEventListener("blur", $.event.special.focusout.handler, true);
			},
			handler: function(event) {
				var args = Array.prototype.slice.call( arguments, 1 );
				args.unshift($.extend($.event.fix(event), { type: "focusout" }));
				return $.event.handle.apply(this, args);
			}
		}
	});
	$.extend($.fn, {
		delegate: function(type, delegate, handler) {
			return this.bind(type, function(event) {
				var target = $(event.target);
				if (target.is(delegate)) {
					return handler.apply(target, arguments);
				}
			});
		},
		triggerEvent: function(type, target) {
			return this.triggerHandler(type, [jQuery.event.fix({ type: type, target: target })]);
		}
	})
})(jQuery);


// Crunch Insert -  Fri Nov 6 16:54:46 EST 2009

jQuery.validator.addMethod("maxWords", function(value, element, params) { 
    return this.optional(element) || value.match(/\b\w+\b/g).length < params; 
}, "Please enter {0} words or less."); 
 
jQuery.validator.addMethod("minWords", function(value, element, params) { 
    return this.optional(element) || value.match(/\b\w+\b/g).length >= params; 
}, "Please enter at least {0} words."); 
 
jQuery.validator.addMethod("rangeWords", function(value, element, params) { 
    return this.optional(element) || value.match(/\b\w+\b/g).length >= params[0] && value.match(/bw+b/g).length < params[1]; 
}, "Please enter between {0} and {1} words.");


jQuery.validator.addMethod("letterswithbasicpunc", function(value, element) {
	return this.optional(element) || /^[a-z-.,()'\"\s]+$/i.test(value);
}, "Letters or punctuation only please");  

jQuery.validator.addMethod("alphanumeric", function(value, element) {
	return this.optional(element) || /^\w+$/i.test(value);
}, "Letters, numbers, spaces or underscores only please");  

jQuery.validator.addMethod("lettersonly", function(value, element) {
	return this.optional(element) || /^[a-z]+$/i.test(value);
}, "Letters only please"); 

jQuery.validator.addMethod("nowhitespace", function(value, element) {
	return this.optional(element) || /^\S+$/i.test(value);
}, "No white space please"); 

jQuery.validator.addMethod("ziprange", function(value, element) {
	return this.optional(element) || /^90[2-5]\d\{2}-\d{4}$/.test(value);
}, "Your ZIP-code must be in the range 902xx-xxxx to 905-xx-xxxx");

/**
* Return true, if the value is a valid vehicle identification number (VIN).
*
* Works with all kind of text inputs.
*
* @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
* @desc Declares a required input element whose value must be a valid vehicle identification number.
*
* @name jQuery.validator.methods.vinUS
* @type Boolean
* @cat Plugins/Validate/Methods
*/ 
jQuery.validator.addMethod(
	"vinUS",
	function(v){
		if (v.length != 17)
			return false;
		var i, n, d, f, cd, cdv;
		var LL    = ["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"];
		var VL    = [1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9];
		var FL    = [8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2];
		var rs    = 0;
		for(i = 0; i < 17; i++){
		    f = FL[i];
		    d = v.slice(i,i+1);
		    if(i == 8){
		        cdv = d;
		    }
		    if(!isNaN(d)){
		        d *= f;
		    }
		    else{
		        for(n = 0; n < LL.length; n++){
		            if(d.toUpperCase() === LL[n]){
		                d = VL[n];
		                d *= f;
		                if(isNaN(cdv) && n == 8){
		                    cdv = LL[n];
		                }
		                break;
		            }
		        }
		    }
		    rs += d;
		}
		cd = rs % 11;
		if(cd == 10){cd = "X";}
		if(cd == cdv){return true;}
		return false; 
	},
	"The specified vehicle identification number (VIN) is invalid."
);

/**
  * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
  *
  * @example jQuery.validator.methods.date("01/01/1900")
  * @result true
  *
  * @example jQuery.validator.methods.date("01/13/1990")
  * @result false
  *
  * @example jQuery.validator.methods.date("01.01.1900")
  * @result false
  *
  * @example <input name="pippo" class="{dateITA:true}" />
  * @desc Declares an optional input element whose value must be a valid date.
  *
  * @name jQuery.validator.methods.dateITA
  * @type Boolean
  * @cat Plugins/Validate/Methods
  */
jQuery.validator.addMethod(
	"dateITA",
	function(value, element) {
		var check = false;
		var re = /^\d{1,2}\/\d{1,2}\/\d{4}$/
		if( re.test(value)){
			var adata = value.split('/');
			var gg = parseInt(adata[0],10);
			var mm = parseInt(adata[1],10);
			var aaaa = parseInt(adata[2],10);
			var xdata = new Date(aaaa,mm-1,gg);
			if ( ( xdata.getFullYear() == aaaa ) && ( xdata.getMonth () == mm - 1 ) && ( xdata.getDate() == gg ) )
				check = true;
			else
				check = false;
		} else
			check = false;
		return this.optional(element) || check;
	}, 
	"Please enter a correct date"
);

/**
 * matches US phone number format 
 * 
 * where the area code may not start with 1 and the prefix may not start with 1 
 * allows '-' or ' ' as a separator and allows parens around area code 
 * some people may want to put a '1' in front of their number 
 * 
 * 1(212)-999-2345
 * or
 * 212 999 2344
 * or
 * 212-999-0983
 * 
 * but not
 * 111-123-5434
 * and not
 * 212 123 4567
 */
jQuery.validator.addMethod("phone", function(phone_number, element) {
    phone_number = phone_number.replace(/\s+/g, ""); 
	return this.optional(element) || phone_number.length > 9 &&
		phone_number.match(/^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/);
}, "Please specify a valid phone number");

// TODO check if value starts with <, otherwise don't try stripping anything
jQuery.validator.addMethod("strippedminlength", function(value, element, param) {
	return jQuery(value).text().length >= param;
}, jQuery.format("Please enter at least {0} characters"));

// same as email, but TLD is optional
jQuery.validator.addMethod("email2", function(value, element, param) {
	return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); 
}, jQuery.validator.messages.email);

// same as url, but TLD is optional
jQuery.validator.addMethod("url2", function(value, element, param) {
	return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); 
}, jQuery.validator.messages.url);


// Crunch Insert -  Fri Nov 6 16:54:46 EST 2009

/**
 * DHTML date validation script. Courtesy of SmartWebby.com (http://www.smartwebby.com/dhtml/)
 */
// Declaring valid date character, minimum year and maximum year
var dtCh= "/";
var minYear=1970;
var maxYear=2037;

function isInteger(s){
	var i;
    for (i = 0; i < s.length; i++){
        // Check that current character is number.
        var c = s.charAt(i);
        if (((c < "0") || (c > "9"))) return false;
    }
    // All characters are numbers.
    return true;
}

function stripCharsInBag(s, bag){
	var i;
    var returnString = "";
    // Search through string's characters one by one.
    // If character is not in bag, append to returnString.
    for (i = 0; i < s.length; i++){
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) returnString += c;
    }
    return returnString;
}

function daysInFebruary (year){
	// February has 29 days in any year evenly divisible by four,
    // EXCEPT for centurial years which are not also divisible by 400.
    return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 );
}
function DaysArray(n) {
	for (var i = 1; i <= n; i++) {
		this[i] = 31
		if (i==4 || i==6 || i==9 || i==11) {this[i] = 30}
		if (i==2) {this[i] = 29}
   }
   return this
}

function isDate(dtStr){
	var daysInMonth = DaysArray(12)
	var pos1=dtStr.indexOf(dtCh)
	var pos2=dtStr.indexOf(dtCh,pos1+1)
	var strMonth=dtStr.substring(0,pos1)
	var strDay=dtStr.substring(pos1+1,pos2)
	var strYear=dtStr.substring(pos2+1)
	strYr=strYear
	if (strDay.charAt(0)=="0" && strDay.length>1) strDay=strDay.substring(1)
	if (strMonth.charAt(0)=="0" && strMonth.length>1) strMonth=strMonth.substring(1)
	for (var i = 1; i <= 3; i++) {
		if (strYr.charAt(0)=="0" && strYr.length>1) strYr=strYr.substring(1)
	}
	month=parseInt(strMonth)
	day=parseInt(strDay)
	year=parseInt(strYr)
	if (pos1==-1 || pos2==-1){
		//alert("The date format should be : mm/dd/yyyy")
		return -1;
	}
	if (strMonth.length<1 || month<1 || month>12){
		//alert("Please enter a valid month")
		return -2;
	}
	if (strDay.length<1 || day<1 || day>31 || (month==2 && day>daysInFebruary(year)) || day > daysInMonth[month]){
		//alert("Please enter a valid day")
		return -3;
	}
	if (strYear.length != 4 || year==0){
		//alert("Please enter a valid 4 digit year between "+minYear+" and "+maxYear)
		return -4;
	}
	if(year<minYear) {
		return -6;
	}
	if(year>maxYear) {
		return -7;
	}
	if (dtStr.indexOf(dtCh,pos2+1)!=-1 || isInteger(stripCharsInBag(dtStr, dtCh))==false){
		//alert("Please enter a valid date")
		return -5
	}
return 1
}


// Crunch Insert -  Fri Nov 6 16:54:46 EST 2009

/* css drop downs */
var totalLists = 1;
var ua = navigator.userAgent.toLowerCase();
var av = navigator.appVersion.toLowerCase();
var mac = ( av.indexOf( 'mac' ) != -1 );
var saf = ( ua.indexOf( 'safari' ) != -1 );
var ie5x = ( document.all && document.getElementById );
var ie5mac = ( mac && ie5x );

function calcHeight() {
	var myHeight = 0;
	if( typeof( window.innerWidth ) == 'number' ) {
		/*Non-IE*/
		myHeight = window.innerHeight;
	} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
		/*IE 6+ in 'standards compliant mode'*/
		myHeight = document.documentElement.clientHeight;
	} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
		/*IE 4 compatible*/
		myHeight = document.body.clientHeight;
	}
	return myHeight;
}

function findPosY(obj) {
	var curtop = 0;
	if (obj.offsetParent) {
		while (obj.offsetParent) {
			curtop += obj.offsetTop;
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

	
function hideall(ListNum) {
	divItem = document.getElementById('Lst'+ListNum);
	divItem.style.display="none";
	//document.getElementById('dropPlus'+ListNum).className = "dropPlus"; // change the drop down icon
}

/* css drop downs - modified js */

var LastListNum = "";

function checkHeightNew(ListNum){
		var list = document.getElementById('Lst' + ListNum);	
  
		var winHeight = calcHeight();
		
		var scrollOffset = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;
		if(!ie5mac) {
			list.style.overflow = "auto";// overflow auto for none ie5 on MAC -- to avoid horizontal scroll bar
			list.style.height = "";
			
			var drop = document.getElementById('Drp' + ListNum);
			var dropPos = findPosY(drop);

// this is a hack to work around a dropPos discrepancy in Safari
			if(saf) {
				dropPos = dropPos + 10;
			}
			
			var dropHeight = drop.offsetHeight;
			var spaceBelow = winHeight - (dropPos + dropHeight - scrollOffset) - 30;
			var spaceAbove = dropPos - scrollOffset - 30;
			var lstHeight = (spaceAbove > spaceBelow)? spaceAbove: spaceBelow;
			
			lstHeight = (list.offsetHeight > lstHeight)? lstHeight: list.offsetHeight;
			list.style.height = lstHeight + "px"; // adjust the menu height according to the space available
			
			var lstTop = dropPos + dropHeight - 1;
			
			list.style.top = lstTop + "px";
			if( (spaceBelow < lstHeight) && (navigator.appName.toUpperCase().indexOf('NETSCAPE') == -1)){ // Display above
				list.style.top = lstTop - dropHeight - lstHeight - 1 + "px";
				//  list.style.top = dropPos - dropHeight - lstHeight + 15;			
			}
				
  	}
  
  	var listTable = document.getElementById('LstTable' + ListNum);
		if(ie5mac){
			var drop = document.getElementById('Drp' + ListNum);
			var dropPos = findPosY(drop);
			var dropHeight = drop.offsetHeight;
			var spaceBelow = winHeight - (dropPos + dropHeight - scrollOffset) - 30;
			var spaceAbove = dropPos - scrollOffset - 30;
			var lstHeight = (spaceAbove > spaceBelow)? spaceAbove: spaceBelow;
			
				lstHeight = (list.offsetHeight > lstHeight)? lstHeight: list.offsetHeight;
				list.style.height = lstHeight + "px";
		}
		
		if(saf) {
			if(listTable.offsetHeight + 3 > list.offsetHeight && list.offsetWidth <= listTable.offsetWidth + 3)
			list.style.width = list.offsetWidth + 15 + "px";
		}
		
		if(ie5mac) {
			if(listTable.offsetHeight + 2 > list.offsetHeight && list.offsetWidth <= listTable.offsetWidth + 2){
				list.style.width = list.offsetWidth + 15 + "px";
				list.style.overflow = "auto"; 
				list.style.height = "";
			}
		}
    
}

function showListNew(ListNum){
  	if(LastListNum == ListNum)
   		 closeDropDownNew();
  	else{
		closeDropDownNew();
    	LastListNum = ListNum;
   		ListId = "Lst" + LastListNum;
    	if(document.getElementById(ListId)){
	    	document.getElementById(ListId).style.display = "block";	
            
            if ( document.all && document.getElementById('dropdown_iframe') != null )
            {
                dropdown_height = document.getElementById(ListId).offsetHeight;
                iframe_height = dropdown_height - 3 + "px";
                document.getElementById('dropdown_iframe').style.height = iframe_height;
			    document.getElementById('dropdown_iframe').style.display = 'block';
                //document.getElementById('dropdown_iframe').style.filter = 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)';
            }
            
            
	    	//document.getElementById('dropPlus'+ListNum).className = "dropPlusOver"; // change the pull down icon
			checkHeightNew(ListNum); 
    }
  }
}

function closeDropDownNew(){
  if(LastListNum!=""){
	    ListId = "Lst" + LastListNum;
    	if(document.getElementById(ListId)){
      		document.getElementById(ListId).style.display = "none";
            
            if ( document.all && document.getElementById('dropdown_iframe') != null )
            {
                document.getElementById('dropdown_iframe').style.display = 'none';
            }
            
      		//document.getElementById('dropPlus'+LastListNum).className = "dropPlus";
    }
    	LastListNum = ""; // set the menu ID to null 
  }
}


// Crunch Insert -  Fri Nov 6 16:54:46 EST 2009

var newEmails;
var username;
var recipientlist;
var cclist;
var bcclist;
var contentDiv;
var errorMsgDiv;
var successMessage;

//these fields are used for stats
var statEmailFrom;
var statEmailTo;

// pduey: this is the function to call in the onSubmit event.
// (from everywhere BUT Vendor-Contact)
function sendEmail(emailForm) {
    if (validateEmailForm(emailForm)) {
	EmailService.sendDWR(checkStatus, emailForm.name.value, emailForm.from.value, recipientlist, cclist, bcclist, emailForm.subject.value, emailForm.message.value, location.href);

	statEmailFrom = emailForm.from.value;
	statEmailTo = emailForm.to.value;

    	sendEvent(emailForm.vpid.value, 'lc_sf');
    	//console.debug('Sent a Friend an email!' );

	page.reloadAssets();
    }
    
    // always return false, else the page will reload
    return false;
}

// this is the function to call in the onSubmit event from Vendor-Contact only.  
function sendVendorEmail(emailForm) {
    if (validateVendorEmailForm(emailForm)) {

	if (emailForm.address != undefined) { 
	    
	    emailForm.message.value = "<p>Sender's information:</p>" +
	  "<p>Name: " + emailForm.name.value + "</p>" +
		"<p>E-mail: " + emailForm.from.value + "</p>" +
		"<p>Phone Number: " + emailForm.phone.value + "</p>" +
		"<p>Wedding Date: " + emailForm.wed_date.value + "</p>" +
		"<p>Vendor: " + $('vendorDisplay').firstChild.innerHTML + "</p>" +
		//"<p>VPID: " + emailForm.vpid.value + "</p>" +
		"<p>Message:<br>" + emailForm.message.value + "</p>" +
    "<p>Address<br>" + emailForm.address.value + "</p>";
        } else {
	    emailForm.message.value = "<p>Sender's information:</p>" +
	        "<p>Name: " + emailForm.name.value + "</p>" +
		"<p>E-mail: " + emailForm.from.value + "</p>" +
		"<p>Phone Number: " + emailForm.phone.value + "</p>" +
		"<p>Wedding Date: " + emailForm.wed_date.value + "</p>" +
		"<p>Vendor: " + $('vendorDisplay').firstChild.innerHTML + "</p>" +
		//"<p>VPID: " + emailForm.vpid.value + "</p>" +
		"<p>Message:<br>" + emailForm.message.value + "</p>";
	}

	EmailService.sendDWR(checkStatus, emailForm.name.value, emailForm.from.value, recipientlist, cclist, bcclist, emailForm.subject.value, emailForm.message.value, "");

	statEmailFrom = emailForm.from.value;
	statEmailTo = emailForm.to.value;

    	sendEmailEvent(emailForm.from.value, emailForm.to.value, emailForm.vpid.value);
    	//console.debug('An email has been sent to vendor! ' );
	page.reloadAssets();
    }
    
    // always return false, else the page will reload
    return false;
}

// this is the function to call in the onSubmit event from list_your_business.  
function sendLYBEmail(emailForm) {
    if (validateLYBEmailForm(emailForm)) {

	theMessage ="<p>Sender's information:</p>" +
	    "<p>Name: " + emailForm.name.value + "</p>" +
	    "<p>Company Name: " + emailForm.cname.value + "</p>" +
	    "<p>E-mail: " + emailForm.email.value + "</p>" +
	    "<p>Phone Number: " + emailForm.phone.value + "</p>" +
	    "<p>Company Website: " + emailForm.website.value + "</p>" +
	    "<p>Message:<br>" + emailForm.message.value + "</p>";
	
	EmailService.sendDWR(checkStatus, emailForm.name.value, emailForm.email.value, emailForm.repEmail.value, cclist, bcclist, "List your Business Email", theMessage, location.href);

	page.reloadAssets();
    }
    
    // always return false, else the page will reload
    return false;
}

// this is the function to call in the onSubmit event from Report Wedding Web Site only.  
function sendReportSiteEmail(form) {
    if (validateReportSiteForm(form)) {

	aMessage = "<p>Report Wedding Web Site</p>" +
	    "<p>By: " + form.username.value + "</p>" +
	    "<p>E-mail: " + form.from.value + "</p>" +
	    "<p>SiteLink: " + form.sitelink.value + "</p>" +
	    "<p>WeddingWebSiteId: " + form.weddingWebsiteId.value + "</p>" +
	    "<p>WeddingWebSiteOwner: " + form.weddingWebsiteOwner.value + "</p>" + 
	    "<p>Additional Information:<br> " + form.reportSiteMessage.value + "</p>";
	
	EmailService.sendDWR(checkStatusReportSite, form.username.value, 
			     form.from.value, 
			     recipientlist, 
			     cclist, 
			     bcclist, form.subject.value, aMessage, "");

	statEmailFrom = form.from.value;
	statEmailTo = form.to.value;
	page.reloadAssets();
    }
    
    // always return false, else the page will reload
    return false;
}

function validateEmailForm(form) {
    username = form.username.value;
    
    // clear out error message div's
    DWRUtil.setValues({emailName:"", emailFrom:"", emailTo:""});

    var valid = true;    

    //validate required
    if(isEmpty(form.name.value)){
	DWRUtil.setValue("emailName", "This is required");
	valid=false;		
    }

    if(isEmpty(form.from.value)){
	DWRUtil.setValue("emailFrom", "This is required");		
	valid=false;		
    }else if(!isEmail(form.from.value)){
	DWRUtil.setValue("emailFrom", "Invalid Email");		
	valid=false;		
    }

    if(!isEmpty(form.to.value)){
	var errMsg = "";
	var emails = form.to.value.split(",");
	for(i=0; i<emails.length; i++){
	    var email = emails[i];
	    if(!isEmpty(email) && !isEmail(email)){
		errMsg = errMsg + email + " is invalid<br/>"
	    }
	}
	if(!isEmpty(errMsg)){
	    DWRUtil.setValue("emailTo", errMsg);					
	    valid=false;
	}	
    }
    
    var contactListSelected = "";
    if (form.contactEmails) {
	for(i=0; i < form.contactEmails.length; i++) {
	    if(form.contactEmails[i].selected) {
		contactListSelected += "," + form.contactEmails[i].value;
	    }
	}
    }
    
    newEmails = form.to.value.replace(/\s+|\n+|\r+|\t+/g, '');		// strip whitespace
    if(isEmpty(newEmails)) {
	contactListSelected = contactListSelected.substring(1);		// remove leading comma
    }

    recipientlist = newEmails + contactListSelected;
    if(isEmpty(recipientlist)){
	DWRUtil.setValue("emailTo", "This is required");		
	valid=false;		
    }

    cclist = '';
    if (form.sendToMe.checked) {
	cclist = form.from.value;
    }
    
    bcclist = '';
    if (form.bcc) {
	bcclist = form.bcc.value;
    }
    
    return valid;
}

function validateVendorEmailForm(form) {
    // clear out error message div's
    DWRUtil.setValues({vendorFrom:""});

    var valid = true;    

    //validate required
    if(isEmpty(form.from.value)){
	DWRUtil.setValue("vendorFrom", "This is required");		
	valid=false;		
    }else if(!isEmail(form.from.value)){
	DWRUtil.setValue("vendorFrom", "Invalid Email");		
	valid=false;		
    }

    recipientlist = form.to.value;
    
    cclist = '';
    if (form.sendToMe.checked) {
	cclist = form.from.value;
    }
    
    bcclist = '';
    if (form.bcc) {
	bcclist = form.bcc.value;
    }
    
    return valid;
}

function validateLYBEmailForm(form) {
    // clear out error message div's
    DWRUtil.setValues({emailName:""});
    DWRUtil.setValues({emailCname:""});
    DWRUtil.setValues({emailFrom:""});
    DWRUtil.setValues({emailPhone:""});

    var valid = true;    

    //validate required
    if(isEmpty(form.name.value)){
	DWRUtil.setValue("emailName", "This is required");
	valid=false;		
    }
    if(isEmpty(form.cname.value)){
	DWRUtil.setValue("emailCname", "This is required");
	valid=false;		
    }
    if(isEmpty(form.phone.value)){
	DWRUtil.setValue("emailPhone", "This is required");
	valid=false;		
    }

    if(isEmpty(form.email.value)){
	DWRUtil.setValue("emailFrom", "This is required");		
	valid=false;		
    }else if(!isEmail(form.email.value)){
	DWRUtil.setValue("emailFrom", "Invalid Email");		
	valid=false;		
    }

    
    cclist = '';
    if (form.sendToMe.checked) {
	cclist = form.email.value;
    }
    

    bcclist = 'listyourbusiness@brides.com';
  
    return valid;
}

function validateReportSiteForm(form) {
    // clear out error message div's
    DWRUtil.setValues({reportSiteMessageError:""});
    DWRUtil.setValues({reportSiteReasonError:""});

    var valid = true;    

    //validate required
    if(isEmpty(form.reportSiteMessage.value)){
	DWRUtil.setValue("reportSiteMessageError", "This is required");		
	valid=false;		
    }
    if(isEmpty(form.reportSiteReason.value) || form.reportSiteReason.value == "Select a reason" ){
	DWRUtil.setValue("reportSiteReasonError", "This is required");		
	valid=false;		
    }

    recipientlist = form.to.value;
    
    cclist = '';	
    bcclist = '';
    
    return valid;
}

function checkStatus(valid) {
    if(valid) {
	contentDiv.innerHTML = "Your message has been sent.";
    } else {
	errorMsgDiv.innerHTML = "Your message was not sent due to server error.<br>Please try again later.";
    }
    
    if(!isEmpty(username) && !isEmpty(newEmails)) {
    	ContactListEmailService.newEmails(callBackAddEmails, username, newEmails);
    }
}

function checkStatusReportSite(valid) {
    if(valid) {
	contentDiv.innerHTML = "Your message has been sent." + "<br><br>" + successMessage;
    } else {
	errorMsgDiv.innerHTML = "Your message was not sent due to server error.<br>Please try again later.";
    }
}


var totalNewEmails = 0;

function callBackAddEmails(data) {
    var newEmails = '';
    if(data!=null) {
	newEmails = '<input type="hidden" name="username" value="' + username + '"/>';
	totalNewEmails = data.length;
	for(i=0; i < totalNewEmails; i++) {
	    newEmails += '&nbsp;<input type="checkbox" name="addEmail" value="' + data[i] + '"/>&nbsp;' + data[i] + '<br/>';
	}
	document.getElementById("newEmails").innerHTML = newEmails;
	contentDiv.innerHTML = contentDiv.innerHTML + document.getElementById("addEmails").innerHTML;
    }
}

function addEmails(form) {
    var emails = "";
    if(totalNewEmails > 1) {
	for(i=0; i < form.addEmail.length; i++) {
	    if(form.addEmail[i].checked) {
		emails += ","  + form.addEmail[i].value;
	    }
	}
	if(emails.length > 0) {
	    emails = emails.substring(1);
	}
    }
    else {	// -- For single checkbox
	if(form.addEmail.checked) {
	    emails = form.addEmail.value;
	}
    }
    if(emails.length==0) {
	DWRUtil.setValue("addEmailsErrorMsg", "Please make a selection");
	return false;
    }
    ContactListEmailService.addEmails(callBackAddedEmails, form.username.value, emails);
    return false;
}


function callBackAddedEmails(isSuccessful) {
    if(isSuccessful) {
	contentDiv.innerHTML = "Emails added to your Guest List";
    }
    else {
	contentDiv.innerHTML = "There was a problem adding emails to your Guest List";
    }
    return false;
}

var emailAction;
var clipAction = '';


function emailAFriendPopup() {
    contentDiv = document.getElementById("emailAFriendContent");
    contentDiv.innerHTML = document.getElementById("emailFriendForm").innerHTML;
    
    savedContent = contentDiv.innerHTML;
    showItem('emailContainer', 'eMailIcon', 'bottomleft');
    emailAction = 'emailAFriend';
    clipAction = 'email';
    errorMsgDiv = document.getElementById("emailAFriendErrorMsg");
    errorMsgDiv.innerHTML = '';
}


function emailAFriendMBOTYPopup() {
    contentDiv = document.getElementById("emailAFriendContent");
    contentDiv.innerHTML = document.getElementById("emailFriendForm").innerHTML;
    savedContent = contentDiv.innerHTML;
    showItem('emailContainer', 'wrapper');
    emailAction = 'emailAFriend';
    clipAction = 'email';
    errorMsgDiv = document.getElementById("emailAFriendErrorMsg");
    errorMsgDiv.innerHTML = '';
}




function emailVendorPopup(buttonId, vendorInfoObj) {
//console.debug('from : '+cvForm.from.value );
    if (document.getElementById("contactContainer").style.visibility == 'visible') {
        hideItem('contactContainer');
    }
    contentDiv = document.getElementById("emailVendorContent");
//    savedContent = document.getElementById("emailVendorForm").innerHTML; // Clone the hidden content
//    document.getElementById("emailVendorForm").innerHTML = ""; // Destroy the original
//    contentDiv.innerHTML = savedContent;

    contentDiv.innerHTML = document.getElementById("emailVendorForm").innerHTML;
    savedContent = contentDiv.innerHTML;

    emailAction = 'emailVendor';
    clipAction = 'email';
    errorMsgDiv = document.getElementById("emailVendorErrorMsg");
    errorMsgDiv.innerHTML = '';
    if (vendorInfoObj) {
        vendorListingId = vendorInfoObj.vendorListingId;
        var displaySpan = document.getElementById("vendorDisplay");
        displaySpan.innerHTML = vendorInfoObj.displayText;
        var cvForm = document.getElementById("contactvendorform");
	if (vendorInfoObj.vpid){
		cvForm.vpid.value = vendorInfoObj.vpid;
	}
        // no idea why dereferencing document.contactvendorform.to.value with '.' doesn't work
        for(i=0;i<cvForm.elements.length;i++){
            if (cvForm.elements[i].name == 'to') {
                cvForm.elements[i].value = vendorInfoObj.toAddr;
            }
        }//for
    }

    if (userData.weddingDate != undefined) {
	var cvForm = document.getElementById("contactvendorform");
	cvForm.flName.value = userData.firstName +" "+userData.lastName ;
	cvForm.eMail.value = userData.email;
	cvForm.wed_date.value = formatMMDDYYYY(userData.weddingDate);
    }
    showItem('contactContainer', buttonId, 'bottomleft');

}

function listYourBusinessPopup(locale) {

  // totally temporary fix that relies on jQuery's ability to specify
	// var regionHeader = document.getElementById("regionHeader");  
	//regionHeader.innerHTML = locale.toUpperCase() + " REGION";	
	var regionHeader = jQuery("#listYourBusinessFormContainer #regionHeader");
	regionHeader.html(locale.toUpperCase() + " REGION");
	
	// var repName = document.getElementById("repName");
	// repName.innerHTML = LYB_REGIONS[locale].repName + ", " + LYB_REGIONS[locale].repTitle;
	 var repName = jQuery("#listYourBusinessFormContainer #repName");
	 repName.html(LYB_REGIONS[locale].repName + ", " + LYB_REGIONS[locale].repTitle);
	
	// var repPhone = document.getElementById("repPhone");
	// repPhone.innerHTML = LYB_REGIONS[locale].repPhone;
	 var repPhone = jQuery("#listYourBusinessFormContainer #repPhone");
	 repPhone.html(LYB_REGIONS[locale].repPhone);
	
	// var repFax = document.getElementById("repFax");
	// repFax.innerHTML = LYB_REGIONS[locale].repFax;
	var repFax = jQuery("#listYourBusinessFormContainer #repFax");
	repFax.html(LYB_REGIONS[locale].repFax);
	
	// var repEmail = document.getElementById("repEmail");
	// repEmail.value = LYB_REGIONS[locale].repEmail;
  var repEmail = jQuery("#listYourBusinessFormContainer #repEmail");
  repEmail.val(LYB_REGIONS[locale].repEmail);


	contentDiv = document.getElementById("listYourBusinessContent");
	contentDiv.innerHTML = document.getElementById("listYourBusinessFormContainer").innerHTML;
	savedContent = contentDiv.innerHTML;
	showItem('emailContainer', 'legendHead', 'bottomright');
	emailAction = 'emailListYourBusiness';
	clipAction = 'email';
	errorMsgDiv = document.getElementById("listYourBusinessErrorMsg");
	errorMsgDiv.innerHTML = '';
}


function reportSitePopup(){
    contentDiv = document.getElementById("reportSiteContent");
    contentDiv.innerHTML = document.getElementById("reportSiteForm").innerHTML;
    successMessage = document.getElementById("reportSiteSuccess").value;
    savedContent = contentDiv.innerHTML;
    showItem('reportSiteContainer', 'reportSiteButton', null);
    emailAction = 'reportSite';
    clipAction = 'email';
    errorMsgDiv = document.getElementById("reportSiteErrorMsg");
    errorMsgDiv.innerHTML = '';
}

function emailAdminWeddingWebsitePopup() {
    contentDiv = document.getElementById("emailAFriendContent");
    contentDiv.innerHTML = document.getElementById("emailFriendForm").innerHTML;
    savedContent = contentDiv.innerHTML;
    showItem('emailContainer', 'eMailIcon', 'bottomleft');
    emailAction = 'emailWeddingWebsite';
    clipAction = 'email';
    errorMsgDiv = document.getElementById("emailAFriendErrorMsg");
    errorMsgDiv.innerHTML = '';
}

function emailOverviewWeddingWebsitePopup() {
    contentDiv = document.getElementById("emailAFriendContent");
    contentDiv.innerHTML = document.getElementById("emailFriendForm").innerHTML;
    savedContent = contentDiv.innerHTML;
    showItem('emailContainer', 'eMailIcon', 'topleft');
    emailAction = 'emailWeddingWebsite';
    clipAction = 'email';
    errorMsgDiv = document.getElementById("emailAFriendErrorMsg");
    errorMsgDiv.innerHTML = '';
}

function emailViewWeddingWebsitePopup() {
    contentDiv = document.getElementById("emailAFriendContent");
    contentDiv.innerHTML = document.getElementById("emailFriendForm").innerHTML;
    savedContent = contentDiv.innerHTML;
    showItem('emailContainer', 'eMailIcon', null);
    emailAction = 'emailWeddingWebsite';
    clipAction = 'email';
    errorMsgDiv = document.getElementById("emailAFriendErrorMsg");
    errorMsgDiv.innerHTML = '';
}

function sendWeddingWebsiteEmail(emailForm) {
    var siteLink = 'http://www.brides.com/weddingwebsite/' + navLink;
    
    if (validateEmailForm(emailForm)){
        EmailService.sendDWR(checkStatus, emailForm.name.value, emailForm.from.value, recipientlist, cclist, bcclist, emailForm.subject.value, emailForm.message.value, siteLink);

        statEmailFrom = emailForm.from.value;
        statEmailTo = emailForm.to.value;
        page.reloadAssets();
    }

    return false;
}



// Crunch Insert -  Fri Nov 6 16:54:46 EST 2009

/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-07-21 18:44:59 -0500 (Sat, 21 Jul 2007) $
 * $Rev: 2446 $
 *
 * Version 2.1.1
 */

(function($){

/**
 * The bgiframe is chainable and applies the iframe hack to get 
 * around zIndex issues in IE6. It will only apply itself in IE6 
 * and adds a class to the iframe called 'bgiframe'. The iframe
 * is appeneded as the first child of the matched element(s) 
 * with a tabIndex and zIndex of -1.
 * 
 * By default the plugin will take borders, sized with pixel units,
 * into account. If a different unit is used for the border's width,
 * then you will need to use the top and left settings as explained below.
 *
 * NOTICE: This plugin has been reported to cause perfromance problems
 * when used on elements that change properties (like width, height and
 * opacity) a lot in IE6. Most of these problems have been caused by 
 * the expressions used to calculate the elements width, height and 
 * borders. Some have reported it is due to the opacity filter. All 
 * these settings can be changed if needed as explained below.
 *
 * @example $('div').bgiframe();
 * @before <div><p>Paragraph</p></div>
 * @result <div><iframe class="bgiframe".../><p>Paragraph</p></div>
 *
 * @param Map settings Optional settings to configure the iframe.
 * @option String|Number top The iframe must be offset to the top
 * 		by the width of the top border. This should be a negative 
 *      number representing the border-top-width. If a number is 
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used. 
 * 		By default the value is "auto" which will use an expression 
 * 		to get the border-top-width if it is in pixels.
 * @option String|Number left The iframe must be offset to the left
 * 		by the width of the left border. This should be a negative 
 *      number representing the border-left-width. If a number is 
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used. 
 * 		By default the value is "auto" which will use an expression 
 * 		to get the border-left-width if it is in pixels.
 * @option String|Number width This is the width of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetWidth.
 * @option String|Number height This is the height of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetHeight.
 * @option Boolean opacity This is a boolean representing whether or not
 * 		to use opacity. If set to true, the opacity of 0 is applied. If
 *		set to false, the opacity filter is not applied. Default: true.
 * @option String src This setting is provided so that one could change 
 *		the src of the iframe to whatever they need.
 *		Default: "javascript:false;"
 *
 * @name bgiframe
 * @type jQuery
 * @cat Plugins/bgiframe
 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 */
$.fn.bgIframe = $.fn.bgiframe = function(s) {
	// This is only for IE6
	if ( $.browser.msie && /6.0/.test(navigator.userAgent) ) {
		s = $.extend({
			top     : 'auto', // auto == .currentStyle.borderTopWidth
			left    : 'auto', // auto == .currentStyle.borderLeftWidth
			width   : 'auto', // auto == offsetWidth
			height  : 'auto', // auto == offsetHeight
			opacity : true,
			src     : 'javascript:false;'
		}, s || {});
		var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
		    html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
		               'style="display:block;position:absolute;z-index:-1;'+
			               (s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
					       'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
					       'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
					       'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
					       'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
					'"/>';
		return this.each(function() {
			if ( $('> iframe.bgiframe', this).length == 0 )
				this.insertBefore( document.createElement(html), this.firstChild );
		});
	}
	return this;
};

})(jQuery);

// Crunch Insert -  Fri Nov 6 16:54:46 EST 2009

/*

jQuery Browser Plugin
	* Version 2.3
	* 2008-09-17 19:27:05
	* URL: http://jquery.thewikies.com/browser
	* Description: jQuery Browser Plugin extends browser detection capabilities and can assign browser selectors to CSS classes.
	* Author: Nate Cavanaugh, Minhchau Dang, & Jonathan Neal
	* Copyright: Copyright (c) 2008 Jonathan Neal under dual MIT/GPL license.
	* JSLint: This javascript file passes JSLint verification.
*//*jslint
		bitwise: true,
		browser: true,
		eqeqeq: true,
		forin: true,
		nomen: true,
		plusplus: true,
		undef: true,
		white: true
*//*global
		jQuery
*/

(function (jQuery) {
	jQuery.browserTest = function (a, z) {
		var u = 'unknown', x = 'X', m = function (r, h) {
			for (var i = 0; i < h.length; i = i + 1) {
				r = r.replace(h[i][0], h[i][1]);
			}

			return r;
		}, c = function (i, a, b, c) {
			var r = {
				name: m((a.exec(i) || [u, u])[1], b)
			};

			r[r.name] = true;

			r.version = (c.exec(i) || [x, x, x, x])[3];

			if (r.name.match(/safari/) && r.version > 400) {
				r.version = '2.0';
			}

			if (r.name === 'presto') {
				r.version = ($.browser.version > 9.27) ? 'futhark' : 'linear_b';
			}
			r.versionNumber = parseFloat(r.version, 10) || 0;
			r.versionX = (r.version !== x) ? (r.version + '').substr(0, 1) : x;
			r.className = r.name + r.versionX;

			return r;
		};

		a = (a.match(/Opera|Navigator|Minefield|KHTML|Chrome/) ? m(a, [
			[/(Firefox|MSIE|KHTML,\slike\sGecko|Konqueror)/, ''],
			['Chrome Safari', 'Chrome'],
			['KHTML', 'Konqueror'],
			['Minefield', 'Firefox'],
			['Navigator', 'Netscape']
		]) : a).toLowerCase();

		jQuery.browser = jQuery.extend((!z) ? jQuery.browser : {}, c(a, /(camino|chrome|firefox|netscape|konqueror|lynx|msie|opera|safari)/, [], /(camino|chrome|firefox|netscape|netscape6|opera|version|konqueror|lynx|msie|safari)(\/|\s)([a-z0-9\.\+]*?)(\;|dev|rel|\s|$)/));

		jQuery.layout = c(a, /(gecko|konqueror|msie|opera|webkit)/, [
			['konqueror', 'khtml'],
			['msie', 'trident'],
			['opera', 'presto']
		], /(applewebkit|rv|konqueror|msie)(\:|\/|\s)([a-z0-9\.]*?)(\;|\)|\s)/);

		jQuery.os = {
			name: (/(win|mac|linux|sunos|solaris|iphone)/.exec(navigator.platform.toLowerCase()) || [u])[0].replace('sunos', 'solaris')
		};

		if (!z) {
			jQuery('html').addClass([jQuery.os.name, jQuery.browser.name, jQuery.browser.className, jQuery.layout.name, jQuery.layout.className].join(' '));
		}
	};

	jQuery.browserTest(navigator.userAgent);
})(jQuery);

// Crunch Insert -  Fri Nov 6 16:54:46 EST 2009

/**
 * History/Remote - jQuery plugin for enabling history support and bookmarking
 * @requires jQuery v1.0.3
 *
 * http://stilbuero.de/jquery/history/
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Version: 0.2.3
 */

(function($) { // block scope

/**
 * Initialize the history manager. Subsequent calls will not result in additional history state change 
 * listeners. Should be called soonest when the DOM is ready, because in IE an iframe needs to be added
 * to the body to enable history support.
 *
 * @example $.ajaxHistory.initialize();
 *
 * @param Function callback A single function that will be executed in case there is no fragment
 *                          identifier in the URL, for example after navigating back to the initial
 *                          state. Use to restore such an initial application state.
 *                          Optional. If specified it will overwrite the default action of 
 *                          emptying all containers that are used to load content into.
 * @type undefined
 *
 * @name $.ajaxHistory.initialize()
 * @cat Plugins/History
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
$.ajaxHistory = new function() {

    var RESET_EVENT = 'historyReset';

    var _currentHash = location.hash;
    var _intervalId = null;
    var _observeHistory; // define outside if/else required by Opera

    this.update = function() { }; // empty function body for graceful degradation

    // create custom event for state reset
    var _defaultReset = function() {
        $('.remote-output').empty();
    };
    $(document).bind(RESET_EVENT, _defaultReset);
    
    // TODO fix for Safari 3
    // if ($.browser.msie)
    // else if hash != _currentHash
    // else check history length

    if ($.browser.msie) {

        var _historyIframe, initialized = false; // for IE

        // add hidden iframe
        $(function() {
            _historyIframe = $('<iframe style="display: none; src="document.open();document.write(\"<scr\"+\"ipt>document.domain=\''+document.domain+'\';</scr\"+\"ipt>\");document.close();"></iframe>').appendTo(document.body).get(0);
            // attempts to access the iframe before the document.write has had time to take effect causes access denied errors.
            // var iframe = _historyIframe.contentWindow.document;
            //             // create initial history entry
            //             iframe.open();
            //             iframe.close();
            //             if (_currentHash && _currentHash != '#') {
            //                 iframe.location.hash = _currentHash.replace('#', '');
            //             }
        });

        this.update = function(hash) {
            _currentHash = hash;
            var iframe = _historyIframe.contentWindow.document;
            iframe.open();
            iframe.close();
            iframe.location.hash = hash.replace('#', '');
        };

        _observeHistory = function() {
            var iframe = _historyIframe.contentWindow.document;
            var iframeHash = iframe.location.hash;
            if (iframeHash != _currentHash) {
                _currentHash = iframeHash;
                if (iframeHash && iframeHash != '#') {
                    // order does matter, set location.hash after triggering the click...
                    $('a[@href$="' + iframeHash + '"]').click();
                    location.hash = iframeHash;
                } else if (initialized) {
                    location.hash = '';
                    $(document).trigger(RESET_EVENT);
                }
            }
            initialized = true;
        };

    } else if ($.browser.mozilla || $.browser.opera) {

        this.update = function(hash) {
            _currentHash = hash;
        };

        _observeHistory = function() {
            if (location.hash) {
                if (_currentHash != location.hash) {
                    _currentHash = location.hash;
                    $('a[@href$="' + _currentHash + '"]').click();
                }
            } else if (_currentHash) {
                _currentHash = '';
                $(document).trigger(RESET_EVENT);
            }
        };

    } else if ($.browser.safari) {

        var _backStack, _forwardStack, _addHistory; // for Safari

        // etablish back/forward stacks
        $(function() {
            _backStack = [];
            _backStack.length = history.length;
            _forwardStack = [];

        });
        var isFirst = false, initialized = false;
        _addHistory = function(hash) {
            _backStack.push(hash);
            _forwardStack.length = 0; // clear forwardStack (true click occured)
            isFirst = false;
        };

        this.update = function(hash) {
            _currentHash = hash;
            _addHistory(_currentHash);
        };

        _observeHistory = function() {
            var historyDelta = history.length - _backStack.length;
            if (historyDelta) { // back or forward button has been pushed
                isFirst = false;
                if (historyDelta < 0) { // back button has been pushed
                    // move items to forward stack
                    for (var i = 0; i < Math.abs(historyDelta); i++) _forwardStack.unshift(_backStack.pop());
                } else { // forward button has been pushed
                    // move items to back stack
                    for (var i = 0; i < historyDelta; i++) _backStack.push(_forwardStack.shift());
                }
                var cachedHash = _backStack[_backStack.length - 1];
                $('a[@href$="' + cachedHash + '"]').click();
                _currentHash = location.hash;
            } else if (_backStack[_backStack.length - 1] == undefined && !isFirst) {
                // back button has been pushed to beginning and URL already pointed to hash (e.g. a bookmark)
                // document.URL doesn't change in Safari
                if (document.URL.indexOf('#') >= 0) {
                    $('a[@href$="' + '#' + document.URL.split('#')[1] + '"]').click();
                } else if (initialized) {
                    $(document).trigger(RESET_EVENT);
                }
                isFirst = true;
            }
            initialized = true;
        };

    }

    this.initialize = function(callback) {
        // custom callback to reset app state (no hash in url)
        if (typeof callback == 'function') {
            $(document).unbind(RESET_EVENT, _defaultReset).bind(RESET_EVENT, callback);
        }
        // look for hash in current URL (not Safari)
        if (location.hash && typeof _addHistory == 'undefined') {
            $('a[@href$="' + location.hash + '"]').trigger('click');
        }
        // start observer
        if (_observeHistory && _intervalId == null) {
            _intervalId = setInterval(_observeHistory, 200); // Safari needs at least 200 ms
        }
    };

};

/**
 * Implement Ajax driven links in a completely unobtrusive and accessible manner (also known as "Hijax")
 * with support for the browser's back/forward navigation buttons and bookmarking.
 *
 * The link's href attribute gets altered to a fragment identifier, such as "#remote-1", so that the browser's
 * URL gets updated on each click, whereas the former value of that attribute is used to load content via
 * XmlHttpRequest from and update the specified element. If no target element is found, a new div element will be
 * created and appended to the body to load the content into. The link informs the history manager of the 
 * state change on click and adds an entry to the browser's history.
 *
 * jQuery's Ajax implementation adds a custom request header of the form "X-Requested-With: XmlHttpRequest"
 * to any Ajax request so that the called page can distinguish between a standard and an Ajax (XmlHttpRequest)
 * request.
 *
 * @example $('a.remote').remote('#output');
 * @before <a class="remote" href="/path/to/content.html">Update</a>
 * @result <a class="remote" href="#remote-1">Update</a>
 * @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from
 *       "/path/to/content.html" via XmlHttpRequest into an element with the id "output".
 * @example $('a.remote').remote('#output', {hashPrefix: 'chapter'});
 * @before <a class="remote" href="/path/to/content.html">Update</a>
 * @result <a class="remote" href="#chapter-1">Update</a>
 * @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from
 *       "/path/to/content.html" via XmlHttpRequest into an element with the id "output".
 *
 * @param String expr A string containing a CSS selector or basic XPath specifying the element to load
 *                    content into via XmlHttpRequest.
 * @param Object settings An object literal containing key/value pairs to provide optional settings.
 * @option String hashPrefix A String that is used for constructing the hash the link's href attribute
 *                           gets altered to, such as "#remote-1". Default value: "remote-".
 * @param Function callback A single function that will be executed when the request is complete. 
 * @type jQuery
 *
 * @name remote
 * @cat Plugins/Remote
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */

/**
 * Implement Ajax driven links in a completely unobtrusive and accessible manner (also known as "Hijax")
 * with support for the browser's back/forward navigation buttons and bookmarking.
 *
 * The link's href attribute gets altered to a fragment identifier, such as "#remote-1", so that the browser's
 * URL gets updated on each click, whereas the former value of that attribute is used to load content via
 * XmlHttpRequest from and update the specified element. If no target element is found, a new div element will be
 * created and appended to the body to load the content into. The link informs the history manager of the 
 * state change on click and adds an entry to the browser's history.
 *
 * jQuery's Ajax implementation adds a custom request header of the form "X-Requested-With: XmlHttpRequest"
 * to any Ajax request so that the called page can distinguish between a standard and an Ajax (XmlHttpRequest)
 * request.
 *
 * @example $('a.remote').remote( $('#output > div')[0] );
 * @before <a class="remote" href="/path/to/content.html">Update</a>
 * @result <a class="remote" href="#remote-1">Update</a>
 * @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from
 *       "/path/to/content.html" via XmlHttpRequest into an element with the id "output".
 * @example $('a.remote').remote('#output', {hashPrefix: 'chapter'});
 * @before <a class="remote" href="/path/to/content.html">Update</a>
 * @result <a class="remote" href="#chapter-1">Update</a>
 * @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from
 *       "/path/to/content.html" via XmlHttpRequest into an element with the id "output".
 *
 * @param Element elem A DOM element to load content into via XmlHttpRequest.
 * @param Object settings An object literal containing key/value pairs to provide optional settings.
 * @option String hashPrefix A String that is used for constructing the hash the link's href attribute
 *                           gets altered to, such as "#remote-1". Default value: "remote-".
 * @param Function callback A single function that will be executed when the request is complete. 
 * @type jQuery
 *
 * @name remote
 * @cat Plugins/Remote
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
$.fn.remote = function(output, settings, callback) {

    callback = callback || function() {};
    if (typeof settings == 'function') { // shift arguments
        callback = settings;
    }
    
    settings = $.extend({
        hashPrefix: 'remote-'
    }, settings || {});

    var target = $(output).size() && $(output) || $('<div></div>').appendTo('body');
    target.addClass('remote-output');

    return this.each(function(i) {
        var href = this.href, hash = '#' + (this.title && this.title.replace(/\s/g, '_') || settings.hashPrefix + (i + 1)),
            a = this;
        this.href = hash;
        $(this).click(function(e) {
            // lock target to prevent double loading in Firefox
            if (!target['locked']) {
                // add to history only if true click occured, not a triggered click
                if (e.clientX) {
                    $.ajaxHistory.update(hash);
                }
                target.load(href, function() {
                    target['locked'] = null;
                    callback.apply(a);
                });
            }
        });
    });

};

/**
 * Provides the ability to use the back/forward navigation buttons in a DHTML application.
 * A change of the application state is reflected by a change of the URL fragment identifier.
 *
 * The link's href attribute needs to point to a fragment identifier within the same resource,
 * although that fragment id does not need to exist. On click the link changes the URL fragment
 * identifier, informs the history manager of the state change and adds an entry to the browser's
 * history.
 *
 * @param Function callback A single function that will be executed as the click handler of the 
 *                          matched element. It will be executed on click (adding an entry to 
 *                          the history) as well as in case the history manager needs to trigger 
 *                          it depending on the value of the URL fragment identifier, e.g. if its 
 *                          current value matches the href attribute of the matched element.
 *                           
 * @type jQuery
 *
 * @name history
 * @cat Plugins/History
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
$.fn.history = function(callback) {
    return this.click(function(e) {        
		// add to history only if true click occured,
		// not a triggered click...
        if (e.clientX) {
	        // ...and die if already active
			if (this.hash == location.hash) {
				return false;
			} 
           	$.ajaxHistory.update(this.hash);
        }
		if (typeof callback == 'function') {
			callback.call(this);
		}
    });
};

})(jQuery);

/*
var logger;
$(function() {
    logger = $('<div style="position: fixed; top: 0; overflow: hidden; border: 1px solid; padding: 3px; width: 120px; height: 150px; background: #fff; color: red;"></div>').appendTo(document.body);
});
function log(m) {    
    logger.prepend(m + '<br />');
};
*/



// Crunch Insert -  Fri Nov 6 16:54:46 EST 2009

eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(5($){$.K.w=5(b,c){2(3.7==0)6;2(14 b==\'15\'){c=(14 c==\'15\')?c:b;6 3.L(5(){2(3.M){3.N();3.M(b,c)}v 2(3.17){4 a=3.17();a.1x(O);a.1y(\'P\',c);a.18(\'P\',b);a.1z()}})}v{2(3[0].M){b=3[0].1A;c=3[0].1B}v 2(Q.R&&Q.R.19){4 d=Q.R.19();b=0-d.1C().18(\'P\',-1D);c=b+d.1E.7}6{t:b,S:c}}};4 q={\'9\':"[0-9]",\'a\':"[A-T-z]",\'*\':"[A-T-1a-9]"};$.1b={1F:5(c,r){q[c]=r}};$.K.U=5(){6 3.1G("U")};$.K.1b=5(m,n){n=$.1H({C:"1I",V:B},n);4 o=D W("^"+$.1J(m.1c(""),5(c,i){6 q[c]||((/[A-T-1a-9]/.1d(c)?"":"\\\\")+c)}).1e(\'\')+"$");6 3.L(5(){4 d=$(3);4 f=D 1f(m.7);4 g=D 1f(m.7);4 h=u;4 j=u;4 l=B;$.L(m.1c(""),5(i,c){g[i]=(q[c]==B);f[i]=g[i]?c:n.C;2(!g[i]&&l==B)l=i});5 X(){x();y();1g(5(){$(d[0]).w(h?m.7:l)},0)};5 Y(e){4 a=$(3).w();4 k=e.Z;j=(k<16||(k>16&&k<10)||(k>10&&k<1h));2((a.t-a.S)!=0&&(!j||k==8||k==1i)){E(a.t,a.S)}2(k==8){11(a.t-->=0){2(!g[a.t]){f[a.t]=n.C;2($.F.1K){s=y();d.G(s.1j(0,a.t)+" "+s.1j(a.t));$(3).w(a.t+1)}v{y();$(3).w(1k.1l(l,a.t))}6 u}}}v 2(k==1i){E(a.t,a.t+1);y();$(3).w(1k.1l(l,a.t));6 u}v 2(k==1L){E(0,m.7);y();$(3).w(l);6 u}};5 12(e){2(j){j=u;6(e.Z==8)?u:B}e=e||1M.1N;4 k=e.1O||e.Z||e.1P;4 a=$(3).w();2(e.1Q||e.1R){6 O}v 2((k>=1h&&k<=1S)||k==10||k>1T){4 p=13(a.t-1);2(p<m.7){2(D W(q[m.H(p)]).1d(1m.1n(k))){f[p]=1m.1n(k);y();4 b=13(p);$(3).w(b);2(n.V&&b==m.7)n.V.1U(d)}}}6 u};5 E(a,b){1o(4 i=a;i<b&&i<m.7;i++){2(!g[i])f[i]=n.C}};5 y(){6 d.G(f.1e(\'\')).G()};5 x(){4 a=d.G();4 b=0;1o(4 i=0;i<m.7;i++){2(!g[i]){f[i]=n.C;11(b++<a.7){4 c=D W(q[m.H(i)]);2(a.H(b-1).1p(c)){f[i]=a.H(b-1);1V}}}}4 s=y();2(!s.1p(o)){d.G("");E(0,m.7);h=u}v h=O};5 13(a){11(++a<m.7){2(!g[a])6 a}6 m.7};d.1W("U",5(){d.I("N",X);d.I("1q",x);d.I("1r",Y);d.I("1s",12);2($.F.1t)3.1u=B;v 2($.F.1v)3.1X(\'1w\',x,u)});d.J("N",X);d.J("1q",x);d.J("1r",Y);d.J("1s",12);2($.F.1t)3.1u=5(){1g(x,0)};v 2($.F.1v)3.1Y(\'1w\',x,u);x()})}})(1Z);',62,124,'||if|this|var|function|return|length||||||||||||||||||||||begin|false|else|caret|checkVal|writeBuffer|||null|placeholder|new|clearBuffer|browser|val|charAt|unbind|bind|fn|each|setSelectionRange|focus|true|character|document|selection|end|Za|unmask|completed|RegExp|focusEvent|keydownEvent|keyCode|32|while|keypressEvent|seekNext|typeof|number||createTextRange|moveStart|createRange|z0|mask|split|test|join|Array|setTimeout|41|46|substring|Math|max|String|fromCharCode|for|match|blur|keydown|keypress|msie|onpaste|mozilla|input|collapse|moveEnd|select|selectionStart|selectionEnd|duplicate|100000|text|addPlaceholder|trigger|extend|_|map|opera|27|window|event|charCode|which|ctrlKey|altKey|122|186|call|break|one|removeEventListener|addEventListener|jQuery'.split('|'),0,{}))

// Crunch Insert -  Fri Nov 6 16:54:46 EST 2009

/* Microsoft Audience Extension tag - 7/23/09 */
jQuery(function(){
    MSEXT_domain = document.location.host.split('.');
    MSEXT_domain = MSEXT_domain[(MSEXT_domain.length - 2)];
    MSEXT_path = document.location.pathname.split('/');
    MSEXT_request = document.location.protocol + "//view.atdmt.com/action/MSFT_CondeNet_AE_ExtData/v3/atc1." + MSEXT_domain;
    MSEXT_request += (MSEXT_path[1] != '' && MSEXT_path[1] != undefined) ? "/atc2." + MSEXT_path[1] : '';
    MSEXT_request += (MSEXT_path[2] != '' && MSEXT_path[2] != undefined) ? "/atc3." + MSEXT_path[2] : '';
    MSEXT_request += '/';
    jQuery('body').append('<img src="'+MSEXT_request+'" height="1" width="1" border="0" />');
});


// Crunch Insert -  Fri Nov 6 16:54:46 EST 2009

// Check whether string s is empty.

function isEmpty(s){
	s = trim(s);
	return ((s == null) || (s.length == 0))
}

function isEmail(email){
	var pattern = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
	return trim(email).match(pattern);
}

function trim(s) {
	 if (s != null) {
	 	 return s.replace(/^\s+|\s+$/, '');
	 }
	 return "";
}

function isAlphanumeric(s){
	var pattern = /^[a-zA-Z0-9]+$/;
	return s.match(pattern);
}

function isValidZip(s){
	if(isEmpty(s)){
		return false;
	}	
	return s.match(/^[0-9]{5}(|-[0-9]{4})$/);
}

function isValidPostalCode(s){
	if(isEmpty(s)){
		return false;
	}
	return s.match(/^[a-zA-Z][0-9][a-zA-Z](|\s|-)[0-9][a-zA-Z][0-9]$/);
}

// Crunch Insert -  Fri Nov 6 16:54:46 EST 2009

/* 
this code adds the hover layer on the print botton across the site. it's an HP promotion.
/fashion/dresses/feature/article/175725/
roll mouse over print button
 */
jQuery(function(){
  jQuery('a#print').hover(
    function() {
      /*in*/
      if (jQuery('#hp_print_promo_image').length == 0) {
        jQuery('body').append('<map name="hp_promo_print_map"><area href="#" onclick="goPrintPage();" shape="rect" coords="149,0,205,19"><area href="http://ad.doubleclick.net/jump/brd.other/_default;sz=254x45;ord=27828?" target="_blank" shape="rect" coords="0,20,216,44"></map><div id="hp_print_promo_image" style="display:none; position: absolute;"><img src="http://ad.doubleclick.net/ad/brd.other/_default;sz=254x45;ord=27828?" usemap="#hp_promo_print_map" /></div>');
        jQuery('#hp_print_promo_image img').bind("mouseleave",function(){ jQuery('#hp_print_promo_image').fadeOut("slow") });
      }
      var special_width = (153 - parseInt(jQuery('a#print img').css('margin-left')));
      jQuery('#hp_print_promo_image').css({top: jQuery('a#print img').position().top + 'px'});
      jQuery('#hp_print_promo_image').css({left: jQuery('a#print img').position().left-special_width + 'px'});
      jQuery('#hp_print_promo_image').css({display: 'block'})
    }, 
    function(){
      /*out*/
      //do nothing.
    }
  );
});

