Generate.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. define("dojox/mvc/Generate", [
  2. "dojo/_base/lang",
  3. "dojo/_base/declare",
  4. "./_Container",
  5. "./Group",
  6. "dijit/form/TextBox"
  7. ], function(lang, declare, Container){
  8. /*=====
  9. Container = dojox.mvc._Container;
  10. declare = dojo.declare;
  11. =====*/
  12. return declare("dojox.mvc.Generate", [Container], {
  13. // summary:
  14. // A container that generates a view based on the data model its bound to.
  15. //
  16. // description:
  17. // A generate introspects its data binding and creates a view contained in
  18. // it that allows displaying the bound data. Child dijits or custom view
  19. // components inside it inherit their parent data binding context from it.
  20. // _counter: [private] Integer
  21. // A count maintained internally to always generate predictable widget
  22. // IDs in the view generated by this container.
  23. _counter : 0,
  24. // defaultWidgetMapping: Object
  25. // The mapping of types to a widget class. Set widgetMapping to override this.
  26. //
  27. _defaultWidgetMapping: {"String" : "dijit.form.TextBox"},
  28. // defaultClassMapping: Object
  29. // The mapping of class to use. Set classMapping to override this.
  30. //
  31. _defaultClassMapping: {"Label" : "generate-label-cell", "String" : "generate-dijit-cell", "Heading" : "generate-heading", "Row" : "row"},
  32. // defaultIdNameMapping: Object
  33. // The mapping of id and name to use. Set idNameMapping to override this. A count will be added to the id and name
  34. //
  35. _defaultIdNameMapping: {"String" : "textbox_t"},
  36. ////////////////////// PRIVATE METHODS ////////////////////////
  37. _updateBinding: function(){
  38. // summary:
  39. // Regenerate if the binding changes.
  40. this.inherited(arguments);
  41. this._buildContained();
  42. },
  43. _buildContained: function(){
  44. // summary:
  45. // Destroy any existing generated view, recreate it from scratch
  46. // parse the new contents.
  47. // tags:
  48. // private
  49. this._destroyBody();
  50. this._counter = 0;
  51. this.srcNodeRef.innerHTML = this._generateBody(this.get("binding"));
  52. this._createBody();
  53. },
  54. _generateBody: function(binding, hideHeading){
  55. // summary:
  56. // Generate the markup for the view associated with this generate
  57. // container.
  58. // binding:
  59. // The associated data binding to generate a view for.
  60. // hideHeading:
  61. // Whether the property name should be displayed as a heading.
  62. // tags:
  63. // private
  64. var body = "";
  65. for(var prop in binding){
  66. if(binding[prop] && lang.isFunction(binding[prop].toPlainObject)){
  67. if(binding[prop].get(0)){
  68. body += this._generateRepeat(binding[prop], prop);
  69. }else if(binding[prop].value){
  70. // TODO: Data types based widgets
  71. body += this._generateTextBox(prop);
  72. }else{
  73. body += this._generateGroup(binding[prop], prop, hideHeading);
  74. }
  75. }
  76. }
  77. return body;
  78. },
  79. _generateRepeat: function(binding, repeatHeading){
  80. // summary:
  81. // Generate a repeating model-bound view.
  82. // binding:
  83. // The bound node (a collection/array node) to generate a
  84. // repeating UI/view for.
  85. // repeatHeading:
  86. // The heading to be used for this portion.
  87. // tags:
  88. // private
  89. var headingClass = (this.classMapping && this.classMapping["Heading"]) ? this.classMapping["Heading"] : this._defaultClassMapping["Heading"];
  90. var repeat = '<div data-dojo-type="dojox.mvc.Group" data-dojo-props="ref: \'' + repeatHeading + '\'" + id="' + this.id + '_r' + this._counter++ + '">' +
  91. '<div class="' + headingClass + '\">' + repeatHeading + '</div>';
  92. repeat += this._generateBody(binding, true);
  93. repeat += '</div>';
  94. return repeat;
  95. },
  96. _generateGroup: function(binding, groupHeading, hideHeading){
  97. // summary:
  98. // Generate a hierarchical model-bound view.
  99. // binding:
  100. // The bound (intermediate) node to generate a hierarchical
  101. // view portion for.
  102. // groupHeading:
  103. // The heading to be used for this portion.
  104. // hideHeading:
  105. // Whether the heading should be hidden for this portion.
  106. // tags:
  107. // private
  108. var group = '<div data-dojo-type="dojox.mvc.Group" data-dojo-props="ref: \'' + groupHeading + '\'" + id="' + this.id + '_g' + this._counter++ + '">';
  109. if(!hideHeading){
  110. var headingClass = (this.classMapping && this.classMapping["Heading"]) ? this.classMapping["Heading"] : this._defaultClassMapping["Heading"];
  111. group += '<div class="' + headingClass + '\">' + groupHeading + '</div>';
  112. }
  113. group += this._generateBody(binding);
  114. group += '</div>';
  115. return group;
  116. },
  117. _generateTextBox: function(prop){
  118. // summary:
  119. // Produce a widget for a simple value.
  120. // prop:
  121. // The data model property name.
  122. // tags:
  123. // private
  124. // TODO: Data type based widget generation / enhanced meta-data
  125. var idname = this.idNameMapping ? this.idNameMapping["String"] : this._defaultIdNameMapping["String"];
  126. idname = idname + this._counter++;
  127. var widClass = this.widgetMapping ? this.widgetMapping["String"] : this._defaultWidgetMapping["String"];
  128. var labelClass = (this.classMapping && this.classMapping["Label"]) ? this.classMapping["Label"] : this._defaultClassMapping["Label"];
  129. var stringClass = (this.classMapping && this.classMapping["String"]) ? this.classMapping["String"] : this._defaultClassMapping["String"];
  130. var rowClass = (this.classMapping && this.classMapping["Row"]) ? this.classMapping["Row"] : this._defaultClassMapping["Row"];
  131. return '<div class="' + rowClass + '\">' +
  132. '<label class="' + labelClass + '\">' + prop + ':</label>' +
  133. '<input class="' + stringClass + '\" data-dojo-type="' + widClass + '\" data-dojo-props="name: \'' + idname + "', ref: '" + prop + '\'" id="' +
  134. idname + '\"></input>' +
  135. '</div>';
  136. }
  137. });
  138. });