76bfeab9dc58b94178ba005143e20aacc75a585c.svn-base 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. if (!dojo._hasResource["dojox.grid._grid.view"]) { // _hasResource checks added
  2. // by build. Do not use
  3. // _hasResource directly in
  4. // your code.
  5. dojo._hasResource["dojox.grid._grid.view"] = true;
  6. dojo.provide("dojox.grid._grid.view");
  7. dojo.require("dijit._Widget");
  8. dojo.require("dijit._Templated");
  9. dojo.require("dojox.grid._grid.builder");
  10. dojo.declare('dojox.GridView', [dijit._Widget, dijit._Templated], {
  11. // summary:
  12. // A collection of grid columns. A grid is comprised of a set of views
  13. // that stack horizontally.
  14. // Grid creates views automatically based on grid's layout structure.
  15. // Users should typically not need to access individual views directly.
  16. defaultWidth : "18em",
  17. // viewWidth: string
  18. // width for the view, in valid css unit
  19. viewWidth : "",
  20. templateString : '<div class="dojoxGrid-view"><div class="dojoxGrid-header" dojoAttachPoint="headerNode"><div style="width: 9000em"><div dojoAttachPoint="headerContentNode"></div></div></div><input type="checkbox" class="dojoxGrid-hidden-focus" dojoAttachPoint="hiddenFocusNode" /><input type="checkbox" class="dojoxGrid-hidden-focus" /><div class="dojoxGrid-scrollbox" dojoAttachPoint="scrollboxNode"><div class="dojoxGrid-content" dojoAttachPoint="contentNode" hidefocus="hidefocus"></div></div></div>',
  21. themeable : false,
  22. classTag : 'dojoxGrid',
  23. marginBottom : 0,
  24. rowPad : 2,
  25. postMixInProperties : function() {
  26. this.rowNodes = [];
  27. },
  28. postCreate : function() {
  29. dojo.connect(this.scrollboxNode, "onscroll", dojo.hitch(this,
  30. "doscroll"));
  31. dojox.grid.funnelEvents(this.contentNode, this, "doContentEvent",
  32. ['mouseover', 'mouseout', 'click', 'dblclick',
  33. 'contextmenu']);
  34. dojox.grid.funnelEvents(this.headerNode, this, "doHeaderEvent", [
  35. 'dblclick', 'mouseover', 'mouseout', 'mousemove',
  36. 'mousedown', 'click', 'contextmenu']);
  37. this.content = new dojox.grid.contentBuilder(this);
  38. this.header = new dojox.grid.headerBuilder(this);
  39. },
  40. destroy : function() {
  41. dojox.grid.removeNode(this.headerNode);
  42. this.inherited("destroy", arguments);
  43. },
  44. // focus
  45. focus : function() {
  46. if (dojo.isSafari || dojo.isOpera) {
  47. this.hiddenFocusNode.focus();
  48. } else {
  49. this.scrollboxNode.focus();
  50. }
  51. },
  52. setStructure : function(inStructure) {
  53. var vs = this.structure = inStructure;
  54. // FIXME: similar logic is duplicated in layout
  55. if (vs.width && dojo.isNumber(vs.width)) {
  56. this.viewWidth = vs.width + 'em';
  57. } else {
  58. this.viewWidth = vs.width || this.viewWidth; // ||
  59. // this.defaultWidth;
  60. }
  61. this.onBeforeRow = vs.onBeforeRow;
  62. this.noscroll = vs.noscroll;
  63. if (this.noscroll) {
  64. this.scrollboxNode.style.overflow = "hidden";
  65. }
  66. // bookkeeping
  67. this.testFlexCells();
  68. // accomodate new structure
  69. this.updateStructure();
  70. },
  71. testFlexCells : function() {
  72. // FIXME: cheater, this function does double duty as initializer and
  73. // tester
  74. this.flexCells = false;
  75. for (var j = 0, row; (row = this.structure.rows[j]); j++) {
  76. for (var i = 0, cell; (cell = row[i]); i++) {
  77. cell.view = this;
  78. this.flexCells = this.flexCells || cell.isFlex();
  79. }
  80. }
  81. return this.flexCells;
  82. },
  83. updateStructure : function() {
  84. // header builder needs to update table map
  85. this.header.update();
  86. // content builder needs to update markup cache
  87. this.content.update();
  88. },
  89. getScrollbarWidth : function() {
  90. return (this.noscroll ? 0 : dojox.grid.getScrollbarWidth());
  91. },
  92. getColumnsWidth : function() {
  93. return this.headerContentNode.firstChild.offsetWidth;
  94. },
  95. getWidth : function() {
  96. return this.viewWidth
  97. || (this.getColumnsWidth() + this.getScrollbarWidth())
  98. + 'px';
  99. },
  100. getContentWidth : function() {
  101. return Math.max(0, dojo._getContentBox(this.domNode).w
  102. - this.getScrollbarWidth())
  103. + 'px';
  104. },
  105. render : function() {
  106. this.scrollboxNode.style.height = '';
  107. this.renderHeader();
  108. },
  109. renderHeader : function() {
  110. this.headerContentNode.innerHTML = this.header
  111. .generateHtml(this._getHeaderContent);
  112. },
  113. // note: not called in 'view' context
  114. _getHeaderContent : function(inCell) {
  115. var n = inCell.name || inCell.grid.getCellName(inCell);
  116. if (inCell.index != inCell.grid.getSortIndex()) {
  117. return n;
  118. }
  119. return [
  120. '<div class="',
  121. inCell.grid.sortInfo > 0
  122. ? 'dojoxGrid-sort-down'
  123. : 'dojoxGrid-sort-up', '">', n, '</div>'].join('');
  124. },
  125. resize : function() {
  126. this.resizeHeight();
  127. this.resizeWidth();
  128. },
  129. hasScrollbar : function() {
  130. return (this.scrollboxNode.clientHeight != this.scrollboxNode.offsetHeight);
  131. },
  132. resizeHeight : function() {
  133. if (!this.grid.autoHeight) {
  134. var h = this.domNode.clientHeight;
  135. if (!this.hasScrollbar()) { // no scrollbar is rendered
  136. h -= dojox.grid.getScrollbarWidth();
  137. }
  138. dojox.grid.setStyleHeightPx(this.scrollboxNode, h);
  139. }
  140. },
  141. resizeWidth : function() {
  142. if (this.flexCells) {
  143. // the view content width
  144. this.contentWidth = this.getContentWidth();
  145. this.headerContentNode.firstChild.style.width = this.contentWidth;
  146. }
  147. // FIXME: it should be easier to get w from
  148. // this.scrollboxNode.clientWidth,
  149. // but clientWidth seemingly does not include scrollbar width in
  150. // some cases
  151. var w = this.scrollboxNode.offsetWidth - this.getScrollbarWidth();
  152. w = Math.max(w, this.getColumnsWidth()) + 'px';
  153. with (this.contentNode) {
  154. style.width = '';
  155. offsetWidth;
  156. style.width = w;
  157. }
  158. },
  159. setSize : function(w, h) {
  160. with (this.domNode.style) {
  161. if (w) {
  162. width = w;
  163. }
  164. height = (h >= 0 ? h + 'px' : '');
  165. }
  166. with (this.headerNode.style) {
  167. if (w) {
  168. width = w;
  169. }
  170. }
  171. },
  172. renderRow : function(inRowIndex, inHeightPx) {
  173. var rowNode = this.createRowNode(inRowIndex);
  174. this.buildRow(inRowIndex, rowNode, inHeightPx);
  175. this.grid.edit.restore(this, inRowIndex);
  176. return rowNode;
  177. },
  178. createRowNode : function(inRowIndex) {
  179. var node = document.createElement("div");
  180. node.className = this.classTag + '-row';
  181. node[dojox.grid.rowIndexTag] = inRowIndex;
  182. this.rowNodes[inRowIndex] = node;
  183. return node;
  184. },
  185. buildRow : function(inRowIndex, inRowNode) {
  186. this.buildRowContent(inRowIndex, inRowNode);
  187. this.styleRow(inRowIndex, inRowNode);
  188. },
  189. buildRowContent : function(inRowIndex, inRowNode) {
  190. inRowNode.innerHTML = this.content.generateHtml(inRowIndex,
  191. inRowIndex);
  192. if (this.flexCells) {
  193. // FIXME: accessing firstChild here breaks encapsulation
  194. inRowNode.firstChild.style.width = this.contentWidth;
  195. }
  196. },
  197. rowRemoved : function(inRowIndex) {
  198. this.grid.edit.save(this, inRowIndex);
  199. delete this.rowNodes[inRowIndex];
  200. },
  201. getRowNode : function(inRowIndex) {
  202. return this.rowNodes[inRowIndex];
  203. },
  204. getCellNode : function(inRowIndex, inCellIndex) {
  205. var row = this.getRowNode(inRowIndex);
  206. if (row) {
  207. return this.content.getCellNode(row, inCellIndex);
  208. }
  209. },
  210. // styling
  211. styleRow : function(inRowIndex, inRowNode) {
  212. inRowNode._style = dojox.grid.getStyleText(inRowNode);
  213. this.styleRowNode(inRowIndex, inRowNode);
  214. },
  215. styleRowNode : function(inRowIndex, inRowNode) {
  216. if (inRowNode) {
  217. this.doStyleRowNode(inRowIndex, inRowNode);
  218. }
  219. },
  220. doStyleRowNode : function(inRowIndex, inRowNode) {
  221. this.grid.styleRowNode(inRowIndex, inRowNode);
  222. },
  223. // updating
  224. updateRow : function(inRowIndex, inHeightPx, inPageNode) {
  225. var rowNode = this.getRowNode(inRowIndex);
  226. if (rowNode) {
  227. rowNode.style.height = '';
  228. this.buildRow(inRowIndex, rowNode);
  229. }
  230. return rowNode;
  231. },
  232. updateRowStyles : function(inRowIndex) {
  233. this.styleRowNode(inRowIndex, this.getRowNode(inRowIndex));
  234. },
  235. // scrolling
  236. lastTop : 0,
  237. doscroll : function(inEvent) {
  238. this.headerNode.scrollLeft = this.scrollboxNode.scrollLeft;
  239. // 'lastTop' is a semaphore to prevent feedback-loop with
  240. // setScrollTop below
  241. var top = this.scrollboxNode.scrollTop;
  242. if (top != this.lastTop) {
  243. this.grid.scrollTo(top);
  244. }
  245. },
  246. setScrollTop : function(inTop) {
  247. // 'lastTop' is a semaphore to prevent feedback-loop with doScroll
  248. // above
  249. this.lastTop = inTop;
  250. this.scrollboxNode.scrollTop = inTop;
  251. return this.scrollboxNode.scrollTop;
  252. },
  253. // event handlers (direct from DOM)
  254. doContentEvent : function(e) {
  255. if (this.content.decorateEvent(e)) {
  256. this.grid.onContentEvent(e);
  257. }
  258. },
  259. doHeaderEvent : function(e) {
  260. if (this.header.decorateEvent(e)) {
  261. this.grid.onHeaderEvent(e);
  262. }
  263. },
  264. // event dispatch(from Grid)
  265. dispatchContentEvent : function(e) {
  266. return this.content.dispatchEvent(e);
  267. },
  268. dispatchHeaderEvent : function(e) {
  269. return this.header.dispatchEvent(e);
  270. },
  271. // column resizing
  272. setColWidth : function(inIndex, inWidth) {
  273. this.grid.setCellWidth(inIndex, inWidth + 'px');
  274. },
  275. update : function() {
  276. var left = this.scrollboxNode.scrollLeft;
  277. this.content.update();
  278. this.grid.update();
  279. this.scrollboxNode.scrollLeft = left;
  280. }
  281. });
  282. }