src/ztfy/myams/resources/js/ext/jquery-dataTables-editable.js
changeset 75 e4c5705087a0
equal deleted inserted replaced
74:c2bd88e15b5c 75:e4c5705087a0
       
     1 /*
       
     2 * File:        jquery.dataTables.editable.js
       
     3 * Version:     2.3.3.
       
     4 * Author:      Jovan Popovic 
       
     5 * 
       
     6 * Copyright 2010-2012 Jovan Popovic, all rights reserved.
       
     7 *
       
     8 * This source file is free software, under either the GPL v2 license or a
       
     9 * BSD style license, as supplied with this software.
       
    10 * 
       
    11 * This source file is distributed in the hope that it will be useful, but 
       
    12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
       
    13 * or FITNESS FOR A PARTICULAR PURPOSE. 
       
    14 * 
       
    15 * Parameters:
       
    16 * @sUpdateURL                       String      URL of the server-side page used for updating cell. Default value is "UpdateData".
       
    17 * @sAddURL                          String      URL of the server-side page used for adding new row. Default value is "AddData".
       
    18 * @sDeleteURL                       String      URL of the server-side page used to delete row by id. Default value is "DeleteData".
       
    19 * @fnShowError                      Function    function(message, action){...}  used to show error message. Action value can be "update", "add" or "delete".
       
    20 * @sAddNewRowFormId                 String      Id of the form for adding new row. Default id is "formAddNewRow".
       
    21 * @oAddNewRowFormOptions            Object        Options that will be set to the "Add new row" dialog
       
    22 * @sAddNewRowButtonId               String      Id of the button for adding new row. Default id is "btnAddNewRow".
       
    23 * @oAddNewRowButtonOptions            Object        Options that will be set to the "Add new" button
       
    24 * @sAddNewRowOkButtonId             String      Id of the OK button placed in add new row dialog. Default value is "btnAddNewRowOk".
       
    25 * @oAddNewRowOkButtonOptions        Object        Options that will be set to the Ok button in the "Add new row" form
       
    26 * @sAddNewRowCancelButtonId         String      Id of the Cancel button placed in add new row dialog. Default value is "btnAddNewRowCancel".
       
    27 * @oAddNewRowCancelButtonOptions    Object        Options that will be set to the Cancel button in the "Add new row" form
       
    28 * @sDeleteRowButtonId               String      Id of the button for adding new row. Default id is "btnDeleteRow".
       
    29 * @oDeleteRowButtonOptions            Object        Options that will be set to the Delete button
       
    30 * @sSelectedRowClass                String      Class that will be associated to the selected row. Default class is "row_selected".
       
    31 * @sReadOnlyCellClass               String      Class of the cells that should not be editable. Default value is "read_only".
       
    32 * @sAddDeleteToolbarSelector        String      Selector used to identify place where add and delete buttons should be placed. Default value is ".add_delete_toolbar".
       
    33 * @fnStartProcessingMode            Function    function(){...} called when AJAX call is started. Use this function to add "Please wait..." message  when some button is pressed.
       
    34 * @fnEndProcessingMode              Function    function(){...} called when AJAX call is ended. Use this function to close "Please wait..." message.
       
    35 * @aoColumns                        Array       Array of the JEditable settings that will be applied on the columns
       
    36 * @sAddHttpMethod                   String      Method used for the Add AJAX request (default is 'POST')
       
    37 * @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'.
       
    38 * @sDeleteHttpMethod                String      Method used for the Delete AJAX request (default is 'POST')
       
    39 * @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'.
       
    40 * @fnOnDeleting                     Function    function(tr, id, fnDeleteRow){...} Function called before row is deleted.
       
    41 tr isJQuery object encapsulating row that will be deleted
       
    42 id is an id of the record that will be deleted.
       
    43 fnDeleteRow(id) callback function that should be called to delete row with id
       
    44 returns true if plugin should continue with deleting row, false will abort delete.
       
    45 * @fnOnDeleted                      Function    function(status){...} Function called after delete action. Status can be "success" or "failure"
       
    46 * @fnOnAdding                       Function    function(){...} Function called before row is added.
       
    47 returns true if plugin should continue with adding row, false will abort add.
       
    48 * @fnOnNewRowPosted                    Function    function(data) Function that can override default function that is called when server-side sAddURL returns result
       
    49 You can use this function to add different behaviour when server-side page returns result
       
    50 * @fnOnAdded                        Function    function(status){...} Function called after add action. Status can be "success" or "failure"
       
    51 * @fnOnEditing                      Function    function(input){...} Function called before cell is updated.
       
    52 input JQuery object wrapping the input element used for editing value in the cell.
       
    53 returns true if plugin should continue with sending AJAX request, false will abort update.
       
    54 * @fnOnEdited                       Function    function(status){...} Function called after edit action. Status can be "success" or "failure"
       
    55 * @sEditorHeight                    String      Default height of the cell editors
       
    56 * @sEditorWidth                     String      Default width of the cell editors
       
    57 * @oDeleteParameters                Object      Additonal objects added to the DELETE Ajax request
       
    58 * @oUpdateParameters                Object      Additonal objects added to the UPDATE Ajax request
       
    59 * @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
       
    60 * @sSuccessResponse                 String        Text returned from the server if record is successfully deleted or edited. Default "ok" 
       
    61 * @sFailureResponsePrefix            String        Prefix of the error message returned form the server during edit action
       
    62 */
       
    63 (function ($) {
       
    64 
       
    65     $.fn.makeEditable = function (options) {
       
    66 
       
    67         var iDisplayStart = 0;
       
    68 
       
    69         function fnGetCellID(cell) {
       
    70             ///<summary>
       
    71             ///Utility function used to determine id of the cell
       
    72             ///By default it is assumed that id is placed as an id attribute of <tr> that that surround the cell (<td> tag). E.g.:
       
    73             ///<tr id="17">
       
    74             ///  <td>...</td><td>...</td><td>...</td><td>...</td>
       
    75             ///</tr>
       
    76             ///</summary>
       
    77             ///<param name="cell" type="DOM" domElement="true">TD cell refference</param>
       
    78 
       
    79             return properties.fnGetRowID($(cell.parentNode));
       
    80         }
       
    81 
       
    82         function _fnSetRowIDInAttribute(row, id, overwrite) {
       
    83             ///<summary>
       
    84             ///Utility function used to set id of the row. Usually when a new record is created, added to the table,
       
    85             ///and when id of the record is retrieved from the server-side.
       
    86             ///It is assumed that id is placed as an id attribute of <tr> that that surround the cell (<td> tag). E.g.:
       
    87             ///<tr id="17">
       
    88             ///  <td>...</td><td>...</td><td>...</td><td>...</td>
       
    89             ///</tr>
       
    90             ///This function is used when a datatable is configured in the server side processing mode or ajax source mode
       
    91             ///</summary>
       
    92             ///<param name="row" type="DOM" domElement="true">TR row where record is placed</param>
       
    93 
       
    94             if (overwrite) {
       
    95                 row.attr("id", id);
       
    96             } else {
       
    97                 if (row.attr("id") == null || row.attr("id") == "")
       
    98                     row.attr("id", id);
       
    99             }
       
   100         }
       
   101 
       
   102         function _fnGetRowIDFromAttribute(row) {
       
   103             ///<summary>
       
   104             ///Utility function used to get id of the row.
       
   105             ///It is assumed that id is placed as an id attribute of <tr> that that surround the cell (<td> tag). E.g.:
       
   106             ///<tr id="17">
       
   107             ///  <td>...</td><td>...</td><td>...</td><td>...</td>
       
   108             ///</tr>
       
   109             ///This function is used when a datatable is configured in the standard client side mode
       
   110             ///</summary>
       
   111             ///<param name="row" type="DOM" domElement="true">TR row where record is placed</param>
       
   112             ///<returns type="Number">Id of the row - by default id attribute placed in the TR tag</returns>
       
   113 
       
   114             return row.attr("id");
       
   115         }
       
   116 
       
   117         function _fnSetRowIDInFirstCell(row, id) {
       
   118             ///<summary>
       
   119             ///Utility function used to set id of the row. Usually when a new record is created, added to the table,
       
   120             ///and when id of the record is retrieved from the server-side).
       
   121             ///It is assumed that id is placed as a value of the first &lt;TD&gt; cell in the &lt;TR&gt;. As example:
       
   122             ///<tr>
       
   123             ///     <td>17</td><td>...</td><td>...</td><td>...</td>
       
   124             ///</tr>
       
   125             ///This function is used when a datatable is configured in the server side processing mode or ajax source mode
       
   126             ///</summary>
       
   127             ///<param name="row" type="DOM" domElement="true">TR row where record is placed</param>
       
   128 
       
   129             $("td:first", row).html(id);
       
   130         }
       
   131 
       
   132 
       
   133         function _fnGetRowIDFromFirstCell(row) {
       
   134             ///<summary>
       
   135             ///Utility function used to get id of the row.
       
   136             ///It is assumed that id is placed as a value of the first &lt;TD&gt; cell in the &lt;TR&gt;. As example:
       
   137             ///<tr>
       
   138             ///     <td>17</td><td>...</td><td>...</td><td>...</td>
       
   139             ///</tr>
       
   140             ///This function is used when a datatable is configured in the server side processing mode or ajax source mode
       
   141             ///</summary>
       
   142             ///<param name="row" type="DOM" domElement="true">TR row where record is placed</param>
       
   143             ///<returns type="Number">Id of the row - by default id attribute placed in the TR tag</returns>
       
   144 
       
   145             return $("td:first", row).html();
       
   146 
       
   147         }
       
   148 
       
   149         //Reference to the DataTable object
       
   150         var oTable;
       
   151         //Refences to the buttons used for manipulating table data
       
   152         var oAddNewRowButton, oDeleteRowButton, oConfirmRowAddingButton, oCancelRowAddingButton;
       
   153         //Reference to the form used for adding new data
       
   154         var oAddNewRowForm;
       
   155 
       
   156         //Plugin options
       
   157         var properties;
       
   158 
       
   159         function _fnShowError(errorText, action) {
       
   160             ///<summary>
       
   161             ///Shows an error message (Default function)
       
   162             ///</summary>
       
   163             ///<param name="errorText" type="String">text that should be shown</param>
       
   164             ///<param name="action" type="String"> action that was executed when error occured e.g. "update", "delete", or "add"</param>
       
   165 
       
   166             alert(errorText);
       
   167         }
       
   168 
       
   169         function _fnStartProcessingMode() {
       
   170             ///<summary>
       
   171             ///Function that starts "Processing" mode i.e. shows "Processing..." dialog while some action is executing(Default function)
       
   172             ///</summary>
       
   173 
       
   174             if (oTable.fnSettings().oFeatures.bProcessing) {
       
   175                 $(".dataTables_processing").css('visibility', 'visible');
       
   176             }
       
   177         }
       
   178 
       
   179         function _fnEndProcessingMode() {
       
   180             ///<summary>
       
   181             ///Function that ends the "Processing" mode and returns the table in the normal state(Default function)
       
   182             ///It shows processing message only if bProcessing setting is set to true
       
   183             ///</summary>
       
   184 
       
   185             if (oTable.fnSettings().oFeatures.bProcessing) {
       
   186                 $(".dataTables_processing").css('visibility', 'hidden');
       
   187             }
       
   188         }
       
   189 
       
   190         var sOldValue, sNewCellValue, sNewCellDislayValue;
       
   191 
       
   192         function fnApplyEditable(aoNodes) {
       
   193             ///<summary>
       
   194             ///Function that applies editable plugin to the array of table rows
       
   195             ///</summary>
       
   196             ///<param name="aoNodes" type="Array[TR]">Aray of table rows &lt;TR&gt; that should be initialized with editable plugin</param>
       
   197 
       
   198             if (properties.bDisableEditing)
       
   199                 return;
       
   200             var oDefaultEditableSettings = {
       
   201                 event: 'dblclick',
       
   202 
       
   203                 "onsubmit": function (settings, original) {
       
   204                     sOldValue = original.revert;
       
   205                     sNewCellValue = null;
       
   206                     sNewCellDisplayValue = null;
       
   207                     iDisplayStart = fnGetDisplayStart();
       
   208 
       
   209                     if(settings.type == "text" || settings.type == "select" || settings.type == "textarea" )
       
   210                     {
       
   211                         var input = $("input,select,textarea", this);
       
   212                         sNewCellValue = $("input,select,textarea", $(this)).val();
       
   213                         if (input.length == 1) {
       
   214                             var oEditElement = input[0];
       
   215                             if (oEditElement.nodeName.toLowerCase() == "select" || oEditElement.tagName.toLowerCase() == "select")
       
   216                                 sNewCellDisplayValue = $("option:selected", oEditElement).text(); //For select list use selected text instead of value for displaying in table
       
   217                             else
       
   218                                 sNewCellDisplayValue = sNewCellValue;
       
   219                         }
       
   220 
       
   221                         if (!properties.fnOnEditing(input, settings, original.revert, fnGetCellID(original)))
       
   222                             return false;
       
   223                         var x = settings;
       
   224                         
       
   225                         //2.2.2 INLINE VALIDATION
       
   226                         if (settings.oValidationOptions != null) {
       
   227                             input.parents("form").validate(settings.oValidationOptions);
       
   228                         }
       
   229                         if (settings.cssclass != null) {
       
   230                             input.addClass(settings.cssclass);
       
   231                         }
       
   232                         if(settings.cssclass == null && settings.oValidationOptions == null){
       
   233                             return true;
       
   234                         }else{
       
   235                             if (!input.valid() || 0 == input.valid())
       
   236                                 return false;
       
   237                             else
       
   238                                 return true;
       
   239                         }
       
   240                         
       
   241                     }
       
   242                     
       
   243                     properties.fnStartProcessingMode();
       
   244                 },
       
   245                 "submitdata": function (value, settings) {
       
   246                     //iDisplayStart = fnGetDisplayStart();
       
   247                     //properties.fnStartProcessingMode();
       
   248                     var id = fnGetCellID(this);
       
   249                     var rowId = oTable.fnGetPosition(this)[0];
       
   250                     var columnPosition = oTable.fnGetPosition(this)[1];
       
   251                     var columnId = oTable.fnGetPosition(this)[2];
       
   252                     var sColumnName = oTable.fnSettings().aoColumns[columnId].sName;
       
   253                     if (sColumnName == null || sColumnName == "")
       
   254                         sColumnName = oTable.fnSettings().aoColumns[columnId].sTitle;
       
   255                     var updateData = null;
       
   256                     if (properties.aoColumns == null || properties.aoColumns[columnId] == null) {
       
   257                         updateData = $.extend({},
       
   258                                             properties.oUpdateParameters,
       
   259                                             {
       
   260                                                 "id": id,
       
   261                                                 "rowId": rowId,
       
   262                                                 "columnPosition": columnPosition,
       
   263                                                 "columnId": columnId,
       
   264                                                 "columnName": sColumnName
       
   265                                             });
       
   266                     }
       
   267                     else {
       
   268                         updateData = $.extend({},
       
   269                                             properties.oUpdateParameters,
       
   270                                             properties.aoColumns[columnId].oUpdateParameters,
       
   271                                             {
       
   272                                                 "id": id,
       
   273                                                 "rowId": rowId,
       
   274                                                 "columnPosition": columnPosition,
       
   275                                                 "columnId": columnId,
       
   276                                                 "columnName": sColumnName
       
   277                                             });
       
   278                     }
       
   279                     return updateData;
       
   280                 },
       
   281                 "callback": function (sValue, settings) {
       
   282                     properties.fnEndProcessingMode();
       
   283                     var status = "";
       
   284                     var aPos = oTable.fnGetPosition(this);
       
   285                     
       
   286                     var bRefreshTable = !oSettings.oFeatures.bServerSide;
       
   287                     $("td.last-updated-cell", oTable.fnGetNodes( )).removeClass("last-updated-cell");
       
   288                     if(sValue.indexOf(properties.sFailureResponsePrefix)>-1)
       
   289                     {
       
   290                         oTable.fnUpdate(sOldValue, aPos[0], aPos[2], bRefreshTable);
       
   291                         $("td.last-updated-cell", oTable).removeClass("last-updated-cell");
       
   292                         $(this).addClass("last-updated-cell");
       
   293                         properties.fnShowError(sValue.replace(properties.sFailureResponsePrefix, "").trim(), "update");
       
   294                         status = "failure";
       
   295                     } else {
       
   296                     
       
   297                         if (properties.sSuccessResponse == "IGNORE" || 
       
   298                             (     properties.aoColumns != null
       
   299                                 && properties.aoColumns[aPos[2]] != null 
       
   300                                 && properties.aoColumns[aPos[2]].sSuccessResponse == "IGNORE") || 
       
   301                             (sNewCellValue == null) || (sNewCellValue == sValue) || 
       
   302                             properties.sSuccessResponse == sValue) {
       
   303                             if(sNewCellDisplayValue == null)
       
   304                             {
       
   305                                 //sNewCellDisplayValue = sValue;
       
   306                                 oTable.fnUpdate(sValue, aPos[0], aPos[2], bRefreshTable);
       
   307                             }else{
       
   308                                 oTable.fnUpdate(sNewCellDisplayValue, aPos[0], aPos[2], bRefreshTable);
       
   309                             }
       
   310                             $("td.last-updated-cell", oTable).removeClass("last-updated-cell");
       
   311                             $(this).addClass("last-updated-cell");
       
   312                             status = "success";
       
   313                         } else {
       
   314                             oTable.fnUpdate(sOldValue, aPos[0], aPos[2], bRefreshTable);
       
   315                             properties.fnShowError(sValue, "update");
       
   316                             status = "failure";
       
   317                         }
       
   318                     }
       
   319 
       
   320                     properties.fnOnEdited(status, sOldValue, sNewCellDisplayValue, aPos[0], aPos[1], aPos[2]);
       
   321                     if (settings.fnOnCellUpdated != null) {
       
   322                         settings.fnOnCellUpdated(status, sValue, aPos[0], aPos[2], settings);
       
   323                     }
       
   324                     
       
   325                     fnSetDisplayStart();
       
   326                     if (properties.bUseKeyTable) {
       
   327                                 var keys = oTable.keys;
       
   328                                 /* Unblock KeyTable, but only after this 'esc' key event has finished. Otherwise
       
   329                                 * it will 'esc' KeyTable as well
       
   330                                 */
       
   331                                 setTimeout(function () { keys.block = false; }, 0);
       
   332                             }
       
   333                 },
       
   334                 "onerror": function () {
       
   335                     properties.fnEndProcessingMode();
       
   336                     properties.fnShowError("Cell cannot be updated", "update");
       
   337                     properties.fnOnEdited("failure");
       
   338                 },
       
   339                 
       
   340                 "onreset": function(){ 
       
   341                         if (properties.bUseKeyTable) {
       
   342                                 var keys = oTable.keys;
       
   343                                 /* Unblock KeyTable, but only after this 'esc' key event has finished. Otherwise
       
   344                                 * it will 'esc' KeyTable as well
       
   345                                 */
       
   346                                 setTimeout(function () { keys.block = false; }, 0);
       
   347                             }
       
   348 
       
   349                 },
       
   350                 "height": properties.sEditorHeight,
       
   351                 "width": properties.sEditorWidth
       
   352             };
       
   353 
       
   354             var cells = null;
       
   355 
       
   356             if (properties.aoColumns != null) {
       
   357 
       
   358                 for (var iDTindex = 0, iDTEindex = 0; iDTindex < oSettings.aoColumns.length; iDTindex++) {
       
   359                     if (oSettings.aoColumns[iDTindex].bVisible) {//if DataTables column is visible
       
   360                         if (properties.aoColumns[iDTEindex] == null) {
       
   361                             //If editor for the column is not defined go to the next column
       
   362                             iDTEindex++;
       
   363                             continue;
       
   364                         }
       
   365                         //Get all cells in the iDTEindex column (nth child is 1-indexed array)
       
   366                         cells = $("td:nth-child(" + (iDTEindex + 1) + ")", aoNodes);
       
   367 
       
   368                         var oColumnSettings = oDefaultEditableSettings;
       
   369                         oColumnSettings = $.extend({}, oDefaultEditableSettings, properties.oEditableSettings, properties.aoColumns[iDTEindex]);
       
   370                         iDTEindex++;
       
   371                         var sUpdateURL = properties.sUpdateURL;
       
   372                         try {
       
   373                             if (oColumnSettings.sUpdateURL != null)
       
   374                                 sUpdateURL = oColumnSettings.sUpdateURL;
       
   375                         } catch (ex) {
       
   376                         }
       
   377                         //cells.editable(sUpdateURL, oColumnSettings);
       
   378                         cells.each(function () {
       
   379                             if (!$(this).hasClass(properties.sReadOnlyCellClass)) {
       
   380                                 $(this).editable(sUpdateURL, oColumnSettings);
       
   381                             }
       
   382                         });
       
   383                     }
       
   384 
       
   385                 } //end for
       
   386             } else {
       
   387                 cells = $('td:not(.' + properties.sReadOnlyCellClass + ')', aoNodes);
       
   388                 cells.editable(properties.sUpdateURL, $.extend({}, oDefaultEditableSettings, properties.oEditableSettings));
       
   389             }
       
   390         }
       
   391 
       
   392         function fnOnRowAdding(event) {
       
   393             ///<summary>
       
   394             ///Event handler called when a user click on the submit button in the "Add new row" form. 
       
   395             ///</summary>
       
   396             ///<param name="event">Event that caused the action</param>
       
   397 
       
   398             if (properties.fnOnAdding()) {
       
   399                 if (oAddNewRowForm.valid()) {
       
   400                     iDisplayStart = fnGetDisplayStart();
       
   401                     properties.fnStartProcessingMode();
       
   402 
       
   403                     if (properties.bUseFormsPlugin) {
       
   404                         //Still in beta(development)
       
   405                         $(oAddNewRowForm).ajaxSubmit({
       
   406                             dataType: 'xml',
       
   407                             success: function (response, statusString, xhr) {
       
   408                                 if (xhr.responseText.toLowerCase().indexOf("error") != -1) {
       
   409                                     properties.fnEndProcessingMode();
       
   410                                     properties.fnShowError(xhr.responseText.replace("Error",""), "add");
       
   411                                     properties.fnOnAdded("failure");
       
   412                                 } else {
       
   413                                     fnOnRowAdded(xhr.responseText);
       
   414                                 }
       
   415 
       
   416                             },
       
   417                             error: function (response) {
       
   418                                 properties.fnEndProcessingMode();
       
   419                                 properties.fnShowError(response.responseText, "add");
       
   420                                 properties.fnOnAdded("failure");
       
   421                             }
       
   422                         }
       
   423                         );
       
   424 
       
   425                     } else {
       
   426 
       
   427                         var params = oAddNewRowForm.serialize();
       
   428                         $.ajax({ 'url': properties.sAddURL,
       
   429                             'data': params,
       
   430                             'type': properties.sAddHttpMethod,
       
   431                             'dataType': properties.sAddDataType,
       
   432                             success: fnOnRowAdded,
       
   433                             error: function (response) {
       
   434                                 properties.fnEndProcessingMode();
       
   435                                 properties.fnShowError(response.responseText, "add");
       
   436                                 properties.fnOnAdded("failure");
       
   437                             }
       
   438                         });
       
   439                     }
       
   440                 }
       
   441             }
       
   442             event.stopPropagation();
       
   443             event.preventDefault();
       
   444         }
       
   445 
       
   446         function _fnOnNewRowPosted(data) {
       
   447             ///<summary>Callback function called BEFORE a new record is posted to the server</summary>
       
   448             ///TODO: Check this
       
   449 
       
   450             return true;
       
   451         }
       
   452 
       
   453         
       
   454         function fnOnRowAdded(data) {
       
   455             ///<summary>
       
   456             ///Function that is called when a new row is added, and Ajax response is returned from server
       
   457             /// This function takes data from the add form and adds them into the table.
       
   458             ///</summary>
       
   459             ///<param name="data" type="int">Id of the new row that is returned from the server</param>
       
   460 
       
   461             properties.fnEndProcessingMode();
       
   462 
       
   463             if (properties.fnOnNewRowPosted(data)) {
       
   464 
       
   465                 var oSettings = oTable.fnSettings();
       
   466                 if (!oSettings.oFeatures.bServerSide) {
       
   467                     jQuery.data(oAddNewRowForm, 'DT_RowId', data);
       
   468                     var values = fnTakeRowDataFromFormElements(oAddNewRowForm);
       
   469                    
       
   470 
       
   471                     var rtn;
       
   472                     //Add values from the form into the table
       
   473                     if (oSettings.aoColumns != null && isNaN(parseInt(oSettings.aoColumns[0].mDataProp))) {
       
   474                         rtn = oTable.fnAddData(rowData);
       
   475                     }
       
   476                     else {
       
   477                         rtn = oTable.fnAddData(values);
       
   478                     }
       
   479 
       
   480                     var oTRAdded = oTable.fnGetNodes(rtn);
       
   481                     //add id returned by server page as an TR id attribute
       
   482                     properties.fnSetRowID($(oTRAdded), data, true);
       
   483                     //Apply editable plugin on the cells of the table
       
   484                     fnApplyEditable(oTRAdded);
       
   485 
       
   486                     $("tr.last-added-row", oTable).removeClass("last-added-row");
       
   487                     $(oTRAdded).addClass("last-added-row");
       
   488                 } /*else {
       
   489                     oTable.fnDraw(false);
       
   490                 }*/
       
   491                 //Close the dialog
       
   492                 oAddNewRowForm.dialog('close');
       
   493                 $(oAddNewRowForm)[0].reset();
       
   494                 $(".error", $(oAddNewRowForm)).html("");
       
   495 
       
   496                 fnSetDisplayStart();
       
   497                 properties.fnOnAdded("success");
       
   498                                     if (properties.bUseKeyTable) {
       
   499                                 var keys = oTable.keys;
       
   500                                 /* Unblock KeyTable, but only after this 'esc' key event has finished. Otherwise
       
   501                                 * it will 'esc' KeyTable as well
       
   502                                 */
       
   503                                 setTimeout(function () { keys.block = false; }, 0);
       
   504                             }
       
   505             }
       
   506         }
       
   507 
       
   508         function fnOnCancelRowAdding(event) {
       
   509             ///<summary>
       
   510             ///Event handler function that is executed when a user press cancel button in the add new row form
       
   511             ///This function clean the add form and error messages if some of them are shown
       
   512             ///</summary>
       
   513             ///<param name="event" type="int">DOM event that caused an error</param>
       
   514 
       
   515             //Clear the validation messages and reset form
       
   516             $(oAddNewRowForm).validate().resetForm();  // Clears the validation errors
       
   517             $(oAddNewRowForm)[0].reset();
       
   518 
       
   519             $(".error", $(oAddNewRowForm)).html("");
       
   520             $(".error", $(oAddNewRowForm)).hide();  // Hides the error element
       
   521 
       
   522             //Close the dialog
       
   523             oAddNewRowForm.dialog('close');
       
   524             event.stopPropagation();
       
   525             event.preventDefault();
       
   526         }
       
   527 
       
   528 
       
   529         function fnDisableDeleteButton() {
       
   530             ///<summary>
       
   531             ///Function that disables delete button
       
   532             ///</summary>
       
   533 
       
   534            if (properties.bUseKeyTable) {
       
   535                 return;
       
   536             }
       
   537             if (properties.oDeleteRowButtonOptions != null) {
       
   538                 //oDeleteRowButton.disable();
       
   539                 oDeleteRowButton.button("option", "disabled", true);
       
   540             } else {
       
   541                 oDeleteRowButton.attr("disabled", "true");
       
   542             }
       
   543         }
       
   544 
       
   545         function fnEnableDeleteButton() {
       
   546             ///<summary>
       
   547             ///Function that enables delete button
       
   548             ///</summary>
       
   549 
       
   550             if (properties.oDeleteRowButtonOptions != null) {
       
   551                 //oDeleteRowButton.enable();
       
   552                 oDeleteRowButton.button("option", "disabled", false);
       
   553             } else {
       
   554                 oDeleteRowButton.removeAttr("disabled");
       
   555             }
       
   556         }
       
   557 
       
   558         var nSelectedRow, nSelectedCell;
       
   559         var oKeyTablePosition;
       
   560 
       
   561 
       
   562         function _fnOnRowDeleteInline(e) {
       
   563 
       
   564             var sURL = $(this).attr("href");
       
   565             if (sURL == null || sURL == "")
       
   566                 sURL = properties.sDeleteURL;
       
   567 
       
   568             e.preventDefault();
       
   569             e.stopPropagation();
       
   570 
       
   571             iDisplayStart = fnGetDisplayStart();
       
   572 
       
   573             nSelectedCell = ($(this).parents('td'))[0];
       
   574             jSelectedRow = ($(this).parents('tr'));
       
   575             nSelectedRow = jSelectedRow[0];
       
   576 
       
   577             jSelectedRow.addClass(properties.sSelectedRowClass);
       
   578 
       
   579             var id = fnGetCellID(nSelectedCell);
       
   580             if (properties.fnOnDeleting(jSelectedRow, id, fnDeleteRow)) {
       
   581                 fnDeleteRow(id, sURL);
       
   582             }
       
   583         }
       
   584 
       
   585 
       
   586         function _fnOnRowDelete(event) {
       
   587             ///<summary>
       
   588             ///Event handler for the delete button
       
   589             ///</summary>
       
   590             ///<param name="event" type="Event">DOM event</param>
       
   591 
       
   592             event.preventDefault();
       
   593             event.stopPropagation();
       
   594 
       
   595             iDisplayStart = fnGetDisplayStart();
       
   596             
       
   597             nSelectedRow = null;
       
   598             nSelectedCell = null;
       
   599             
       
   600             if (!properties.bUseKeyTable) {
       
   601                 if ($('tr.' + properties.sSelectedRowClass + ' td', oTable).length == 0) {
       
   602                     //oDeleteRowButton.attr("disabled", "true");
       
   603                     _fnDisableDeleteButton();
       
   604                     return;
       
   605                 }
       
   606                 nSelectedCell = $('tr.' + properties.sSelectedRowClass + ' td', oTable)[0];
       
   607             } else {
       
   608                 nSelectedCell = $('td.focus', oTable)[0];
       
   609 
       
   610             }
       
   611             if (nSelectedCell == null) {
       
   612                 fnDisableDeleteButton();
       
   613                 return;
       
   614             }
       
   615             if (properties.bUseKeyTable) {
       
   616                 oKeyTablePosition = oTable.keys.fnGetCurrentPosition();
       
   617             }
       
   618             var id = fnGetCellID(nSelectedCell);
       
   619             var jSelectedRow = $(nSelectedCell).parent("tr");
       
   620             nSelectedRow = jSelectedRow[0];
       
   621             if (properties.fnOnDeleting(jSelectedRow, id, fnDeleteRow)) {
       
   622                 fnDeleteRow(id);
       
   623             }
       
   624         }
       
   625 
       
   626         function _fnOnDeleting(tr, id, fnDeleteRow) {
       
   627             ///<summary>
       
   628             ///The default function that is called before row is deleted
       
   629             ///Returning false will abort delete
       
   630             ///Function can be overriden via plugin properties in order to create custom delete functionality
       
   631             ///in that case call fnDeleteRow with parameter id, and return false to prevent double delete action
       
   632             ///</summary>
       
   633             ///<param name="tr" type="JQuery">JQuery wrapper around the TR tag that will be deleted</param>
       
   634             ///<param name="id" type="String">Id of the record that wil be deleted</param>
       
   635             ///<param name="fnDeleteRow" type="Function(id)">Function that will be called to delete a row. Default - fnDeleteRow(id)</param>
       
   636 
       
   637             return confirm("Are you sure that you want to delete this record?"); ;
       
   638         }
       
   639         
       
   640         
       
   641         function fnDeleteRow(id, sDeleteURL) {
       
   642             ///<summary>
       
   643             ///Function that deletes a row with an id, using the sDeleteURL server page
       
   644             ///</summary>
       
   645             ///<param name="id" type="int">Id of the row that will be deleted. Id value is placed in the attribute of the TR tag that will be deleted</param>
       
   646             ///<param name="sDeleteURL" type="String">Server URL where delete request will be posted</param>
       
   647 
       
   648             var sURL = sDeleteURL;
       
   649             if (sDeleteURL == null)
       
   650                 sURL = properties.sDeleteURL;
       
   651             properties.fnStartProcessingMode();
       
   652             var data = $.extend(properties.oDeleteParameters, { "id": id });
       
   653             $.ajax({ 'url': sURL,
       
   654                 'type': properties.sDeleteHttpMethod,
       
   655                 'data': data,
       
   656                 "success": fnOnRowDeleted,
       
   657                 "dataType": properties.sDeleteDataType,
       
   658                 "error": function (response) {
       
   659                     properties.fnEndProcessingMode();
       
   660                     properties.fnShowError(response.responseText, "delete");
       
   661                     properties.fnOnDeleted("failure");
       
   662 
       
   663                 }
       
   664             });
       
   665         }
       
   666 
       
   667 
       
   668 
       
   669         function fnOnRowDeleted(response) {
       
   670             ///<summary>
       
   671             ///Called after the record is deleted on the server (in the ajax success callback)
       
   672             ///</summary>
       
   673             ///<param name="response" type="String">Response text eturned from the server-side page</param>
       
   674 
       
   675             properties.fnEndProcessingMode();
       
   676             var oTRSelected = nSelectedRow;
       
   677 /*
       
   678             if (!properties.bUseKeyTable) {
       
   679                 oTRSelected = $('tr.' + properties.sSelectedRowClass, oTable)[0];
       
   680             } else {
       
   681                 oTRSelected = $("td.focus", oTable)[0].parents("tr")[0];
       
   682             }
       
   683             */
       
   684             if (response == properties.sSuccessResponse || response == "") {
       
   685                 oTable.fnDeleteRow(oTRSelected);
       
   686                 fnDisableDeleteButton();
       
   687                 fnSetDisplayStart();
       
   688                 if (properties.bUseKeyTable) {
       
   689                     oTable.keys.fnSetPosition( oKeyTablePosition[0], oKeyTablePosition[1] ); 
       
   690                 }
       
   691                 properties.fnOnDeleted("success");
       
   692             }
       
   693             else {
       
   694                 properties.fnShowError(response, "delete");
       
   695                 properties.fnOnDeleted("failure");
       
   696             }
       
   697         }
       
   698 
       
   699 
       
   700 
       
   701         /* Function called after delete action
       
   702         * @param    result  string 
       
   703         *           "success" if row is actually deleted 
       
   704         *           "failure" if delete failed
       
   705         * @return   void
       
   706         */
       
   707         function _fnOnDeleted(result) { }
       
   708 
       
   709         function _fnOnEditing(input) { return true; }
       
   710         function _fnOnEdited(result, sOldValue, sNewValue, iRowIndex, iColumnIndex, iRealColumnIndex) {
       
   711 
       
   712         }
       
   713 
       
   714         function fnOnAdding() { return true; }
       
   715         function _fnOnAdded(result) { }
       
   716 
       
   717         var oSettings;
       
   718         function fnGetDisplayStart() {
       
   719             return oSettings._iDisplayStart;
       
   720         }
       
   721 
       
   722         function fnSetDisplayStart() {
       
   723             ///<summary>
       
   724             ///Set the pagination position(do nothing in the server-side mode)
       
   725             ///</summary>
       
   726 
       
   727             //To refresh table with preserver pagination on cell edit
       
   728             //if (oSettings.oFeatures.bServerSide === false) {
       
   729                 oSettings._iDisplayStart = iDisplayStart;
       
   730                 oSettings.oApi._fnCalculateEnd(oSettings);
       
   731                 //draw the 'current' page
       
   732                 oSettings.oApi._fnDraw(oSettings);
       
   733             //}
       
   734         }
       
   735 
       
   736         function _fnOnBeforeAction(sAction) {
       
   737             return true;
       
   738         }
       
   739 
       
   740         function _fnOnActionCompleted(sStatus) {
       
   741 
       
   742         }
       
   743 
       
   744         function fnGetActionSettings(sAction) {
       
   745             ///<summary>Returns settings object for the action</summary>
       
   746             ///<param name="sAction" type="String">The name of the action</param>
       
   747 
       
   748             if (properties.aoTableAction)
       
   749                 properties.fnShowError("Configuration error - aoTableAction setting are not set", sAction);
       
   750             var i = 0;
       
   751 
       
   752             for (i = 0; i < properties.aoTableActions.length; i++) {
       
   753                 if (properties.aoTableActions[i].sAction == sAction)
       
   754                     return properties.aoTableActions[i];
       
   755             }
       
   756 
       
   757             properties.fnShowError("Cannot find action configuration settings", sAction);
       
   758         }
       
   759 
       
   760 
       
   761         function fnPopulateFormWithRowCells(oForm, oTR) {
       
   762             ///<summary>Populates forms with row data</summary>
       
   763             ///<param name="oForm" type="DOM">Form used to enter data</param>
       
   764             ///<param name="oTR" type="DOM">Table Row that will populate data</param>
       
   765 
       
   766             var iRowID = oTable.fnGetPosition(oTR);
       
   767 
       
   768             var id = properties.fnGetRowID($(oTR));
       
   769 
       
   770             $(oForm).validate().resetForm();
       
   771             jQuery.data($(oForm)[0], 'DT_RowId', id);
       
   772             $("input.DT_RowId", $(oForm)).val(id);
       
   773             jQuery.data($(oForm)[0], 'ROWID', iRowID);
       
   774             $("input.ROWID", $(oForm)).val(iRowID);
       
   775 
       
   776 
       
   777             var oSettings = oTable.fnSettings();
       
   778             var iColumnCount = oSettings.aoColumns.length;
       
   779 
       
   780 
       
   781             $("input:text[rel],input:radio[rel][checked],input:hidden[rel],select[rel],textarea[rel],input:checkbox[rel]",
       
   782                                     $(oForm)).each(function () {
       
   783                                         var rel = $(this).attr("rel");
       
   784 
       
   785                                         if (rel >= iColumnCount)
       
   786                                             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");
       
   787                                         else {
       
   788                                             var sCellValue = oTable.fnGetData(oTR)[rel];
       
   789                                             if (this.nodeName.toLowerCase() == "select" || this.tagName.toLowerCase() == "select") {
       
   790 
       
   791                                                 if (this.multiple == true) {
       
   792                                                     var aoSelectedValue = new Array();
       
   793                                                     aoCellValues = sCellValue.split(",");
       
   794                                                     for (i = 0; i <= this.options.length - 1; i++) {
       
   795                                                         if (jQuery.inArray(this.options[i].text.toLowerCase().trim(), aoCellValues) != -1) {
       
   796                                                              aoSelectedValue.push(this.options[i].value);
       
   797                                                         }
       
   798                                                      }
       
   799                                                      $(this).val(aoSelectedValue);
       
   800                                                 } else {
       
   801                                                     for (i = 0; i <= this.options.length - 1; i++) {
       
   802                                                         if (this.options[i].text.toLowerCase() == sCellValue.toLowerCase()) {
       
   803                                                                 $(this).val(this.options[i].value);
       
   804                                                         }
       
   805                                                     }
       
   806                                                 }
       
   807 
       
   808                                             }
       
   809                                             else if (this.nodeName.toLowerCase() == "span" || this.tagName.toLowerCase() == "span")
       
   810                                                 $(this).html(sCellValue);
       
   811                                             else {
       
   812                                                 if (this.type == "checkbox") {
       
   813                                                     if (sCellValue == "true") {
       
   814                                                         $(this).attr("checked", true);
       
   815                                                     }
       
   816                                                 } else {
       
   817                                                     if (this.type == "radio") {
       
   818                                                         if (this.value == sCellValue) {
       
   819                                                             this.checked = true;
       
   820                                                         }
       
   821                                                     } else {
       
   822                                                         this.value = sCellValue;
       
   823                                                     }
       
   824                                                 }
       
   825                                             }
       
   826 
       
   827                                             //sCellValue = sCellValue.replace(properties.sIDToken, data);
       
   828                                             //values[rel] = sCellValue;
       
   829                                             //oTable.fnUpdate(sCellValue, iRowID, rel);
       
   830                                         }
       
   831                                     });
       
   832 
       
   833 
       
   834 
       
   835         } //End function fnPopulateFormWithRowCells
       
   836 
       
   837         function fnTakeRowDataFromFormElements(oForm) {
       
   838             ///<summary>Populates row with form elements(This should be nly function that read fom elements from form)</summary>
       
   839             ///<param name="iRowID" type="DOM">DatabaseRowID</param>
       
   840             ///<param name="oForm" type="DOM">Form used to enter data</param>
       
   841             ///<returns>Object or array</returns>
       
   842 
       
   843             var iDT_RowId = jQuery.data(oForm, 'DT_RowId');
       
   844             var iColumnCount = oSettings.aoColumns.length;
       
   845 
       
   846             var values = new Array();
       
   847             var rowData = new Object();
       
   848 
       
   849             $("input:text[rel],input:radio[rel][checked],input:hidden[rel],select[rel],textarea[rel],span.datafield[rel],input:checkbox[rel]", oForm).each(function () {
       
   850                 var rel = $(this).attr("rel");
       
   851                 var sCellValue = "";
       
   852                 if (rel >= iColumnCount)
       
   853                     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");
       
   854                 else {
       
   855                     if (this.nodeName.toLowerCase() == "select" || this.tagName.toLowerCase() == "select") {
       
   856                         //sCellValue = $("option:selected", this).text();
       
   857                         sCellValue = $.map(
       
   858                                              $.makeArray($("option:selected", this)),
       
   859                                              function (n, i) {
       
   860                                                  return $(n).text();
       
   861                                              }).join(",");
       
   862                     }
       
   863                     else if (this.nodeName.toLowerCase() == "span" || this.tagName.toLowerCase() == "span")
       
   864                         sCellValue = $(this).html();
       
   865                     else {
       
   866                         if (this.type == "checkbox") {
       
   867                             if (this.checked)
       
   868                                 sCellValue = (this.value != "on") ? this.value : "true";
       
   869                             else
       
   870                                 sCellValue = (this.value != "on") ? "" : "false";
       
   871                         } else
       
   872                             sCellValue = this.value;
       
   873                     }
       
   874                     //Deprecated
       
   875                     sCellValue = sCellValue.replace("DATAROWID", iDT_RowId);
       
   876                     sCellValue = sCellValue.replace(properties.sIDToken, iDT_RowId);
       
   877                     if (oSettings.aoColumns != null
       
   878                                 && oSettings.aoColumns[rel] != null
       
   879                                 && isNaN(parseInt(oSettings.aoColumns[0].mDataProp))) {
       
   880                         rowData[oSettings.aoColumns[rel].mDataProp] = sCellValue;
       
   881                     } else {
       
   882                         values[rel] = sCellValue;
       
   883                     }
       
   884                 }
       
   885             });
       
   886 
       
   887             if (oSettings.aoColumns != null && isNaN(parseInt(oSettings.aoColumns[0].mDataProp))) {
       
   888                 return rowData;
       
   889             }
       
   890             else {
       
   891                 return values;
       
   892             }
       
   893 
       
   894 
       
   895         } //End function fnPopulateRowWithFormElements
       
   896 
       
   897 
       
   898 
       
   899         
       
   900         function fnSendFormUpdateRequest(nActionForm) {
       
   901             ///<summary>Updates table row using  form fields</summary>
       
   902             ///<param name="nActionForm" type="DOM">Form used to enter data</param>
       
   903 
       
   904             var jActionForm = $(nActionForm);
       
   905             var sAction = jActionForm.attr("id");
       
   906             
       
   907             sAction = sAction.replace("form", "");
       
   908             var sActionURL = jActionForm.attr("action");
       
   909             if (properties.fnOnBeforeAction(sAction)) {
       
   910                 if (jActionForm.valid()) {
       
   911                     iDisplayStart = fnGetDisplayStart();
       
   912                     properties.fnStartProcessingMode();
       
   913                     if (properties.bUseFormsPlugin) {
       
   914 
       
   915                         //Still in beta(development)
       
   916                         var oAjaxSubmitOptions = {
       
   917                             success: function (response, statusString, xhr) {
       
   918                                 properties.fnEndProcessingMode();
       
   919                                 if (response.toLowerCase().indexOf("error") != -1 || statusString != "success") {
       
   920                                     properties.fnShowError(response, sAction);
       
   921                                     properties.fnOnActionCompleted("failure");
       
   922                                 } else {
       
   923                                     fnUpdateRowOnSuccess(nActionForm);
       
   924                                     properties.fnOnActionCompleted("success");
       
   925                                 }
       
   926 
       
   927                             },
       
   928                             error: function (response) {
       
   929                                 properties.fnEndProcessingMode();
       
   930                                 properties.fnShowError(response.responseText, sAction);
       
   931                                 properties.fnOnActionCompleted("failure");
       
   932                             }
       
   933                         };
       
   934                         var oActionSettings = fnGetActionSettings(sAction);
       
   935                         oAjaxSubmitOptions = $.extend({}, properties.oAjaxSubmitOptions, oAjaxSubmitOptions);
       
   936                         $(oActionForm).ajaxSubmit(oAjaxSubmitOptions);
       
   937 
       
   938                     } else {
       
   939                         var params = jActionForm.serialize();
       
   940                         $.ajax({ 'url': sActionURL,
       
   941                             'data': params,
       
   942                             'type': properties.sAddHttpMethod,
       
   943                             'dataType': properties.sAddDataType,
       
   944                             success: function (response) {
       
   945                                 properties.fnEndProcessingMode();
       
   946                                 fnUpdateRowOnSuccess(nActionForm);
       
   947                                 properties.fnOnActionCompleted("success");
       
   948                             },
       
   949                             error: function (response) {
       
   950                                 properties.fnEndProcessingMode();
       
   951                                 properties.fnShowError(response.responseText, sAction);
       
   952                                 properties.fnOnActionCompleted("failure");
       
   953                             }
       
   954                         });
       
   955                     }
       
   956                 }
       
   957             }
       
   958         }
       
   959 
       
   960     function fnUpdateRowOnSuccess(nActionForm) {
       
   961             ///<summary>Updates table row using  form fields after the ajax success callback is executed</summary>
       
   962             ///<param name="nActionForm" type="DOM">Form used to enter data</param>
       
   963 
       
   964             var values = fnTakeRowDataFromFormElements(nActionForm);
       
   965 
       
   966             var iRowID = jQuery.data(nActionForm, 'ROWID');
       
   967             var oSettings = oTable.fnSettings();
       
   968             var iColumnCount = oSettings.aoColumns.length;
       
   969             for (var rel = 0; rel < iColumnCount; rel++) {
       
   970                 if (oSettings.aoColumns != null
       
   971                                 && oSettings.aoColumns[rel] != null
       
   972                                 && isNaN(parseInt(oSettings.aoColumns[0].mDataProp))) {
       
   973                     sCellValue = rowData[oSettings.aoColumns[rel].mDataProp];
       
   974                 } else {
       
   975                     sCellValue = values[rel];
       
   976                 }
       
   977                 if (sCellValue != undefined)
       
   978                     oTable.fnUpdate(sCellValue, iRowID, rel);
       
   979             }
       
   980 
       
   981             fnSetDisplayStart();
       
   982             $(nActionForm).dialog('close');
       
   983             return;       
       
   984 
       
   985         }
       
   986         
       
   987         
       
   988         oTable = this;
       
   989 
       
   990         var defaults = {
       
   991 
       
   992             sUpdateURL: "UpdateData",
       
   993             sAddURL: "AddData",
       
   994             sDeleteURL: "DeleteData",
       
   995             sAddNewRowFormId: "formAddNewRow",
       
   996             oAddNewRowFormOptions: { autoOpen: false, modal: true },
       
   997             sAddNewRowButtonId: "btnAddNewRow",
       
   998             oAddNewRowButtonOptions: null,
       
   999             sAddNewRowOkButtonId: "btnAddNewRowOk",
       
  1000             sAddNewRowCancelButtonId: "btnAddNewRowCancel",
       
  1001             oAddNewRowOkButtonOptions: { label: "Ok" },
       
  1002             oAddNewRowCancelButtonOptions: { label: "Cancel" },
       
  1003             sDeleteRowButtonId: "btnDeleteRow",
       
  1004             oDeleteRowButtonOptions: null,
       
  1005             sSelectedRowClass: "row_selected",
       
  1006             sReadOnlyCellClass: "read_only",
       
  1007             sAddDeleteToolbarSelector: ".add_delete_toolbar",
       
  1008             fnShowError: _fnShowError,
       
  1009             fnStartProcessingMode: _fnStartProcessingMode,
       
  1010             fnEndProcessingMode: _fnEndProcessingMode,
       
  1011             aoColumns: null,
       
  1012             fnOnDeleting: _fnOnDeleting,
       
  1013             fnOnDeleted: _fnOnDeleted,
       
  1014             fnOnAdding: fnOnAdding,
       
  1015             fnOnNewRowPosted: _fnOnNewRowPosted,
       
  1016             fnOnAdded: _fnOnAdded,
       
  1017             fnOnEditing: _fnOnEditing,
       
  1018             fnOnEdited: _fnOnEdited,
       
  1019             sAddHttpMethod: 'POST',
       
  1020             sAddDataType: "text",
       
  1021             sDeleteHttpMethod: 'POST',
       
  1022             sDeleteDataType: "text",
       
  1023             fnGetRowID: _fnGetRowIDFromAttribute,
       
  1024             fnSetRowID: _fnSetRowIDInAttribute,
       
  1025             sEditorHeight: "100%",
       
  1026             sEditorWidth: "100%",
       
  1027             bDisableEditing: false,
       
  1028             oEditableSettings: null,
       
  1029             oDeleteParameters: {},
       
  1030             oUpdateParameters: {},
       
  1031             sIDToken: "DT_RowId",
       
  1032             aoTableActions: null,
       
  1033             fnOnBeforeAction: _fnOnBeforeAction,
       
  1034             bUseFormsPlugin: false,
       
  1035             fnOnActionCompleted: _fnOnActionCompleted,
       
  1036             sSuccessResponse: "ok",
       
  1037             sFailureResponsePrefix: "ERROR",
       
  1038             oKeyTable: null        //KEYTABLE
       
  1039         };
       
  1040 
       
  1041         properties = $.extend(defaults, options);
       
  1042         oSettings = oTable.fnSettings();
       
  1043         properties.bUseKeyTable = (properties.oKeyTable != null);
       
  1044 
       
  1045         return this.each(function () {
       
  1046             var sTableId = oTable.dataTableSettings[0].sTableId;
       
  1047             //KEYTABLE
       
  1048             if (properties.bUseKeyTable) {
       
  1049                 var keys = new KeyTable({
       
  1050                     "table": document.getElementById(sTableId),
       
  1051                     "datatable": oTable
       
  1052                 });
       
  1053                 oTable.keys = keys;
       
  1054 
       
  1055                 /* Apply a return key event to each cell in the table */
       
  1056                 keys.event.action(null, null, function (nCell) {
       
  1057                     if( $(nCell).hasClass(properties.sReadOnlyCellClass))
       
  1058                         return;
       
  1059                     /* Block KeyTable from performing any events while jEditable is in edit mode */
       
  1060                     keys.block = true;
       
  1061                     /* Dispatch click event to go into edit mode - Saf 4 needs a timeout... */
       
  1062                     setTimeout(function () { $(nCell).dblclick(); }, 0);
       
  1063                     //properties.bDisableEditing = true;
       
  1064                 });
       
  1065             }
       
  1066 
       
  1067 
       
  1068 
       
  1069 
       
  1070 
       
  1071 
       
  1072             //KEYTABLE
       
  1073 
       
  1074             if (oTable.fnSettings().sAjaxSource != null) {
       
  1075                 oTable.fnSettings().aoDrawCallback.push({
       
  1076                     "fn": function () {
       
  1077                         //Apply jEditable plugin on the table cells
       
  1078                         fnApplyEditable(oTable.fnGetNodes());
       
  1079                         $(oTable.fnGetNodes()).each(function () {
       
  1080                             var position = oTable.fnGetPosition(this);
       
  1081                             var id = oTable.fnGetData(position)[0];
       
  1082                             properties.fnSetRowID($(this), id);
       
  1083                         }
       
  1084                         );
       
  1085                     },
       
  1086                     "sName": "fnApplyEditable"
       
  1087                 });
       
  1088 
       
  1089             } else {
       
  1090                 //Apply jEditable plugin on the table cells
       
  1091                 fnApplyEditable(oTable.fnGetNodes());
       
  1092             }
       
  1093 
       
  1094             //Setup form to open in dialog
       
  1095             oAddNewRowForm = $("#" + properties.sAddNewRowFormId);
       
  1096             if (oAddNewRowForm.length != 0) {
       
  1097 
       
  1098                 ///Check does the add new form has all nessecary fields
       
  1099                 var oSettings = oTable.fnSettings();
       
  1100                 var iColumnCount = oSettings.aoColumns.length;
       
  1101                 for (i = 0; i < iColumnCount; i++) {
       
  1102                     if ($("[rel=" + i + "]", oAddNewRowForm).length == 0)
       
  1103                         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");
       
  1104                 }
       
  1105 
       
  1106 
       
  1107                 if (properties.oAddNewRowFormOptions != null) {
       
  1108                     properties.oAddNewRowFormOptions.autoOpen = false;
       
  1109                 } else {
       
  1110                     properties.oAddNewRowFormOptions = { autoOpen: false };
       
  1111                 }
       
  1112                 oAddNewRowForm.dialog(properties.oAddNewRowFormOptions);
       
  1113 
       
  1114                 //Add button click handler on the "Add new row" button
       
  1115                 oAddNewRowButton = $("#" + properties.sAddNewRowButtonId);
       
  1116                 if (oAddNewRowButton.length != 0) {
       
  1117                 
       
  1118                         if(oAddNewRowButton.data("add-event-attached")!="true")
       
  1119                         {
       
  1120                             oAddNewRowButton.click(function () {
       
  1121                                 oAddNewRowForm.dialog('open');
       
  1122                             });
       
  1123                             oAddNewRowButton.data("add-event-attached", "true");
       
  1124                         }
       
  1125 
       
  1126                 } else {
       
  1127                     if ($(properties.sAddDeleteToolbarSelector).length == 0) {
       
  1128                         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";
       
  1129                     } else {
       
  1130                         oAddNewRowButton = null; //It will be auto-generated later
       
  1131                     }
       
  1132                 }
       
  1133 
       
  1134                 //Prevent Submit handler
       
  1135                 if (oAddNewRowForm[0].nodeName.toLowerCase() == "form") {
       
  1136                     oAddNewRowForm.unbind('submit');
       
  1137                     oAddNewRowForm.submit(function (event) {
       
  1138                         fnOnRowAdding(event);
       
  1139                         return false;
       
  1140                     });
       
  1141                 } else {
       
  1142                     $("form", oAddNewRowForm[0]).unbind('submit');
       
  1143                     $("form", oAddNewRowForm[0]).submit(function (event) {
       
  1144                         fnOnRowAdding(event);
       
  1145                         return false;
       
  1146                     });
       
  1147                 }
       
  1148 
       
  1149                 // array to add default buttons to
       
  1150                 var aAddNewRowFormButtons = [];
       
  1151 
       
  1152                 oConfirmRowAddingButton = $("#" + properties.sAddNewRowOkButtonId, oAddNewRowForm);
       
  1153                 if (oConfirmRowAddingButton.length == 0) {
       
  1154                     //If someone forgotten to set the button text
       
  1155                     if (properties.oAddNewRowOkButtonOptions.text == null
       
  1156                         || properties.oAddNewRowOkButtonOptions.text == "") {
       
  1157                         properties.oAddNewRowOkButtonOptions.text = "Ok";
       
  1158                     }
       
  1159                     properties.oAddNewRowOkButtonOptions.click = fnOnRowAdding;
       
  1160                     properties.oAddNewRowOkButtonOptions.id = properties.sAddNewRowOkButtonId;
       
  1161                     // push the add button onto the array
       
  1162                     aAddNewRowFormButtons.push(properties.oAddNewRowOkButtonOptions);
       
  1163                 } else {
       
  1164                     oConfirmRowAddingButton.click(fnOnRowAdding);
       
  1165                 }
       
  1166 
       
  1167                 oCancelRowAddingButton = $("#" + properties.sAddNewRowCancelButtonId);
       
  1168                 if (oCancelRowAddingButton.length == 0) {
       
  1169                     //If someone forgotten to the button text
       
  1170                     if (properties.oAddNewRowCancelButtonOptions.text == null
       
  1171                         || properties.oAddNewRowCancelButtonOptions.text == "") {
       
  1172                         properties.oAddNewRowCancelButtonOptions.text = "Cancel";
       
  1173                     }
       
  1174                     properties.oAddNewRowCancelButtonOptions.click = fnOnCancelRowAdding;
       
  1175                     properties.oAddNewRowCancelButtonOptions.id = properties.sAddNewRowCancelButtonId;
       
  1176                     // push the cancel button onto the array
       
  1177                     aAddNewRowFormButtons.push(properties.oAddNewRowCancelButtonOptions);
       
  1178                 } else {
       
  1179                     oCancelRowAddingButton.click(fnOnCancelRowAdding);
       
  1180                 }
       
  1181                 // if the array contains elements, add them to the dialog
       
  1182                 if (aAddNewRowFormButtons.length > 0) {
       
  1183                     oAddNewRowForm.dialog('option', 'buttons', aAddNewRowFormButtons);
       
  1184                 }
       
  1185                 //Issue: It cannot find it with this call:
       
  1186                 //oConfirmRowAddingButton = $("#" + properties.sAddNewRowOkButtonId, oAddNewRowForm);
       
  1187                 //oCancelRowAddingButton = $("#" + properties.sAddNewRowCancelButtonId, oAddNewRowForm);
       
  1188                 oConfirmRowAddingButton = $("#" + properties.sAddNewRowOkButtonId);
       
  1189                 oCancelRowAddingButton = $("#" + properties.sAddNewRowCancelButtonId);
       
  1190                 
       
  1191                 if (properties.oAddNewRowFormValidation != null) {
       
  1192                     oAddNewRowForm.validate(properties.oAddNewRowFormValidation);
       
  1193                     }
       
  1194             } else {
       
  1195                 oAddNewRowForm = null;
       
  1196             }
       
  1197 
       
  1198             //Set the click handler on the "Delete selected row" button
       
  1199             oDeleteRowButton = $('#' + properties.sDeleteRowButtonId);
       
  1200             if (oDeleteRowButton.length != 0)
       
  1201             {
       
  1202                 if(oDeleteRowButton.data("delete-event-attached")!="true")
       
  1203                 {
       
  1204                     oDeleteRowButton.click(_fnOnRowDelete);
       
  1205                     oDeleteRowButton.data("delete-event-attached", "true");
       
  1206                 }
       
  1207             }
       
  1208             else {
       
  1209                 oDeleteRowButton = null;
       
  1210             }
       
  1211 
       
  1212             //If an add and delete buttons does not exists but Add-delete toolbar is specificed
       
  1213             //Autogenerate these buttons
       
  1214             oAddDeleteToolbar = $(properties.sAddDeleteToolbarSelector);
       
  1215             if (oAddDeleteToolbar.length != 0) {
       
  1216                 if (oAddNewRowButton == null && properties.sAddNewRowButtonId != ""
       
  1217                     && oAddNewRowForm != null) {
       
  1218                     oAddDeleteToolbar.append("<button id='" + properties.sAddNewRowButtonId + "' class='add_row'>Add</button>");
       
  1219                     oAddNewRowButton = $("#" + properties.sAddNewRowButtonId);
       
  1220                     oAddNewRowButton.click(function () { oAddNewRowForm.dialog('open'); });
       
  1221                 }
       
  1222                 if (oDeleteRowButton == null && properties.sDeleteRowButtonId != "") {
       
  1223                     oAddDeleteToolbar.append("<button id='" + properties.sDeleteRowButtonId + "' class='delete_row'>Delete</button>");
       
  1224                     oDeleteRowButton = $("#" + properties.sDeleteRowButtonId);
       
  1225                     oDeleteRowButton.click(_fnOnRowDelete);
       
  1226                 }
       
  1227             }
       
  1228 
       
  1229             //If delete button exists disable it until some row is selected
       
  1230             if (oDeleteRowButton != null) {
       
  1231                 if (properties.oDeleteRowButtonOptions != null) {
       
  1232                     oDeleteRowButton.button(properties.oDeleteRowButtonOptions);
       
  1233                 }
       
  1234                 fnDisableDeleteButton();
       
  1235             }
       
  1236 
       
  1237             //If add button exists convert it to the JQuery-ui button
       
  1238             if (oAddNewRowButton != null) {
       
  1239                 if (properties.oAddNewRowButtonOptions != null) {
       
  1240                     oAddNewRowButton.button(properties.oAddNewRowButtonOptions);
       
  1241                 }
       
  1242             }
       
  1243 
       
  1244 
       
  1245             //If form ok button exists convert it to the JQuery-ui button
       
  1246             if (oConfirmRowAddingButton != null) {
       
  1247                 if (properties.oAddNewRowOkButtonOptions != null) {
       
  1248                     oConfirmRowAddingButton.button(properties.oAddNewRowOkButtonOptions);
       
  1249                 }
       
  1250             }
       
  1251 
       
  1252             //If form cancel button exists convert it to the JQuery-ui button
       
  1253             if (oCancelRowAddingButton != null) {
       
  1254                 if (properties.oAddNewRowCancelButtonOptions != null) {
       
  1255                     oCancelRowAddingButton.button(properties.oAddNewRowCancelButtonOptions);
       
  1256                 }
       
  1257             }
       
  1258 
       
  1259             //Add handler to the inline delete buttons
       
  1260             $(".table-action-deletelink", oTable).live("click", _fnOnRowDeleteInline);
       
  1261 
       
  1262             if (!properties.bUseKeyTable) {
       
  1263             //Set selected class on row that is clicked
       
  1264             //Enable delete button if row is selected, disable delete button if selected class is removed
       
  1265             $("tbody", oTable).click(function (event) {
       
  1266                 if ($(event.target.parentNode).hasClass(properties.sSelectedRowClass)) {
       
  1267                     $(event.target.parentNode).removeClass(properties.sSelectedRowClass);
       
  1268                     if (oDeleteRowButton != null) {
       
  1269                         fnDisableDeleteButton();
       
  1270                     }
       
  1271                 } else {
       
  1272                     $(oTable.fnSettings().aoData).each(function () {
       
  1273                         $(this.nTr).removeClass(properties.sSelectedRowClass);
       
  1274                     });
       
  1275                     $(event.target.parentNode).addClass(properties.sSelectedRowClass);
       
  1276                     if (oDeleteRowButton != null) {
       
  1277                         fnEnableDeleteButton();
       
  1278                     }
       
  1279                 }
       
  1280             });
       
  1281             } else {
       
  1282                 oTable.keys.event.focus(null, null, function (nNode, x, y) {
       
  1283 
       
  1284                 });
       
  1285             }
       
  1286 
       
  1287             if (properties.aoTableActions != null) {
       
  1288                 for (var i = 0; i < properties.aoTableActions.length; i++) {
       
  1289                     var oTableAction = $.extend({ sType: "edit" }, properties.aoTableActions[i]);
       
  1290                     var sAction = oTableAction.sAction;
       
  1291                     var sActionFormId = oTableAction.sActionFormId;
       
  1292 
       
  1293                     var oActionForm = $("#form" + sAction);
       
  1294                     if (oActionForm.length != 0) {
       
  1295                         var oFormOptions = { autoOpen: false, modal: true };
       
  1296                         oFormOptions = $.extend({}, oTableAction.oFormOptions, oFormOptions);
       
  1297                         oActionForm.dialog(oFormOptions);
       
  1298                         oActionForm.data("action-options", oTableAction);
       
  1299 
       
  1300                         var oActionFormLink = $(".table-action-" + sAction);
       
  1301                         if (oActionFormLink.length != 0) {
       
  1302 
       
  1303                             oActionFormLink.live("click", function () {
       
  1304 
       
  1305 
       
  1306                                 var sClass = this.className;
       
  1307                                 var classList = sClass.split(/\s+/);
       
  1308                                 var sActionFormId = "";
       
  1309                                 var sAction = "";
       
  1310                                 for (i = 0; i < classList.length; i++) {
       
  1311                                     if (classList[i].indexOf("table-action-") > -1) {
       
  1312                                         sAction = classList[i].replace("table-action-", "");
       
  1313                                         sActionFormId = "#form" + sAction;
       
  1314                                     }
       
  1315                                 }
       
  1316                                 if (sActionFormId == "") {
       
  1317                                     properties.fnShowError("Cannot find a form with an id " + sActionFormId + " that should be associated to the action - " + sAction, sAction)
       
  1318                                 }
       
  1319 
       
  1320                                 var oTableAction = $(sActionFormId).data("action-options");
       
  1321 
       
  1322                                 if (oTableAction.sType == "edit") {
       
  1323 
       
  1324                                     //var oTD = ($(this).parents('td'))[0];
       
  1325                                     var oTR = ($(this).parents('tr'))[0];
       
  1326                                     fnPopulateFormWithRowCells(oActionForm, oTR);
       
  1327                                 }
       
  1328                                 $(oActionForm).dialog('open');
       
  1329                             });
       
  1330                         }
       
  1331 
       
  1332                         oActionForm.submit(function (event) {
       
  1333 
       
  1334                             fnSendFormUpdateRequest(this);
       
  1335                             return false;
       
  1336                             
       
  1337                         });
       
  1338 
       
  1339 
       
  1340                         var aActionFormButtons = new Array();
       
  1341 
       
  1342                         //var oActionSubmitButton = $("#form" + sAction + "Ok", oActionForm);
       
  1343                         //aActionFormButtons.push(oActionSubmitButton);
       
  1344                         var oActionFormCancel = $("#form" + sAction + "Cancel", oActionForm);
       
  1345                         if (oActionFormCancel.length != 0) {
       
  1346                             aActionFormButtons.push(oActionFormCancel);
       
  1347                             oActionFormCancel.click(function () {
       
  1348 
       
  1349                                 var oActionForm = $(this).parents("form")[0];
       
  1350                                 //Clear the validation messages and reset form
       
  1351                                 $(oActionForm).validate().resetForm();  // Clears the validation errors
       
  1352                                 $(oActionForm)[0].reset();
       
  1353 
       
  1354                                 $(".error", $(oActionForm)).html("");
       
  1355                                 $(".error", $(oActionForm)).hide();  // Hides the error element
       
  1356                                 $(oActionForm).dialog('close');
       
  1357                             });
       
  1358                         }
       
  1359 
       
  1360                         //Convert all action form buttons to the JQuery UI buttons
       
  1361                         $("button", oActionForm).button();
       
  1362                         /*
       
  1363                         if (aActionFormButtons.length > 0) {
       
  1364                         oActionForm.dialog('option', 'buttons', aActionFormButtons);
       
  1365                         }
       
  1366                         */
       
  1367 
       
  1368 
       
  1369 
       
  1370                     }
       
  1371 
       
  1372 
       
  1373 
       
  1374 
       
  1375                 } // end for (var i = 0; i < properties.aoTableActions.length; i++)
       
  1376             } //end if (properties.aoTableActions != null)
       
  1377 
       
  1378 
       
  1379         });
       
  1380     };
       
  1381 })(jQuery);
       
  1382