/* Copyright (c) 2004-2006, The Dojo Foundation All Rights Reserved. Licensed under the Academic Free License version 2.1 or above OR the modified BSD license. For more information on Dojo licensing, see: http://dojotoolkit.org/community/licensing.shtml */ dojo.provide("dojo.html"); dojo.require("dojo.lang.func"); dojo.require("dojo.dom"); dojo.require("dojo.style"); dojo.require("dojo.string"); dojo.lang.mixin(dojo.html, dojo.dom); dojo.lang.mixin(dojo.html, dojo.style); // FIXME: we are going to assume that we can throw any and every rendering // engine into the IE 5.x box model. In Mozilla, we do this w/ CSS. // Need to investigate for KHTML and Opera dojo.html.clearSelection = function(){ try{ if(window["getSelection"]){ if(dojo.render.html.safari){ // pulled from WebCore/ecma/kjs_window.cpp, line 2536 window.getSelection().collapse(); }else{ window.getSelection().removeAllRanges(); } }else if(document.selection){ if(document.selection.empty){ document.selection.empty(); }else if(document.selection.clear){ document.selection.clear(); } } return true; }catch(e){ dojo.debug(e); return false; } } dojo.html.disableSelection = function(element){ element = dojo.byId(element)||document.body; var h = dojo.render.html; if(h.mozilla){ element.style.MozUserSelect = "none"; }else if(h.safari){ element.style.KhtmlUserSelect = "none"; }else if(h.ie){ element.unselectable = "on"; }else{ return false; } return true; } dojo.html.enableSelection = function(element){ element = dojo.byId(element)||document.body; var h = dojo.render.html; if(h.mozilla){ element.style.MozUserSelect = ""; }else if(h.safari){ element.style.KhtmlUserSelect = ""; }else if(h.ie){ element.unselectable = "off"; }else{ return false; } return true; } dojo.html.selectElement = function(element){ element = dojo.byId(element); if(document.selection && document.body.createTextRange){ // IE var range = document.body.createTextRange(); range.moveToElementText(element); range.select(); }else if(window["getSelection"]){ var selection = window.getSelection(); // FIXME: does this work on Safari? if(selection["selectAllChildren"]){ // Mozilla selection.selectAllChildren(element); } } } dojo.html.selectInputText = function(element){ element = dojo.byId(element); if(document.selection && document.body.createTextRange){ // IE var range = element.createTextRange(); range.moveStart("character", 0); range.moveEnd("character", element.value.length); range.select(); }else if(window["getSelection"]){ var selection = window.getSelection(); // FIXME: does this work on Safari? element.setSelectionRange(0, element.value.length); } element.focus(); } dojo.html.isSelectionCollapsed = function(){ if(document["selection"]){ // IE return document.selection.createRange().text == ""; }else if(window["getSelection"]){ var selection = window.getSelection(); if(dojo.lang.isString(selection)){ // Safari return selection == ""; }else{ // Mozilla/W3 return selection.isCollapsed; } } } dojo.html.getEventTarget = function(evt){ if(!evt) { evt = window.event || {} }; var t = (evt.srcElement ? evt.srcElement : (evt.target ? evt.target : null)); while((t)&&(t.nodeType!=1)){ t = t.parentNode; } return t; } dojo.html.getDocumentWidth = function(){ dojo.deprecated("dojo.html.getDocument*", "replaced by dojo.html.getViewport*", "0.4"); return dojo.html.getViewportWidth(); } dojo.html.getDocumentHeight = function(){ dojo.deprecated("dojo.html.getDocument*", "replaced by dojo.html.getViewport*", "0.4"); return dojo.html.getViewportHeight(); } dojo.html.getDocumentSize = function(){ dojo.deprecated("dojo.html.getDocument*", "replaced of dojo.html.getViewport*", "0.4"); return dojo.html.getViewportSize(); } dojo.html.getViewportWidth = function(){ var w = 0; if(window.innerWidth){ w = window.innerWidth; } if(dojo.exists(document, "documentElement.clientWidth")){ // IE6 Strict var w2 = document.documentElement.clientWidth; // this lets us account for scrollbars if(!w || w2 && w2 < w) { w = w2; } return w; } if(document.body){ // IE return document.body.clientWidth; } return 0; } dojo.html.getViewportHeight = function(){ if (window.innerHeight){ return window.innerHeight; } if (dojo.exists(document, "documentElement.clientHeight")){ // IE6 Strict return document.documentElement.clientHeight; } if (document.body){ // IE return document.body.clientHeight; } return 0; } dojo.html.getViewportSize = function(){ var ret = [dojo.html.getViewportWidth(), dojo.html.getViewportHeight()]; ret.w = ret[0]; ret.h = ret[1]; return ret; } dojo.html.getScrollTop = function(){ return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; } dojo.html.getScrollLeft = function(){ return window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0; } dojo.html.getScrollOffset = function(){ var off = [dojo.html.getScrollLeft(), dojo.html.getScrollTop()]; off.x = off[0]; off.y = off[1]; return off; } dojo.html.getParentOfType = function(node, type){ dojo.deprecated("dojo.html.getParentOfType", "replaced by dojo.html.getParentByType*", "0.4"); return dojo.html.getParentByType(node, type); } dojo.html.getParentByType = function(node, type) { var parent = dojo.byId(node); type = type.toLowerCase(); while((parent)&&(parent.nodeName.toLowerCase()!=type)){ if(parent==(document["body"]||document["documentElement"])){ return null; } parent = parent.parentNode; } return parent; } // RAR: this function comes from nwidgets and is more-or-less unmodified. // We should probably look ant Burst and f(m)'s equivalents dojo.html.getAttribute = function(node, attr){ node = dojo.byId(node); // FIXME: need to add support for attr-specific accessors if((!node)||(!node.getAttribute)){ // if(attr !== 'nwType'){ // alert("getAttr of '" + attr + "' with bad node"); // } return null; } var ta = typeof attr == 'string' ? attr : new String(attr); // first try the approach most likely to succeed var v = node.getAttribute(ta.toUpperCase()); if((v)&&(typeof v == 'string')&&(v!="")){ return v; } // try returning the attributes value, if we couldn't get it as a string if(v && v.value){ return v.value; } // this should work on Opera 7, but it's a little on the crashy side if((node.getAttributeNode)&&(node.getAttributeNode(ta))){ return (node.getAttributeNode(ta)).value; }else if(node.getAttribute(ta)){ return node.getAttribute(ta); }else if(node.getAttribute(ta.toLowerCase())){ return node.getAttribute(ta.toLowerCase()); } return null; } /** * Determines whether or not the specified node carries a value for the * attribute in question. */ dojo.html.hasAttribute = function(node, attr){ node = dojo.byId(node); return dojo.html.getAttribute(node, attr) ? true : false; } /** * Returns the string value of the list of CSS classes currently assigned * directly to the node in question. Returns an empty string if no class attribute * is found; */ dojo.html.getClass = function(node){ node = dojo.byId(node); if(!node){ return ""; } var cs = ""; if(node.className){ cs = node.className; }else if(dojo.html.hasAttribute(node, "class")){ cs = dojo.html.getAttribute(node, "class"); } return dojo.string.trim(cs); } /** * Returns an array of CSS classes currently assigned * directly to the node in question. Returns an empty array if no classes * are found; */ dojo.html.getClasses = function(node) { var c = dojo.html.getClass(node); return (c == "") ? [] : c.split(/\s+/g); } /** * Returns whether or not the specified classname is a portion of the * class list currently applied to the node. Does not cover cascaded * styles, only classes directly applied to the node. */ dojo.html.hasClass = function(node, classname){ return dojo.lang.inArray(dojo.html.getClasses(node), classname); } /** * Adds the specified class to the beginning of the class list on the * passed node. This gives the specified class the highest precidence * when style cascading is calculated for the node. Returns true or * false; indicating success or failure of the operation, respectively. */ dojo.html.prependClass = function(node, classStr){ classStr += " " + dojo.html.getClass(node); return dojo.html.setClass(node, classStr); } /** * Adds the specified class to the end of the class list on the * passed &node;. Returns &true; or &false; indicating success or failure. */ dojo.html.addClass = function(node, classStr){ if (dojo.html.hasClass(node, classStr)) { return false; } classStr = dojo.string.trim(dojo.html.getClass(node) + " " + classStr); return dojo.html.setClass(node, classStr); } /** * Clobbers the existing list of classes for the node, replacing it with * the list given in the 2nd argument. Returns true or false * indicating success or failure. */ dojo.html.setClass = function(node, classStr){ node = dojo.byId(node); var cs = new String(classStr); try{ if(typeof node.className == "string"){ node.className = cs; }else if(node.setAttribute){ node.setAttribute("class", classStr); node.className = cs; }else{ return false; } }catch(e){ dojo.debug("dojo.html.setClass() failed", e); } return true; } /** * Removes the className from the node;. Returns * true or false indicating success or failure. */ dojo.html.removeClass = function(node, classStr, allowPartialMatches){ var classStr = dojo.string.trim(new String(classStr)); try{ var cs = dojo.html.getClasses(node); var nca = []; if(allowPartialMatches){ for(var i = 0; i= left && mouse.x <= right && mouse.y >= top && mouse.y <= bottom); } dojo.html.setActiveStyleSheet = function(title){ var i = 0, a, els = document.getElementsByTagName("link"); while (a = els[i++]) { if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")){ a.disabled = true; if (a.getAttribute("title") == title) { a.disabled = false; } } } } dojo.html.getActiveStyleSheet = function(){ var i = 0, a, els = document.getElementsByTagName("link"); while (a = els[i++]) { if (a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title") && !a.disabled) { return a.getAttribute("title"); } } return null; } dojo.html.getPreferredStyleSheet = function(){ var i = 0, a, els = document.getElementsByTagName("link"); while (a = els[i++]) { if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("rel").indexOf("alt") == -1 && a.getAttribute("title")) { return a.getAttribute("title"); } } return null; } dojo.html.body = function(){ // Note: document.body is not defined for a strict xhtml document return document.body || document.getElementsByTagName("body")[0]; } /** * Like dojo.dom.isTag, except case-insensitive **/ dojo.html.isTag = function(node /* ... */) { node = dojo.byId(node); if(node && node.tagName) { var arr = dojo.lang.map(dojo.lang.toArray(arguments, 1), function(a) { return String(a).toLowerCase(); }); return arr[ dojo.lang.find(node.tagName.toLowerCase(), arr) ] || ""; } return ""; } dojo.html.copyStyle = function(target, source){ // work around for opera which doesn't have cssText, and for IE which fails on setAttribute if(dojo.lang.isUndefined(source.style.cssText)){ target.setAttribute("style", source.getAttribute("style")); }else{ target.style.cssText = source.style.cssText; } dojo.html.addClass(target, dojo.html.getClass(source)); } dojo.html._callExtrasDeprecated = function(inFunc, args) { var module = "dojo.html.extras"; dojo.deprecated("dojo.html." + inFunc, "moved to " + module, "0.4"); dojo["require"](module); // weird syntax to fool list-profile-deps (build) return dojo.html[inFunc].apply(dojo.html, args); } dojo.html.createNodesFromText = function() { return dojo.html._callExtrasDeprecated('createNodesFromText', arguments); } dojo.html.gravity = function() { return dojo.html._callExtrasDeprecated('gravity', arguments); } dojo.html.placeOnScreen = function() { return dojo.html._callExtrasDeprecated('placeOnScreen', arguments); } dojo.html.placeOnScreenPoint = function() { return dojo.html._callExtrasDeprecated('placeOnScreenPoint', arguments); } dojo.html.renderedTextContent = function() { return dojo.html._callExtrasDeprecated('renderedTextContent', arguments); } dojo.html.BackgroundIframe = function() { return dojo.html._callExtrasDeprecated('BackgroundIframe', arguments); }