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 <TD> cell in the <TR>. 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 <TD> cell in the <TR>. 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 <TR> 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 |
|