/*!
 * BELL CANADA jQuery JavaScript Library version 1.2018
 *
 * Development Team: Son Pham
 * http://www.bellsolutionsweb.ca/
 *
 * Date: June 10th 14:00:00 2010 -0500
 */
(function($) {
//*******************************************************************
//	Bell: Common utils functions
//
//	developed by: Son Pham
//
//	Date: november 2009
//
//	requirement: jQuery 1.3.2
//
//	description: this function will handle multiple common front-end helper tasks//				
//******************************************************************
/*global jQuery */
jQuery.bell = {
	//*****************************************************
	//  function: $.bell.map()
	//
	//	developed by: Son Pham
	//
	//  description: Maps an HTML with string-placeholder that will replaced by JSon
	//				JSON object (string-placeholder vs Json property)
	//
	//	scenario: you have a JSON object that needs to generate HTML output.  typically
	//			  you need to repeat HTML to fill your JSON.  Use this function when you
	//			  only need to display a list of items.
	//
	//			  if you need to display something like (Title -> List) then use $.bell.mapExtender();
	//
	//	Requirement:	1) jQuery 1.3.2
	//					2) $.bell.mapper() (see below)
	//
	//	template string-placeHolder are:
	//	1) tpl-[property]  : replace property by its value
	//	2) map-index : replace map-index by generic index value
	//
	//	usage:  1) $.bell.map("#myTemplate",jSonObject);
	//			2) $.bell.map($("#myTemplate"),jSonObject);
	//			3) $.bell.map($("#myTemplate"),jSonObject, callBack);	
	//			4) $.bell.map($("#myTemplate"),jSonObject,"myCustomIdForCaching", callBack);
	//
	//	params:
	//	@1 htmlTemplateId (string/object): html element Id representing the output template and element to be replaced.  You can also pass the jQuery object of the element  ex: #myDivTemplate / $("#myDivTemplate")
	//	@2 data (object): JSON object representing the data to be mapped
	//	@3 userMapId (string - optional): You can specify your own mapId.  use this for caching purposes
	//	@4 callBack (function - optional): optionaly you can pass a function as a callBack, and the function
	//				 will contain the map object{html,mapId}
	//				 note: use the callBack when the process flow must be after the mapping process
	//
	//	Extra infos: here are the steps to use the map function
	//	step 1: Identify the HTML that will serve has a template (to be repeated)
	//	step 2: take a look at your JSON object structure !important -> property
	//	step 3: In your template, put the appropriate stringPlaceHolder
	//			example: tpl-sku  and this stringPlaceHolder will be replaced by its value
	//
	//			!important: When you repeat a template and you use the attribute ID, remember
	//			to use "map-index".  This will ensure that you will not have duplicate ID
	//			
	//			example: <div id="myDiv_map-index"></div> -> will output <div id="myDiv_0"></div>
	//
	//	step 4: in your javascript file call the map
	//			example: $.bell.map("#myTemplateId",jSonObject);
	//
	//	!important: We recommand you to hide (display:none) the template so you should add the css className "htmlTemplate"
	//				example: <div id="template_1" class="htmlTemplate">
	//								tpl-title
	//						 </div>	
	//*****************************************************
	map : function(htmlTemplateId, data, userMapId) {
		var validFormatTemplate = false,
			$map, $template, $templateParent, html, 
			identifier, obj, templateHTML,
			mapId, fn;
					
		switch (typeof(htmlTemplateId)) {
			case "object":
				validFormatTemplate = true;
				break;			
			case "string":
				if (htmlTemplateId.indexOf("#") === -1 && htmlTemplateId.indexOf(".") === -1) {
					htmlTemplateId = "#"+htmlTemplateId;
				}
				validFormatTemplate = true;
				break;			
		}
		// params validation
		if (validFormatTemplate) {			
			// get html object			
			$template = $(htmlTemplateId);

			// Only map if template exists
			if ($template.length) {
				if (!this.isEmpty(data)) {
					html = "";
					identifier = 0;
					
					templateHTML = $("<div></div>").append($template.clone()).html();
					
					$.each(data, function(idx, val) {
						// Map process
						if (!val.push) {
							obj = $.bell.mapper(identifier, val, templateHTML, html);
							html = obj.html;							
							identifier = obj.mapIndex;
						} else {
							// Array mapping
							$.each(val, function(index, valueObj) {
								obj = $.bell.mapper(identifier, valueObj, templateHTML, html);
								html = obj.html;								
								identifier = obj.mapIndex;
							});
						}
					});
					
					if (html !== "") {						
						if (!$.isFunction(arguments[2]) && typeof(arguments[2]) !== "undefined") {
							// Create a wrapper around the html to enable easy DOM manipulation after map process. ideal for caching
							mapId = arguments[2];
							$map = $("<div></div>").attr("id",mapId).append(html);
							// Template is being replaced.  You can reuse that template at any point
							$template.after($map);
						} else {
							$templateParent = $template.parent();
							if ($templateParent.length === 0 || $templateParent.get(0).parentNode === null) {
								mapId = "bell-map-"+($.bell.getRandomNumber());
								$map = $("<div></div>").attr("id",mapId).append(html);
								// Template is being replaced.  You can reuse that template at any point
								$template.after($map);
							} else {
								$templateParent.append(html);
								$map = $templateParent;
							}
						}
					}
					
					// callBack
					fn = this.getCallBack(arguments);
					if ($.isFunction(fn)) {
						fn.apply(this, [$map]);	
					}
				} 
			}
		} 
		return $map;		
	},
	//*****************************************************
	//  function: $.bell.mapper() *** DO NOT USE (internal function for $.bell.map() ***
	//
	//	developed by: Son Pham
	//
	//  description: this function is used in the $.bell.map() in order to make the
	//				 mapping process
	//*****************************************************	
	mapper : function(index, data, templateHTML, html) {
		var stringPlaceHolder;
		
		$.each(data, function(property, value) {
			stringPlaceHolder = "tpl-"+property;
			// mapping the content
			templateHTML = templateHTML.replace(new RegExp(stringPlaceHolder,"gi"),value);
		});
		// generating index
		templateHTML = templateHTML.replace(/map-index/gi,index);

		// removing htmlTemplate tag
		templateHTML = templateHTML.replace(/htmlTemplate/gi,'htmlMappedJs');

		html += templateHTML;
		index++;

		return {mapIndex: index, html: html};
	},
	//*****************************************************
	//  function: $.bell.mapExtender()
	//
	//	developed by: Son Pham
	//
	//  description: Maps an HTML with string-placeholder that will replaced by JSON data
	//				(string-placeholder vs Json property).  This function
	//				 "extends" the standard $.bell.map() function by iterating sub objects list
	//				 within the JSON object
	//
	//	scenario: you have a JSON object that needs to generate HTML output.  typically
	//			  you need to repeat HTML to fill your JSON.  Your JSON data has two levels
	//			  of structure: e.g usually you have level 1 wich can display a Name and the level2
	//			  displays a list of items of that name  (Title -> List)
	//
	//	Requirement:	1) jQuery 1.3.2
	//					2) $.bell.map()
	//					3) $.bell.mapper()
	//
	//	template string-placeHolder are:
	//	1) tpl-[property]  : replace property by its value
	//	2) map-index : replace map-index by generic index value
	//	3) map-parent-index : only used in the extended template to use the map-indexs of the parent (level1)
	//
	//	usage:  1) $.bell.mapExtender("#myTemplate",jSonObject);
	//			2) $.bell.mapExtender($("#myTemplate"),jSonObject);
	//			3) $.bell.mapExtender($("#myTemplate"),jSonObject, callBack);
	//			4) $.bell.mapExtender($("#myTemplate"),jSonObject,"myCachedId", callBack);	
	//
	//	params:
	//	@1 htmlTemplateId (string/object): html element Id representing the output template and element to be replaced.  You can also pass the jQuery object of the element  ex: #myDivTemplate / $("#myDivTemplate")
	//	@2 data (object): JSON object representing the data to be mapped
	//	@3 userMapId (string - optional): You can specify your own mapId.  If not specified the default one will be generated
	//	@3 callBack (function - optional): optionaly you can pass a function as a callBack, and the function
	//				 will contain the map object{html,mapId}
	//				 note: use the callBack when the process flow must be after the mapping process
	//
	//	!IMPORTANT: the id of the extended template MUST be the same as the parent id that you append -extended
	//				also we recommand you to hide (display:none) the template so you should add the css className "htmlTemplate"
	//
	//				example: <div id="template_1" class="htmlTemplate">
	//								tpl-title
	//								<div id="template_1-extended">
	//									tpl-description
	//								</div>
	//						 </div>
	//*****************************************************
	mapExtender: function(htmlTemplateId, data, userMapId) {
		var validFormatTemplate = false,
			$map, $template, $templateParent, html, obj,					
			templateHTML, mapExtenderTemplateId,
			mapId, fn;

		switch (typeof(htmlTemplateId)) {
			case "object":
				validFormatTemplate = true;
				break;			
			case "string":
				if (htmlTemplateId.indexOf("#") === -1 && htmlTemplateId.indexOf(".") === -1) {
					htmlTemplateId = "#"+htmlTemplateId;
				}
				validFormatTemplate = true;
				break;			
		}
		// params validation
		if (validFormatTemplate) {
			
			// get html object			
			$template = $(htmlTemplateId);
			
			// Only map if template exists
			if ($template.length) {
				if (!this.isEmpty(data)) {
					html = "";
					
					templateHTML = $("<div></div>").append($template.clone()).html();
					// different from regular map is the mapExtender Template
					mapExtenderTemplateId = $template.attr("id")+"-extended";

					$.each(data, function(idx, val) {
						// Map process
						if (!val.push) {
							// Object mapping (Object -> Object)
							obj = $.bell.mapperExtender(idx, val, templateHTML, mapExtenderTemplateId, html);
							html = obj.html;
						} else {
							// Array mapping (Object -> Array)
							$.each(val, function(index, valueObj) {
								// Object -> Array -> Objects
								obj = $.bell.mapperExtender(idx, val, templateHTML, mapExtenderTemplateId, html);
								html = obj.html;
							});
						}
					});

					if (html !== "") {
						html = html.replace(/htmlTemplate/gi,"htmlMappedJs");
						if (!$.isFunction(arguments[2]) && typeof(arguments[2]) !== "undefined") {
							// Create a wrapper around the html to enable easy DOM manipulation after map process.  Ideal for caching
							mapId = arguments[2];
							$map = $("<div></div>").attr("id",mapId).append(html);
							// Template is being replaced.  You can reuse that template at any point
							$template.after($map);
						} else {
							$templateParent = $template.parent();
							if ($templateParent.length === 0 || $templateParent.get(0).parentNode === null) {
								mapId = "bell-mapExtender-"+($.bell.getRandomNumber());
								$map = $("<div></div>").attr("id",mapId).append(html);
								// Template is being replaced.  You can reuse that template at any point
								$template.after($map);
							} else {
								$templateParent.append(html);
								$map = $templateParent;								
							}
						}
					} 
					// callBack
					fn = this.getCallBack(arguments);
					if ($.isFunction(fn)) {
						fn.apply(this, [$map]);
					}
				} 
			}
		}
		return $map;		
	},
	//*****************************************************
	//  function: $.bell.mapper() *** DO NOT USE (internal function for $.bell.map() ***
	//
	//	developed by: Son Pham
	//
	//  description: this function is used in the $.bell.map() in order to make the
	//				 mapping process
	//*****************************************************	
	mapperExtender : function(index, data, templateHTML, mapExtenderTemplateId, html) {
		var $dump, stringPlaceHolder,
			mapTemplateId, mapTemplateId_tmp, $extendedTemplate, 
			extendedTemplateHTML, $template;

		$.each(data, function(property, value) {
			stringPlaceHolder = "tpl-"+property;
			
			// First we map non-object property.  This is the first level
			if (typeof(value)!=="object" && templateHTML.indexOf(stringPlaceHolder) !== -1) {
				// mapping the content not in the extended template
				templateHTML = templateHTML.replace(new RegExp(stringPlaceHolder,"gi"),value);
				return {html:templateHTML};
				
			} else if (typeof(value)==="object") {
				$dump = $("<div></div>");

				// manipulate parent map-index
				mapTemplateId = mapExtenderTemplateId.replace("-extended","");
				mapTemplateId_tmp = mapTemplateId.replace("map-index",index);
				templateHTML = templateHTML.replace(mapTemplateId, mapTemplateId_tmp);

				// extract extented template
				$("body").append($dump.hide().append(templateHTML));
				$extendedTemplate = $dump.find("#"+mapExtenderTemplateId);
				$dump.remove();

				// manipulate map-index from the extented template
				extendedTemplateHTML = $("<div></div>").append($extendedTemplate).html();
				
				// parent map-index must be applied in extended template 
				extendedTemplateHTML = extendedTemplateHTML.replace(/map-index/gi,"map-parent-index-map-index");

				// map value data
				$.bell.map($(extendedTemplateHTML), value, function($mapObj) {
					// insert extented mapped html in the parent container
					$template = $(templateHTML);
					$("#"+mapExtenderTemplateId,$template).before($mapObj.html()).remove();
					
					html += $("<div></div>").append($template).html();

					// map-parent-index replacement in the extended HTML
					html = html.replace(/map-parent-index/gi,index);
				});
			}
		});
		return {html:html};			
	},
	// *** DO NOT USE internal usage ****
	getCallBack: function(args) {
		var fn = null, i;
		for (i=0;i<args.length;i++) {
			if ($.isFunction(args[i])) {
				return args[i];	
			}
		}
		return fn;
	},
	// *** DO NOT USE internal usage ****	
	runCallBack: function(args) {
		var randomVar = "bellCallBack_"+this.getRandomNumber(5);
		/*global window, setTimeout, clearTimeout */
		window[randomVar] = setTimeout(function() {
			clearTimeout(window[randomVar]);
			var fn = $.bell.getCallBack(args);
			if (fn !== null) { fn.call(); }		
		}, 1);
	},
	//*****************************************************
	//  function: $.bell.fillDropDown()
	//
	//	developed by: Son Pham
	//
	//  description: Add select Options in an existing select element. if data is empty
	//				 then if the select element exists its will removed it from DOM
	//
	//	scenario: you have a "dropdown" or "select element" that you want to add (fill) "option" item
	//			  based on an Object -> Object / Array -> Object	  
	//
	//	Requirement: jQuery 1.3.2
	//				 all parameters are mandatory excepts the selectedValue
	//
	//	usage: $.bell.fillDropDown("#myTemplate",jSonObject,"id","label",3);
	//
	//	params:
	//	@1 elementId (string): html element Id representing the output template and element to be replaced  ex: #mySelect
	//	@2 data (object): JSON object representing the data that will fill the select element.  Data can be
	//					  an Object -> Object / Array -> Object
	//	@3 propertyValue (string): property that will be the option value
	//	@4 propertyText (string): property that will be the option Text
	//	@5 selectedValue (mixed string or number) : if propertyValue matches the selectedValue, the option will be selected
	//*****************************************************	
	fillDropDown: function(elementId, data, propertyValue, propertyText, selectedValue) {
		var $element = $(elementId), html = "", selected;
		
		if ($element.length) {
			if (!this.isEmpty(data)) {
				$.each(data, function(idx, val){
					if (!val.push) {
						selected  = val[propertyValue] == selectedValue? "selected" : "";
						html += "<option value='"+val[propertyValue]+"' "+selected+">"+val[propertyText]+"</option>";
					} else {
						$.each(val, function(subIdx, value) {
							selected  = value[propertyValue] == selectedValue? "selected" : "";
							html += "<option value='"+value[propertyValue]+"' "+selected+">"+value[propertyText]+"</option>";
						});
					}
				});
			} 
			
			if (html !== "") {
				$element.empty().append(html);
			} else {
				$element.remove();	
			}
		}
		this.runCallBack(arguments);
	},
	//*****************************************************
	//  function: $.bell.setElementActive()
	//
	//	developed by: Son Pham
	//
	//  description: This function will set a given activeClassName among
	//				 of a common groupClassName.
	//
	//				you can also use setElementActive multiple times on the same
	//				element to perform different task for instance in step1 you 
	//				may want to set the step1 active element when the user clicks
	//				a radio button while at the same time setting element option radio
	//				button 1 in step2
	//
	//	scenario: you have a list of div's containing radio buttons and when
	//			  you select a radio button you want to set an active css className to
	//			  the selected div
	//
	//	Requirement: jQuery 1.3.2
	//
	//	usage:  1) $.bell.setElementActive(this,"commonClassName","myActiveClassName");
	//			2) $.bell.setElementActive($("#myHTMLElementId"),"commonClassName","myActiveClassName");
	//
	//	params:
	//	@1 currentObject (object): html object representing the selected html element 
	//							   this object will determinate the selected one
	//	@2 selector (string): indicates which group of HTML elements that are binded togheter
	//	@3 activeClassName (string): CSS ClassName that will be added once the selected element have been found
	//*****************************************************
	setElementActive : function(currentObject,selector,activeClassName) {
		var $selector, selectorArr, groupClassName, $element;
		
		if (currentObject) {		
			//string support //backward compatibility
			if (!/\./.test(selector)) {
				selector = "."+selector;	
			}
			
			// reset group
			$selector = $(selector);
			$selector.each(function() {
				$(this).removeClass(activeClassName);
			});
	
			// set active
			selectorArr = selector.split(".");
			if (selectorArr.length) {
				groupClassName = selectorArr[1];
	
				if (currentObject instanceof jQuery === false) { currentObject = $(currentObject); }
				$element = currentObject;
				if ($element.get(0)) {
					if ($element.get(0).nodeName === "INPUT") {
						try {
							$element.attr("checked",true);
						} catch(e) {}
					}
				}
				if ($element.hasClass(groupClassName)) {
					$element.addClass(activeClassName);
				} else if ($element.find("."+groupClassName).length) {
					$element.find("."+groupClassName+":first").addClass(activeClassName);
				} else {
					$element.parents("."+groupClassName+":first").each(function() {
						$(this).addClass(activeClassName);
						return false;
					});
				}
			}
		}
		this.runCallBack(arguments);
	},
	//*****************************************************
	//  function: $.bell.setCheckBoxState()
	//
	//	developed by: Son Pham
	//
	//  description: This function will find and set the state of checkBox (check/uncheck) for
	//				 a given selector parameter. 
	//
	//				 optionaly you can specify an activeClassName to add or remove accordinly to its state
	//
	//	scenario: you want to set the state of a given checkBox sets or single checkbox
	//
	//	Requirement: jQuery 1.3.2
	//
	//	usage:  1) $.bell.setCheckBoxState("#containerOfMultipleCheckBox",false,"capSelected");
	//			2) $.bell.setCheckBoxState("#mySingleCheckBoxInput",false,"capSelected");
	//			3) $.bell.setCheckBoxState("#mySingleCheckBoxInput",true);
	//
	//	params:
	//	@1 selector (object): 1.1 object representing the container html that contains the checkBox
	//						      that you want to apply (multiple or batch process)
	//						  1.2 object representing the single checkBox
	//
	//	@2 state (boolean): true = check / false = uncheck
	//	@3 activeClassName (string): CSS ClassName that will be added once the selected element have been found
	//
	//	Note: if the activeClassName is not on the input itself then you should instead pass the input selector on the
	//		  element that the activeClassName should be applied.  Of cours the input must be a children of that selector
	//*****************************************************
	setCheckBoxState: function(selector, state, activeClassName) {		
		var setCheckBox, processActiveClass, $selector;
		
		setCheckBox = function($checkBox, state, processActiveClass, activeClassName, $targetActiveElement) {
			$checkBox.attr("checked",state);
			if (processActiveClass) {
				if ($targetActiveElement !== null) {
					if (state) {
						$targetActiveElement.addClass(activeClassName);
					} else {
						$targetActiveElement.removeClass(activeClassName);						
					}
				}				
			}

		};
		
		$(selector).each(function() {
			// validation 
			if (typeof(state) !== "boolean") { state = false; }
			
			processActiveClass = false;
			if (typeof(activeClassName) !== "undefined") { processActiveClass = true; }

			$selector = $(this);
			
			if (this.type === "checkbox") {
				setCheckBox($(this), state, processActiveClass, activeClassName, null);
			} else {
				$("input[type='checkbox']", $(this)).each(function() {
					setCheckBox($(this), state, processActiveClass, activeClassName, $selector);															   
				});
			}
		});
		this.runCallBack(arguments);		
	},
	//*****************************************************
	//  function: $.bell.setRadioState()
	//
	//	developed by: Son Pham
	//
	//  description: This function will find and set the state of radio (selected/unSelect) for
	//				 a given selector parameter. 
	//
	//				 optionaly you can specify an activeClassName to add or remove accordinly to its state
	//
	//	scenario: you want to set the state of a given checkBox sets or single radio
	//
	//	Requirement: jQuery 1.3.2
	//
	//	usage:  1) $.bell.setRadioState("#containerOfMultipleCheckBox",false,"capSelected");
	//			2) $.bell.setRadioState("#mySingleCheckBoxInput",false,"capSelected");
	//			3) $.bell.setRadioState("#mySingleCheckBoxInput",true);
	//
	//	params:
	//	@1 selector (object): 1.1 object representing the container html that contains the radio button
	//						      that you want to apply (multiple or batch process)
	//						  1.2 object representing the single radio
	//
	//	@2 state (boolean): true = select / false = unselect
	//	@3 activeClassName (string): CSS ClassName that will be added once the selected element have been found
	//
	//	Note: if the activeClassName is not on the input itself then you should instead pass the input selector on the
	//		  element that the activeClassName should be applied.  Of cours the input must be a children of that selector
	//*****************************************************
	setRadioState: function(selector, state, activeClassName) {		
		var setCheckBox, processActiveClass, $selector;
		
		setCheckBox = function($checkBox, state, processActiveClass, activeClassName, $targetActiveElement) {
			$checkBox.attr("checked",state);
			if (processActiveClass) {
				if ($targetActiveElement !== null) {
					if (state) {
						$targetActiveElement.addClass(activeClassName);
					} else {
						$targetActiveElement.removeClass(activeClassName);						
					}
				}				
			}

		};
		
		$(selector).each(function() {
			// validation 
			if (typeof(state) !== "boolean") { state = false; }
			
			processActiveClass = false;
			if (typeof(activeClassName) !== "undefined") { processActiveClass = true; }

			$selector = $(this);
			
			if (this.type === "radio") {
				setCheckBox($(this), state, processActiveClass, activeClassName, null);
			} else {
				$("input[type='radio']", $(this)).each(function() {
					setCheckBox($(this), state, processActiveClass, activeClassName, $selector);															   
				});
			}
		});
		this.runCallBack(arguments);		
	},
	//*****************************************************
	//  function: $.bell.toggleElementActive()
	//
	//	developed by: Son Pham
	//
	//  description: This function will toggle a given activeClassName on an groupClassName
	//
	//	scenario: you have a checkBox and when the user clicks on the checkbox you want
	//			  to toggle an ActiveClassName on its groupClassName
	//
	//	Requirement: jQuery 1.3.2
	//
	//	usage:  1) $.bell.toggleElementActive('#step3CallJs','capSelected');
	//
	//	params:
	//	@2 selector (string): indicates which selector to toggle the activeClassName
	//	@3 activeClassName (string): CSS ClassName that will be added once the selected element have been found
	//*****************************************************
	toggleElementActive : function(selector,activeClassName) {
		var $element = $(selector);

		// set active
		if ($element.length) {
			if ($element.hasClass(activeClassName)) {
				$element.removeClass(activeClassName);
			} else {
				$element.addClass(activeClassName);				
			}
		}
		this.runCallBack(arguments);
	},
	//*****************************************************
	//  function: $.bell.toggleYesNoActive()
	//
	//	developed by: Son Pham
	//
	//  description: This function will set the activeClassName on YES
	//
	//	scenario: you have a two radio button "yes"/"no" type of question in the same block "div"
	//			  and you want to set ActiveClassName when yes has been clicked
	//
	//			  if you have a YES/NO NOT IN THE SAME block "div", you should use $.bell.setElementActive()
	//
	//	Requirement: jQuery 1.3.2
	//
	//	usage:  1) $.bell.toggleYesNoActive(this,'#step5Js','capSelected');
	//
	//	!important: the value of radio button YES must equal 1
	//
	//	params:
	//	@1 currentObject (object): html object representing the selected html element 
	//							   this object will determinate the selected one
	//	@2 selector (string): indicates which selector to toggle the activeClassName
	//	@3 activeClassName (string): CSS ClassName that will be added once the selected element have been found
	//*****************************************************
	toggleYesNoActive : function(currentObject,selector,activeClassName) {
		var $selector = $(selector),
			$element = $(currentObject);

		// set active
		if ($element.length && $selector.length && activeClassName) {
			if ($element.val() === "1") {
				$selector.addClass(activeClassName);
			} else {
				$selector.removeClass(activeClassName);				
			}
		}
		this.runCallBack(arguments);
	},	
	//*****************************************************
	//  function: $.bell.toggleExclusiveElement()
	//
	//	developed by: Son Pham
	//
	//  description: This function will hide a group of html elements
	//				 and show only the selected element
	//
	//	scenario: you have two or three or more radio buttons that will show
	//			  a group (div) containing elements specific to this selected
	//			  radio button.  Other groups element will be hidden
	//
	//	Requirement: jQuery 1.3.2
	//
	//	usage:  1) $.bell.toggleExclusiveElement("#myHTMLElementId"),"#step1 .commonClassName");
	//
	//	params:
	//	@1 selectedId (string): html element ID of the selected group to be showned 
	//	@2 selector (string): indicates which group of HTML elements that are binded togheter
	//*****************************************************
	toggleExclusiveElement: function(selectedId, selector) {
		var $group;
		
		// reset group
		$(selector).each(function() {
			$group = $(this);
			if ($group.attr("id")) {
				if ($group.attr("id") === selectedId.replace("#","")) {
					$group.show();				
				} else {
					$group.hide();
				}
			}
		});
		this.runCallBack(arguments);
	},
	//*****************************************************
	//  function: $.bell.updateLinkParam()
	//
	//	developed by: Son Pham
	//
	//  description: This function will update a link parameter with a newValue
	//
	//	scenario: you have a dropdown with quantity values and you want to update
	//			  a link parameter when you change the selection.
	//
	//	Requirement: jQuery 1.3.2
	//
	//	usage:  1) $.bell.updateLinkParam(this,"#myLink","parameterName");
	//
	//	params:
	//	@1 currentObject (object): the source element who triggers/called the function
	//	@2 linkId (string): which parameter you want to update its value	
	//	@3 linkParameter (string): new parameter value
	//*****************************************************
	updateLinkParam: function(currentObject, linkId, linkParameter) {
		var $element = $(currentObject), $link,
			linkParams, paramRight, currentValue;
		
		if (linkId.indexOf("#") !== -1) {
			$link = $(linkId);
			if ($link.length > 0 && linkParameter !== "") {
				if ($link.attr("href").indexOf("?") !== -1) {
					linkParams = $link.attr("href").split("?")[1];
					if (linkParams.indexOf(linkParameter+"=") !== -1) {
						paramRight = linkParams.split(linkParameter+"=");
						if (paramRight.length > 0) {
							currentValue = paramRight[1].split("&")[0];
							$link.attr("href",$link.attr("href").replace(linkParameter+"="+currentValue,linkParameter+"="+$element.val()));
						}
					}
				}
			}
		}
	},
	//*****************************************************
	//  function: $.bell.clearLinkParam()
	//
	//	developed by: Son Pham
	//
	//  description: This function will delete/clear a link parameter
	//
	//	scenario: you have a dropdown with quantity values and you want to clear
	//			  a link parameter when you change the selection.
	//
	//	Requirement: jQuery 1.3.2+
	//
	//	usage:  1) $.bell.clearLinkParam("#myLink", "parameterName");
	//
	//	params:
	//	@1 linkId (string): which parameter you want to clear its value	
	//	@2 linkParameter (string): parameter to clear its value
	//*****************************************************
	clearLinkParam: function(linkId, linkParameter) {
		var $link, linkParams, paramRight, currentValue;
		
		if (linkId.indexOf("#") !== -1) {
			$link = $(linkId);
			if ($link.length > 0 && linkParameter !== "") {
				if ($link.attr("href").indexOf("?") !== -1) {
					linkParams = $link.attr("href").split("?")[1];
					if (linkParams.indexOf(linkParameter+"=") !== -1) {
						paramRight = linkParams.split(linkParameter+"=");
						if (paramRight.length > 0) {
							currentValue = paramRight[1].split("&")[0];
							$link.attr("href",$link.attr("href").replace(linkParameter+"="+currentValue,linkParameter+"="));
						}
					}
				}
			}
		}
	},
	//*****************************************************
	//  function: $.bell.toggleDisable()
	//
	//	developed by: Son Pham
	//
	//  description: This function will toggle the disable/enable className of the
	//				 targetted selector and will toggle the disable/enable state of any
	//				 form controls in its child
	//
	//	scenario: you need to toggle the disable/enable target(s) html element(s) and disable/enable
	//			  any child form controls
	//
	//	Requirement: jQuery 1.3.2
	//
	//	usage:  1) $.bell.toggleDisable('#step3 .className','capDisabled','capSelected');
	//
	//	params:
	//	@1 targetElement (string): target html element(s) to put disableClassName
	//	@2 disableClassName (string): the disable className	
	//	@3 activeClassName (string - optional): when disabling you may want to remove the activeClassName
	//*****************************************************	
	toggleDisable: function(targetElement, disableClassName, activeClassName) {
		var $targetElement, argDisable, hasDisableClassName, hasActiveClassName,
			argActive, $element, $input, $control;
		
		// determinate the target(s)
		$targetElement = $(targetElement);

		argDisable = arguments[1];
		hasDisableClassName = argDisable?1:0;
		if (hasDisableClassName) { hasDisableClassName = $.trim(argDisable) !== ""?1:0; }
		
		argActive = arguments[2];
		hasActiveClassName = argActive?1:0;
		if (hasActiveClassName) { hasActiveClassName = $.trim(argActive)!== ""?1:0; }
		
		// toggle Class/disable state
		$targetElement.each(function() {
			$element = $(this);
			if (hasDisableClassName) {
				// enable
				if ($element.hasClass(disableClassName)) {
					$element.removeClass(disableClassName);
					$element.find(":input").each(function() {
						$(this).removeAttr("disabled");
					});
				} else {
					// disable
					$element.addClass(disableClassName);
					$element.find(":input").each(function() {
						$input = $(this);
						$input.attr("disabled", true);
						if (hasActiveClassName) {
							$input.parents("."+activeClassName+":first").each(function() {
								$(this).removeClass(activeClassName);
							});
						}
					});
				}
			} else { 
				$element.find(":input").each(function() {
					$control = $(this);
					if ($control.is(":disabled")) {
						// enable
						$control.removeAttr("disabled");					
					} else {
						// disable
						$control.attr("disabled", true);
						if (hasActiveClassName) {
							$control.parents("."+activeClassName+":first").each(function() {
								$(this).removeClass(activeClassName);
							});
						}
					}
				});			
			}
		});
		this.runCallBack(arguments);
	},
	//*****************************************************
	//  function: $.bell.disable()
	//
	//	developed by: Son Pham
	//
	//  description: This function will set the disable className of the
	//				 targetted selector and will disable state of any
	//				 form controls in its child
	//
	//	scenario: you need to disable target(s) html element(s) and disable
	//			  any child form controls 
	//			  note: if you need to toggle then use $.bell.toggleDisable(...)
	//
	//	Requirement: jQuery 1.3.2
	//
	//	usage:  1) $.bell.disable("#myLink", "capDisabled");
	//			2) $.bell.disable(".myClass", "myDisableClassName");
	//
	//	params:
	//	@1 targetElement (string): target html element(s) to put disableClassName
	//	@2 disableClassName (string): the disable className	
	//	@3 activeClassName (string - optional): when disabling you may want to remove the activeClassName
	//*****************************************************	
	disable: function(targetElement, disableClassName, activeClassName) {
		var $targetElement, argDisable, hasDisableClassName, hasActiveClassName,
			argActive, $element;
		
		// determinate the target(s)
		$targetElement = $(targetElement);
		
		argDisable = arguments[1];
		hasDisableClassName = argDisable?1:0;
		if (hasDisableClassName) { hasDisableClassName = $.trim(argDisable) !== ""?1:0; }
		
		argActive = arguments[2];
		hasActiveClassName = argActive?1:0;
		if (hasActiveClassName) { hasActiveClassName = $.trim(argActive)!== ""?1:0; }
		
		// toggle Class/disable state
		$targetElement.each(function() {
			$element = $(this);
			if (hasDisableClassName) {
				if (disableClassName!=="") {
					$element.addClass(disableClassName);
				}
			}
			if (hasActiveClassName) {
				if ($element.hasClass(activeClassName)){
					$element.removeClass(activeClassName);
				} else if ($element.find("."+activeClassName).length > 0) {
					$element.find("."+activeClassName).each(function() {
						$(this).removeClass(activeClassName);
					});
				} else {
					$element.parents("."+activeClassName+":first").each(function() {
						$(this).removeClass(activeClassName);		 
					});
				}
			}
			if ($element.is(":input")) {
				$element.attr("disabled", true);
			} else {
				$element.find(":input").each(function() {
					$(this).attr("disabled", true);									  
				});
			}				
		});
		this.runCallBack(arguments);
	},
	//*****************************************************
	//  function: $.bell.enable()
	//
	//	developed by: Son Pham
	//
	//  description: This function will set the enable className of the
	//				 targetted selector and will enable state of any
	//				 form controls in its child
	//
	//	scenario: you need to enable target(s) html element(s) and enable
	//			  any child form controls 
	//			  note: if you need to toggle then use $.bell.toggleDisable(...)
	//
	//	Requirement: jQuery 1.3.2
	//
	//	usage:  1) $.bell.enable("#myLink", "capDisabled"); 
	//			2) $.bell.enable(".myClass", "myDisableClassName"); 
	//
	//	params:
	//	@1 targetElement (string): target html element(s) to remove the disableClassName
	//	@2 disableClassName (string): the disable className to be removed
	//*****************************************************	
	enable: function(targetElement, disableClassName) {
		var	$targetElement, argDisable, hasDisableClassName,
			$element;
		
		// determinate the target(s)
		$targetElement = $(targetElement);
		
		argDisable = arguments[1];
		hasDisableClassName = argDisable?1:0;
		if (hasDisableClassName) { hasDisableClassName = $.trim(argDisable) !== ""?1:0; }
		
		// toggle Class/disable state
		$targetElement.each(function() {
			$element = $(this);
			if (hasDisableClassName) {
				if (disableClassName!=="") {
					$element.removeClass(disableClassName);
				}
			} 
			if ($element.is(":input")) {
				$element.removeAttr("disabled");
			} else {
				$element.find(":input").each(function() {
					$(this).removeAttr("disabled");
				});
			}				
		});
		this.runCallBack(arguments);	
	},
	//*****************************************************
	//  function: $.bell.pageRender() *** DO NOT USE THIS FUNCTION use $.pageRender() instead ***
	//
	//	developed by: Son Pham
	//
	//  description: This function is specific to bell.ca and
	//				 when called will perform page layout formatting routines
	//
	//	scenario: You are using ajax call to get Data and use the map function
	//			  to output the data.  The Data pricing needs to be formatted for example
	//
	//	Requirement: jQuery 1.3.2
	//
	//	!important: *** DO NOT USE THIS FUNCTION use $.pageRender() instead ***
	//	usage:  1) $.bell.pageRender("#myDiv"); // only for content in #myDiv
	//			2) $.bell.pageRender(); // all the page
	//
	//	params:
	//	@1 context (string): target html element(s) to apply pageRender
	//	@2 useCase (string): preDefined in bell_master.js will allow to target specific actions
	//*****************************************************	
	pageRender: function(context, useCase) {
		if ($.isFunction($.pageRender)) {
			var fn = $.getCallBack(arguments);
			$.pageRender(context, useCase, fn);
		}		
	},
	//*****************************************************
	//  function: $.bell.getRandomNumber()
	//
	//	developed by: Son Pham
	//
	//  description: will generate a random number (defaults 1-999)
	//
	//	scenario: You need to create unique random ID
	//
	//	Requirement: jQuery 1.3.2
	//
	//	usage:  1) $.bell.getRandomNumber(); // 1-999
	//			2) $.bell.getRandomNumber(5); // 1-99999
	//
	//	params:
	//	@1 numberLength (integer): number range
	//*****************************************************	
	getRandomNumber: function(numberLength) {
		if (isNaN(numberLength)) { numberLength = 3; }
		var strLength = "1", i;
		for (i=0; i<numberLength; i++) {
			strLength += i;
		}
		return Math.floor(Math.random()*parseInt(strLength,10));
	},
	//*****************************************************
	//  function: $.bell.isEmpty() **** PLEASE USE jQuery.isEmptyObject()
	//
	//	developed by: Son Pham
	//
	//  description: will determinate if your data contains items
	//
	//	scenario: You need to check if there is some data before using it
	//
	//	Requirement: 1) jQuery 1.3.2
	//
	//	usage:  1) $.bell.isEmpty({}); // returns true
	//			2) $.bell.isEmpty({id:9874}); // returns false
	//			3) $.bell.isEmpty(""); // returns true	
	//			4) $.bell.isEmpty("blabla"); // returns false
	//
	//	params:
	//	@1 element (anything): only object and string are evaluated
	//*****************************************************
	isEmpty: function(data) {
		var empty = true, i;
		if (typeof(data) === "object") {
			for(i in data){ 
				if (data.hasOwnProperty(i)) {return false;}
			}
		}
		if (typeof(data) === "string") {
			if ($.trim(data).length !== 0) {
				return false;	
			}
		}
		if (typeof(data) === "undefined") {
			return true;
		}
		return empty;
	}
};

})(jQuery);
