diff -r 000000000000 -r bca7a7e058a3 src/pyams_skin/resources/js/ext/jquery-dataTables-editable.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_skin/resources/js/ext/jquery-dataTables-editable.js Thu Feb 13 11:43:31 2020 +0100 @@ -0,0 +1,1382 @@ +/* +* File: jquery.dataTables.editable.js +* Version: 2.3.3. +* Author: Jovan Popovic +* +* Copyright 2010-2012 Jovan Popovic, all rights reserved. +* +* This source file is free software, under either the GPL v2 license or a +* BSD style license, as supplied with this software. +* +* This source file is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. +* +* Parameters: +* @sUpdateURL String URL of the server-side page used for updating cell. Default value is "UpdateData". +* @sAddURL String URL of the server-side page used for adding new row. Default value is "AddData". +* @sDeleteURL String URL of the server-side page used to delete row by id. Default value is "DeleteData". +* @fnShowError Function function(message, action){...} used to show error message. Action value can be "update", "add" or "delete". +* @sAddNewRowFormId String Id of the form for adding new row. Default id is "formAddNewRow". +* @oAddNewRowFormOptions Object Options that will be set to the "Add new row" dialog +* @sAddNewRowButtonId String Id of the button for adding new row. Default id is "btnAddNewRow". +* @oAddNewRowButtonOptions Object Options that will be set to the "Add new" button +* @sAddNewRowOkButtonId String Id of the OK button placed in add new row dialog. Default value is "btnAddNewRowOk". +* @oAddNewRowOkButtonOptions Object Options that will be set to the Ok button in the "Add new row" form +* @sAddNewRowCancelButtonId String Id of the Cancel button placed in add new row dialog. Default value is "btnAddNewRowCancel". +* @oAddNewRowCancelButtonOptions Object Options that will be set to the Cancel button in the "Add new row" form +* @sDeleteRowButtonId String Id of the button for adding new row. Default id is "btnDeleteRow". +* @oDeleteRowButtonOptions Object Options that will be set to the Delete button +* @sSelectedRowClass String Class that will be associated to the selected row. Default class is "row_selected". +* @sReadOnlyCellClass String Class of the cells that should not be editable. Default value is "read_only". +* @sAddDeleteToolbarSelector String Selector used to identify place where add and delete buttons should be placed. Default value is ".add_delete_toolbar". +* @fnStartProcessingMode Function function(){...} called when AJAX call is started. Use this function to add "Please wait..." message when some button is pressed. +* @fnEndProcessingMode Function function(){...} called when AJAX call is ended. Use this function to close "Please wait..." message. +* @aoColumns Array Array of the JEditable settings that will be applied on the columns +* @sAddHttpMethod String Method used for the Add AJAX request (default is 'POST') +* @sAddDataType String Data type expected from the server when adding a row; allowed values are the same as those accepted by JQuery's "datatype" parameter, e.g. 'text' and 'json'. The default is 'text'. +* @sDeleteHttpMethod String Method used for the Delete AJAX request (default is 'POST') +* @sDeleteDataType String Data type expected from the server when deleting a row; allowed values are the same as those accepted by JQuery's "datatype" parameter, e.g. 'text' and 'json'. The default is 'text'. +* @fnOnDeleting Function function(tr, id, fnDeleteRow){...} Function called before row is deleted. +tr isJQuery object encapsulating row that will be deleted +id is an id of the record that will be deleted. +fnDeleteRow(id) callback function that should be called to delete row with id +returns true if plugin should continue with deleting row, false will abort delete. +* @fnOnDeleted Function function(status){...} Function called after delete action. Status can be "success" or "failure" +* @fnOnAdding Function function(){...} Function called before row is added. +returns true if plugin should continue with adding row, false will abort add. +* @fnOnNewRowPosted Function function(data) Function that can override default function that is called when server-side sAddURL returns result +You can use this function to add different behaviour when server-side page returns result +* @fnOnAdded Function function(status){...} Function called after add action. Status can be "success" or "failure" +* @fnOnEditing Function function(input){...} Function called before cell is updated. +input JQuery object wrapping the input element used for editing value in the cell. +returns true if plugin should continue with sending AJAX request, false will abort update. +* @fnOnEdited Function function(status){...} Function called after edit action. Status can be "success" or "failure" +* @sEditorHeight String Default height of the cell editors +* @sEditorWidth String Default width of the cell editors +* @oDeleteParameters Object Additonal objects added to the DELETE Ajax request +* @oUpdateParameters Object Additonal objects added to the UPDATE Ajax request +* @sIDToken String Token in the add new row dialog that will be replaced with a returned id of the record that is created eg DT_RowId +* @sSuccessResponse String Text returned from the server if record is successfully deleted or edited. Default "ok" +* @sFailureResponsePrefix String Prefix of the error message returned form the server during edit action +*/ +(function ($) { + + $.fn.makeEditable = function (options) { + + var iDisplayStart = 0; + + function fnGetCellID(cell) { + /// + ///Utility function used to determine id of the cell + ///By default it is assumed that id is placed as an id attribute of that that surround the cell ( tag). E.g.: + /// + /// ............ + /// + /// + ///TD cell refference + + return properties.fnGetRowID($(cell.parentNode)); + } + + function _fnSetRowIDInAttribute(row, id, overwrite) { + /// + ///Utility function used to set id of the row. Usually when a new record is created, added to the table, + ///and when id of the record is retrieved from the server-side. + ///It is assumed that id is placed as an id attribute of that that surround the cell ( tag). E.g.: + /// + /// ............ + /// + ///This function is used when a datatable is configured in the server side processing mode or ajax source mode + /// + ///TR row where record is placed + + if (overwrite) { + row.attr("id", id); + } else { + if (row.attr("id") == null || row.attr("id") == "") + row.attr("id", id); + } + } + + function _fnGetRowIDFromAttribute(row) { + /// + ///Utility function used to get id of the row. + ///It is assumed that id is placed as an id attribute of that that surround the cell ( tag). E.g.: + /// + /// ............ + /// + ///This function is used when a datatable is configured in the standard client side mode + /// + ///TR row where record is placed + ///Id of the row - by default id attribute placed in the TR tag + + return row.attr("id"); + } + + function _fnSetRowIDInFirstCell(row, id) { + /// + ///Utility function used to set id of the row. Usually when a new record is created, added to the table, + ///and when id of the record is retrieved from the server-side). + ///It is assumed that id is placed as a value of the first <TD> cell in the <TR>. As example: + /// + /// 17......... + /// + ///This function is used when a datatable is configured in the server side processing mode or ajax source mode + /// + ///TR row where record is placed + + $("td:first", row).html(id); + } + + + function _fnGetRowIDFromFirstCell(row) { + /// + ///Utility function used to get id of the row. + ///It is assumed that id is placed as a value of the first <TD> cell in the <TR>. As example: + /// + /// 17......... + /// + ///This function is used when a datatable is configured in the server side processing mode or ajax source mode + /// + ///TR row where record is placed + ///Id of the row - by default id attribute placed in the TR tag + + return $("td:first", row).html(); + + } + + //Reference to the DataTable object + var oTable; + //Refences to the buttons used for manipulating table data + var oAddNewRowButton, oDeleteRowButton, oConfirmRowAddingButton, oCancelRowAddingButton; + //Reference to the form used for adding new data + var oAddNewRowForm; + + //Plugin options + var properties; + + function _fnShowError(errorText, action) { + /// + ///Shows an error message (Default function) + /// + ///text that should be shown + /// action that was executed when error occured e.g. "update", "delete", or "add" + + alert(errorText); + } + + function _fnStartProcessingMode() { + /// + ///Function that starts "Processing" mode i.e. shows "Processing..." dialog while some action is executing(Default function) + /// + + if (oTable.fnSettings().oFeatures.bProcessing) { + $(".dataTables_processing").css('visibility', 'visible'); + } + } + + function _fnEndProcessingMode() { + /// + ///Function that ends the "Processing" mode and returns the table in the normal state(Default function) + ///It shows processing message only if bProcessing setting is set to true + /// + + if (oTable.fnSettings().oFeatures.bProcessing) { + $(".dataTables_processing").css('visibility', 'hidden'); + } + } + + var sOldValue, sNewCellValue, sNewCellDislayValue; + + function fnApplyEditable(aoNodes) { + /// + ///Function that applies editable plugin to the array of table rows + /// + ///Aray of table rows <TR> that should be initialized with editable plugin + + if (properties.bDisableEditing) + return; + var oDefaultEditableSettings = { + event: 'dblclick', + + "onsubmit": function (settings, original) { + sOldValue = original.revert; + sNewCellValue = null; + sNewCellDisplayValue = null; + iDisplayStart = fnGetDisplayStart(); + + if(settings.type == "text" || settings.type == "select" || settings.type == "textarea" ) + { + var input = $("input,select,textarea", this); + sNewCellValue = $("input,select,textarea", $(this)).val(); + if (input.length == 1) { + var oEditElement = input[0]; + if (oEditElement.nodeName.toLowerCase() == "select" || oEditElement.tagName.toLowerCase() == "select") + sNewCellDisplayValue = $("option:selected", oEditElement).text(); //For select list use selected text instead of value for displaying in table + else + sNewCellDisplayValue = sNewCellValue; + } + + if (!properties.fnOnEditing(input, settings, original.revert, fnGetCellID(original))) + return false; + var x = settings; + + //2.2.2 INLINE VALIDATION + if (settings.oValidationOptions != null) { + input.parents("form").validate(settings.oValidationOptions); + } + if (settings.cssclass != null) { + input.addClass(settings.cssclass); + } + if(settings.cssclass == null && settings.oValidationOptions == null){ + return true; + }else{ + if (!input.valid() || 0 == input.valid()) + return false; + else + return true; + } + + } + + properties.fnStartProcessingMode(); + }, + "submitdata": function (value, settings) { + //iDisplayStart = fnGetDisplayStart(); + //properties.fnStartProcessingMode(); + var id = fnGetCellID(this); + var rowId = oTable.fnGetPosition(this)[0]; + var columnPosition = oTable.fnGetPosition(this)[1]; + var columnId = oTable.fnGetPosition(this)[2]; + var sColumnName = oTable.fnSettings().aoColumns[columnId].sName; + if (sColumnName == null || sColumnName == "") + sColumnName = oTable.fnSettings().aoColumns[columnId].sTitle; + var updateData = null; + if (properties.aoColumns == null || properties.aoColumns[columnId] == null) { + updateData = $.extend({}, + properties.oUpdateParameters, + { + "id": id, + "rowId": rowId, + "columnPosition": columnPosition, + "columnId": columnId, + "columnName": sColumnName + }); + } + else { + updateData = $.extend({}, + properties.oUpdateParameters, + properties.aoColumns[columnId].oUpdateParameters, + { + "id": id, + "rowId": rowId, + "columnPosition": columnPosition, + "columnId": columnId, + "columnName": sColumnName + }); + } + return updateData; + }, + "callback": function (sValue, settings) { + properties.fnEndProcessingMode(); + var status = ""; + var aPos = oTable.fnGetPosition(this); + + var bRefreshTable = !oSettings.oFeatures.bServerSide; + $("td.last-updated-cell", oTable.fnGetNodes( )).removeClass("last-updated-cell"); + if(sValue.indexOf(properties.sFailureResponsePrefix)>-1) + { + oTable.fnUpdate(sOldValue, aPos[0], aPos[2], bRefreshTable); + $("td.last-updated-cell", oTable).removeClass("last-updated-cell"); + $(this).addClass("last-updated-cell"); + properties.fnShowError(sValue.replace(properties.sFailureResponsePrefix, "").trim(), "update"); + status = "failure"; + } else { + + if (properties.sSuccessResponse == "IGNORE" || + ( properties.aoColumns != null + && properties.aoColumns[aPos[2]] != null + && properties.aoColumns[aPos[2]].sSuccessResponse == "IGNORE") || + (sNewCellValue == null) || (sNewCellValue == sValue) || + properties.sSuccessResponse == sValue) { + if(sNewCellDisplayValue == null) + { + //sNewCellDisplayValue = sValue; + oTable.fnUpdate(sValue, aPos[0], aPos[2], bRefreshTable); + }else{ + oTable.fnUpdate(sNewCellDisplayValue, aPos[0], aPos[2], bRefreshTable); + } + $("td.last-updated-cell", oTable).removeClass("last-updated-cell"); + $(this).addClass("last-updated-cell"); + status = "success"; + } else { + oTable.fnUpdate(sOldValue, aPos[0], aPos[2], bRefreshTable); + properties.fnShowError(sValue, "update"); + status = "failure"; + } + } + + properties.fnOnEdited(status, sOldValue, sNewCellDisplayValue, aPos[0], aPos[1], aPos[2]); + if (settings.fnOnCellUpdated != null) { + settings.fnOnCellUpdated(status, sValue, aPos[0], aPos[2], settings); + } + + fnSetDisplayStart(); + if (properties.bUseKeyTable) { + var keys = oTable.keys; + /* Unblock KeyTable, but only after this 'esc' key event has finished. Otherwise + * it will 'esc' KeyTable as well + */ + setTimeout(function () { keys.block = false; }, 0); + } + }, + "onerror": function () { + properties.fnEndProcessingMode(); + properties.fnShowError("Cell cannot be updated", "update"); + properties.fnOnEdited("failure"); + }, + + "onreset": function(){ + if (properties.bUseKeyTable) { + var keys = oTable.keys; + /* Unblock KeyTable, but only after this 'esc' key event has finished. Otherwise + * it will 'esc' KeyTable as well + */ + setTimeout(function () { keys.block = false; }, 0); + } + + }, + "height": properties.sEditorHeight, + "width": properties.sEditorWidth + }; + + var cells = null; + + if (properties.aoColumns != null) { + + for (var iDTindex = 0, iDTEindex = 0; iDTindex < oSettings.aoColumns.length; iDTindex++) { + if (oSettings.aoColumns[iDTindex].bVisible) {//if DataTables column is visible + if (properties.aoColumns[iDTEindex] == null) { + //If editor for the column is not defined go to the next column + iDTEindex++; + continue; + } + //Get all cells in the iDTEindex column (nth child is 1-indexed array) + cells = $("td:nth-child(" + (iDTEindex + 1) + ")", aoNodes); + + var oColumnSettings = oDefaultEditableSettings; + oColumnSettings = $.extend({}, oDefaultEditableSettings, properties.oEditableSettings, properties.aoColumns[iDTEindex]); + iDTEindex++; + var sUpdateURL = properties.sUpdateURL; + try { + if (oColumnSettings.sUpdateURL != null) + sUpdateURL = oColumnSettings.sUpdateURL; + } catch (ex) { + } + //cells.editable(sUpdateURL, oColumnSettings); + cells.each(function () { + if (!$(this).hasClass(properties.sReadOnlyCellClass)) { + $(this).editable(sUpdateURL, oColumnSettings); + } + }); + } + + } //end for + } else { + cells = $('td:not(.' + properties.sReadOnlyCellClass + ')', aoNodes); + cells.editable(properties.sUpdateURL, $.extend({}, oDefaultEditableSettings, properties.oEditableSettings)); + } + } + + function fnOnRowAdding(event) { + /// + ///Event handler called when a user click on the submit button in the "Add new row" form. + /// + ///Event that caused the action + + if (properties.fnOnAdding()) { + if (oAddNewRowForm.valid()) { + iDisplayStart = fnGetDisplayStart(); + properties.fnStartProcessingMode(); + + if (properties.bUseFormsPlugin) { + //Still in beta(development) + $(oAddNewRowForm).ajaxSubmit({ + dataType: 'xml', + success: function (response, statusString, xhr) { + if (xhr.responseText.toLowerCase().indexOf("error") != -1) { + properties.fnEndProcessingMode(); + properties.fnShowError(xhr.responseText.replace("Error",""), "add"); + properties.fnOnAdded("failure"); + } else { + fnOnRowAdded(xhr.responseText); + } + + }, + error: function (response) { + properties.fnEndProcessingMode(); + properties.fnShowError(response.responseText, "add"); + properties.fnOnAdded("failure"); + } + } + ); + + } else { + + var params = oAddNewRowForm.serialize(); + $.ajax({ 'url': properties.sAddURL, + 'data': params, + 'type': properties.sAddHttpMethod, + 'dataType': properties.sAddDataType, + success: fnOnRowAdded, + error: function (response) { + properties.fnEndProcessingMode(); + properties.fnShowError(response.responseText, "add"); + properties.fnOnAdded("failure"); + } + }); + } + } + } + event.stopPropagation(); + event.preventDefault(); + } + + function _fnOnNewRowPosted(data) { + ///Callback function called BEFORE a new record is posted to the server + ///TODO: Check this + + return true; + } + + + function fnOnRowAdded(data) { + /// + ///Function that is called when a new row is added, and Ajax response is returned from server + /// This function takes data from the add form and adds them into the table. + /// + ///Id of the new row that is returned from the server + + properties.fnEndProcessingMode(); + + if (properties.fnOnNewRowPosted(data)) { + + var oSettings = oTable.fnSettings(); + if (!oSettings.oFeatures.bServerSide) { + jQuery.data(oAddNewRowForm, 'DT_RowId', data); + var values = fnTakeRowDataFromFormElements(oAddNewRowForm); + + + var rtn; + //Add values from the form into the table + if (oSettings.aoColumns != null && isNaN(parseInt(oSettings.aoColumns[0].mDataProp))) { + rtn = oTable.fnAddData(rowData); + } + else { + rtn = oTable.fnAddData(values); + } + + var oTRAdded = oTable.fnGetNodes(rtn); + //add id returned by server page as an TR id attribute + properties.fnSetRowID($(oTRAdded), data, true); + //Apply editable plugin on the cells of the table + fnApplyEditable(oTRAdded); + + $("tr.last-added-row", oTable).removeClass("last-added-row"); + $(oTRAdded).addClass("last-added-row"); + } /*else { + oTable.fnDraw(false); + }*/ + //Close the dialog + oAddNewRowForm.dialog('close'); + $(oAddNewRowForm)[0].reset(); + $(".error", $(oAddNewRowForm)).html(""); + + fnSetDisplayStart(); + properties.fnOnAdded("success"); + if (properties.bUseKeyTable) { + var keys = oTable.keys; + /* Unblock KeyTable, but only after this 'esc' key event has finished. Otherwise + * it will 'esc' KeyTable as well + */ + setTimeout(function () { keys.block = false; }, 0); + } + } + } + + function fnOnCancelRowAdding(event) { + /// + ///Event handler function that is executed when a user press cancel button in the add new row form + ///This function clean the add form and error messages if some of them are shown + /// + ///DOM event that caused an error + + //Clear the validation messages and reset form + $(oAddNewRowForm).validate().resetForm(); // Clears the validation errors + $(oAddNewRowForm)[0].reset(); + + $(".error", $(oAddNewRowForm)).html(""); + $(".error", $(oAddNewRowForm)).hide(); // Hides the error element + + //Close the dialog + oAddNewRowForm.dialog('close'); + event.stopPropagation(); + event.preventDefault(); + } + + + function fnDisableDeleteButton() { + /// + ///Function that disables delete button + /// + + if (properties.bUseKeyTable) { + return; + } + if (properties.oDeleteRowButtonOptions != null) { + //oDeleteRowButton.disable(); + oDeleteRowButton.button("option", "disabled", true); + } else { + oDeleteRowButton.attr("disabled", "true"); + } + } + + function fnEnableDeleteButton() { + /// + ///Function that enables delete button + /// + + if (properties.oDeleteRowButtonOptions != null) { + //oDeleteRowButton.enable(); + oDeleteRowButton.button("option", "disabled", false); + } else { + oDeleteRowButton.removeAttr("disabled"); + } + } + + var nSelectedRow, nSelectedCell; + var oKeyTablePosition; + + + function _fnOnRowDeleteInline(e) { + + var sURL = $(this).attr("href"); + if (sURL == null || sURL == "") + sURL = properties.sDeleteURL; + + e.preventDefault(); + e.stopPropagation(); + + iDisplayStart = fnGetDisplayStart(); + + nSelectedCell = ($(this).parents('td'))[0]; + jSelectedRow = ($(this).parents('tr')); + nSelectedRow = jSelectedRow[0]; + + jSelectedRow.addClass(properties.sSelectedRowClass); + + var id = fnGetCellID(nSelectedCell); + if (properties.fnOnDeleting(jSelectedRow, id, fnDeleteRow)) { + fnDeleteRow(id, sURL); + } + } + + + function _fnOnRowDelete(event) { + /// + ///Event handler for the delete button + /// + ///DOM event + + event.preventDefault(); + event.stopPropagation(); + + iDisplayStart = fnGetDisplayStart(); + + nSelectedRow = null; + nSelectedCell = null; + + if (!properties.bUseKeyTable) { + if ($('tr.' + properties.sSelectedRowClass + ' td', oTable).length == 0) { + //oDeleteRowButton.attr("disabled", "true"); + _fnDisableDeleteButton(); + return; + } + nSelectedCell = $('tr.' + properties.sSelectedRowClass + ' td', oTable)[0]; + } else { + nSelectedCell = $('td.focus', oTable)[0]; + + } + if (nSelectedCell == null) { + fnDisableDeleteButton(); + return; + } + if (properties.bUseKeyTable) { + oKeyTablePosition = oTable.keys.fnGetCurrentPosition(); + } + var id = fnGetCellID(nSelectedCell); + var jSelectedRow = $(nSelectedCell).parent("tr"); + nSelectedRow = jSelectedRow[0]; + if (properties.fnOnDeleting(jSelectedRow, id, fnDeleteRow)) { + fnDeleteRow(id); + } + } + + function _fnOnDeleting(tr, id, fnDeleteRow) { + /// + ///The default function that is called before row is deleted + ///Returning false will abort delete + ///Function can be overriden via plugin properties in order to create custom delete functionality + ///in that case call fnDeleteRow with parameter id, and return false to prevent double delete action + /// + ///JQuery wrapper around the TR tag that will be deleted + ///Id of the record that wil be deleted + ///Function that will be called to delete a row. Default - fnDeleteRow(id) + + return confirm("Are you sure that you want to delete this record?"); ; + } + + + function fnDeleteRow(id, sDeleteURL) { + /// + ///Function that deletes a row with an id, using the sDeleteURL server page + /// + ///Id of the row that will be deleted. Id value is placed in the attribute of the TR tag that will be deleted + ///Server URL where delete request will be posted + + var sURL = sDeleteURL; + if (sDeleteURL == null) + sURL = properties.sDeleteURL; + properties.fnStartProcessingMode(); + var data = $.extend(properties.oDeleteParameters, { "id": id }); + $.ajax({ 'url': sURL, + 'type': properties.sDeleteHttpMethod, + 'data': data, + "success": fnOnRowDeleted, + "dataType": properties.sDeleteDataType, + "error": function (response) { + properties.fnEndProcessingMode(); + properties.fnShowError(response.responseText, "delete"); + properties.fnOnDeleted("failure"); + + } + }); + } + + + + function fnOnRowDeleted(response) { + /// + ///Called after the record is deleted on the server (in the ajax success callback) + /// + ///Response text eturned from the server-side page + + properties.fnEndProcessingMode(); + var oTRSelected = nSelectedRow; +/* + if (!properties.bUseKeyTable) { + oTRSelected = $('tr.' + properties.sSelectedRowClass, oTable)[0]; + } else { + oTRSelected = $("td.focus", oTable)[0].parents("tr")[0]; + } + */ + if (response == properties.sSuccessResponse || response == "") { + oTable.fnDeleteRow(oTRSelected); + fnDisableDeleteButton(); + fnSetDisplayStart(); + if (properties.bUseKeyTable) { + oTable.keys.fnSetPosition( oKeyTablePosition[0], oKeyTablePosition[1] ); + } + properties.fnOnDeleted("success"); + } + else { + properties.fnShowError(response, "delete"); + properties.fnOnDeleted("failure"); + } + } + + + + /* Function called after delete action + * @param result string + * "success" if row is actually deleted + * "failure" if delete failed + * @return void + */ + function _fnOnDeleted(result) { } + + function _fnOnEditing(input) { return true; } + function _fnOnEdited(result, sOldValue, sNewValue, iRowIndex, iColumnIndex, iRealColumnIndex) { + + } + + function fnOnAdding() { return true; } + function _fnOnAdded(result) { } + + var oSettings; + function fnGetDisplayStart() { + return oSettings._iDisplayStart; + } + + function fnSetDisplayStart() { + /// + ///Set the pagination position(do nothing in the server-side mode) + /// + + //To refresh table with preserver pagination on cell edit + //if (oSettings.oFeatures.bServerSide === false) { + oSettings._iDisplayStart = iDisplayStart; + oSettings.oApi._fnCalculateEnd(oSettings); + //draw the 'current' page + oSettings.oApi._fnDraw(oSettings); + //} + } + + function _fnOnBeforeAction(sAction) { + return true; + } + + function _fnOnActionCompleted(sStatus) { + + } + + function fnGetActionSettings(sAction) { + ///Returns settings object for the action + ///The name of the action + + if (properties.aoTableAction) + properties.fnShowError("Configuration error - aoTableAction setting are not set", sAction); + var i = 0; + + for (i = 0; i < properties.aoTableActions.length; i++) { + if (properties.aoTableActions[i].sAction == sAction) + return properties.aoTableActions[i]; + } + + properties.fnShowError("Cannot find action configuration settings", sAction); + } + + + function fnPopulateFormWithRowCells(oForm, oTR) { + ///Populates forms with row data + ///Form used to enter data + ///Table Row that will populate data + + var iRowID = oTable.fnGetPosition(oTR); + + var id = properties.fnGetRowID($(oTR)); + + $(oForm).validate().resetForm(); + jQuery.data($(oForm)[0], 'DT_RowId', id); + $("input.DT_RowId", $(oForm)).val(id); + jQuery.data($(oForm)[0], 'ROWID', iRowID); + $("input.ROWID", $(oForm)).val(iRowID); + + + var oSettings = oTable.fnSettings(); + var iColumnCount = oSettings.aoColumns.length; + + + $("input:text[rel],input:radio[rel][checked],input:hidden[rel],select[rel],textarea[rel],input:checkbox[rel]", + $(oForm)).each(function () { + var rel = $(this).attr("rel"); + + if (rel >= iColumnCount) + properties.fnShowError("In the form is placed input element with the name '" + $(this).attr("name") + "' with the 'rel' attribute that must be less than a column count - " + iColumnCount, "action"); + else { + var sCellValue = oTable.fnGetData(oTR)[rel]; + if (this.nodeName.toLowerCase() == "select" || this.tagName.toLowerCase() == "select") { + + if (this.multiple == true) { + var aoSelectedValue = new Array(); + aoCellValues = sCellValue.split(","); + for (i = 0; i <= this.options.length - 1; i++) { + if (jQuery.inArray(this.options[i].text.toLowerCase().trim(), aoCellValues) != -1) { + aoSelectedValue.push(this.options[i].value); + } + } + $(this).val(aoSelectedValue); + } else { + for (i = 0; i <= this.options.length - 1; i++) { + if (this.options[i].text.toLowerCase() == sCellValue.toLowerCase()) { + $(this).val(this.options[i].value); + } + } + } + + } + else if (this.nodeName.toLowerCase() == "span" || this.tagName.toLowerCase() == "span") + $(this).html(sCellValue); + else { + if (this.type == "checkbox") { + if (sCellValue == "true") { + $(this).attr("checked", true); + } + } else { + if (this.type == "radio") { + if (this.value == sCellValue) { + this.checked = true; + } + } else { + this.value = sCellValue; + } + } + } + + //sCellValue = sCellValue.replace(properties.sIDToken, data); + //values[rel] = sCellValue; + //oTable.fnUpdate(sCellValue, iRowID, rel); + } + }); + + + + } //End function fnPopulateFormWithRowCells + + function fnTakeRowDataFromFormElements(oForm) { + ///Populates row with form elements(This should be nly function that read fom elements from form) + ///DatabaseRowID + ///Form used to enter data + ///Object or array + + var iDT_RowId = jQuery.data(oForm, 'DT_RowId'); + var iColumnCount = oSettings.aoColumns.length; + + var values = new Array(); + var rowData = new Object(); + + $("input:text[rel],input:radio[rel][checked],input:hidden[rel],select[rel],textarea[rel],span.datafield[rel],input:checkbox[rel]", oForm).each(function () { + var rel = $(this).attr("rel"); + var sCellValue = ""; + if (rel >= iColumnCount) + properties.fnShowError("In the add form is placed input element with the name '" + $(this).attr("name") + "' with the 'rel' attribute that must be less than a column count - " + iColumnCount, "add"); + else { + if (this.nodeName.toLowerCase() == "select" || this.tagName.toLowerCase() == "select") { + //sCellValue = $("option:selected", this).text(); + sCellValue = $.map( + $.makeArray($("option:selected", this)), + function (n, i) { + return $(n).text(); + }).join(","); + } + else if (this.nodeName.toLowerCase() == "span" || this.tagName.toLowerCase() == "span") + sCellValue = $(this).html(); + else { + if (this.type == "checkbox") { + if (this.checked) + sCellValue = (this.value != "on") ? this.value : "true"; + else + sCellValue = (this.value != "on") ? "" : "false"; + } else + sCellValue = this.value; + } + //Deprecated + sCellValue = sCellValue.replace("DATAROWID", iDT_RowId); + sCellValue = sCellValue.replace(properties.sIDToken, iDT_RowId); + if (oSettings.aoColumns != null + && oSettings.aoColumns[rel] != null + && isNaN(parseInt(oSettings.aoColumns[0].mDataProp))) { + rowData[oSettings.aoColumns[rel].mDataProp] = sCellValue; + } else { + values[rel] = sCellValue; + } + } + }); + + if (oSettings.aoColumns != null && isNaN(parseInt(oSettings.aoColumns[0].mDataProp))) { + return rowData; + } + else { + return values; + } + + + } //End function fnPopulateRowWithFormElements + + + + + function fnSendFormUpdateRequest(nActionForm) { + ///Updates table row using form fields + ///Form used to enter data + + var jActionForm = $(nActionForm); + var sAction = jActionForm.attr("id"); + + sAction = sAction.replace("form", ""); + var sActionURL = jActionForm.attr("action"); + if (properties.fnOnBeforeAction(sAction)) { + if (jActionForm.valid()) { + iDisplayStart = fnGetDisplayStart(); + properties.fnStartProcessingMode(); + if (properties.bUseFormsPlugin) { + + //Still in beta(development) + var oAjaxSubmitOptions = { + success: function (response, statusString, xhr) { + properties.fnEndProcessingMode(); + if (response.toLowerCase().indexOf("error") != -1 || statusString != "success") { + properties.fnShowError(response, sAction); + properties.fnOnActionCompleted("failure"); + } else { + fnUpdateRowOnSuccess(nActionForm); + properties.fnOnActionCompleted("success"); + } + + }, + error: function (response) { + properties.fnEndProcessingMode(); + properties.fnShowError(response.responseText, sAction); + properties.fnOnActionCompleted("failure"); + } + }; + var oActionSettings = fnGetActionSettings(sAction); + oAjaxSubmitOptions = $.extend({}, properties.oAjaxSubmitOptions, oAjaxSubmitOptions); + $(oActionForm).ajaxSubmit(oAjaxSubmitOptions); + + } else { + var params = jActionForm.serialize(); + $.ajax({ 'url': sActionURL, + 'data': params, + 'type': properties.sAddHttpMethod, + 'dataType': properties.sAddDataType, + success: function (response) { + properties.fnEndProcessingMode(); + fnUpdateRowOnSuccess(nActionForm); + properties.fnOnActionCompleted("success"); + }, + error: function (response) { + properties.fnEndProcessingMode(); + properties.fnShowError(response.responseText, sAction); + properties.fnOnActionCompleted("failure"); + } + }); + } + } + } + } + + function fnUpdateRowOnSuccess(nActionForm) { + ///Updates table row using form fields after the ajax success callback is executed + ///Form used to enter data + + var values = fnTakeRowDataFromFormElements(nActionForm); + + var iRowID = jQuery.data(nActionForm, 'ROWID'); + var oSettings = oTable.fnSettings(); + var iColumnCount = oSettings.aoColumns.length; + for (var rel = 0; rel < iColumnCount; rel++) { + if (oSettings.aoColumns != null + && oSettings.aoColumns[rel] != null + && isNaN(parseInt(oSettings.aoColumns[0].mDataProp))) { + sCellValue = rowData[oSettings.aoColumns[rel].mDataProp]; + } else { + sCellValue = values[rel]; + } + if (sCellValue != undefined) + oTable.fnUpdate(sCellValue, iRowID, rel); + } + + fnSetDisplayStart(); + $(nActionForm).dialog('close'); + return; + + } + + + oTable = this; + + var defaults = { + + sUpdateURL: "UpdateData", + sAddURL: "AddData", + sDeleteURL: "DeleteData", + sAddNewRowFormId: "formAddNewRow", + oAddNewRowFormOptions: { autoOpen: false, modal: true }, + sAddNewRowButtonId: "btnAddNewRow", + oAddNewRowButtonOptions: null, + sAddNewRowOkButtonId: "btnAddNewRowOk", + sAddNewRowCancelButtonId: "btnAddNewRowCancel", + oAddNewRowOkButtonOptions: { label: "Ok" }, + oAddNewRowCancelButtonOptions: { label: "Cancel" }, + sDeleteRowButtonId: "btnDeleteRow", + oDeleteRowButtonOptions: null, + sSelectedRowClass: "row_selected", + sReadOnlyCellClass: "read_only", + sAddDeleteToolbarSelector: ".add_delete_toolbar", + fnShowError: _fnShowError, + fnStartProcessingMode: _fnStartProcessingMode, + fnEndProcessingMode: _fnEndProcessingMode, + aoColumns: null, + fnOnDeleting: _fnOnDeleting, + fnOnDeleted: _fnOnDeleted, + fnOnAdding: fnOnAdding, + fnOnNewRowPosted: _fnOnNewRowPosted, + fnOnAdded: _fnOnAdded, + fnOnEditing: _fnOnEditing, + fnOnEdited: _fnOnEdited, + sAddHttpMethod: 'POST', + sAddDataType: "text", + sDeleteHttpMethod: 'POST', + sDeleteDataType: "text", + fnGetRowID: _fnGetRowIDFromAttribute, + fnSetRowID: _fnSetRowIDInAttribute, + sEditorHeight: "100%", + sEditorWidth: "100%", + bDisableEditing: false, + oEditableSettings: null, + oDeleteParameters: {}, + oUpdateParameters: {}, + sIDToken: "DT_RowId", + aoTableActions: null, + fnOnBeforeAction: _fnOnBeforeAction, + bUseFormsPlugin: false, + fnOnActionCompleted: _fnOnActionCompleted, + sSuccessResponse: "ok", + sFailureResponsePrefix: "ERROR", + oKeyTable: null //KEYTABLE + }; + + properties = $.extend(defaults, options); + oSettings = oTable.fnSettings(); + properties.bUseKeyTable = (properties.oKeyTable != null); + + return this.each(function () { + var sTableId = oTable.dataTableSettings[0].sTableId; + //KEYTABLE + if (properties.bUseKeyTable) { + var keys = new KeyTable({ + "table": document.getElementById(sTableId), + "datatable": oTable + }); + oTable.keys = keys; + + /* Apply a return key event to each cell in the table */ + keys.event.action(null, null, function (nCell) { + if( $(nCell).hasClass(properties.sReadOnlyCellClass)) + return; + /* Block KeyTable from performing any events while jEditable is in edit mode */ + keys.block = true; + /* Dispatch click event to go into edit mode - Saf 4 needs a timeout... */ + setTimeout(function () { $(nCell).dblclick(); }, 0); + //properties.bDisableEditing = true; + }); + } + + + + + + + //KEYTABLE + + if (oTable.fnSettings().sAjaxSource != null) { + oTable.fnSettings().aoDrawCallback.push({ + "fn": function () { + //Apply jEditable plugin on the table cells + fnApplyEditable(oTable.fnGetNodes()); + $(oTable.fnGetNodes()).each(function () { + var position = oTable.fnGetPosition(this); + var id = oTable.fnGetData(position)[0]; + properties.fnSetRowID($(this), id); + } + ); + }, + "sName": "fnApplyEditable" + }); + + } else { + //Apply jEditable plugin on the table cells + fnApplyEditable(oTable.fnGetNodes()); + } + + //Setup form to open in dialog + oAddNewRowForm = $("#" + properties.sAddNewRowFormId); + if (oAddNewRowForm.length != 0) { + + ///Check does the add new form has all nessecary fields + var oSettings = oTable.fnSettings(); + var iColumnCount = oSettings.aoColumns.length; + for (i = 0; i < iColumnCount; i++) { + if ($("[rel=" + i + "]", oAddNewRowForm).length == 0) + properties.fnShowError("In the form that is used for adding new records cannot be found an input element with rel=" + i + " that will be bound to the value in the column " + i + ". See http://code.google.com/p/jquery-datatables-editable/wiki/AddingNewRecords#Add_new_record_form for more details", "init"); + } + + + if (properties.oAddNewRowFormOptions != null) { + properties.oAddNewRowFormOptions.autoOpen = false; + } else { + properties.oAddNewRowFormOptions = { autoOpen: false }; + } + oAddNewRowForm.dialog(properties.oAddNewRowFormOptions); + + //Add button click handler on the "Add new row" button + oAddNewRowButton = $("#" + properties.sAddNewRowButtonId); + if (oAddNewRowButton.length != 0) { + + if(oAddNewRowButton.data("add-event-attached")!="true") + { + oAddNewRowButton.click(function () { + oAddNewRowForm.dialog('open'); + }); + oAddNewRowButton.data("add-event-attached", "true"); + } + + } else { + if ($(properties.sAddDeleteToolbarSelector).length == 0) { + throw "Cannot find a button with an id '" + properties.sAddNewRowButtonId + "', or placeholder with an id '" + properties.sAddDeleteToolbarSelector + "' that should be used for adding new row although form for adding new record is specified"; + } else { + oAddNewRowButton = null; //It will be auto-generated later + } + } + + //Prevent Submit handler + if (oAddNewRowForm[0].nodeName.toLowerCase() == "form") { + oAddNewRowForm.unbind('submit'); + oAddNewRowForm.submit(function (event) { + fnOnRowAdding(event); + return false; + }); + } else { + $("form", oAddNewRowForm[0]).unbind('submit'); + $("form", oAddNewRowForm[0]).submit(function (event) { + fnOnRowAdding(event); + return false; + }); + } + + // array to add default buttons to + var aAddNewRowFormButtons = []; + + oConfirmRowAddingButton = $("#" + properties.sAddNewRowOkButtonId, oAddNewRowForm); + if (oConfirmRowAddingButton.length == 0) { + //If someone forgotten to set the button text + if (properties.oAddNewRowOkButtonOptions.text == null + || properties.oAddNewRowOkButtonOptions.text == "") { + properties.oAddNewRowOkButtonOptions.text = "Ok"; + } + properties.oAddNewRowOkButtonOptions.click = fnOnRowAdding; + properties.oAddNewRowOkButtonOptions.id = properties.sAddNewRowOkButtonId; + // push the add button onto the array + aAddNewRowFormButtons.push(properties.oAddNewRowOkButtonOptions); + } else { + oConfirmRowAddingButton.click(fnOnRowAdding); + } + + oCancelRowAddingButton = $("#" + properties.sAddNewRowCancelButtonId); + if (oCancelRowAddingButton.length == 0) { + //If someone forgotten to the button text + if (properties.oAddNewRowCancelButtonOptions.text == null + || properties.oAddNewRowCancelButtonOptions.text == "") { + properties.oAddNewRowCancelButtonOptions.text = "Cancel"; + } + properties.oAddNewRowCancelButtonOptions.click = fnOnCancelRowAdding; + properties.oAddNewRowCancelButtonOptions.id = properties.sAddNewRowCancelButtonId; + // push the cancel button onto the array + aAddNewRowFormButtons.push(properties.oAddNewRowCancelButtonOptions); + } else { + oCancelRowAddingButton.click(fnOnCancelRowAdding); + } + // if the array contains elements, add them to the dialog + if (aAddNewRowFormButtons.length > 0) { + oAddNewRowForm.dialog('option', 'buttons', aAddNewRowFormButtons); + } + //Issue: It cannot find it with this call: + //oConfirmRowAddingButton = $("#" + properties.sAddNewRowOkButtonId, oAddNewRowForm); + //oCancelRowAddingButton = $("#" + properties.sAddNewRowCancelButtonId, oAddNewRowForm); + oConfirmRowAddingButton = $("#" + properties.sAddNewRowOkButtonId); + oCancelRowAddingButton = $("#" + properties.sAddNewRowCancelButtonId); + + if (properties.oAddNewRowFormValidation != null) { + oAddNewRowForm.validate(properties.oAddNewRowFormValidation); + } + } else { + oAddNewRowForm = null; + } + + //Set the click handler on the "Delete selected row" button + oDeleteRowButton = $('#' + properties.sDeleteRowButtonId); + if (oDeleteRowButton.length != 0) + { + if(oDeleteRowButton.data("delete-event-attached")!="true") + { + oDeleteRowButton.click(_fnOnRowDelete); + oDeleteRowButton.data("delete-event-attached", "true"); + } + } + else { + oDeleteRowButton = null; + } + + //If an add and delete buttons does not exists but Add-delete toolbar is specificed + //Autogenerate these buttons + oAddDeleteToolbar = $(properties.sAddDeleteToolbarSelector); + if (oAddDeleteToolbar.length != 0) { + if (oAddNewRowButton == null && properties.sAddNewRowButtonId != "" + && oAddNewRowForm != null) { + oAddDeleteToolbar.append(""); + oAddNewRowButton = $("#" + properties.sAddNewRowButtonId); + oAddNewRowButton.click(function () { oAddNewRowForm.dialog('open'); }); + } + if (oDeleteRowButton == null && properties.sDeleteRowButtonId != "") { + oAddDeleteToolbar.append(""); + oDeleteRowButton = $("#" + properties.sDeleteRowButtonId); + oDeleteRowButton.click(_fnOnRowDelete); + } + } + + //If delete button exists disable it until some row is selected + if (oDeleteRowButton != null) { + if (properties.oDeleteRowButtonOptions != null) { + oDeleteRowButton.button(properties.oDeleteRowButtonOptions); + } + fnDisableDeleteButton(); + } + + //If add button exists convert it to the JQuery-ui button + if (oAddNewRowButton != null) { + if (properties.oAddNewRowButtonOptions != null) { + oAddNewRowButton.button(properties.oAddNewRowButtonOptions); + } + } + + + //If form ok button exists convert it to the JQuery-ui button + if (oConfirmRowAddingButton != null) { + if (properties.oAddNewRowOkButtonOptions != null) { + oConfirmRowAddingButton.button(properties.oAddNewRowOkButtonOptions); + } + } + + //If form cancel button exists convert it to the JQuery-ui button + if (oCancelRowAddingButton != null) { + if (properties.oAddNewRowCancelButtonOptions != null) { + oCancelRowAddingButton.button(properties.oAddNewRowCancelButtonOptions); + } + } + + //Add handler to the inline delete buttons + $(".table-action-deletelink", oTable).live("click", _fnOnRowDeleteInline); + + if (!properties.bUseKeyTable) { + //Set selected class on row that is clicked + //Enable delete button if row is selected, disable delete button if selected class is removed + $("tbody", oTable).click(function (event) { + if ($(event.target.parentNode).hasClass(properties.sSelectedRowClass)) { + $(event.target.parentNode).removeClass(properties.sSelectedRowClass); + if (oDeleteRowButton != null) { + fnDisableDeleteButton(); + } + } else { + $(oTable.fnSettings().aoData).each(function () { + $(this.nTr).removeClass(properties.sSelectedRowClass); + }); + $(event.target.parentNode).addClass(properties.sSelectedRowClass); + if (oDeleteRowButton != null) { + fnEnableDeleteButton(); + } + } + }); + } else { + oTable.keys.event.focus(null, null, function (nNode, x, y) { + + }); + } + + if (properties.aoTableActions != null) { + for (var i = 0; i < properties.aoTableActions.length; i++) { + var oTableAction = $.extend({ sType: "edit" }, properties.aoTableActions[i]); + var sAction = oTableAction.sAction; + var sActionFormId = oTableAction.sActionFormId; + + var oActionForm = $("#form" + sAction); + if (oActionForm.length != 0) { + var oFormOptions = { autoOpen: false, modal: true }; + oFormOptions = $.extend({}, oTableAction.oFormOptions, oFormOptions); + oActionForm.dialog(oFormOptions); + oActionForm.data("action-options", oTableAction); + + var oActionFormLink = $(".table-action-" + sAction); + if (oActionFormLink.length != 0) { + + oActionFormLink.live("click", function () { + + + var sClass = this.className; + var classList = sClass.split(/\s+/); + var sActionFormId = ""; + var sAction = ""; + for (i = 0; i < classList.length; i++) { + if (classList[i].indexOf("table-action-") > -1) { + sAction = classList[i].replace("table-action-", ""); + sActionFormId = "#form" + sAction; + } + } + if (sActionFormId == "") { + properties.fnShowError("Cannot find a form with an id " + sActionFormId + " that should be associated to the action - " + sAction, sAction) + } + + var oTableAction = $(sActionFormId).data("action-options"); + + if (oTableAction.sType == "edit") { + + //var oTD = ($(this).parents('td'))[0]; + var oTR = ($(this).parents('tr'))[0]; + fnPopulateFormWithRowCells(oActionForm, oTR); + } + $(oActionForm).dialog('open'); + }); + } + + oActionForm.submit(function (event) { + + fnSendFormUpdateRequest(this); + return false; + + }); + + + var aActionFormButtons = new Array(); + + //var oActionSubmitButton = $("#form" + sAction + "Ok", oActionForm); + //aActionFormButtons.push(oActionSubmitButton); + var oActionFormCancel = $("#form" + sAction + "Cancel", oActionForm); + if (oActionFormCancel.length != 0) { + aActionFormButtons.push(oActionFormCancel); + oActionFormCancel.click(function () { + + var oActionForm = $(this).parents("form")[0]; + //Clear the validation messages and reset form + $(oActionForm).validate().resetForm(); // Clears the validation errors + $(oActionForm)[0].reset(); + + $(".error", $(oActionForm)).html(""); + $(".error", $(oActionForm)).hide(); // Hides the error element + $(oActionForm).dialog('close'); + }); + } + + //Convert all action form buttons to the JQuery UI buttons + $("button", oActionForm).button(); + /* + if (aActionFormButtons.length > 0) { + oActionForm.dialog('option', 'buttons', aActionFormButtons); + } + */ + + + + } + + + + + } // end for (var i = 0; i < properties.aoTableActions.length; i++) + } //end if (properties.aoTableActions != null) + + + }); + }; +})(jQuery); +