-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjquery.formRowRepeater.js
135 lines (108 loc) · 3.95 KB
/
jquery.formRowRepeater.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
* jQuery Form Row Repeater Plugin
* Version: 2.0
*
* A jQuery plugin to handle dynamic form row repetition with sorting functionality.
* Allows adding, removing, and sorting form rows based on a template.
*
* @author Nabeel Javaid <[email protected]>
* @version 2.0
*
* @param {Object} options - Plugin options for customization.
* @param {string} [options.templateRow='.template-row'] - Selector for the template row.
* @param {string} [options.addRowButton='#add-row'] - Selector for the add row button.
* @param {string} [options.sortableContainer] - Selector for the sortable container.
* @param {string} [options.rowClass='.form-row'] - Class for each form row.
* @param {string} [options.handleClass='.handle'] - Class for the handle of sortable rows.
* @param {string} [options.removeButtonClass='.remove-row'] - Class for the remove row button.
* @param {string} [options.sortOrderClass='.sort-order'] - Class for sorting order input field.
* @param {number} [options.level=0] - Nested level to replace `[number]` in field names.
* @param {function} [options.afterAddedRow=null] - Callback function after adding a row.
*/
(function($) {
// Define the plugin
$.fn.formRowRepeater = function(options) {
const settings = $.extend({
templateRow: '.template-row',
addRowButton: '#add-row',
sortableContainer: this,
rowClass: '.form-row',
handleClass: '.handle',
removeButtonClass: '.remove-row',
sortOrderClass: '.sort-order',
level: 0,
afterAddedRow: null // Callback function
}, options);
let $template = null;
// Function to update sort order
this.updateSortOrder = function() {
$(settings.sortableContainer, this).find(settings.rowClass).each(function(index) {
$(this).find(settings.sortOrderClass).val(index + 1);
});
}
// Clear values of a form row
function clearRowValues($row) {
$row.find('input[type="text"]').val('');
$row.find('input[type="hidden"]').val('');
$row.find('select').each(function() {
$(this).val($(this).find('option:first').val());
});
$row.find('input[type="checkbox"], input[type="radio"]').prop('checked', false);
}
// Add a new row
this.addRow = function() {
const $rowId = Date.now();
let $newRow = $template.clone();
$newRow.attr('data-row-id', $rowId); // Set UUID attribute
const rowCount = $(settings.sortableContainer, this).children(settings.rowClass).length;
const level = settings.level;
$newRow.find('input, select').each(function() {
let name = $(this).attr('name');
let count = 0;
name = name.replace(/\[\d+\]/g, function(match) {
count++;
return count === level + 1 ? `[${rowCount}]` : match;
});
$(this).attr('name', name);
});
clearRowValues($newRow); // Clear input values
$newRow.find(settings.sortOrderClass).val(rowCount + 1);
$(settings.sortableContainer, this).append($newRow);
this.updateSortOrder();
// Call the afterAddedRow callback if provided
if (typeof settings.afterAddedRow === 'function') {
settings.afterAddedRow($newRow);
}
};
// Initialize sortable functionality
this.makeSortable = function() {
const self = this; // Capture `this` context
$(settings.sortableContainer, this).sortable({
handle: settings.handleClass,
axis: 'y',
update: function(event, ui) {
self.updateSortOrder();
}
});
};
// Initialize the plugin
this.init = function() {
console.log('Initialized the plugin');
$template = $(settings.templateRow, this).first().clone();
this.makeSortable();
// Add row event handler
$(settings.addRowButton, this).on('click', (event) => {
event.preventDefault();
this.addRow();
this.makeSortable();
});
// Remove row event handler
$(settings.sortableContainer, this).on('click', settings.removeButtonClass, function() {
$(this).closest(settings.rowClass).remove();
});
// Update sort order initially
this.updateSortOrder();
};
return this.init();
};
}(jQuery));