dom-prop.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. define(["exports", "./_base/kernel", "./sniff", "./_base/lang", "./dom", "./dom-style", "./dom-construct", "./_base/connect"],
  2. function(exports, dojo, has, lang, dom, style, ctr, conn){
  3. // module:
  4. // dojo/dom-prop
  5. // summary:
  6. // This module defines the core dojo DOM properties API.
  7. // TODOC: summary not showing up in output, see https://github.com/csnover/js-doc-parse/issues/42
  8. // =============================
  9. // Element properties Functions
  10. // =============================
  11. // helper to connect events
  12. var _evtHdlrMap = {}, _ctr = 0, _attrId = dojo._scopeName + "attrid";
  13. has.add('dom-textContent', function (global, doc, element) { return 'textContent' in element; });
  14. exports.names = {
  15. // properties renamed to avoid clashes with reserved words
  16. "class": "className",
  17. "for": "htmlFor",
  18. // properties written as camelCase
  19. tabindex: "tabIndex",
  20. readonly: "readOnly",
  21. colspan: "colSpan",
  22. frameborder: "frameBorder",
  23. rowspan: "rowSpan",
  24. textcontent: "textContent",
  25. valuetype: "valueType"
  26. };
  27. function getText(/*DOMNode*/node){
  28. // summary:
  29. // recursion method for get('textContent') to use. Gets text value for a node.
  30. // description:
  31. // Juse uses nodedValue so things like <br/> tags do not end up in
  32. // the text as any sort of line return.
  33. var text = "", ch = node.childNodes;
  34. for(var i = 0, n; n = ch[i]; i++){
  35. //Skip comments.
  36. if(n.nodeType != 8){
  37. if(n.nodeType == 1){
  38. text += getText(n);
  39. }else{
  40. text += n.nodeValue;
  41. }
  42. }
  43. }
  44. return text;
  45. }
  46. exports.get = function getProp(/*DOMNode|String*/ node, /*String*/ name){
  47. // summary:
  48. // Gets a property on an HTML element.
  49. // description:
  50. // Handles normalized getting of properties on DOM nodes.
  51. //
  52. // node: DOMNode|String
  53. // id or reference to the element to get the property on
  54. // name: String
  55. // the name of the property to get.
  56. // returns:
  57. // the value of the requested property or its default value
  58. //
  59. // example:
  60. // | // get the current value of the "foo" property on a node
  61. // | require(["dojo/dom-prop", "dojo/dom"], function(domProp, dom){
  62. // | domProp.get(dom.byId("nodeId"), "foo");
  63. // | // or we can just pass the id:
  64. // | domProp.get("nodeId", "foo");
  65. // | });
  66. node = dom.byId(node);
  67. var lc = name.toLowerCase(), propName = exports.names[lc] || name;
  68. if(propName == "textContent" && !has("dom-textContent")){
  69. return getText(node);
  70. }
  71. return node[propName]; // Anything
  72. };
  73. exports.set = function setProp(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){
  74. // summary:
  75. // Sets a property on an HTML element.
  76. // description:
  77. // Handles normalized setting of properties on DOM nodes.
  78. //
  79. // When passing functions as values, note that they will not be
  80. // directly assigned to slots on the node, but rather the default
  81. // behavior will be removed and the new behavior will be added
  82. // using `dojo.connect()`, meaning that event handler properties
  83. // will be normalized and that some caveats with regards to
  84. // non-standard behaviors for onsubmit apply. Namely that you
  85. // should cancel form submission using `dojo.stopEvent()` on the
  86. // passed event object instead of returning a boolean value from
  87. // the handler itself.
  88. // node: DOMNode|String
  89. // id or reference to the element to set the property on
  90. // name: String|Object
  91. // the name of the property to set, or a hash object to set
  92. // multiple properties at once.
  93. // value: String?
  94. // The value to set for the property
  95. // returns:
  96. // the DOM node
  97. //
  98. // example:
  99. // | // use prop() to set the tab index
  100. // | require(["dojo/dom-prop"], function(domProp){
  101. // | domProp.set("nodeId", "tabIndex", 3);
  102. // | });
  103. //
  104. // example:
  105. // Set multiple values at once, including event handlers:
  106. // | require(["dojo/dom-prop"], function(domProp){
  107. // | domProp.set("formId", {
  108. // | "foo": "bar",
  109. // | "tabIndex": -1,
  110. // | "method": "POST",
  111. // | });
  112. // | });
  113. node = dom.byId(node);
  114. var l = arguments.length;
  115. if(l == 2 && typeof name != "string"){ // inline'd type check
  116. // the object form of setter: the 2nd argument is a dictionary
  117. for(var x in name){
  118. exports.set(node, x, name[x]);
  119. }
  120. return node; // DomNode
  121. }
  122. var lc = name.toLowerCase(), propName = exports.names[lc] || name;
  123. if(propName == "style" && typeof value != "string"){ // inline'd type check
  124. // special case: setting a style
  125. style.set(node, value);
  126. return node; // DomNode
  127. }
  128. if(propName == "innerHTML"){
  129. // special case: assigning HTML
  130. // the hash lists elements with read-only innerHTML on IE
  131. if(has("ie") && node.tagName.toLowerCase() in {col: 1, colgroup: 1,
  132. table: 1, tbody: 1, tfoot: 1, thead: 1, tr: 1, title: 1}){
  133. ctr.empty(node);
  134. node.appendChild(ctr.toDom(value, node.ownerDocument));
  135. }else{
  136. node[propName] = value;
  137. }
  138. return node; // DomNode
  139. }
  140. if(propName == "textContent" && !has("dom-textContent")) {
  141. ctr.empty(node);
  142. node.appendChild(node.ownerDocument.createTextNode(value));
  143. return node;
  144. }
  145. if(lang.isFunction(value)){
  146. // special case: assigning an event handler
  147. // clobber if we can
  148. var attrId = node[_attrId];
  149. if(!attrId){
  150. attrId = _ctr++;
  151. node[_attrId] = attrId;
  152. }
  153. if(!_evtHdlrMap[attrId]){
  154. _evtHdlrMap[attrId] = {};
  155. }
  156. var h = _evtHdlrMap[attrId][propName];
  157. if(h){
  158. //h.remove();
  159. conn.disconnect(h);
  160. }else{
  161. try{
  162. delete node[propName];
  163. }catch(e){}
  164. }
  165. // ensure that event objects are normalized, etc.
  166. if(value){
  167. //_evtHdlrMap[attrId][propName] = on(node, propName, value);
  168. _evtHdlrMap[attrId][propName] = conn.connect(node, propName, value);
  169. }else{
  170. node[propName] = null;
  171. }
  172. return node; // DomNode
  173. }
  174. node[propName] = value;
  175. return node; // DomNode
  176. };
  177. });