Не был слишком уверен, как именно озаглавить этот вопрос, но вот проблема, которая у меня возникла:
Мне нужно иметь возможность отправить массив или связанный список данных через форму HTML. Поскольку этот массив может иметь переменную длину, у меня есть два варианта:
- Использовать некоторую форму разделителя (например, разделенные запятыми элементы в списке)
- Наличие нескольких входов (для каждого элемента массива), динамически генерируемых при необходимости добавления новых элементов
Я бы хотел воспользоваться вторым вариантом, хотя я чувствовал, что, поскольку в этом конкретном проекте будет много таких «входов массива», я должен создать плагин jQuery, чтобы мне было легче реализовать эту функцию в будущих формах. *
Поскольку я работаю над этим, я также добавляю функциональность для нескольких типов ввода, выбирает, выбирает кратные (через разделитель) и связанные входы (например, имея два текстовых ввода для «имени» и «фамилии» «который должен быть представлен как пара)
У меня есть базовый макет того, как я думаю, что он должен работать:
(function($) { // Self-calling anonymous function to avoid namespace collisions or compatibility issues
$.fn.dynamicList = function( options ) { // jQuery plugin definition
/* Set up default options here */
defaults = {
option1: "value1",
option2: "value2"
};
var options = $.extend( defaults, options );
/* Step 1. Add a jQuery-UI plus icon to the DOM */
/* Note: I have an option to specify where this icon should go in the DOM. It defaults right after the last input */
plus = $("<span>").addClass( 'jquery-ui-classes' );
this.last().after( plus );
/* Step 2. Add a table to the DOM for displaying added values */
/* Note: I have an option to specify where this table should go in the DOM. It defaults right after the plus icon */
plus.after( table );
/* Step 3. Add a handler for our plus button */
this.delegate( plus, 'click', function() {
/* Read the inputs, add their values to the table, empty the inputs */
/* Also, the last column of the table contains a minus button */
/* This is where I THOUGHT my first issue was.... */
minus = $("<span>").addClass( 'jquery-ui-classes' );
table.append( row ).append( minus );
});
/* Step 4. Add a handler for our minus button */
/* Since the minus is created within the plus handler we can't use "minus" here */
/* Instead I use a class name to locate it */
this.delegate( '.jquery-ui-minus-class', 'click', function() {
/* Remove the relevant row from the table */
$(this).parents('tr').remove();
});
/* Step 5. Add our submit handler */
this.parents('form').first().submit(function() {
/* We want all of the data in the table to be submitted with the form */
/* Therefore we create an input per cell and name it accordingly */
/* The name is just the name of the original input plus "[]" to make it an array */
/* This is where I thought my second problem was */
});
return this; // Maintain chain-ability
};
)(jQuery);
Этот код вызывается для входов, которые вы хотите заменить динамическим списком. Если у вас выбрано несколько входов, они станут списком связанных данных (например, имя и фамилия). Пример того, как это вызвать, может быть следующим:
<html>
<head>
<!-- Include jQuery and my dynamic list library here -->
<script>
$('#fn,#ln').dynamicList();
</script>
</head>
<body>
<form>
<input id="fn" name="first_name" />
<input id="ln" name="last_name" />
</form>
</body>
</html>
Это создаст динамический список, в котором вы можете ввести имя и фамилию, затем нажать кнопку «плюс» (теперь справа от или под вводом фамилии в соответствии с вашими правилами CSS) и добавить строку в таблица, содержащая имя в одном столбце, фамилию в другом и кнопку минус в последнем. Вы можете продолжать вводить имена и нажимать эту кнопку «плюс», и таблица расширяется вниз до бесконечности. После отправки формы (с помощью кнопки отправки или любого другого метода) ячейки таблицы должны стать входными данными.
Я думал, что первая проблема, с которой я столкнусь, была в обработчике плюса. Поскольку я нахожусь внутри функции, вызываемой нажатием кнопки «плюс», ключевое слово «this» теперь относится к элементу DOM значка «плюс». Я не могу взять значения входов, чтобы добавить их в таблицу. Одно из предложенных мной решений состояло в том, чтобы создать глобальную переменную, которая является копией объекта, для которого функция динамического списка была вызвана так:
.
.
.
/* Step 2. Add a table to the DOM for displaying added values */
/* Note: I have an option to specify where this table should go in the DOM. It defaults right after the plus icon */
plus.after( table );
var dynamicList = this;
/* Step 3. Add a handler for our plus button */
this.delegate( plus, 'click', function() {
/* Read the inputs, add their values to the table, empty the inputs */
/* Also, the last column of the table contains a minus button */
/* This is where I THOUGHT my first issue was.... */
for( i = 0; i < dynamicList.length; i++ ) {
// dynamicList.get(i) will give us each input in order
}
minus = $("<span>").addClass( 'jquery-ui-classes' );
table.append( row ).append( minus );
});
.
.
.
Меня беспокоит то, что если я создаю несколько динамических списков, они переопределяют друг друга. Это правда? Если да, то как мне преодолеть это?
Моя вторая проблема, с которой я столкнулся, была похожей. После отправки формы мне нужно найти таблицу, чтобы получить значения для отправки И найти входные данные, чтобы получить имена, под которыми они должны быть представлены.
Однако, поиграв с кодом, чтобы попытаться исправить его самостоятельно, я столкнулся с проблемой гораздо раньше, чем ожидалось.
Uncaught TypeError: Object [object Object] has no method 'replace'
jquery-1.6.2.min.js:16
f.each.f.fn.(anonymous function) jquery-1.6.2.min.js:17
f.fn.extend.delegate jquery-1.6.2.min.js:17
$.fn.dynamicList jquery.dynamicList.js:76
(anonymous function) test.php:16
f.extend._Deferred.e.resolveWith jquery-1.6.2.min.js:16
e.extend.ready jquery-1.6.2.min.js:16
c.addEventListener.B jquery-1.6.2.min.js:16
Посмотрите на строку 76 моего кода динамического списка, это следующая строка:
this.delegate( plus, 'click', function() {
Могу ли я не вызвать .delegate()
, так как "this" относится к нескольким объектам jQuery? Или я не могу позвонить .delegate()
, потому что «это» не является родительским элементом значка «плюс»? И как только эта проблема будет решена, как мне решить две другие мои проблемы?
РЕДАКТИРОВАТЬ -
Я изменил заголовок и нашел решение моей проблемы в строке 76. Я не совсем уверен, как работает .delegate()
, потому что сначала я попытался:
this.first().parent().delegate( plus, 'click', function() {
и он все еще был расстроен из-за меня. Затем я понял, что мог бы просто использовать функцию .click()
вместо этого (я вроде как дурак)
plus.click( function() {
Я использовал похожую логику при создании кнопки минус в строке. Я добавил minus.click()
после создания кнопки минус и перед ее вставкой в DOM, избавив меня от необходимости использовать .delegate()
в любом месте кода.
До сих пор не уверен, как получить значения из полей ввода в обработчике плюса, поскольку ключевое слово "this" было перезаписано в этот момент для ссылки на кнопку плюса, а не на мои поля ввода.