5ce69d5b8fea0ced622cd02db7cb9da7636a7c117e31517fbf528ad5457ee6ffe46aa3d0ede708823abb4f5465306b3e510be3a50acc9032f6094672a6844e 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import {
  2. addClass,
  3. fastInnerText,
  4. isVisible,
  5. removeClass,
  6. } from './../../../helpers/dom/element';
  7. import {objectEach} from './../../../helpers/object';
  8. import {toUpperCaseFirst, randomString} from './../../../helpers/string';
  9. import Event from './event';
  10. import Overlays from './overlays';
  11. import Scroll from './scroll';
  12. import Settings from './settings';
  13. import Table from './table';
  14. import Viewport from './viewport';
  15. /**
  16. * @class Walkontable
  17. */
  18. class Walkontable {
  19. /**
  20. * @param {Object} settings
  21. */
  22. constructor(settings) {
  23. let originalHeaders = [];
  24. // this is the namespace for global events
  25. this.guid = `wt_${randomString()}`;
  26. // bootstrap from settings
  27. if (settings.cloneSource) {
  28. this.cloneSource = settings.cloneSource;
  29. this.cloneOverlay = settings.cloneOverlay;
  30. this.wtSettings = settings.cloneSource.wtSettings;
  31. this.wtTable = new Table(this, settings.table, settings.wtRootElement);
  32. this.wtScroll = new Scroll(this);
  33. this.wtViewport = settings.cloneSource.wtViewport;
  34. this.wtEvent = new Event(this);
  35. this.selections = this.cloneSource.selections;
  36. } else {
  37. this.wtSettings = new Settings(this, settings);
  38. this.wtTable = new Table(this, settings.table);
  39. this.wtScroll = new Scroll(this);
  40. this.wtViewport = new Viewport(this);
  41. this.wtEvent = new Event(this);
  42. this.selections = this.getSetting('selections');
  43. this.wtOverlays = new Overlays(this);
  44. this.exportSettingsAsClassNames();
  45. }
  46. // find original headers
  47. if (this.wtTable.THEAD.childNodes.length && this.wtTable.THEAD.childNodes[0].childNodes.length) {
  48. for (let c = 0, clen = this.wtTable.THEAD.childNodes[0].childNodes.length; c < clen; c++) {
  49. originalHeaders.push(this.wtTable.THEAD.childNodes[0].childNodes[c].innerHTML);
  50. }
  51. if (!this.getSetting('columnHeaders').length) {
  52. this.update('columnHeaders', [
  53. function(column, TH) {
  54. fastInnerText(TH, originalHeaders[column]);
  55. }
  56. ]);
  57. }
  58. }
  59. this.drawn = false;
  60. this.drawInterrupted = false;
  61. }
  62. /**
  63. * Force rerender of Walkontable
  64. *
  65. * @param {Boolean} [fastDraw=false] When `true`, try to refresh only the positions of borders without rerendering
  66. * the data. It will only work if Table.draw() does not force
  67. * rendering anyway
  68. * @returns {Walkontable}
  69. */
  70. draw(fastDraw = false) {
  71. this.drawInterrupted = false;
  72. if (!fastDraw && !isVisible(this.wtTable.TABLE)) {
  73. // draw interrupted because TABLE is not visible
  74. this.drawInterrupted = true;
  75. } else {
  76. this.wtTable.draw(fastDraw);
  77. }
  78. return this;
  79. }
  80. /**
  81. * Returns the TD at coords. If topmost is set to true, returns TD from the topmost overlay layer,
  82. * if not set or set to false, returns TD from the master table.
  83. *
  84. * @param {CellCoords} coords
  85. * @param {Boolean} [topmost=false]
  86. * @returns {Object}
  87. */
  88. getCell(coords, topmost = false) {
  89. if (!topmost) {
  90. return this.wtTable.getCell(coords);
  91. }
  92. let totalRows = this.wtSettings.getSetting('totalRows');
  93. let fixedRowsTop = this.wtSettings.getSetting('fixedRowsTop');
  94. let fixedRowsBottom = this.wtSettings.getSetting('fixedRowsBottom');
  95. let fixedColumns = this.wtSettings.getSetting('fixedColumnsLeft');
  96. if (coords.row < fixedRowsTop && coords.col < fixedColumns) {
  97. return this.wtOverlays.topLeftCornerOverlay.clone.wtTable.getCell(coords);
  98. } else if (coords.row < fixedRowsTop) {
  99. return this.wtOverlays.topOverlay.clone.wtTable.getCell(coords);
  100. } else if (coords.col < fixedColumns && coords.row >= totalRows - fixedRowsBottom) {
  101. if (this.wtOverlays.bottomLeftCornerOverlay && this.wtOverlays.bottomLeftCornerOverlay.clone) {
  102. return this.wtOverlays.bottomLeftCornerOverlay.clone.wtTable.getCell(coords);
  103. }
  104. } else if (coords.col < fixedColumns) {
  105. return this.wtOverlays.leftOverlay.clone.wtTable.getCell(coords);
  106. } else if (coords.row < totalRows && coords.row > totalRows - fixedRowsBottom) {
  107. if (this.wtOverlays.bottomOverlay && this.wtOverlays.bottomOverlay.clone) {
  108. return this.wtOverlays.bottomOverlay.clone.wtTable.getCell(coords);
  109. }
  110. }
  111. return this.wtTable.getCell(coords);
  112. }
  113. /**
  114. * @param {Object} settings
  115. * @param {*} value
  116. * @returns {Walkontable}
  117. */
  118. update(settings, value) {
  119. return this.wtSettings.update(settings, value);
  120. }
  121. /**
  122. * Scroll the viewport to a row at the given index in the data source
  123. *
  124. * @param {Number} row
  125. * @returns {Walkontable}
  126. */
  127. scrollVertical(row) {
  128. this.wtOverlays.topOverlay.scrollTo(row);
  129. this.getSetting('onScrollVertically');
  130. return this;
  131. }
  132. /**
  133. * Scroll the viewport to a column at the given index in the data source
  134. *
  135. * @param {Number} column
  136. * @returns {Walkontable}
  137. */
  138. scrollHorizontal(column) {
  139. this.wtOverlays.leftOverlay.scrollTo(column);
  140. this.getSetting('onScrollHorizontally');
  141. return this;
  142. }
  143. /**
  144. * Scrolls the viewport to a cell (rerenders if needed)
  145. *
  146. * @param {CellCoords} coords
  147. * @returns {Walkontable}
  148. */
  149. scrollViewport(coords) {
  150. this.wtScroll.scrollViewport(coords);
  151. return this;
  152. }
  153. /**
  154. * @returns {Array}
  155. */
  156. getViewport() {
  157. return [
  158. this.wtTable.getFirstVisibleRow(),
  159. this.wtTable.getFirstVisibleColumn(),
  160. this.wtTable.getLastVisibleRow(),
  161. this.wtTable.getLastVisibleColumn()
  162. ];
  163. }
  164. /**
  165. * Get overlay name
  166. *
  167. * @returns {String}
  168. */
  169. getOverlayName() {
  170. return this.cloneOverlay ? this.cloneOverlay.type : 'master';
  171. }
  172. /**
  173. * Check overlay type of this Walkontable instance.
  174. *
  175. * @param {String} name Clone type @see {Overlay.CLONE_TYPES}.
  176. * @returns {Boolean}
  177. */
  178. isOverlayName(name) {
  179. if (this.cloneOverlay) {
  180. return this.cloneOverlay.type === name;
  181. }
  182. return false;
  183. }
  184. /**
  185. * Export settings as class names added to the parent element of the table.
  186. */
  187. exportSettingsAsClassNames() {
  188. let toExport = {
  189. rowHeaders: ['array'],
  190. columnHeaders: ['array']
  191. };
  192. let allClassNames = [];
  193. let newClassNames = [];
  194. objectEach(toExport, (optionType, key) => {
  195. if (optionType.indexOf('array') > -1 && this.getSetting(key).length) {
  196. newClassNames.push(`ht${toUpperCaseFirst(key)}`);
  197. }
  198. allClassNames.push(`ht${toUpperCaseFirst(key)}`);
  199. });
  200. removeClass(this.wtTable.wtRootElement.parentNode, allClassNames);
  201. addClass(this.wtTable.wtRootElement.parentNode, newClassNames);
  202. }
  203. /**
  204. * Get/Set Walkontable instance setting
  205. *
  206. * @param {String} key
  207. * @param {*} [param1]
  208. * @param {*} [param2]
  209. * @param {*} [param3]
  210. * @param {*} [param4]
  211. * @returns {*}
  212. */
  213. getSetting(key, param1, param2, param3, param4) {
  214. // this is faster than .apply - https://github.com/handsontable/handsontable/wiki/JavaScript-&-DOM-performance-tips
  215. return this.wtSettings.getSetting(key, param1, param2, param3, param4);
  216. }
  217. /**
  218. * Checks if setting exists
  219. *
  220. * @param {String} key
  221. * @returns {Boolean}
  222. */
  223. hasSetting(key) {
  224. return this.wtSettings.has(key);
  225. }
  226. /**
  227. * Destroy instance
  228. */
  229. destroy() {
  230. this.wtOverlays.destroy();
  231. this.wtEvent.destroy();
  232. }
  233. }
  234. export default Walkontable;