गतिशील रूप से बनाए गए तत्वों के लिए jQuery "क्रिएट ऑन" ईवेंट


81

मुझे गतिशील रूप से <select>तत्व बनाने और इसे jQuery में बदलने में सक्षम होने की आवश्यकता है .combobox()। यह तत्व निर्माण घटना होनी चाहिए, क्योंकि कुछ "क्लिक" घटना के विपरीत, जिस स्थिति में मैं सिर्फ jQuery का उपयोग कर सकता था .on()

तो क्या ऐसा कुछ मौजूद है?

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

मैं लाइवक्लेरी का उपयोग करने के लिए अनिच्छुक हूं, क्योंकि यह बहुत पुराना है।

अद्यतन का उल्लेख किया गया चयन / combobox ajax के माध्यम से एक jQuery के कलरबॉक्स (मोडल विंडो) में लोड किया जाता है, इस प्रकार समस्या - मैं केवल कलरबॉक्स का उपयोग करके कॉम्बोक्स शुरू कर सकता हूं onComplete, हालांकि एक कॉम्बोक्स के परिवर्तन पर दूसरे का चयन / कॉम्बोक्स को गतिशील रूप से बनाया जाना चाहिए, इसके लिए मुझे एक की आवश्यकता है एक तत्व के निर्माण का पता लगाने के लिए और अधिक सामान्य तरीका ( selectइस मामले में)।

UPDATE2 समस्या को आगे बढ़ाने और समझाने के लिए - मेरे पास select/comboboxपुनरावर्ती रूप से बनाए गए तत्व हैं, अंदर बहुत से आरंभ करने वाले कोड भी हैं .combobox(), इसलिए यदि मैं एक क्लासिक दृष्टिकोण का उपयोग करता हूं, जैसे @ bipen के उत्तर में , मेरा कोड पागल स्तर तक बढ़ जाएगा। आशा है कि यह समस्या को बेहतर ढंग से समझाता है।

UPDATE3 सभी को धन्यवाद, अब मुझे समझ में आया है कि चूंकि डीआरएDOMNodeInserted म्यूटेशन में कोई शून्य छोड़ दिया गया है और इस समस्या का कोई समाधान नहीं है। मुझे बस अपने आवेदन पर पुनर्विचार करना होगा।


1
तैयार घटना के साथ हो सकता है? $(select).ready(function() { });
पाब्लो बंडारस

@PabloBanderas readyका उपयोग किया जाता है: "DOM के पूर्ण लोड होने पर निष्पादित करने के लिए फ़ंक्शन निर्दिष्ट करें।" (jquery.com से)
कैबेलेरो

1
combobox()निर्माण / सम्मिलन के बिंदु पर पद्धति को लागू क्यों नहीं किया जाता है, बल्कि इसके बाद?
डेविड का कहना है कि मोनिका

@DavidThomas मेरी दूसरी अद्यतन में कारण की व्याख्या करने की कोशिश की
Caballero

