PageRenderTime 168ms CodeModel.GetById 61ms app.highlight 67ms RepoModel.GetById 33ms app.codeStats 0ms

/ajax/scripts/dom.js

http://showslow.googlecode.com/
JavaScript | 355 lines | 290 code | 43 blank | 22 comment | 137 complexity | cb091a4428f4b2f297c16e8d8860b55a MD5 | raw file
  1/*==================================================
  2 *  DOM Utility Functions
  3 *==================================================
  4 */
  5
  6SimileAjax.DOM = new Object();
  7
  8SimileAjax.DOM.registerEventWithObject = function(elmt, eventName, obj, handlerName) {
  9    SimileAjax.DOM.registerEvent(elmt, eventName, function(elmt2, evt, target) {
 10        return obj[handlerName].call(obj, elmt2, evt, target);
 11    });
 12};
 13
 14SimileAjax.DOM.registerEvent = function(elmt, eventName, handler) {
 15    var handler2 = function(evt) {
 16        evt = (evt) ? evt : ((event) ? event : null);
 17        if (evt) {
 18            var target = (evt.target) ? 
 19                evt.target : ((evt.srcElement) ? evt.srcElement : null);
 20            if (target) {
 21                target = (target.nodeType == 1 || target.nodeType == 9) ? 
 22                    target : target.parentNode;
 23            }
 24            
 25            return handler(elmt, evt, target);
 26        }
 27        return true;
 28    }
 29    
 30    if (SimileAjax.Platform.browser.isIE) {
 31        elmt.attachEvent("on" + eventName, handler2);
 32    } else {
 33        elmt.addEventListener(eventName, handler2, false);
 34    }
 35};
 36
 37SimileAjax.DOM.getPageCoordinates = function(elmt) {
 38    var left = 0;
 39    var top = 0;
 40    
 41    if (elmt.nodeType != 1) {
 42        elmt = elmt.parentNode;
 43    }
 44    
 45    var elmt2 = elmt;
 46    while (elmt2 != null) {
 47        left += elmt2.offsetLeft;
 48        top += elmt2.offsetTop;
 49        elmt2 = elmt2.offsetParent;
 50    }
 51    
 52    var body = document.body;
 53    while (elmt != null && elmt != body) {
 54        if ("scrollLeft" in elmt) {
 55            left -= elmt.scrollLeft;
 56            top -= elmt.scrollTop;
 57        }
 58        elmt = elmt.parentNode;
 59    }
 60    
 61    return { left: left, top: top };
 62};
 63
 64SimileAjax.DOM.getSize = function(elmt) {
 65	var w = this.getStyle(elmt,"width");
 66	var h = this.getStyle(elmt,"height");
 67	if (w.indexOf("px") > -1) w = w.replace("px","");
 68	if (h.indexOf("px") > -1) h = h.replace("px","");
 69	return {
 70		w: w,
 71		h: h
 72	}
 73}
 74
 75SimileAjax.DOM.getStyle = function(elmt, styleProp) {
 76    if (elmt.currentStyle) { // IE
 77        var style = elmt.currentStyle[styleProp];
 78    } else if (window.getComputedStyle) { // standard DOM
 79        var style = document.defaultView.getComputedStyle(elmt, null).getPropertyValue(styleProp);
 80    } else {
 81    	var style = "";
 82    }
 83    return style;
 84}
 85
 86SimileAjax.DOM.getEventRelativeCoordinates = function(evt, elmt) {
 87    if (SimileAjax.Platform.browser.isIE) {
 88      if (evt.type == "mousewheel") {
 89        var coords = SimileAjax.DOM.getPageCoordinates(elmt);
 90        return {
 91          x: evt.clientX - coords.left, 
 92          y: evt.clientY - coords.top
 93        };        
 94      } else {
 95        return {
 96          x: evt.offsetX,
 97          y: evt.offsetY
 98        };
 99      }
100    } else {
101        var coords = SimileAjax.DOM.getPageCoordinates(elmt);
102
103        if ((evt.type == "DOMMouseScroll") &&
104          SimileAjax.Platform.browser.isFirefox &&
105          (SimileAjax.Platform.browser.majorVersion == 2)) {
106          // Due to: https://bugzilla.mozilla.org/show_bug.cgi?id=352179                  
107
108          return {
109            x: evt.screenX - coords.left,
110            y: evt.screenY - coords.top 
111          };
112        } else {
113          return {
114              x: evt.pageX - coords.left,
115              y: evt.pageY - coords.top
116          };
117        }
118    }
119};
120
121SimileAjax.DOM.getEventPageCoordinates = function(evt) {
122    if (SimileAjax.Platform.browser.isIE) {
123
124        var scrOfY = 0;
125        var scrOfX = 0;
126
127        if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
128            //DOM compliant
129            scrOfY = document.body.scrollTop;
130            scrOfX = document.body.scrollLeft;
131        } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
132            //IE6 standards compliant mode
133            scrOfY = document.documentElement.scrollTop;
134            scrOfX = document.documentElement.scrollLeft;
135        }
136
137        return { x: evt.clientX + scrOfX, y: evt.clientY + scrOfY }; 
138    } else {
139        return {
140            x: evt.pageX,
141            y: evt.pageY
142        };
143    }
144};
145
146SimileAjax.DOM.hittest = function(x, y, except) {
147    return SimileAjax.DOM._hittest(document.body, x, y, except);
148};
149
150SimileAjax.DOM._hittest = function(elmt, x, y, except) {
151    var childNodes = elmt.childNodes;
152    outer: for (var i = 0; i < childNodes.length; i++) {
153        var childNode = childNodes[i];
154        for (var j = 0; j < except.length; j++) {
155            if (childNode == except[j]) {
156                continue outer;
157            }
158        }
159        
160        if (childNode.offsetWidth == 0 && childNode.offsetHeight == 0) {
161            /*
162             *  Sometimes SPAN elements have zero width and height but
163             *  they have children like DIVs that cover non-zero areas.
164             */
165            var hitNode = SimileAjax.DOM._hittest(childNode, x, y, except);
166            if (hitNode != childNode) {
167                return hitNode;
168            }
169        } else {
170            var top = 0;
171            var left = 0;
172            
173            var node = childNode;
174            while (node) {
175                top += node.offsetTop;
176                left += node.offsetLeft;
177                node = node.offsetParent;
178            }
179            
180            if (left <= x && top <= y && (x - left) < childNode.offsetWidth && (y - top) < childNode.offsetHeight) {
181                return SimileAjax.DOM._hittest(childNode, x, y, except);
182            } else if (childNode.nodeType == 1 && childNode.tagName == "TR") {
183                /*
184                 *  Table row might have cells that span several rows.
185                 */
186                var childNode2 = SimileAjax.DOM._hittest(childNode, x, y, except);
187                if (childNode2 != childNode) {
188                    return childNode2;
189                }
190            }
191        }
192    }
193    return elmt;
194};
195
196SimileAjax.DOM.cancelEvent = function(evt) {
197    evt.returnValue = false;
198    evt.cancelBubble = true;
199    if ("preventDefault" in evt) {
200        evt.preventDefault();
201    }
202};
203
204SimileAjax.DOM.appendClassName = function(elmt, className) {
205    var classes = elmt.className.split(" ");
206    for (var i = 0; i < classes.length; i++) {
207        if (classes[i] == className) {
208            return;
209        }
210    }
211    classes.push(className);
212    elmt.className = classes.join(" ");
213};
214
215SimileAjax.DOM.createInputElement = function(type) {
216    var div = document.createElement("div");
217    div.innerHTML = "<input type='" + type + "' />";
218    
219    return div.firstChild;
220};
221
222SimileAjax.DOM.createDOMFromTemplate = function(template) {
223    var result = {};
224    result.elmt = SimileAjax.DOM._createDOMFromTemplate(template, result, null);
225    
226    return result;
227};
228
229SimileAjax.DOM._createDOMFromTemplate = function(templateNode, result, parentElmt) {
230    if (templateNode == null) {
231        /*
232        var node = doc.createTextNode("--null--");
233        if (parentElmt != null) {
234            parentElmt.appendChild(node);
235        }
236        return node;
237        */
238        return null;
239    } else if (typeof templateNode != "object") {
240        var node = document.createTextNode(templateNode);
241        if (parentElmt != null) {
242            parentElmt.appendChild(node);
243        }
244        return node;
245    } else {
246        var elmt = null;
247        if ("tag" in templateNode) {
248            var tag = templateNode.tag;
249            if (parentElmt != null) {
250                if (tag == "tr") {
251                    elmt = parentElmt.insertRow(parentElmt.rows.length);
252                } else if (tag == "td") {
253                    elmt = parentElmt.insertCell(parentElmt.cells.length);
254                }
255            }
256            if (elmt == null) {
257                elmt = tag == "input" ?
258                    SimileAjax.DOM.createInputElement(templateNode.type) :
259                    document.createElement(tag);
260                    
261                if (parentElmt != null) {
262                    parentElmt.appendChild(elmt);
263                }
264            }
265        } else {
266            elmt = templateNode.elmt;
267            if (parentElmt != null) {
268                parentElmt.appendChild(elmt);
269            }
270        }
271        
272        for (var attribute in templateNode) {
273            var value = templateNode[attribute];
274            
275            if (attribute == "field") {
276                result[value] = elmt;
277                
278            } else if (attribute == "className") {
279                elmt.className = value;
280            } else if (attribute == "id") {
281                elmt.id = value;
282            } else if (attribute == "title") {
283                elmt.title = value;
284            } else if (attribute == "type" && elmt.tagName == "input") {
285                // do nothing
286            } else if (attribute == "style") {
287                for (n in value) {
288                    var v = value[n];
289                    if (n == "float") {
290                        n = SimileAjax.Platform.browser.isIE ? "styleFloat" : "cssFloat";
291                    }
292                    elmt.style[n] = v;
293                }
294            } else if (attribute == "children") {
295                for (var i = 0; i < value.length; i++) {
296                    SimileAjax.DOM._createDOMFromTemplate(value[i], result, elmt);
297                }
298            } else if (attribute != "tag" && attribute != "elmt") {
299                elmt.setAttribute(attribute, value);
300            }
301        }
302        return elmt;
303    }
304}
305
306SimileAjax.DOM._cachedParent = null;
307SimileAjax.DOM.createElementFromString = function(s) {
308    if (SimileAjax.DOM._cachedParent == null) {
309        SimileAjax.DOM._cachedParent = document.createElement("div");
310    }
311    SimileAjax.DOM._cachedParent.innerHTML = s;
312    return SimileAjax.DOM._cachedParent.firstChild;
313};
314
315SimileAjax.DOM.createDOMFromString = function(root, s, fieldElmts) {
316    var elmt = typeof root == "string" ? document.createElement(root) : root;
317    elmt.innerHTML = s;
318    
319    var dom = { elmt: elmt };
320    SimileAjax.DOM._processDOMChildrenConstructedFromString(dom, elmt, fieldElmts != null ? fieldElmts : {} );
321    
322    return dom;
323};
324
325SimileAjax.DOM._processDOMConstructedFromString = function(dom, elmt, fieldElmts) {
326    var id = elmt.id;
327    if (id != null && id.length > 0) {
328        elmt.removeAttribute("id");
329        if (id in fieldElmts) {
330            var parentElmt = elmt.parentNode;
331            parentElmt.insertBefore(fieldElmts[id], elmt);
332            parentElmt.removeChild(elmt);
333            
334            dom[id] = fieldElmts[id];
335            return;
336        } else {
337            dom[id] = elmt;
338        }
339    }
340    
341    if (elmt.hasChildNodes()) {
342        SimileAjax.DOM._processDOMChildrenConstructedFromString(dom, elmt, fieldElmts);
343    }
344};
345
346SimileAjax.DOM._processDOMChildrenConstructedFromString = function(dom, elmt, fieldElmts) {
347    var node = elmt.firstChild;
348    while (node != null) {
349        var node2 = node.nextSibling;
350        if (node.nodeType == 1) {
351            SimileAjax.DOM._processDOMConstructedFromString(dom, node, fieldElmts);
352        }
353        node = node2;
354    }
355};