dom.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. define(["./sniff", "./_base/window"],
  2. function(has, win){
  3. // module:
  4. // dojo/dom
  5. // FIXME: need to add unit tests for all the semi-public methods
  6. if(has("ie") <= 7){
  7. try{
  8. document.execCommand("BackgroundImageCache", false, true);
  9. }catch(e){
  10. // sane browsers don't have cache "issues"
  11. }
  12. }
  13. // =============================
  14. // DOM Functions
  15. // =============================
  16. // the result object
  17. var dom = {
  18. // summary:
  19. // This module defines the core dojo DOM API.
  20. };
  21. if(has("ie")){
  22. dom.byId = function(id, doc){
  23. if(typeof id != "string"){
  24. return id;
  25. }
  26. var _d = doc || win.doc, te = id && _d.getElementById(id);
  27. // attributes.id.value is better than just id in case the
  28. // user has a name=id inside a form
  29. if(te && (te.attributes.id.value == id || te.id == id)){
  30. return te;
  31. }else{
  32. var eles = _d.all[id];
  33. if(!eles || eles.nodeName){
  34. eles = [eles];
  35. }
  36. // if more than 1, choose first with the correct id
  37. var i = 0;
  38. while((te = eles[i++])){
  39. if((te.attributes && te.attributes.id && te.attributes.id.value == id) || te.id == id){
  40. return te;
  41. }
  42. }
  43. }
  44. };
  45. }else{
  46. dom.byId = function(id, doc){
  47. // inline'd type check.
  48. // be sure to return null per documentation, to match IE branch.
  49. return ((typeof id == "string") ? (doc || win.doc).getElementById(id) : id) || null; // DOMNode
  50. };
  51. }
  52. /*=====
  53. dom.byId = function(id, doc){
  54. // summary:
  55. // Returns DOM node with matching `id` attribute or falsy value (ex: null or undefined)
  56. // if not found. If `id` is a DomNode, this function is a no-op.
  57. //
  58. // id: String|DOMNode
  59. // A string to match an HTML id attribute or a reference to a DOM Node
  60. //
  61. // doc: Document?
  62. // Document to work in. Defaults to the current value of
  63. // dojo/_base/window.doc. Can be used to retrieve
  64. // node references from other documents.
  65. //
  66. // example:
  67. // Look up a node by ID:
  68. // | require(["dojo/dom"], function(dom){
  69. // | var n = dom.byId("foo");
  70. // | });
  71. //
  72. // example:
  73. // Check if a node exists, and use it.
  74. // | require(["dojo/dom"], function(dom){
  75. // | var n = dom.byId("bar");
  76. // | if(n){ doStuff() ... }
  77. // | });
  78. //
  79. // example:
  80. // Allow string or DomNode references to be passed to a custom function:
  81. // | require(["dojo/dom"], function(dom){
  82. // | var foo = function(nodeOrId){
  83. // | nodeOrId = dom.byId(nodeOrId);
  84. // | // ... more stuff
  85. // | }
  86. // | });
  87. };
  88. =====*/
  89. dom.isDescendant = function(/*DOMNode|String*/ node, /*DOMNode|String*/ ancestor){
  90. // summary:
  91. // Returns true if node is a descendant of ancestor
  92. // node: DOMNode|String
  93. // string id or node reference to test
  94. // ancestor: DOMNode|String
  95. // string id or node reference of potential parent to test against
  96. //
  97. // example:
  98. // Test is node id="bar" is a descendant of node id="foo"
  99. // | require(["dojo/dom"], function(dom){
  100. // | if(dom.isDescendant("bar", "foo")){ ... }
  101. // | });
  102. try{
  103. node = dom.byId(node);
  104. ancestor = dom.byId(ancestor);
  105. while(node){
  106. if(node == ancestor){
  107. return true; // Boolean
  108. }
  109. node = node.parentNode;
  110. }
  111. }catch(e){ /* squelch, return false */ }
  112. return false; // Boolean
  113. };
  114. // TODO: do we need setSelectable in the base?
  115. // Add feature test for user-select CSS property
  116. // (currently known to work in all but IE < 10 and Opera)
  117. // TODO: The user-select CSS property as of May 2014 is no longer part of
  118. // any CSS specification. In IE, -ms-user-select does not do the same thing
  119. // as the unselectable attribute on elements; namely, dijit Editor buttons
  120. // do not properly prevent the content of the editable content frame from
  121. // unblurring. As a result, the -ms- prefixed version is omitted here.
  122. has.add("css-user-select", function(global, doc, element){
  123. // Avoid exception when dom.js is loaded in non-browser environments
  124. if(!element){ return false; }
  125. var style = element.style;
  126. var prefixes = ["Khtml", "O", "Moz", "Webkit"],
  127. i = prefixes.length,
  128. name = "userSelect",
  129. prefix;
  130. // Iterate prefixes from most to least likely
  131. do{
  132. if(typeof style[name] !== "undefined"){
  133. // Supported; return property name
  134. return name;
  135. }
  136. }while(i-- && (name = prefixes[i] + "UserSelect"));
  137. // Not supported if we didn't return before now
  138. return false;
  139. });
  140. /*=====
  141. dom.setSelectable = function(node, selectable){
  142. // summary:
  143. // Enable or disable selection on a node
  144. // node: DOMNode|String
  145. // id or reference to node
  146. // selectable: Boolean
  147. // state to put the node in. false indicates unselectable, true
  148. // allows selection.
  149. // example:
  150. // Make the node id="bar" unselectable
  151. // | require(["dojo/dom"], function(dom){
  152. // | dom.setSelectable("bar");
  153. // | });
  154. // example:
  155. // Make the node id="bar" selectable
  156. // | require(["dojo/dom"], function(dom){
  157. // | dom.setSelectable("bar", true);
  158. // | });
  159. };
  160. =====*/
  161. var cssUserSelect = has("css-user-select");
  162. dom.setSelectable = cssUserSelect ? function(node, selectable){
  163. // css-user-select returns a (possibly vendor-prefixed) CSS property name
  164. dom.byId(node).style[cssUserSelect] = selectable ? "" : "none";
  165. } : function(node, selectable){
  166. node = dom.byId(node);
  167. // (IE < 10 / Opera) Fall back to setting/removing the
  168. // unselectable attribute on the element and all its children
  169. var nodes = node.getElementsByTagName("*"),
  170. i = nodes.length;
  171. if(selectable){
  172. node.removeAttribute("unselectable");
  173. while(i--){
  174. nodes[i].removeAttribute("unselectable");
  175. }
  176. }else{
  177. node.setAttribute("unselectable", "on");
  178. while(i--){
  179. nodes[i].setAttribute("unselectable", "on");
  180. }
  181. }
  182. };
  183. return dom;
  184. });