तो $(document).on('onComplete', 'select', function(){ // bind here? });? (जाहिर है document, हालांकि, की तुलना में एक करीबी माता-पिता का उपयोग करें ।)
डेविड कहते हैं मोनिका

जवाबों:


59

आप कर सकते हैं घटना जब वह अपने कोड द्वारा दस्तावेज़ को जोड़ा गया है के लिए एक घटना प्राप्त करने के लिए।onDOMNodeInserted

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

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

यहां क्लिक किया गया: http://jsfiddle.net/Codesleuth/qLAB2/3/

संपादित करें: मेरे चारों ओर पढ़ने के बाद मुझे केवल डबल चेक करने की आवश्यकता है DOMNodeInsertedजिससे ब्राउज़र में समस्याएँ पैदा न हों। 2010 के इस सवाल से पता चलता है कि IE घटना का समर्थन नहीं करता है, इसलिए यदि आप कर सकते हैं तो इसका परीक्षण करें।

यहाँ देखें: [लिंक] चेतावनी! DOMNodeInserted घटना प्रकार संदर्भ और पूर्णता के लिए इस विनिर्देश में परिभाषित किया गया है, लेकिन इस विनिर्देश deprecates इस घटना प्रकार का उपयोग।


.delegatejQuery के संस्करण 1.7 से वंचित नहीं किया गया है और इसके द्वारा सुपरसीड किया गया है .on?
कैबेलेरो

1
हाँ, तुम सही हो। मैं इस उत्तर को संशोधित करूंगा, लेकिन मैं ईमानदारी से अनिश्चित हूं यदि आपको इसका उपयोग करना चाहिए क्योंकि DOMNodeInsertedअब यह पदावनत हो गया है।
कोड्सुथ

मैंने on('DOMNodeInserted'यह प्रश्न पोस्ट करने से पहले कोशिश की है । यह स्पष्ट रूप से काम नहीं किया।
कैबेलेरो

20
चूंकि यह आपके सवाल में नहीं है कि आपने इसे आज़माया है, इसलिए मैं कहूंगा कि यह एक अनुचित वोट है। किसी भी मामले में, मैं यहाँ आपकी मदद नहीं कर सकता।
कोडस्लेथ

21

आप DOMNodeInsertedम्यूटेशन इवेंट (प्रतिनिधि की आवश्यकता नहीं) का उपयोग कर सकते हैं :

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

संपादित करें: उत्परिवर्तन घटनाओं को पदावनत किया जाता है , इसके बजाय म्यूटेशन प्रेक्षक का उपयोग करें


20

जैसा कि कई अन्य उत्तरों में उल्लेख किया गया है, उत्परिवर्तन घटनाओं को हटा दिया गया है, इसलिए आपको इसके बजाय MutationObserver का उपयोग करना चाहिए । चूँकि किसी ने उस पर अभी तक कोई विवरण नहीं दिया है, यहाँ यह है ...

मूल जावास्क्रिप्ट एपीआई

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>

चलो कि नीचे तोड़ो।

var observer = new MutationObserver(callback);

इससे प्रेक्षक का निर्माण होता है। पर्यवेक्षक अभी तक कुछ भी नहीं देख रहा है; यह वह जगह है जहाँ इवेंट श्रोता संलग्न होता है।

observer.observe(targetNode, { childList: true, subtree: true });

इससे प्रेक्षक को शुरुआत होती है। पहला तर्क नोड है जो पर्यवेक्षक बदलावों के लिए देखेगा। दूसरा तर्क क्या देखना है इसके लिए विकल्प हैं

  • childList इसका मतलब है कि मैं बाल तत्वों को जोड़ा या हटाया जाना देखना चाहता हूं।
  • subtreeएक ऐसा संशोधक है जो इस तत्व के सबट्री में कहीं भी बदलावों को देखने के लिए विस्तारित childList होता है (अन्यथा, यह केवल सीधे परिवर्तनों को देखेगा targetNode)।

इसके अलावा अन्य दो मुख्य विकल्प childListहैं , attributesऔर characterDataइसका मतलब है कि वे क्या पसंद करते हैं। आपको उन तीन में से एक का उपयोग करना होगा।

function callback(records) {
  records.forEach(function (record) {

कॉलबैक के अंदर चीजें थोड़ी मुश्किल हो जाती हैं। कॉलबैक में MutationRecord s की एक सरणी मिलती है । प्रत्येक MutationRecord एक प्रकार के कई परिवर्तनों का वर्णन कर सकते हैं ( childList, attributes, या characterData)। चूंकि मैंने केवल पर्यवेक्षक को देखने के लिए कहा था childList, इसलिए मैं प्रकार की जांच करने से परेशान नहीं होगा।

var list = record.addedNodes;

यहाँ मैं सभी बच्चे नोड्स के एक नोडलिस्ट को जोड़ता हूं जो जोड़े गए थे। यह उन सभी रिकॉर्डों के लिए रिक्त होगा जहां नोड्स नहीं जोड़े गए हैं (और ऐसे कई रिकॉर्ड हो सकते हैं)।

वहां से, मैं जोड़े गए नोड्स के माध्यम से लूप करता हूं और किसी भी <select>तत्व को ढूंढता हूं ।

यहां वास्तव में कुछ भी जटिल नहीं है।

jQuery

... लेकिन आपने jQuery के लिए कहा। ठीक।

(function($) {

  var observers = [];

  $.event.special.domNodeInserted = {

    setup: function setup(data, namespaces) {
      var observer = new MutationObserver(checkObservers);

      observers.push([this, observer, []]);
    },

    teardown: function teardown(namespaces) {
      var obs = getObserverData(this);

      obs[1].disconnect();

      observers = $.grep(observers, function(item) {
        return item !== obs;
      });
    },

    remove: function remove(handleObj) {
      var obs = getObserverData(this);

      obs[2] = obs[2].filter(function(event) {
        return event[0] !== handleObj.selector && event[1] !== handleObj.handler;
      });
    },

    add: function add(handleObj) {
      var obs = getObserverData(this);

      var opts = $.extend({}, {
        childList: true,
        subtree: true
      }, handleObj.data);

      obs[1].observe(this, opts);

      obs[2].push([handleObj.selector, handleObj.handler]);
    }
  };

  function getObserverData(element) {
    var $el = $(element);

    return $.grep(observers, function(item) {
      return $el.is(item[0]);
    })[0];
  }

  function checkObservers(records, observer) {
    var obs = $.grep(observers, function(item) {
      return item[1] === observer;
    })[0];

    var triggers = obs[2];

    var changes = [];

    records.forEach(function(record) {
      if (record.type === 'attributes') {
        if (changes.indexOf(record.target) === -1) {
          changes.push(record.target);
        }

        return;
      }

      $(record.addedNodes).toArray().forEach(function(el) {
        if (changes.indexOf(el) === -1) {
          changes.push(el);
        }
      })
    });

    triggers.forEach(function checkTrigger(item) {
      changes.forEach(function(el) {
        var $el = $(el);

        if ($el.is(item[0])) {
          $el.trigger('domNodeInserted');
        }
      });
    });
  }

})(jQuery);

यह jQuery के विशेष ईवेंट APIdomNodeInserted का उपयोग करके एक नया ईवेंट बनाता है । आप इसे इस तरह से उपयोग कर सकते हैं:

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

मैं व्यक्तिगत रूप से एक वर्ग की तलाश करने का सुझाव दूंगा क्योंकि कुछ पुस्तकालय selectपरीक्षण उद्देश्यों के लिए तत्व बनाएंगे ।

स्वाभाविक रूप से, आप .off("domNodeInserted", ...)इस तरह से डेटा पास करके देखने का उपयोग कर सकते हैं या ठीक कर सकते हैं :

$(document.body).on("domNodeInserted", "select.test", {
  attributes: true,
  subtree: false
}, function () {
  $(this).combobox();
});

यह एक select.testतत्व की उपस्थिति के लिए जाँच को ट्रिगर करेगा जब भी तत्व सीधे शरीर के अंदर के लिए बदल जाते हैं।

आप इसे नीचे या jsField पर लाइव देख सकते हैं ।


ध्यान दें

यह jQuery कोड एक काफी बुनियादी कार्यान्वयन है। यह उन मामलों में ट्रिगर नहीं होता है जहां संशोधन कहीं और आपके चयनकर्ता को वैध बनाते हैं।

उदाहरण के लिए, मान लीजिए कि आपका चयनकर्ता है .test selectऔर दस्तावेज में पहले से ही ए <select>। चयनकर्ता को मान्य testकरने के लिए वर्ग जोड़ने से <body>, लेकिन क्योंकि मैं केवल जाँच करता हूँ record.targetऔर record.addedNodes, घटना नहीं होगी। परिवर्तन उस तत्व के साथ होना है जिसे आप स्वयं चुनना चाहते हैं।

जब भी म्यूटेशन होता है, तो चयनकर्ता के लिए क्वेरी करने से बचा जा सकता है। मैंने ऐसा नहीं करने का फैसला किया, जो पहले से ही संभाल चुके तत्वों के लिए डुप्लिकेट घटनाओं से बचने के लिए नहीं था। आसन्न या सामान्य सहोदर संयोजकों के साथ उचित व्यवहार करने से चीजें और भी पेचीदा हो जाएंगी।

अधिक व्यापक समाधान के लिए, https://github.com/pie6k/jquery.initialize देखें , जैसा कि डेमियन s Ceallaigh के उत्तर में वर्णित है । हालाँकि, उस पुस्तकालय के लेखक ने घोषणा की है कि पुस्तकालय पुराना है और सुझाव देता है कि आपको इसके लिए jQuery का उपयोग नहीं करना चाहिए।


9

बस इस समाधान के साथ आया था जो मेरी सभी अजाक्स समस्याओं को हल करने के लिए लगता है।

तैयार घटनाओं के लिए मैं अब इसका उपयोग करता हूं:

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लेकिन यह केवल फ़ायरफ़ॉक्स 14 + / क्रोम 18+ (अभी के लिए) में काम करेगा।

हालाँकि, एक " महाकाव्य हैक " है (लेखक के शब्द मेरा नहीं!) जो उन सभी ब्राउज़रों में काम करता है जो CSS3 के एनिमेशन का समर्थन करते हैं जो हैं: IE10, Firefox 5+, Chrome 3+, ओपेरा 12, Android 2.0+, Safari 4+। ब्लॉग से डेमो देखें । हैक एक CSS3 एनीमेशन घटना का उपयोग करने के लिए दिया गया है जिसका नाम दिया गया है और जावास्क्रिप्ट पर काम किया है।


4

एक तरीका, जो विश्वसनीय लगता है (हालांकि केवल फ़ायरफ़ॉक्स और क्रोम में परीक्षण किया गया है) जावास्क्रिप्ट का उपयोग animationend(या उसके ऊंट, और उपसर्ग, भाई 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>

और (संक्षिप्त, उपसर्ग-संस्करण-हटाए गए हालांकि फ़िडल में मौजूद हैं, नीचे) सीएसएस:

/* 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;
}

जेएस फिडेल डेमो

स्पष्ट रूप से CSS को संबंधित तत्वों के प्लेसमेंट के अनुरूप समायोजित किया जा सकता है, साथ ही चयनकर्ता jQuery में उपयोग किया जाता है (यह वास्तव में संभव के रूप में प्रविष्टि के करीब होना चाहिए)।

घटना-नामों का दस्तावेजीकरण:

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

संदर्भ:


4

मेरे लिए शरीर को बांधना काम नहीं करता है। JQuery.bind () का उपयोग करते हुए दस्तावेज़ को बाइंडिंग।

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

1

मुझे लगता है कि यह ध्यान देने योग्य है कि कुछ मामलों में, यह काम करेगा:

$( document ).ajaxComplete(function() {
// Do Stuff
});

1

के बजाय...

$(".class").click( function() {
    // do something
});

तुम लिख सकते हो...

$('body').on('click', '.class', function() {
    // do something
});

0

<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दिखाने के बाद .. और उपयोग खोजें ..

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

-1

यदि आप एंगुलरज का उपयोग कर रहे हैं तो आप अपना निर्देश लिख सकते हैं। मेरे पास वही समस्या थी जो बूटस्ट्रैपस्विच थी। मुझे $("[name='my-checkbox']").bootstrapSwitch(); जावास्क्रिप्ट में कॉल करना है लेकिन उस समय मेरी html इनपुट ऑब्जेक्ट नहीं बनाई गई थी। इसलिए मैं स्वयं एक निर्देश लिखता हूं और इनपुट तत्व बनाता हूं <input type="checkbox" checkbox-switch>

निर्देश में मैं जावास्क्रिप्ट कमांड के माध्यम से एक्सेस प्राप्त करने के लिए तत्व को संकलित करता हूं (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();
    }
}
});

अकेले jQuery से संबंधित प्रश्न, AngularJS नहीं। समाधान jQuery और jQuery प्लगइन्स तक सीमित होना चाहिए।
जेम्स डन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.