Проблема при клонировании jQuery UI datepicker

У меня есть div, в котором есть datepicker. Я использую что-то подобное для клонирования:

mydiv = $('#someDiv');

// works fine so far
mydiv.find('input.datefield').datepicker();

// clone without the events and insert
newDiv = myDiv.clone(false).insertAfter(myDiv);

// datepicker won't re-init if this class is present
newDiv.find('.hadDatepicker').removeClass('hadDatepicker');

// reinitialize datepicker
newDiv.find('input.datefield').datepicker();

Это урезанная версия моего кода. Он работает, и календарь отображается так, как ожидалось, где он ожидается.. но когда нажимается дата, обновляется предыдущее значение datepicker.. (тот, из которого он был клонирован).

Я пытался уничтожить экземпляр (inexisting) до этого:

newDiv.find('input.datefield').datepicker('destroy').datepicker();

Не повезло..

Я проверил, как он отслеживает экземпляры и вручную очищает данные следующим образом:

newDiv.find('input.datefield').data('datepicker', false).datepicker('destroy').datepicker();

По-прежнему не повезло.

Что я не понимаю, так это то, что только поведение выбора даты является ошибкой, все остальное работает так, как ожидалось.

Я действительно не знаю, что еще проверить сейчас.

Ответы

Ответ 1

Вот проблема. datepicker создает атрибуты идентификаторов на основе UUID для полей ввода, которые он связывает при его инициализации. Вы клонируете эти элементы, вы получаете больше элементов с одинаковым идентификатором (который не нравится jQuery) или другим идентификатором, если ваша рутина клонирования управляет этим (что означает, что datepicker не знает о клонах). Другими словами, datepicker только инициализирует все элементы, соответствующие вашему селектору, в момент его вызова. на самом деле не имеет смысла пытаться уничтожать/отключать/включать снова и снова, когда вы можете просто обернуть вызов init внутри любой функции, которую вы используете для создания клонов.

Поскольку мои функции клона обычно копируются из скрытых элементов DOM, а не из видимых, у меня есть роскошь, решающая, нужно ли связывать до или после клонирования. Итак, make #templateDiv - скрытый элемент на вашей странице с уже включенным элементом INPUT.

mydiv = $('#templateDiv');
mydest = $('#someDiv');

function make_the_donuts() {
    newDiv = myDiv.clone(true).insertAfter(mydest);  
    // attach datepickers by instance rather than by class
    newDiv.find('input.datefield').datepicker();
}

и это в значительной степени делает это. Clone (true), когда это возможно, это сэкономит вам головные боли в долгосрочной перспективе.

Ответ 2

Это работает для меня с jQuery UI 1.7.2

var mydiv = $('#someDiv');
mydiv.find('input.datefield').datepicker();
var newDiv = mydiv.clone(false).attr("id", "someDiv2").insertAfter(mydiv);
newDiv.find('input.datefield')
  .attr("id", "")
  .removeClass('hasDatepicker')
  .removeData('datepicker')
  .unbind()
  .datepicker();

Отметьте http://jsbin.com/ahoqa3/2 для быстрой демонстрации

кстати. у вас, похоже, есть разные ошибки в коде вашего вопроса. Класс css hasDatepicker not hadDatepicker и в одно время вы написали mydiv, а в следующий раз переменная mydiv, которая не является одинаковой.

Ответ 3

Если вы вызываете .datepicker('destroy').removeAttr('id') перед клонированием, а затем повторно запустите сборщик дат, он будет работать.

Кажется, это ошибка с уничтожением, поскольку она должна вернуть элемент обратно в исходное состояние.

Ответ 4

просто

$('input.datefield').datepicker("destroy");

перед клонированием div. Затем после, вставляя клон, снова привяжите datepicker

$('input.datefield').datepicker();

своего рода "хакерское" решение, но оно отлично работает.

Ответ 5

$('input.datefield').datepicker("destroy");
$('input.datefield').datepicker();

он работает хорошо. Но просто сделав это, datepicker откроется на клонированном входе и установит дату на исходный вход (потому что у них одинаковый идентификатор)

чтобы решить эту проблему, вы должны изменить атрибут id клонированного ввода.

dp = < cloned input >
var d = $('input.vDateField');
dp.removeClass('hasDatepicker');
dp.attr('id', dp.attr('id')+d.length);
d.datepicker("destroy");
d.datepicker();

