dom.js 5.4 KB

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