Подтвердить что ты не робот

Событие jQuery "create" для динамически созданных элементов

Мне нужно иметь возможность динамически создавать элемент <select> и превращать его в jQuery .combobox(). Это должно быть событие создания элемента, в отличие от некоторого события "click", и в этом случае я мог бы просто использовать jQuery .on().

Так что-то вроде этого существует?

$(document).on("create", "select", function() {
    $(this).combobox();
}

Я не хочу использовать livequery, потому что он очень устарел.

UPDATE. Выбранный select/combobox загружается через ajax в цветной ящик jQuery (модальное окно), поэтому проблема - я могу инициировать только поле со списком с помощью colorbox onComplete, однако при изменении одного combobox другой select/combobox должен быть динамически создан, поэтому мне нужен более общий способ обнаружения создания элемента (select в этом случае).

UPDATE2 Чтобы попытаться объяснить проблему дальше - у меня есть элементы select/combobox, созданные рекурсивно, внутри .combobox() также много инициирующего кода, поэтому, если бы я использовал классический подход, например в @bipen answer мой код будет раздуваться до безумных уровней. Надеюсь, это объяснит проблему лучше.

UPDATE3 Спасибо всем, теперь я понимаю, что с момента устаревания DOMNodeInserted в DOM-мутации есть пустота, и нет решения этой проблемы. Я просто должен пересмотреть мое приложение.

4b9b3361

Ответ 1

Вы можете on событие DOMNodeInserted, чтобы получить событие, когда оно добавлено в документ по вашему коду.

$('body').on('DOMNodeInserted', 'select', function () {
      //$(this).combobox();
});

$('<select>').appendTo('body');
$('<select>').appendTo('body');

Спрятано здесь: http://jsfiddle.net/Codesleuth/qLAB2/3/

EDIT: после прочтения мне просто нужно дважды проверить DOMNodeInserted не вызовет проблем в браузерах. Этот вопрос от 2010 года предполагает, что IE не поддерживает событие, поэтому проверьте его, если сможете.

Смотрите здесь: [ссылка] Предупреждение! тип события DOMNodeInserted определен в этой спецификации для справки и полноты, но эта спецификация обесценивает использование этого типа события.

Ответ 2

Вы можете использовать DOMNodeInserted мутации DOMNodeInserted (нет необходимости в деле делегирования):

$('body').on('DOMNodeInserted',function(e){
    var target = e.target; //inserted element;
});

EDIT: события мутации устарели, вместо этого используйте наблюдателя- мутанта

Ответ 3

Просто придумал это решение, которое, похоже, решает все мои проблемы с ajax.

Для готовых событий я теперь использую это:

function loaded(selector, callback){
    //trigger after page load.
    $(function () {
        callback($(selector));
    });
    //trigger after page update eg ajax event or jquery insert.
    $(document).on('DOMNodeInserted', selector, function () {
        callback($(this));
    });
}

loaded('.foo', function(el){
    //some action
    el.css('background', 'black');
});

И для обычных событий триггера я теперь использую это:

$(document).on('click', '.foo', function () {
    //some action
    $(this).css('background', 'pink');
});

Ответ 4

Это можно сделать с помощью DOM4 MutationObservers, но будет работать только в Firefox 14 +/Chrome 18+ (на данный момент).

Однако существует эпический взлом (авторские слова не мои!), который работает во всех браузерах, поддерживающих анимацию CSS3, которые: IE10, Firefox 5+, Chrome 3+, Opera 12, Android 2.0+, Safari 4+. См. демо из блога. Взлом заключается в использовании события анимации CSS3 с заданным именем, которое наблюдается и действует в JavaScript.

Ответ 5

Один из способов, который кажется надежным (хотя тестируется только в Firefox и Chrome), заключается в использовании JavaScript для прослушивания события animationend (или его camelCased и prefixed, sibling animationend) и применения недолговечного (в демо 0,01 секунды) анимации к типу-элементу, который вы планируете добавить. Это, конечно, не событие onCreate, а аппроксимирует (в совместимых браузерах) тип события onInsertion; следующее является доказательством концепции:

$(document).on('webkitAnimationEnd animationend MSAnimationEnd oanimationend', function(e){
    var eTarget = e.target;
    console.log(eTarget.tagName.toLowerCase() + ' added to ' + eTarget.parentNode.tagName.toLowerCase());
    $(eTarget).draggable(); // or whatever other method you'd prefer
});

В следующем HTML:

<div class="wrapper">
    <button class="add">add a div element</button>
</div>

И (сокращенно, префикс-версии-удалены, хотя присутствует в скрипте ниже) CSS:

/* vendor-prefixed alternatives removed for brevity */
@keyframes added {
    0% {
        color: #fff;
    }
}

div {
    color: #000;
    /* vendor-prefixed properties removed for brevity */
    animation: added 0.01s linear;
    animation-iteration-count: 1;
}

JS Fiddle demo.

Очевидно, что CSS можно настроить в соответствии с расположением соответствующих элементов, а также селектором, используемым в jQuery (он должен быть как можно ближе к точке вставки).

Документация имен событий:

Mozilla   |  animationend
Microsoft |  MSAnimationEnd
Opera     |  oanimationend
Webkit    |  webkitAnimationEnd
W3C       |  animationend

Литература:

Ответ 6

Для меня привязка к телу не работает. Привязка к документу с помощью jQuery.bind() делает.

$(document).bind('DOMNodeInserted',function(e){
             var target = e.target;
         });

Ответ 7

Существует плагин adampietrasiak/jquery.initialize, который основан на MutationObserver, который достигает этого просто.

$.initialize(".some-element", function() {
    $(this).css("color", "blue");
});

Ответ 8

Как упоминалось в нескольких других ответах, события мутации устарели, поэтому вместо этого вы должны использовать MutationObserver. Поскольку никто пока не дал никаких подробностей, вот он...

Основной API JavaScript

API для MutationObserver довольно прост. Это не так просто, как события мутации, но все равно все в порядке.

function callback(records) {
  records.forEach(function (record) {
    var list = record.addedNodes;
    var i = list.length - 1;
    
	for ( ; i > -1; i-- ) {
	  if (list[i].nodeName === 'SELECT') {
	    // Insert code here...
	    console.log(list[i]);
	  }
	}
  });
}

var observer = new MutationObserver(callback);

var targetNode = document.body;

observer.observe(targetNode, { childList: true, subtree: true });
<script>
  // For testing
  setTimeout(function() {
    var $el = document.createElement('select');
    document.body.appendChild($el);
  }, 500);
</script>

Ответ 9

создайте <select> с идентификатором, добавьте его в документ.. и вызовите .combobox

  var dynamicScript='<select id="selectid"><option value="1">...</option>.....</select>'
  $('body').append(dynamicScript); //append this to the place your wanted.
  $('#selectid').combobox();  //get the id and add .combobox();

это должно сделать трюк.. вы можете скрыть выбор, если хотите, и после .combobox показать его... или еще использовать find..

 $(document).find('select').combobox() //though this is not good performancewise

Ответ 10

Если вы используете angularjs, вы можете написать свою собственную директиву. У меня была такая же проблема с bootstrapSwitch. Я должен позвонить   $("[name='my-checkbox']").bootstrapSwitch(); в javascript, но мой объект ввода html не был создан в то время. Поэтому я пишу собственную директиву и создаю входной элемент с   <input type="checkbox" checkbox-switch>

В директиве я компилирую элемент для получения доступа через javascript выполнить команду jquery (например, вашу команду .combobox()). Очень важно удалить атрибут. В противном случае эта директива будет вызывать себя, и вы создали цикл

app.directive("checkboxSwitch", function($compile) {
return {
    link: function($scope, element) {
        var input = element[0];
        input.removeAttribute("checkbox-switch");
        var inputCompiled = $compile(input)($scope.$parent);
        inputCompiled.bootstrapSwitch();
    }
}
});