и он будет работать отлично!

Ответ 6

Как насчет изменения порядка?

mydiv = $('#someDiv');

// clone without the events and insert
newDiv = myDiv.clone(false).insertAfter(myDiv);

// datepicker won't re-init if this class is present
// not necessary anymore
// newDiv.find('.hadDatepicker').removeClass('hadDatepicker');

newDiv.find('input.datefield').datepicker();

// datepicker attached as a last step
mydiv.find('input.datefield').datepicker();

Честно говоря, я не знаю, как датпикер работает внутри. Я подозреваю, что он хранит что-то в хранилище JQuery DOM. Позвольте избежать его копирования любой ценой.

(У вас может быть длинная бизнес-логика между этими строками кода. Дело в том, что у вас есть резервная копия #someDiv, прежде чем положить на нее датупинг.)

Ответ 7

Удостоверьтесь, что ваш новый клонированный дампинг имеет другое имя и идентификатор, чем оригинал. Если оба они имеют одинаковое имя, то поведение, которое вы описываете, будет нормальным.

Попробуйте изменить эту последнюю строку на что-то вроде:

newDiv.find('input.datefield').attr('id', 'newDatePicker').attr('name', 'newDatePicker').datepicker();

Ответ 8

Полное решение, которое работает для меня.

//before
$('input.fecha').datepicker("destroy");
newcell.innerHTML = table.rows[0].cells[i].innerHTML;
//change de input id
$("input.fecha").attr("id", function (arr) {return "fecha" + arr;});
//after
$('input.fecha').datepicker({defaultDate: "+1w",changeMonth: true,numberOfMonths: 1, showOn: "button", buttonImage: "<?php echo base_url() ?>images/calendar.gif", buttonImageOnly: true, showLabel:false, dateFormat:"yy-mm-dd"});

И таблица html td.

<td><?php echo form_input(array('name' => 'fecha','id' => 'fecha','class' => 'fecha')); ?></td>

Надеюсь, это поможет вам.

Добрый день

Ответ 9

var dt = new Date();
var month = dt.getMonth();
var day = dt.getDate();
var year = dt.getFullYear()-5;
            $newClone.children().children("#fna"+clickID)
    .attr({
        'id': 'fna1'+newID,
        'name': 'fna'+newID,
        'value': day + '-' + month + '-' + year
    })
    .datepicker("destroy")
    .datepicker({
        firstDay: 1, 
        changeMonth: true, 
        changeYear: true,
        yearRange: 'c-100:c',
        defaultDate: '-1y',
        dateFormat: 'dd-mm-yy' ,
        nextText: "Mes siguiente",
        prevText: "Mes anterior",
        monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun','Jul','Ago','Sep','Oct','Nov','Dic'],
        dayNamesMin: ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa']
    });

Ответ 10

Это может быть немного поздно, но все предложения, приведенные выше, не помогли мне, я придумал для этого легкое решение.

Во-первых, что вызывает проблему: JQuery присваивает datepicker идентификатору элемента. если вы клонируете элемент, то тот же идентификатор также может быть клонирован. который jQuery не нравится. В результате вы можете получить либо нулевую опорную ошибку, либо дату, назначенную для первого поля ввода, независимо от того, в какое поле ввода вы нажимаете.

Решение:

1) уничтожить datepicker 2) назначить новые уникальные идентификаторы для всех полей ввода 3) назначить datepicker для каждого входа

Убедитесь, что ваш ввод похож на этот

<input type="text" name="ndate[]" id="date1" class="n1datepicker">

Прежде чем клонировать, уничтожьте datepicker

$('.n1datepicker').datepicker('destroy');

После того, как вы клонируете, добавьте также эти строки

var i = 0;
$('.n1datepicker').each(function () {
    $(this).attr("id",'date' + i).datepicker();
    i++;
});

и происходит волшебство

Ответ 11

Datepicker не делает, если идентификатор элемента изменен. Поэтому лучше не изменять идентификатор элемента, если это необходимо. Но если вам действительно нужно изменить идентификатор, и этот измененный идентификатор должен работать с datepicker, то следуйте ему:

$(selector).removeClass('hasDatepicker');
$(selector).datepicker({
  changeMonth: true,
  changeYear: true
});