/************************************************************************ * DELETION extension for jTable * *************************************************************************/ (function ($) { //Reference to base object members var base = { _create: $.hik.jtable.prototype._create, _addColumnsToHeaderRow: $.hik.jtable.prototype._addColumnsToHeaderRow, _addCellsToRowUsingRecord: $.hik.jtable.prototype._addCellsToRowUsingRecord }; //extension members $.extend(true, $.hik.jtable.prototype, { /************************************************************************ * DEFAULT OPTIONS / EVENTS * *************************************************************************/ options: { //Options deleteConfirmation: true, //Events recordDeleted: function (event, data) { }, //Localization messages: { deleteConfirmation: 'This record will be deleted. Are you sure?', deleteText: 'Delete', deleting: 'Deleting', canNotDeletedRecords: 'Can not delete {0} of {1} records!', deleteProggress: 'Deleting {0} of {1} records, processing...' } }, /************************************************************************ * PRIVATE FIELDS * *************************************************************************/ _$deleteRecordDiv: null, //Reference to the adding new record dialog div (jQuery object) _$deletingRow: null, //Reference to currently deleting row (jQuery object) /************************************************************************ * CONSTRUCTOR * *************************************************************************/ /* Overrides base method to do deletion-specific constructions. *************************************************************************/ _create: function () { base._create.apply(this, arguments); this._createDeleteDialogDiv(); }, /* Creates and prepares delete record confirmation dialog div. *************************************************************************/ _createDeleteDialogDiv: function () { var self = this; //Check if deleteAction is supplied if (!self.options.actions.deleteAction) { return; } //Create div element for delete confirmation dialog self._$deleteRecordDiv = $('

').appendTo(self._$mainContainer); //Prepare dialog self._$deleteRecordDiv.dialog({ autoOpen: false, show: self.options.dialogShowEffect, hide: self.options.dialogHideEffect, modal: true, title: self.options.messages.areYouSure, buttons: [{ //cancel button text: self.options.messages.cancel, click: function () { self._$deleteRecordDiv.dialog("close"); } }, {//delete button id: 'DeleteDialogButton', text: self.options.messages.deleteText, click: function () { //row maybe removed by another source, if so, do nothing if (self._$deletingRow.hasClass('jtable-row-removed')) { self._$deleteRecordDiv.dialog('close'); return; } var $deleteButton = self._$deleteRecordDiv.parent().find('#DeleteDialogButton'); self._setEnabledOfDialogButton($deleteButton, false, self.options.messages.deleting); self._deleteRecordFromServer( self._$deletingRow, function () { self._removeRowsFromTableWithAnimation(self._$deletingRow); self._$deleteRecordDiv.dialog('close'); }, function (message) { //error self._showError(message); self._setEnabledOfDialogButton($deleteButton, true, self.options.messages.deleteText); } ); } }], close: function () { var $deleteButton = self._$deleteRecordDiv.parent().find('#DeleteDialogButton'); self._setEnabledOfDialogButton($deleteButton, true, self.options.messages.deleteText); } }); }, /************************************************************************ * PUBLIC METHODS * *************************************************************************/ /* This method is used to delete one or more rows from server and the table. *************************************************************************/ deleteRows: function ($rows) { var self = this; if ($rows.length <= 0) { self._logWarn('No rows specified to jTable deleteRows method.'); return; } if (self._isBusy()) { self._logWarn('Can not delete rows since jTable is busy!'); return; } //Deleting just one row if ($rows.length == 1) { self._deleteRecordFromServer( $rows, function () { //success self._removeRowsFromTableWithAnimation($rows); }, function (message) { //error self._showError(message); } ); return; } //Deleting multiple rows self._showBusy(self._formatString(self.options.messages.deleteProggress, 0, $rows.length)); //This method checks if deleting of all records is completed var completedCount = 0; var isCompleted = function () { return (completedCount >= $rows.length); }; //This method is called when deleting of all records completed var completed = function () { var $deletedRows = $rows.filter('.jtable-row-ready-to-remove'); if ($deletedRows.length < $rows.length) { self._showError(self._formatString(self.options.messages.canNotDeletedRecords, $rows.length - $deletedRows.length, $rows.length)); } if ($deletedRows.length > 0) { self._removeRowsFromTableWithAnimation($deletedRows); } self._hideBusy(); }; //Delete all rows var deletedCount = 0; $rows.each(function () { var $row = $(this); self._deleteRecordFromServer( $row, function () { //success ++deletedCount; ++completedCount; $row.addClass('jtable-row-ready-to-remove'); self._showBusy(self._formatString(self.options.messages.deleteProggress, deletedCount, $rows.length)); if (isCompleted()) { completed(); } }, function () { //error ++completedCount; if (isCompleted()) { completed(); } } ); }); }, /* Deletes a record from the table (optionally from the server also). *************************************************************************/ deleteRecord: function (options) { var self = this; options = $.extend({ clientOnly: false, animationsEnabled: self.options.animationsEnabled, url: self.options.actions.deleteAction, success: function () { }, error: function () { } }, options); if (options.key == undefined) { self._logWarn('options parameter in deleteRecord method must contain a key property.'); return; } var $deletingRow = self.getRowByKey(options.key); if ($deletingRow == null) { self._logWarn('Can not found any row by key: ' + options.key); return; } if (options.clientOnly) { self._removeRowsFromTableWithAnimation($deletingRow, options.animationsEnabled); options.success(); return; } self._deleteRecordFromServer( $deletingRow, function (data) { //success self._removeRowsFromTableWithAnimation($deletingRow, options.animationsEnabled); options.success(data); }, function (message) { //error self._showError(message); options.error(message); }, options.url ); }, /************************************************************************ * OVERRIDED METHODS * *************************************************************************/ /* Overrides base method to add a 'deletion column cell' to header row. *************************************************************************/ _addColumnsToHeaderRow: function ($tr) { base._addColumnsToHeaderRow.apply(this, arguments); if (this.options.actions.deleteAction != undefined) { $tr.append(this._createEmptyCommandHeader()); } }, /* Overrides base method to add a 'delete command cell' to a row. *************************************************************************/ _addCellsToRowUsingRecord: function ($row) { base._addCellsToRowUsingRecord.apply(this, arguments); var self = this; if (self.options.actions.deleteAction != undefined) { var $span = $('').html(self.options.messages.deleteText); var $button = $('') .addClass('jtable-command-button jtable-delete-command-button') .append($span) .click(function (e) { e.preventDefault(); e.stopPropagation(); self._deleteButtonClickedForRow($row); }); $('') .addClass('jtable-command-column') .append($button) .appendTo($row); } }, /************************************************************************ * PRIVATE METHODS * *************************************************************************/ /* This method is called when user clicks delete button on a row. *************************************************************************/ _deleteButtonClickedForRow: function ($row) { var self = this; var deleteConfirm; var deleteConfirmMessage = self.options.messages.deleteConfirmation; //If options.deleteConfirmation is function then call it if ($.isFunction(self.options.deleteConfirmation)) { var data = { row: $row, record: $row.data('record'), deleteConfirm: true, deleteConfirmMessage: deleteConfirmMessage, cancel: false, cancelMessage: null }; self.options.deleteConfirmation(data); //If delete progress is cancelled if (data.cancel) { //If a canlellation reason is specified if (data.cancelMessage) { self._showError(data.cancelMessage); //TODO: show warning/stop message instead of error (also show warning/error ui icon)! } return; } deleteConfirmMessage = data.deleteConfirmMessage; deleteConfirm = data.deleteConfirm; } else { deleteConfirm = self.options.deleteConfirmation; } if (deleteConfirm != false) { //Confirmation self._$deleteRecordDiv.find('.jtable-delete-confirm-message').html(deleteConfirmMessage); self._showDeleteDialog($row); } else { //No confirmation self._deleteRecordFromServer( $row, function () { //success self._removeRowsFromTableWithAnimation($row); }, function (message) { //error self._showError(message); } ); } }, /* Shows delete comfirmation dialog. *************************************************************************/ _showDeleteDialog: function ($row) { this._$deletingRow = $row; this._$deleteRecordDiv.dialog('open'); }, /* Performs an ajax call to server to delete record * and removes row of the record from table if ajax call success. *************************************************************************/ _deleteRecordFromServer: function ($row, success, error, url) { var self = this; var completeDelete = function(data) { if (data.Result != 'OK') { $row.data('deleting', false); if (error) { error(data.Message); } return; } self._trigger("recordDeleted", null, { record: $row.data('record'), row: $row, serverResponse: data }); if (success) { success(data); } }; //Check if it is already being deleted right now if ($row.data('deleting') == true) { return; } $row.data('deleting', true); var postData = {}; postData[self._keyField] = self._getKeyValueOfRecord($row.data('record')); //deleteAction may be a function, check if it is if (!url && $.isFunction(self.options.actions.deleteAction)) { //Execute the function var funcResult = self.options.actions.deleteAction(postData); //Check if result is a jQuery Deferred object if (self._isDeferredObject(funcResult)) { //Wait promise funcResult.done(function (data) { completeDelete(data); }).fail(function () { $row.data('deleting', false); if (error) { error(self.options.messages.serverCommunicationError); } }); } else { //assume it returned the deletion result completeDelete(funcResult); } } else { //Assume it's a URL string //Make ajax call to delete the record from server this._ajax({ url: (url || self.options.actions.deleteAction), data: postData, success: function (data) { completeDelete(data); }, error: function () { $row.data('deleting', false); if (error) { error(self.options.messages.serverCommunicationError); } } }); } }, /* Removes a row from table after a 'deleting' animation. *************************************************************************/ _removeRowsFromTableWithAnimation: function ($rows, animationsEnabled) { var self = this; if (animationsEnabled == undefined) { animationsEnabled = self.options.animationsEnabled; } if (animationsEnabled) { var className = 'jtable-row-deleting'; if (this.options.jqueryuiTheme) { className = className + ' ui-state-disabled'; } //Stop current animation (if does exists) and begin 'deleting' animation. $rows.stop(true, true).addClass(className, 'slow', '').promise().done(function () { self._removeRowsFromTable($rows, 'deleted'); }); } else { self._removeRowsFromTable($rows, 'deleted'); } } }); })(jQuery);