1 /**
  2  * DOM
  3  * 
  4  * Dom manipulation module
  5  */
  6 (function (){
  7 
  8 	"use strict";
  9 
 10 	var d;
 11 	
 12 	//Private function for getting/setting attributes/properties
 13 	function _attr(sel, name, value)
 14 	{
 15 		var oldVal, doAttr;
 16 
 17 		//Get the value of the attribute, if it exists
 18 		if (typeof sel.hasAttribute !== "undefined")
 19 		{
 20 			if (sel.hasAttribute(name))
 21 			{
 22 				oldVal = sel.getAttribute(name);
 23 			}
 24 
 25 			doAttr = true;
 26 		}
 27 		else if (typeof sel[name] !== "undefined")
 28 		{
 29 			oldVal = sel[name];
 30 			doAttr = false;
 31 		}
 32 		else if (name === "class" && typeof sel.className !== "undefined") //className attribute
 33 		{
 34 			name = "className";
 35 			oldVal = sel.className;
 36 			doAttr = false;
 37 		}
 38 
 39 		//Well, I guess that attribute doesn't exist
 40 		if (typeof oldVal === "undefined" && (typeof value === "undefined" || value === null))
 41 		{
 42 			console.log(value);
 43 			console.log(sel);
 44 			console.log("Element does not have the selected attribute");
 45 			return;
 46 		}
 47 
 48 		//No value to set? Return the current value
 49 		if (typeof value === "undefined")
 50 		{
 51 			return oldVal;
 52 		}
 53 
 54 		//Determine what to do with the attribute
 55 		if (typeof value !== "undefined" && value !== null)
 56 		{
 57 			if(doAttr === true)
 58 			{
 59 				sel.setAttribute(name, value);
 60 			}
 61 			else
 62 			{
 63 				sel[name] = value;
 64 			} 
 65 		}
 66 		else if (value === null)
 67 		{
 68 			if(doAttr === true)
 69 			{
 70 				sel.removeAttribute(name);
 71 			}
 72 			else
 73 			{
 74 				delete sel[name];
 75 			} 
 76 		}
 77 
 78 		return (typeof value !== "undefined") ? value : oldVal;
 79 	}
 80 	
 81 	function _toCamel(s)
 82 	{
 83 		return s.replace(/(\-[a-z])/g, function($1){
 84 			return $1.toUpperCase().replace('-','');
 85 		});
 86 	}
 87 
 88 	function _css(sel, prop, val)
 89 	{
 90 		var equi;
 91 		
 92 		//Camel-case
 93 		prop = _toCamel(prop);
 94 
 95 		//Equivalent properties for 'special' browsers
 96 		equi = {
 97 			outerHeight: "offsetHeight",
 98 			outerWidth: "offsetWidth",
 99 			top: "posTop"
100 		};
101 		
102 		
103 		//If you don't define a value, try returning the existing value
104 		if(typeof val === "undefined" && sel.style[prop] !== "undefined")
105 		{
106 			return sel.style[prop];
107 		}
108 		else if(typeof val === "undefined" && sel.style[equi[prop]] !== "undefined")
109 		{
110 			return sel.style[equi[prop]];
111 		}
112 
113 		//Let's try the easy way first
114 		if(typeof sel.style[prop] !== "undefined")
115 		{
116 			sel.style[prop] = val;
117 
118 			//Short circuit
119 			return;
120 		}
121 		else if(sel.style[equi[prop]])
122 		{
123 			sel.style[equi[prop]] = val;
124 			return;
125 		}
126 		
127 		//No matches? Well, lets log it for now
128 		console.log("Property " + prop + " nor an equivalent seems to exist");
129 	}
130 	
131 	// --------------------------------------------------------------------------
132 
133 	/**
134 	 * DOM
135 	 * 
136 	 * Dom manipulation module
137 	 * @namespace
138 	 * @memberOf $_
139 	 * @name dom
140 	 */
141 	d = {
142 		/**
143 		 * Adds a class to the element(s) specified by the current
144 		 * selector
145 		 * 
146 		 * @name addClass
147 		 * @memberOf $_.dom
148 		 * @function
149 		 * @param string class
150 		 */
151 		addClass: function (c)
152 		{
153 			$_.each(function (e){
154 				e.classList.add(c);
155 			});
156 		},
157 		/**
158 		 * Removes a class from the element(s) specified by the current
159 		 * selector
160 		 * 
161 		 * @name removeClass
162 		 * @memberOf $_.dom
163 		 * @function
164 		 * @param string class
165 		 */
166 		removeClass: function (c)
167 		{
168 			$_.each(function (e){
169 				e.classList.remove(c);
170 			});
171 		},
172 		/**
173 		 * Hides the element(s) specified by the current selector
174 		 * 
175 		 * @name hide
176 		 * @memberOf $_.dom
177 		 * @function
178 		 */
179 		hide: function ()
180 		{
181 			this.css('display', 'none');
182 		},
183 		/**
184 		 * Shows the element(s) specified by the current selector. 
185 		 * if type is specified, the element will have it's style
186 		 * property set to "display:[your type]". If type is not
187 		 * specified, the element is set to "display:block".
188 		 * 
189 		 * @name  show
190 		 * @memberOf $_.dom
191 		 * @function
192 		 * @param [string] type
193 		 */
194 		show: function (type)
195 		{
196 			if (typeof type === "undefined")
197 			{
198 				type = "block";
199 			}
200 
201 			this.css("display", type);
202 		},
203 		/**
204 		 * Sets attributes on element(s) specified by the current 
205 		 * selector, or, if name is not specified, returns the 
206 		 * value of the attribute of the element specified by the
207 		 * current selector.
208 		 *
209 		 * @name attr
210 		 * @memberOf $_.dom
211 		 * @function
212 		 * @param string name
213 		 * @param [string] value
214 		 * @return string
215 		 * @type string
216 		 */
217 		attr: function (name, value)
218 		{
219 			var sel = this.el;
220 
221 			//Make sure you don't try to get a bunch of elements
222 			if (sel.length > 1 && typeof value === "undefined")
223 			{
224 				console.log(sel);
225 				console.log("Must be a singular element");
226 				return;
227 			}
228 			else if (sel.length > 1 && typeof value !== "undefined") //You can set a bunch, though
229 			{
230 				$_.each(function (e){
231 					return _attr(e, name, value);
232 				});
233 			}
234 			else //Normal behavior
235 			{
236 				return _attr(sel, name, value);
237 			}
238 		},
239 		/**
240 		 * Sets or retrieves the text content of the element
241 		 * specified by the current selector. If a value is 
242 		 * passed, it will set that value on the current element,
243 		 * otherwise it will return the value of the current element
244 		 *
245 		 * @name text
246 		 * @memberOf $_.dom
247 		 * @function
248 		 * @param [string] value
249 		 * @return string
250 		 * @type string
251 		 */
252 		text: function (value)
253 		{
254 			var oldValue, set, type, sel;
255 		
256 			sel = this.el;
257 			
258 			set = (typeof value !== "undefined") ? true : false;
259 			
260 			type = (typeof sel.innerText !== "undefined")
261 				? "innerText"
262 				: (typeof sel.textContent !== "undefined")
263 					? "textContent"
264 					: "innerHTML";
265 
266 			oldValue = sel[type];
267 			
268 			if(set)
269 			{
270 				sel[type] = value;
271 				return value;
272 			}
273 			else
274 			{
275 				return oldValue;
276 			}
277 		},
278 		/**
279 		 * Sets or retrieves a css property of the element
280 		 * specified by the current selector. If a value is 
281 		 * passed, it will set that value on the current element,
282 		 * otherwise it will return the value of the css property
283 		 * on the current element
284 		 *
285 		 * @name css
286 		 * @memberOf $_.dom
287 		 * @function
288 		 * @param string property
289 		 * @param [string] value
290 		 * @return string
291 		 * @type string
292 		 */
293 		css: function (prop, val)
294 		{
295 			//Return the current value if a value is not set
296 			if(typeof val === "undefined")
297 			{
298 				return _css(this.el, prop);
299 			}
300 		
301 			$_.each(function (e){
302 				_css(e, prop, val);
303 			});
304 		},
305 		/**
306 		 * Adds to the innerHTML of the current element, after the last child.
307 		 * 
308 		 * @example $_("ul").dom.append("<li></li>") adds an li element to the end of the selected ul element
309 		 * @name append
310 		 * @memberOf $_.dom
311 		 * @function
312 		 * @param string htm
313 		 */
314 		append: function(htm)
315 		{
316 			if(typeof document.insertAdjacentHTML !== "undefined")
317 			{
318 				this.el.insertAdjacentHTML('beforeend', htm);
319 			}
320 			else
321 			{
322 				this.el.innerHTML += htm;
323 			}
324 		},
325 		/**
326 		 * Adds to the innerHTML of the selected element, before the current children
327 		 * 
328 		 * @name prepend
329 		 * @memberOf $_.dom
330 		 * @function
331 		 * @param string htm
332 		 */
333 		 prepend: function(htm)
334 		 {
335 		 	if(typeof document.insertAdjacentHTML !== "undefined")
336 		 	{
337 		 		this.el.insertAdjacentHTML('afterbegin', htm);
338 		 	}
339 		 	else
340 		 	{
341 		 		this.el.innerHTML = htm + this.el.innerHTML;
342 		 	}
343 		 },
344 		/**
345 		 * Sets or gets the innerHTML propery of the element(s) passed
346 		 *
347 		 * @name html
348 		 * @memberOf $_.dom
349 		 * @function
350 		 * @param [string] htm
351 		 * @return string
352 		 * @type string
353 		 */
354 		html: function(htm)
355 		{
356 			
357 			if(typeof htm !== "undefined")
358 			{
359 				this.el.innerHTML = htm;
360 			}
361 			
362 			//If the parameter is undefined, just return the current value
363 			return this.el.innerHTML;
364 		}
365 	};
366 
367 	$_.ext('dom', d);
368 	
369 }());
370