footable.editing.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. /*
  2. * FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
  3. * @version 3.1.6
  4. * @link http://fooplugins.com
  5. * @copyright Steven Usher & Brad Vincent 2015
  6. * @license Released under the GPLv3 license.
  7. */
  8. (function($, F){
  9. F.Editing = F.Component.extend(/** @lends FooTable.Editing */{
  10. /**
  11. * The editing component adds a column with edit and delete buttons to each row as well as a single add row button in the footer.
  12. * @constructs
  13. * @extends FooTable.Component
  14. * @param {FooTable.Table} table - The parent {@link FooTable.Table} object for the component.
  15. * @returns {FooTable.Editing}
  16. */
  17. construct: function(table){
  18. // call the base constructor
  19. this._super(table, table.o.editing.enabled);
  20. /**
  21. * Whether or not to automatically page to a new row when it is added to the table.
  22. * @type {boolean}
  23. */
  24. this.pageToNew = table.o.editing.pageToNew;
  25. /**
  26. * Whether or not the editing column and add row button are always visible.
  27. * @type {boolean}
  28. */
  29. this.alwaysShow = table.o.editing.alwaysShow;
  30. /**
  31. * The options for the editing column. @see {@link FooTable.EditingColumn} for more info.
  32. * @type {object}
  33. * @prop {string} classes="footable-editing" - A space separated string of class names to apply to all cells in the column.
  34. * @prop {string} name="editing" - The name of the column.
  35. * @prop {string} title="" - The title displayed in the header row of the table for the column.
  36. * @prop {boolean} filterable=false - Whether or not the column should be filterable when using the filtering component.
  37. * @prop {boolean} sortable=false - Whether or not the column should be sortable when using the sorting component.
  38. */
  39. this.column = $.extend(true, {}, table.o.editing.column, {visible: this.alwaysShow});
  40. /**
  41. * The position of the editing column in the table as well as the alignment of the buttons.
  42. * @type {string}
  43. */
  44. this.position = table.o.editing.position;
  45. /**
  46. * The text that appears in the show button. This can contain HTML.
  47. * @type {string}
  48. */
  49. this.showText = table.o.editing.showText;
  50. /**
  51. * The text that appears in the hide button. This can contain HTML.
  52. * @type {string}
  53. */
  54. this.hideText = table.o.editing.hideText;
  55. /**
  56. * The text that appears in the add button. This can contain HTML.
  57. * @type {string}
  58. */
  59. this.addText = table.o.editing.addText;
  60. /**
  61. * The text that appears in the edit button. This can contain HTML.
  62. * @type {string}
  63. */
  64. this.editText = table.o.editing.editText;
  65. /**
  66. * The text that appears in the delete button. This can contain HTML.
  67. * @type {string}
  68. */
  69. this.deleteText = table.o.editing.deleteText;
  70. /**
  71. * The text that appears in the view button. This can contain HTML.
  72. * @type {string}
  73. */
  74. this.viewText = table.o.editing.viewText;
  75. /**
  76. * Whether or not to show the Add Row button.
  77. * @type {boolean}
  78. */
  79. this.allowAdd = table.o.editing.allowAdd;
  80. /**
  81. * Whether or not to show the Edit Row button.
  82. * @type {boolean}
  83. */
  84. this.allowEdit = table.o.editing.allowEdit;
  85. /**
  86. * Whether or not to show the Delete Row button.
  87. * @type {boolean}
  88. */
  89. this.allowDelete = table.o.editing.allowDelete;
  90. /**
  91. * Whether or not to show the View Row button.
  92. * @type {boolean}
  93. */
  94. this.allowView = table.o.editing.allowView;
  95. /**
  96. * Caches the row button elements to help with performance.
  97. * @type {(null|jQuery)}
  98. * @private
  99. */
  100. this._$buttons = null;
  101. /**
  102. * This object is used to contain the callbacks for the add, edit and delete row buttons.
  103. * @type {object}
  104. * @prop {function} addRow
  105. * @prop {function} editRow
  106. * @prop {function} deleteRow
  107. * @prop {function} viewRow
  108. */
  109. this.callbacks = {
  110. addRow: F.checkFnValue(this, table.o.editing.addRow),
  111. editRow: F.checkFnValue(this, table.o.editing.editRow),
  112. deleteRow: F.checkFnValue(this, table.o.editing.deleteRow),
  113. viewRow: F.checkFnValue(this, table.o.editing.viewRow)
  114. };
  115. },
  116. /* PROTECTED */
  117. /**
  118. * Checks the supplied data and options for the editing component.
  119. * @instance
  120. * @protected
  121. * @param {object} data - The jQuery data object from the parent table.
  122. * @fires FooTable.Editing#"preinit.ft.editing"
  123. */
  124. preinit: function(data){
  125. var self = this;
  126. /**
  127. * The preinit.ft.editing event is raised before the UI is created and provides the tables jQuery data object for additional options parsing.
  128. * Calling preventDefault on this event will disable the component.
  129. * @event FooTable.Editing#"preinit.ft.editing"
  130. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  131. * @param {FooTable.Table} ft - The instance of the plugin raising the event.
  132. * @param {object} data - The jQuery data object of the table raising the event.
  133. */
  134. this.ft.raise('preinit.ft.editing', [data]).then(function(){
  135. if (self.ft.$el.hasClass('footable-editing'))
  136. self.enabled = true;
  137. self.enabled = F.is.boolean(data.editing)
  138. ? data.editing
  139. : self.enabled;
  140. if (!self.enabled) return;
  141. self.pageToNew = F.is.boolean(data.editingPageToNew) ? data.editingPageToNew : self.pageToNew;
  142. self.alwaysShow = F.is.boolean(data.editingAlwaysShow) ? data.editingAlwaysShow : self.alwaysShow;
  143. self.position = F.is.string(data.editingPosition) ? data.editingPosition : self.position;
  144. self.showText = F.is.string(data.editingShowText) ? data.editingShowText : self.showText;
  145. self.hideText = F.is.string(data.editingHideText) ? data.editingHideText : self.hideText;
  146. self.addText = F.is.string(data.editingAddText) ? data.editingAddText : self.addText;
  147. self.editText = F.is.string(data.editingEditText) ? data.editingEditText : self.editText;
  148. self.deleteText = F.is.string(data.editingDeleteText) ? data.editingDeleteText : self.deleteText;
  149. self.viewText = F.is.string(data.editingViewText) ? data.editingViewText : self.viewText;
  150. self.allowAdd = F.is.boolean(data.editingAllowAdd) ? data.editingAllowAdd : self.allowAdd;
  151. self.allowEdit = F.is.boolean(data.editingAllowEdit) ? data.editingAllowEdit : self.allowEdit;
  152. self.allowDelete = F.is.boolean(data.editingAllowDelete) ? data.editingAllowDelete : self.allowDelete;
  153. self.allowView = F.is.boolean(data.editingAllowView) ? data.editingAllowView : self.allowView;
  154. self.column = new F.EditingColumn(self.ft, self, $.extend(true, {}, self.column, data.editingColumn, {visible: self.alwaysShow}));
  155. if (self.ft.$el.hasClass('footable-editing-left'))
  156. self.position = 'left';
  157. if (self.ft.$el.hasClass('footable-editing-right'))
  158. self.position = 'right';
  159. if (self.position === 'right'){
  160. self.column.index = self.ft.columns.array.length;
  161. } else {
  162. self.column.index = 0;
  163. for (var i = 0, len = self.ft.columns.array.length; i < len; i++){
  164. self.ft.columns.array[i].index += 1;
  165. }
  166. }
  167. self.ft.columns.array.push(self.column);
  168. self.ft.columns.array.sort(function(a, b){ return a.index - b.index; });
  169. self.callbacks.addRow = F.checkFnValue(self, data.editingAddRow, self.callbacks.addRow);
  170. self.callbacks.editRow = F.checkFnValue(self, data.editingEditRow, self.callbacks.editRow);
  171. self.callbacks.deleteRow = F.checkFnValue(self, data.editingDeleteRow, self.callbacks.deleteRow);
  172. self.callbacks.viewRow = F.checkFnValue(self, data.editingViewRow, self.callbacks.viewRow);
  173. }, function(){
  174. self.enabled = false;
  175. });
  176. },
  177. /**
  178. * Initializes the editing component for the plugin using the supplied table and options.
  179. * @instance
  180. * @protected
  181. * @fires FooTable.Editing#"init.ft.editing"
  182. */
  183. init: function(){
  184. /**
  185. * The init.ft.editing event is raised before its UI is generated.
  186. * Calling preventDefault on this event will disable the component.
  187. * @event FooTable.Editing#"init.ft.editing"
  188. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  189. * @param {FooTable.Table} ft - The instance of the plugin raising the event.
  190. */
  191. var self = this;
  192. this.ft.raise('init.ft.editing').then(function(){
  193. self.$create();
  194. }, function(){
  195. self.enabled = false;
  196. });
  197. },
  198. /**
  199. * Destroys the editing component removing any UI generated from the table.
  200. * @instance
  201. * @protected
  202. * @fires FooTable.Editing#"destroy.ft.editing"
  203. */
  204. destroy: function () {
  205. /**
  206. * The destroy.ft.editing event is raised before its UI is removed.
  207. * Calling preventDefault on this event will prevent the component from being destroyed.
  208. * @event FooTable.Editing#"destroy.ft.editing"
  209. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  210. * @param {FooTable.Table} ft - The instance of the plugin raising the event.
  211. */
  212. var self = this;
  213. this.ft.raise('destroy.ft.editing').then(function(){
  214. self.ft.$el.removeClass('footable-editing footable-editing-always-show footable-editing-no-add footable-editing-no-edit footable-editing-no-delete footable-editing-no-view')
  215. .off('click.ft.editing').find('tfoot > tr.footable-editing').remove();
  216. });
  217. },
  218. /**
  219. * Creates the editing UI from the current options setting the various jQuery properties of this component.
  220. * @instance
  221. * @protected
  222. */
  223. $create: function(){
  224. var self = this, position = self.position === 'right' ? 'footable-editing-right' : 'footable-editing-left';
  225. self.ft.$el.addClass('footable-editing').addClass(position)
  226. .on('click.ft.editing', '.footable-show', {self: self}, self._onShowClick)
  227. .on('click.ft.editing', '.footable-hide', {self: self}, self._onHideClick)
  228. .on('click.ft.editing', '.footable-edit', {self: self}, self._onEditClick)
  229. .on('click.ft.editing', '.footable-delete', {self: self}, self._onDeleteClick)
  230. .on('click.ft.editing', '.footable-view', {self: self}, self._onViewClick)
  231. .on('click.ft.editing', '.footable-add', {self: self}, self._onAddClick);
  232. self.$cell = $('<td/>').attr('colspan', self.ft.columns.visibleColspan).append(self.$buttonShow());
  233. if (self.allowAdd){
  234. self.$cell.append(self.$buttonAdd());
  235. }
  236. self.$cell.append(self.$buttonHide());
  237. if (self.alwaysShow){
  238. self.ft.$el.addClass('footable-editing-always-show');
  239. }
  240. if (!self.allowAdd) self.ft.$el.addClass('footable-editing-no-add');
  241. if (!self.allowEdit) self.ft.$el.addClass('footable-editing-no-edit');
  242. if (!self.allowDelete) self.ft.$el.addClass('footable-editing-no-delete');
  243. if (!self.allowView) self.ft.$el.addClass('footable-editing-no-view');
  244. var $tfoot = self.ft.$el.children('tfoot');
  245. if ($tfoot.length == 0){
  246. $tfoot = $('<tfoot/>');
  247. self.ft.$el.append($tfoot);
  248. }
  249. self.$row = $('<tr/>', { 'class': 'footable-editing' }).append(self.$cell).appendTo($tfoot);
  250. },
  251. /**
  252. * Creates the show button for the editing component.
  253. * @instance
  254. * @protected
  255. * @returns {(string|HTMLElement|jQuery)}
  256. */
  257. $buttonShow: function(){
  258. return '<button type="button" class="btn btn-primary footable-show">' + this.showText + '</button>';
  259. },
  260. /**
  261. * Creates the hide button for the editing component.
  262. * @instance
  263. * @protected
  264. * @returns {(string|HTMLElement|jQuery)}
  265. */
  266. $buttonHide: function(){
  267. return '<button type="button" class="btn btn-default footable-hide">' + this.hideText + '</button>';
  268. },
  269. /**
  270. * Creates the add button for the editing component.
  271. * @instance
  272. * @protected
  273. * @returns {(string|HTMLElement|jQuery)}
  274. */
  275. $buttonAdd: function(){
  276. return '<button type="button" class="btn btn-primary footable-add">' + this.addText + '</button> ';
  277. },
  278. /**
  279. * Creates the edit button for the editing component.
  280. * @instance
  281. * @protected
  282. * @returns {(string|HTMLElement|jQuery)}
  283. */
  284. $buttonEdit: function(){
  285. return '<button type="button" class="btn btn-default footable-edit">' + this.editText + '</button> ';
  286. },
  287. /**
  288. * Creates the delete button for the editing component.
  289. * @instance
  290. * @protected
  291. * @returns {(string|HTMLElement|jQuery)}
  292. */
  293. $buttonDelete: function(){
  294. return '<button type="button" class="btn btn-default footable-delete">' + this.deleteText + '</button>';
  295. },
  296. /**
  297. * Creates the view button for the editing component.
  298. * @instance
  299. * @protected
  300. * @returns {(string|HTMLElement|jQuery)}
  301. */
  302. $buttonView: function(){
  303. return '<button type="button" class="btn btn-default footable-view">' + this.viewText + '</button> ';
  304. },
  305. /**
  306. * Creates the button group for the row buttons.
  307. * @instance
  308. * @protected
  309. * @returns {(string|HTMLElement|jQuery)}
  310. */
  311. $rowButtons: function(){
  312. if (F.is.jq(this._$buttons)) return this._$buttons.clone();
  313. this._$buttons = $('<div class="btn-group btn-group-xs" role="group"></div>');
  314. if (this.allowView) this._$buttons.append(this.$buttonView());
  315. if (this.allowEdit) this._$buttons.append(this.$buttonEdit());
  316. if (this.allowDelete) this._$buttons.append(this.$buttonDelete());
  317. return this._$buttons;
  318. },
  319. /**
  320. * Performs the drawing of the component.
  321. */
  322. draw: function(){
  323. this.$cell.attr('colspan', this.ft.columns.visibleColspan);
  324. },
  325. /**
  326. * Handles the edit button click event.
  327. * @instance
  328. * @private
  329. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  330. * @fires FooTable.Editing#"edit.ft.editing"
  331. */
  332. _onEditClick: function(e){
  333. e.preventDefault();
  334. var self = e.data.self, row = $(this).closest('tr').data('__FooTableRow__');
  335. if (row instanceof F.Row){
  336. /**
  337. * The edit.ft.editing event is raised before its callback is executed.
  338. * Calling preventDefault on this event will prevent the callback from being executed.
  339. * @event FooTable.Editing#"edit.ft.editing"
  340. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  341. * @param {FooTable.Table} ft - The instance of the plugin raising the event.
  342. * @param {FooTable.Row} row - The row to be edited.
  343. */
  344. self.ft.raise('edit.ft.editing', [row]).then(function(){
  345. self.callbacks.editRow.call(self.ft, row);
  346. });
  347. }
  348. },
  349. /**
  350. * Handles the delete button click event.
  351. * @instance
  352. * @private
  353. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  354. * @fires FooTable.Editing#"delete.ft.editing"
  355. */
  356. _onDeleteClick: function(e){
  357. e.preventDefault();
  358. var self = e.data.self, row = $(this).closest('tr').data('__FooTableRow__');
  359. if (row instanceof F.Row){
  360. /**
  361. * The delete.ft.editing event is raised before its callback is executed.
  362. * Calling preventDefault on this event will prevent the callback from being executed.
  363. * @event FooTable.Editing#"delete.ft.editing"
  364. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  365. * @param {FooTable.Table} ft - The instance of the plugin raising the event.
  366. * @param {FooTable.Row} row - The row to be deleted.
  367. */
  368. self.ft.raise('delete.ft.editing', [row]).then(function(){
  369. self.callbacks.deleteRow.call(self.ft, row);
  370. });
  371. }
  372. },
  373. /**
  374. * Handles the view button click event.
  375. * @instance
  376. * @private
  377. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  378. * @fires FooTable.Editing#"view.ft.editing"
  379. */
  380. _onViewClick: function(e){
  381. e.preventDefault();
  382. var self = e.data.self, row = $(this).closest('tr').data('__FooTableRow__');
  383. if (row instanceof F.Row){
  384. /**
  385. * The view.ft.editing event is raised before its callback is executed.
  386. * Calling preventDefault on this event will prevent the callback from being executed.
  387. * @event FooTable.Editing#"view.ft.editing"
  388. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  389. * @param {FooTable.Table} ft - The instance of the plugin raising the event.
  390. * @param {FooTable.Row} row - The row to be viewed.
  391. */
  392. self.ft.raise('view.ft.editing', [row]).then(function(){
  393. self.callbacks.viewRow.call(self.ft, row);
  394. });
  395. }
  396. },
  397. /**
  398. * Handles the add button click event.
  399. * @instance
  400. * @private
  401. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  402. * @fires FooTable.Editing#"add.ft.editing"
  403. */
  404. _onAddClick: function(e){
  405. e.preventDefault();
  406. var self = e.data.self;
  407. /**
  408. * The add.ft.editing event is raised before its callback is executed.
  409. * Calling preventDefault on this event will prevent the callback from being executed.
  410. * @event FooTable.Editing#"add.ft.editing"
  411. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  412. * @param {FooTable.Table} ft - The instance of the plugin raising the event.
  413. */
  414. self.ft.raise('add.ft.editing').then(function(){
  415. self.callbacks.addRow.call(self.ft);
  416. });
  417. },
  418. /**
  419. * Handles the show button click event.
  420. * @instance
  421. * @private
  422. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  423. * @fires FooTable.Editing#"show.ft.editing"
  424. */
  425. _onShowClick: function(e){
  426. e.preventDefault();
  427. var self = e.data.self;
  428. /**
  429. * The show.ft.editing event is raised before its callback is executed.
  430. * Calling preventDefault on this event will prevent the callback from being executed.
  431. * @event FooTable.Editing#"show.ft.editing"
  432. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  433. * @param {FooTable.Table} ft - The instance of the plugin raising the event.
  434. */
  435. self.ft.raise('show.ft.editing').then(function(){
  436. self.ft.$el.addClass('footable-editing-show');
  437. self.column.visible = true;
  438. self.ft.draw();
  439. });
  440. },
  441. /**
  442. * Handles the hide button click event.
  443. * @instance
  444. * @private
  445. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  446. * @fires FooTable.Editing#"show.ft.editing"
  447. */
  448. _onHideClick: function(e){
  449. e.preventDefault();
  450. var self = e.data.self;
  451. /**
  452. * The hide.ft.editing event is raised before its callback is executed.
  453. * Calling preventDefault on this event will prevent the callback from being executed.
  454. * @event FooTable.Editing#"hide.ft.editing"
  455. * @param {jQuery.Event} e - The jQuery.Event object for the event.
  456. * @param {FooTable.Table} ft - The instance of the plugin raising the event.
  457. */
  458. self.ft.raise('hide.ft.editing').then(function(){
  459. self.ft.$el.removeClass('footable-editing-show');
  460. self.column.visible = false;
  461. self.ft.draw();
  462. });
  463. }
  464. });
  465. F.components.register('editing', F.Editing, 850);
  466. })(jQuery, FooTable);
  467. (function($, F){
  468. F.EditingColumn = F.Column.extend(/** @lends FooTable.EditingColumn */{
  469. /**
  470. * The Editing column class is used to create the column containing the editing buttons.
  471. * @constructs
  472. * @extends FooTable.Column
  473. * @param {FooTable.Table} instance - The parent {@link FooTable.Table} this column belongs to.
  474. * @param {FooTable.Editing} editing - The parent {@link FooTable.Editing} component this column is used with.
  475. * @param {object} definition - An object containing all the properties to set for the column.
  476. * @returns {FooTable.EditingColumn}
  477. */
  478. construct: function(instance, editing, definition){
  479. this._super(instance, definition, 'editing');
  480. this.editing = editing;
  481. this.internal = true;
  482. },
  483. /**
  484. * After the column has been defined this ensures that the $el property is a jQuery object by either creating or updating the current value.
  485. * @instance
  486. * @protected
  487. * @this FooTable.Column
  488. */
  489. $create: function(){
  490. (this.$el = !this.virtual && F.is.jq(this.$el) ? this.$el : $('<th/>', {'class': 'footable-editing'})).html(this.title);
  491. },
  492. /**
  493. * This is supplied either the cell value or jQuery object to parse. Any value can be returned from this method and
  494. * will be provided to the {@link FooTable.EditingColumn#format} function
  495. * to generate the cell contents.
  496. * @instance
  497. * @protected
  498. * @param {(*|jQuery)} valueOrElement - The value or jQuery cell object.
  499. * @returns {(jQuery)}
  500. */
  501. parser: function(valueOrElement){
  502. if (F.is.string(valueOrElement)) valueOrElement = $($.trim(valueOrElement));
  503. if (F.is.element(valueOrElement)) valueOrElement = $(valueOrElement);
  504. if (F.is.jq(valueOrElement)){
  505. var tagName = valueOrElement.prop('tagName').toLowerCase();
  506. if (tagName == 'td' || tagName == 'th') return valueOrElement.data('value') || valueOrElement.contents();
  507. return valueOrElement;
  508. }
  509. return null;
  510. },
  511. /**
  512. * Creates a cell to be used in the supplied row for this column.
  513. * @param {FooTable.Row} row - The row to create the cell for.
  514. * @returns {FooTable.Cell}
  515. */
  516. createCell: function(row){
  517. var $buttons = this.editing.$rowButtons(), $cell = $('<td/>').append($buttons);
  518. if (F.is.jq(row.$el)){
  519. if (this.index === 0){
  520. $cell.prependTo(row.$el);
  521. } else {
  522. $cell.insertAfter(row.$el.children().eq(this.index-1));
  523. }
  524. }
  525. return new F.Cell(this.ft, row, this, $cell || $cell.html());
  526. }
  527. });
  528. F.columns.register('editing', F.EditingColumn);
  529. })(jQuery, FooTable);
  530. (function($, F) {
  531. /**
  532. * An object containing the editing options for the plugin. Added by the {@link FooTable.Editing} component.
  533. * @type {object}
  534. * @prop {boolean} enabled=false - Whether or not to allow editing on the table.
  535. * @prop {boolean} pageToNew=true - Whether or not to automatically page to a new row when it is added to the table.
  536. * @prop {string} position="right" - The position of the editing column in the table as well as the alignment of the buttons.
  537. * @prop {boolean} alwaysShow=false - Whether or not the editing column and add row button are always visible.
  538. * @prop {function} addRow - The callback function to execute when the add row button is clicked.
  539. * @prop {function} editRow - The callback function to execute when the edit row button is clicked.
  540. * @prop {function} deleteRow - The callback function to execute when the delete row button is clicked.
  541. * @prop {function} viewRow - The callback function to execute when the view row button is clicked.
  542. * @prop {string} showText - The text that appears in the show button. This can contain HTML.
  543. * @prop {string} hideText - The text that appears in the hide button. This can contain HTML.
  544. * @prop {string} addText - The text that appears in the add button. This can contain HTML.
  545. * @prop {string} editText - The text that appears in the edit button. This can contain HTML.
  546. * @prop {string} deleteText - The text that appears in the delete button. This can contain HTML.
  547. * @prop {string} viewText - The text that appears in the view button. This can contain HTML.
  548. * @prop {boolean} allowAdd - Whether or not to show the Add Row button.
  549. * @prop {boolean} allowEdit - Whether or not to show the Edit Row button.
  550. * @prop {boolean} allowDelete - Whether or not to show the Delete Row button.
  551. * @prop {boolean} allowView - Whether or not to show the View Row button.
  552. * @prop {object} column - The options for the editing column. @see {@link FooTable.EditingColumn} for more info.
  553. * @prop {string} column.classes="footable-editing" - A space separated string of class names to apply to all cells in the column.
  554. * @prop {string} column.name="editing" - The name of the column.
  555. * @prop {string} column.title="" - The title displayed in the header row of the table for the column.
  556. * @prop {boolean} column.filterable=false - Whether or not the column should be filterable when using the filtering component.
  557. * @prop {boolean} column.sortable=false - Whether or not the column should be sortable when using the sorting component.
  558. */
  559. F.Defaults.prototype.editing = {
  560. enabled: false,
  561. pageToNew: true,
  562. position: 'right',
  563. alwaysShow: false,
  564. addRow: function(){},
  565. editRow: function(row){},
  566. deleteRow: function(row){},
  567. viewRow: function(row){},
  568. showText: '<span class="fooicon fooicon-pencil" aria-hidden="true"></span> Edit rows',
  569. hideText: 'Cancel',
  570. addText: 'New row',
  571. editText: '<span class="fooicon fooicon-pencil" aria-hidden="true"></span>',
  572. deleteText: '<span class="fooicon fooicon-trash" aria-hidden="true"></span>',
  573. viewText: '<span class="fooicon fooicon-stats" aria-hidden="true"></span>',
  574. allowAdd: true,
  575. allowEdit: true,
  576. allowDelete: true,
  577. allowView: false,
  578. column: {
  579. classes: 'footable-editing',
  580. name: 'editing',
  581. title: '',
  582. filterable: false,
  583. sortable: false
  584. }
  585. };
  586. })(jQuery, FooTable);
  587. (function($, F){
  588. if (F.is.defined(F.Paging)){
  589. /**
  590. * Holds a shallow clone of the un-paged {@link FooTable.Rows#array} value before paging occurs and superfluous rows are removed. Added by the {@link FooTable.Editing} component.
  591. * @instance
  592. * @public
  593. * @type {Array<FooTable.Row>}
  594. */
  595. F.Paging.prototype.unpaged = [];
  596. // override the default predraw method with one that sets the unpaged property.
  597. F.Paging.extend('predraw', function(){
  598. this.unpaged = this.ft.rows.array.slice(0); // create a shallow clone for later use
  599. this._super(); // call the original method
  600. });
  601. }
  602. })(jQuery, FooTable);
  603. (function($, F){
  604. /**
  605. * Adds the row to the table.
  606. * @param {boolean} [redraw=true] - Whether or not to redraw the table, defaults to true but for bulk operations this
  607. * can be set to false and then followed by a call to the {@link FooTable.Table#draw} method.
  608. * @returns {jQuery.Deferred}
  609. */
  610. F.Row.prototype.add = function(redraw){
  611. redraw = F.is.boolean(redraw) ? redraw : true;
  612. var self = this;
  613. return $.Deferred(function(d){
  614. var index = self.ft.rows.all.push(self) - 1;
  615. if (redraw){
  616. return self.ft.draw().then(function(){
  617. d.resolve(index);
  618. });
  619. } else {
  620. d.resolve(index);
  621. }
  622. });
  623. };
  624. /**
  625. * Removes the row from the table.
  626. * @param {boolean} [redraw=true] - Whether or not to redraw the table, defaults to true but for bulk operations this
  627. * can be set to false and then followed by a call to the {@link FooTable.Table#draw} method.
  628. * @returns {jQuery.Deferred}
  629. */
  630. F.Row.prototype.delete = function(redraw){
  631. redraw = F.is.boolean(redraw) ? redraw : true;
  632. var self = this;
  633. return $.Deferred(function(d){
  634. var index = self.ft.rows.all.indexOf(self);
  635. if (F.is.number(index) && index >= 0 && index < self.ft.rows.all.length){
  636. self.ft.rows.all.splice(index, 1);
  637. if (redraw){
  638. return self.ft.draw().then(function(){
  639. d.resolve(self);
  640. });
  641. }
  642. }
  643. d.resolve(self);
  644. });
  645. };
  646. if (F.is.defined(F.Paging)){
  647. // override the default add method with one that supports paging
  648. F.Row.extend('add', function(redraw){
  649. redraw = F.is.boolean(redraw) ? redraw : true;
  650. var self = this,
  651. added = this._super(redraw),
  652. editing = self.ft.use(F.Editing),
  653. paging;
  654. if (editing && editing.pageToNew && (paging = self.ft.use(F.Paging)) && redraw){
  655. return added.then(function(){
  656. var index = paging.unpaged.indexOf(self); // find this row in the unpaged array (this array will be sorted and filtered)
  657. var page = Math.ceil((index + 1) / paging.size); // calculate the page the new row is on
  658. if (paging.current !== page){ // goto the page if we need to
  659. return paging.goto(page);
  660. }
  661. });
  662. }
  663. return added;
  664. });
  665. }
  666. if (F.is.defined(F.Sorting)){
  667. // override the default val method with one that supports sorting and paging
  668. F.Row.extend('val', function(data, redraw){
  669. redraw = F.is.boolean(redraw) ? redraw : true;
  670. var result = this._super(data);
  671. if (!F.is.hash(data)){
  672. return result;
  673. }
  674. var self = this;
  675. if (redraw){
  676. self.ft.draw().then(function(){
  677. var editing = self.ft.use(F.Editing), paging;
  678. if (F.is.defined(F.Paging) && editing && editing.pageToNew && (paging = self.ft.use(F.Paging))){
  679. var index = paging.unpaged.indexOf(self); // find this row in the unpaged array (this array will be sorted and filtered)
  680. var page = Math.ceil((index + 1) / paging.size); // calculate the page the new row is on
  681. if (paging.current !== page){ // goto the page if we need to
  682. return paging.goto(page);
  683. }
  684. }
  685. });
  686. }
  687. return result;
  688. });
  689. }
  690. })(jQuery, FooTable);
  691. (function(F){
  692. /**
  693. * Adds a row to the underlying {@link FooTable.Rows#all} array.
  694. * @param {(object|FooTable.Row)} dataOrRow - A hash containing the row values or an actual {@link FooTable.Row} object.
  695. * @param {boolean} [redraw=true] - Whether or not to redraw the table, defaults to true but for bulk operations this
  696. * can be set to false and then followed by a call to the {@link FooTable.Table#draw} method.
  697. */
  698. F.Rows.prototype.add = function(dataOrRow, redraw){
  699. var row = dataOrRow;
  700. if (F.is.hash(dataOrRow)){
  701. row = new FooTable.Row(this.ft, this.ft.columns.array, dataOrRow);
  702. }
  703. if (row instanceof FooTable.Row){
  704. row.add(redraw);
  705. }
  706. };
  707. /**
  708. * Updates a row in the underlying {@link FooTable.Rows#all} array.
  709. * @param {(number|FooTable.Row)} indexOrRow - The index to update or the actual {@link FooTable.Row} object.
  710. * @param {object} data - A hash containing the new row values.
  711. * @param {boolean} [redraw=true] - Whether or not to redraw the table, defaults to true but for bulk operations this
  712. * can be set to false and then followed by a call to the {@link FooTable.Table#draw} method.
  713. */
  714. F.Rows.prototype.update = function(indexOrRow, data, redraw){
  715. var len = this.ft.rows.all.length,
  716. row = indexOrRow;
  717. if (F.is.number(indexOrRow) && indexOrRow >= 0 && indexOrRow < len){
  718. row = this.ft.rows.all[indexOrRow];
  719. }
  720. if (row instanceof FooTable.Row && F.is.hash(data)){
  721. row.val(data, redraw);
  722. }
  723. };
  724. /**
  725. * Deletes a row from the underlying {@link FooTable.Rows#all} array.
  726. * @param {(number|FooTable.Row)} indexOrRow - The index to delete or the actual {@link FooTable.Row} object.
  727. * @param {boolean} [redraw=true] - Whether or not to redraw the table, defaults to true but for bulk operations this
  728. * can be set to false and then followed by a call to the {@link FooTable.Table#draw} method.
  729. */
  730. F.Rows.prototype.delete = function(indexOrRow, redraw){
  731. var len = this.ft.rows.all.length,
  732. row = indexOrRow;
  733. if (F.is.number(indexOrRow) && indexOrRow >= 0 && indexOrRow < len){
  734. row = this.ft.rows.all[indexOrRow];
  735. }
  736. if (row instanceof FooTable.Row){
  737. row.delete(redraw);
  738. }
  739. };
  740. })(FooTable);