1 /**
  2  * Copyright (c) 2008 Brad Harris - bmharris@gmail.com
  3  * http://slikcalc.selfcontained.us
  4  * Code licensed under the MIT License:
  5  * http://www.opensource.org/licenses/mit-license.php
  6  * version X.X
  7  */
  8  
  9 var slikcalc;
 10 if(!slikcalc) {
 11 	slikcalc = {};
 12 }else if (typeof slikcalc != 'object') {
 13 	throw new Error('slikcalc already exists and is not an object');
 14 }
 15 
 16 /**
 17  * @namespace slikcalc
 18  */
 19 slikcalc = {
 20 	
 21 	/**
 22 	 * @description Reference to 3rd party library slikcalc adapter
 23 	 */
 24 	adapter : null,
 25 	
 26 	/**
 27 	 * @description Gets the elements value.  This handles getting actual input values, 
 28 	 * or inner text of an element, depending on the type of element
 29 	 * @param {String/HTMLElement} el Element id or reference
 30 	 * @returns {String} Elements value or innerHTML
 31 	 */
 32 	getValue : function(el) {
 33 		var value = null, element = this.get(el);
 34 		if(element !== null) {
 35 			value = this.isInput(element) ? element.value : element.innerHTML;
 36 		}
 37 		return value;
 38 	},
 39 	
 40 	/**
 41 	 * @description Sets elements value or innerHTML depending on element type
 42 	 * @param {String/HTMLElement} el Element ID or reference
 43 	 * @param {String} value Value to set for the element passed in
 44 	 */
 45 	
 46 	setValue : function(el, value) {
 47 		var element = this.get(el);
 48 		if(element !== null) {
 49 			if(this.isInput(element)) {
 50 				element.value = value;
 51 			}else {
 52 				element.innerHTML = value;
 53 			}
 54 		}
 55 	},
 56 	
 57 	/**
 58 	 * @description Returns an elements value or innerHTML as a float formatted as currency
 59 	 * @param {String/HTMLElement} Element ID or reference
 60 	 * @returns {Float} Float value of element, formatted as currency
 61 	 */
 62 	
 63 	getAmount : function(el) {
 64 		var amount = this.getValue(el);
 65 		amount = amount !== null ? parseFloat(this.formatCurrency(amount)) : parseFloat(this.formatCurrency(0));
 66 		return amount;
 67 	},
 68 	
 69 	/**
 70 	 * @description Sets elements value or innerHTML depending on element type formatted as currency
 71 	 * @param {String/HTMLElement} el Element ID or reference to set
 72 	 * @param {String/Number} value Amount to set, can be a string or number
 73 	 */
 74 	setAmount : function(el, value) {
 75 		this.setValue(el, this.formatCurrency(value));
 76 	},
 77 	
 78 	/**
 79 	 * @description Determines if the element passed in is an HTML input
 80 	 * @param {String/HTMLElement} element
 81 	 * @returns {Boolean} true/false if the element is an HTML input
 82 	 */
 83 	isInput : function(element) {
 84 		return element.tagName === 'INPUT' || element.tagName === 'TEXTAREA' || element.tagName === 'SELECT';
 85 	},
 86 
 87 	/**
 88 	 * @description returns a Float of two decimal places from the provided String/Number.  
 89 	 * Returns 0.00 if no number or an improperly formatted String is passed in
 90 	 * @param {String/Number} num
 91 	 * @return {Float} Float value of set to two decimal places.
 92 	 */
 93 	formatCurrency : function(num) {
 94 		num = isNaN(num) || num === '' || num === null ? 0.00 : num;
 95 		return parseFloat(num).toFixed(2);
 96     },
 97 	
 98 	/**
 99 	 * @description Removes whitespace from the head/tail of a string
100 	 * @param {String} string
101 	 * @returns {String}
102 	 */
103     trim : function(string) {
104 		return string.replace(/^\s+|\s+$/g, '');
105 	},
106 	
107 	/**
108 	 * @description Retrieves an HTML Element by delegating to the adapter library.
109 	 * @param {String/HTMLElement} id
110 	 */
111 	get : function(id) {
112 		this.validateAdapter();
113 		return this.adapter.get(id);
114 	},
115 	
116 	/**
117 	 * @description Ensures that the slikcalc 3rd party library adapter has been set.
118 	 */
119 	validateAdapter : function() {
120 	    if(this.adapter === null) {
121 			throw new Error('slikcalc requires an external javascript library adapter');
122 		}
123 	},
124 	
125 	/**
126 	 * @description Adds an event listener to the element passed in.
127 	 * @param {String/HTMLElement} elementId Element to attach event to
128 	 * @param {String} type String representation of the type of event to attach to
129 	 * @param {Function} method Reference to a callback method to fire when the event fires
130 	 * @param {Object} scope (Optional) Scope object to use when executing the callback if required
131 	 */
132 	addListener : function(elementId, type, method, scope) {
133 		this.validateAdapter();
134 		this.adapter.addListener(elementId, type, method, scope);
135 	},
136 	
137 	/**
138 	 * @description Attaches an event to the onLoad event of the page
139 	 * @param {Function} method Reference to a callback method to fire when the onLoad event fires
140 	 * @param {Object} scope (Optional) Scope object to use when executing the callback if required
141 	 */
142 	addOnLoad : function(method, scope) {
143 		this.validateAdapter();
144 		this.adapter.addOnLoad(method, scope);
145 	},
146 	
147 	/**
148 	 * @description Creates a custom event through delegating to the 3rd party library adapter.
149 	 * This custom event is used internally for slikcalc custom events.
150 	 * @param {String} eventType String identifier for custom event type
151 	 * @returns {Object} Custom event object for internal slikcalc use
152 	 */
153 	createCustomEvent : function(eventType) {
154 	    this.validateAdapter();
155 		return this.adapter.createCustomEvent(eventType);
156 	},
157 	
158 	/**
159 	 * @description Binds the provided callback to the custom event passed in.  This delegates to the 3rd party library adapter
160 	 * @param {Object} event Reference to slikcalc custom event
161 	 * @param {Object} method Callback method to bind to the custom event
162 	 * @param {Object} scope (Optional) Scope object to use when executing the callback if required
163 	 */
164 	bindEvent : function(event, method, scope) {
165 	    this.validateAdapter();
166 		this.adapter.bindEvent(event, method, scope);
167 	},
168 	
169 	/**
170 	 * @description Triggers the custom event passed in
171 	 * @param {Object} event Reference to slikcalc custom event to fire
172 	 */
173 	fireEvent : function(event) {
174 	    this.validateAdapter();
175 		this.adapter.fireEvent(event);
176 	},
177 	
178 	/**
179 	 * @description Utility method for class extension.  Copies the prototype of the superclass onto the subclass
180 	 * @param {Object} subc Subclass 
181 	 * @param {Object} superc Superclass
182 	 */
183 	extend : function(subc, superc) {
184 		if (! superc || ! subc) {
185 			throw new Error('slikcalc.extend failed, please check that all dependencies are included.');
186 		}
187 	
188 		var F = function() {};
189 		F.prototype = superc.prototype;
190 		subc.prototype = new F();
191 		subc.prototype.constructor = subc;
192 		subc.prototype.parent = superc.prototype;
193 		subc.prototype.parent.constructor = superc;
194 	},
195 	
196 	/**
197 	 * @description Factory method for creating calculator objects
198 	 * @param {String} type String representing the type of calculator to create.  Either 'column' or 'formula'.
199 	 * @param {Object} config config object for calculator being created, see calculators constructor for options.
200 	 * @returns {slikcalc.BaseCalc} Returns the concrete type of slikcalc.BaseCalc specified
201 	 */
202 	create : function(type, config) {
203 		var calcType = type === 'column' ? slikcalc.ColumnCalc : type === 'formula' ? slikcalc.FormulaCalc : null;
204 		return calcType !== null ? new calcType(config) : null;
205 	}
206 	
207 };