dom.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. define("dojox/dtl/contrib/dom", [
  2. "dojo/_base/kernel",
  3. "dojo/_base/lang",
  4. "dojo/_base/connect",
  5. "dojo/dom-style",
  6. "dojo/dom-construct",
  7. "../_base",
  8. "../dom"
  9. ], function(kernel,lang,connect,domStyle,domConstruct,dd,dddom){
  10. /*=====
  11. dd = dojox.dtl;
  12. =====*/
  13. var ddch = lang.getObject("dojox.dtl.contrib.dom", true);
  14. var simple = {render: function(){ return this.contents; }};
  15. ddch.StyleNode = lang.extend(function(styles){
  16. this.contents = {};
  17. this._current = {};
  18. this._styles = styles;
  19. for(var key in styles){
  20. if(styles[key].indexOf("{{") != -1){
  21. var node = new dd.Template(styles[key]);
  22. }else{
  23. var node = lang.delegate(simple);
  24. node.contents = styles[key];
  25. }
  26. this.contents[key] = node;
  27. }
  28. },
  29. {
  30. render: function(context, buffer){
  31. for(var key in this.contents){
  32. var value = this.contents[key].render(context);
  33. if(this._current[key] != value){
  34. domStyle.set(buffer.getParent(), key, this._current[key] = value);
  35. }
  36. }
  37. return buffer;
  38. },
  39. unrender: function(context, buffer){
  40. this._current = {};
  41. return buffer;
  42. },
  43. clone: function(buffer){
  44. return new this.constructor(this._styles);
  45. }
  46. });
  47. ddch.BufferNode = lang.extend(function(nodelist, options){
  48. this.nodelist = nodelist;
  49. this.options = options;
  50. },
  51. {
  52. _swap: function(type, node){
  53. if(!this.swapped && this.parent.parentNode){
  54. if(type == "node"){
  55. if((node.nodeType == 3 && !this.options.text) || (node.nodeType == 1 && !this.options.node)){
  56. return;
  57. }
  58. }else if(type == "class"){
  59. if(type != "class"){
  60. return;
  61. }
  62. }
  63. this.onAddNode && connect.disconnect(this.onAddNode);
  64. this.onRemoveNode && connect.disconnect(this.onRemoveNode);
  65. this.onChangeAttribute && connect.disconnect(this.onChangeAttribute);
  66. this.onChangeData && connect.disconnect(this.onChangeData);
  67. this.swapped = this.parent.cloneNode(true);
  68. this.parent.parentNode.replaceChild(this.swapped, this.parent);
  69. }
  70. },
  71. render: function(context, buffer){
  72. this.parent = buffer.getParent();
  73. if(this.options.node){
  74. this.onAddNode = connect.connect(buffer, "onAddNode", lang.hitch(this, "_swap", "node"));
  75. this.onRemoveNode = connect.connect(buffer, "onRemoveNode", lang.hitch(this, "_swap", "node"));
  76. }
  77. if(this.options.text){
  78. this.onChangeData = connect.connect(buffer, "onChangeData", lang.hitch(this, "_swap", "node"));
  79. }
  80. if(this.options["class"]){
  81. this.onChangeAttribute = connect.connect(buffer, "onChangeAttribute", lang.hitch(this, "_swap", "class"));
  82. }
  83. buffer = this.nodelist.render(context, buffer);
  84. if(this.swapped){
  85. this.swapped.parentNode.replaceChild(this.parent, this.swapped);
  86. domConstruct.destroy(this.swapped);
  87. }else{
  88. this.onAddNode && connect.disconnect(this.onAddNode);
  89. this.onRemoveNode && connect.disconnect(this.onRemoveNode);
  90. this.onChangeAttribute && connect.disconnect(this.onChangeAttribute);
  91. this.onChangeData && connect.disconnect(this.onChangeData);
  92. }
  93. delete this.parent;
  94. delete this.swapped;
  95. return buffer;
  96. },
  97. unrender: function(context, buffer){
  98. return this.nodelist.unrender(context, buffer);
  99. },
  100. clone: function(buffer){
  101. return new this.constructor(this.nodelist.clone(buffer), this.options);
  102. }
  103. });
  104. lang.mixin(ddch, {
  105. buffer: function(parser, token){
  106. // summary:
  107. // Buffer large DOM manipulations during re-render.
  108. // description:
  109. // When using DomTemplate, wrap any content
  110. // that you expect to change often during
  111. // re-rendering. It will then remove its parent
  112. // from the main document while it re-renders that
  113. // section of code. It will only remove it from
  114. // the main document if a mainpulation of somes sort
  115. // happens. ie It won't swap out if it diesn't have to.
  116. // example:
  117. // By default, it considers only node addition/removal
  118. // to be "changing"
  119. //
  120. // | {% buffer %}{% for item in items %}<li>{{ item }}</li>{% endfor %}{% endbuffer %}
  121. // example:
  122. // You can explicitly declare options:
  123. //
  124. // * node: Watch node removal/addition
  125. // * class: Watch for a classname to be changed
  126. // * text: Watch for any text to be changed
  127. //
  128. // | {% buffer node class %}{% for item in items %}<li>{{ item }}</li>{% endfor %}{% endbuffer %}
  129. var parts = token.contents.split().slice(1);
  130. var options = {};
  131. var found = false;
  132. for(var i = parts.length; i--;){
  133. found = true;
  134. options[parts[i]] = true;
  135. }
  136. if(!found){
  137. options.node = true;
  138. }
  139. var nodelist = parser.parse(["endbuffer"]);
  140. parser.next_token();
  141. return new ddch.BufferNode(nodelist, options);
  142. },
  143. html: function(parser, token){
  144. kernel.deprecated("{% html someVariable %}", "Use {{ someVariable|safe }} instead");
  145. return parser.create_variable_node(token.contents.slice(5) + "|safe");
  146. },
  147. style_: function(parser, token){
  148. var styles = {};
  149. token = token.contents.replace(/^style\s+/, "");
  150. var rules = token.split(/\s*;\s*/g);
  151. for(var i = 0, rule; rule = rules[i]; i++){
  152. var parts = rule.split(/\s*:\s*/g);
  153. var key = parts[0];
  154. var value = lang.trim(parts[1]);
  155. if(value){
  156. styles[key] = value;
  157. }
  158. }
  159. return new ddch.StyleNode(styles);
  160. }
  161. });
  162. dd.register.tags("dojox.dtl.contrib", {
  163. "dom": ["html", "attr:style", "buffer"]
  164. });
  165. return dojox.dtl.contrib.dom;
  166. });