14

अद्यतन:(संक्षिप्त, बेला और इनाम)जावास्क्रिप्ट: इंटरनेट एक्सप्लोरर (प्रतिनिधिमंडल) में परिवर्तन घटना अनुकरण करने के लिए कैसे

यह सवाल बहुत अधिक ध्यान नहीं जा रहा है, इसलिए मैं जा रहा हूँ इस पर कुछ प्रतिनिधि खर्च करें। मुझे पता है कि मैं अपने उत्तरों और सवालों दोनों में अत्यधिक वर्बोज़ होने लगता हूं। यही कारण है कि मैं आगे बढ़ गया और this fiddle स्थापित किया, जो कि मेरे विचार में, वर्तमान में कोड के प्रकार का एक सभ्य प्रतिनिधित्व है जिसे मैं वर्तमान में change ईवेंट के बगल में आने के लिए उपयोग कर रहा हूं। कुछ मुद्दों को हल करने का प्रयास कर रहा हूं:

  1. pseudo-change ईवेंट किसी चयनित तत्व पर आग नहीं लगाता है, जब तक कि यह फोकस न हो जाए। कुछ मामलों में ग्राहक को एक नया मूल्य चुनने पर पुनर्निर्देशित किया जाना चाहिए। मुझे यह कैसे हासिल होगा?
  2. लेबलर क्लिक किए जाने पर हैंडलर दोनों को कॉल किया जाता है, साथ ही चेकबॉक्स स्वयं भी होते हैं। अपने आप में यही उम्मीद है कि आप इसकी अपेक्षा करेंगे, लेकिन घटना के कारण (AFAIK) यह निर्धारित करना असंभव है कि कौन सा तत्व क्लिक किया गया था। आईई की घटना वस्तु में realTarget संपत्ति नहीं है।
  3. लेबल पर क्लिक करके checked- आईई में चेकबॉक्स का सेट बदलते समय, सभी ठीक है (हालांकि इसे कुछ ग़लत कामकाज की आवश्यकता है), लेकिन सीधे चेकबॉक्स पर क्लिक करते समय, हैंडलर को कॉल किया जाता है, लेकिन चेक की गई स्थिति अपरिवर्तित बनी हुई है, जब तक मैं दूसरी बार क्लिक नहीं करता। फिर मान बदलता है, लेकिन हैंडलर को नहीं कहा जाता है।
  4. जब मैं एक अलग टैब पर स्विच करता हूं, और फिर वापस, हैंडलर को कई बार कहा जाता है। तीन बार यदि चेक की गई स्थिति वास्तव में बदल जाती है, तो दो बार अगर मैं केवल एक बार चेकबॉक्स पर क्लिक करता हूं।

कोई भी जानकारी जो ऊपर दिए गए एक या अधिक मुद्दों को हल करने में मेरी सहायता कर सकती है, उसकी सराहना की जाएगी। कृपया, मैं jQuery टैग जोड़ने के लिए नहीं भूल गया, मुझे शुद्ध जेएस पसंद है, इसलिए मैं एक शुद्ध जेएस उत्तर की तलाश में हूं।


मेरे पास 250 से अधिक चुनिंदा तत्वों के साथ एक वेब पेज है, और 20 ~ 30 चेकबॉक्स हैं। मुझे उपयोगकर्ताओं के कार्यों को ट्रैक करना होगा, और उचित कार्रवाई करना होगा। इसलिए मेरे लिए परिवर्तन कार्यक्रम का प्रतिनिधि होना काफी स्वाभाविक है, बल्कि सैकड़ों श्रोताओं, आईएमएचओ को जोड़ना।

बेशक, आईई-कॉम्पनी नीति: आईई 8 को समर्थित होना है- जब मुझे इसकी आवश्यकता हो तो एक्सचेंज ईवेंट को आग नहीं लगती है। तो मैं नकली एक अस्थायी घटना की कोशिश कर रहा हूँ। जो मैंने अभी तक किया है वह 1 चीज के अलावा काफी अच्छी तरह से काम कर रहा है जो वास्तव में मुझे खराब करता है।
मैं घटनाओं को पंजीकृत करने के लिए onfocusin और onfocusout का उपयोग कर रहा हूं। कुछ मामलों में, जब उपयोगकर्ता किसी चयनित तत्व से नया मान चुनता है, तो स्क्रिप्ट तुरंत प्रतिक्रिया देनी चाहिए। हालांकि, जब तक चयन फोकस नहीं खोला है, यह नहीं होगा।

यहाँ मैं अब तक के साथ आया है:

i = document.getElementById('content'); 
if (!i.addEventListener) 
{ 
    i.attachEvent('onfocusin',(function(self) 
    { 
     return function(e) 
     { 
      e = e || window.event; 
      var target = e.target || e.srcElement; 
      switch (target.tagName.toLowerCase()) 
      { 
       case 'input': 
        if (target.getAttribute('type') !== 'checkbox') 
        { 
         return true; 
        } 
        return changeDelegator.apply(self,[e]);//(as is 
       case 'select': 
        self.attachEvent('onfocusout',(function(self,current) 
        { 
         return function(e) 
         { 
          e = e || window.event; 
          var target = e.target || e.srcElement; 
          if (target !== current) 
          { 
           return; 
          } 
          self.detachEvent('onfocusout',arguments.callee);//(remove closure 
          return changeDelegator.apply(self,[e]); 
         } 
        })(self,target)); 
       default: return; 
      } 
     } 
    })(i));//(fake change event, buggy 
} 
else 
{//(to put things into perspective: all major browsers: 
    i.addEventListener('change',changeDelegator,false); 
} 

मैं onfocusin हैंडलर के अंदर एक और घटना श्रोता, onclick घटना के लिए बाध्य संलग्न की कोशिश की है। इसने onfocusout घटना को निकाल दिया जो किसी भी विकल्प पर केंद्रित है एटीएम। एकमात्र समस्या यह है कि 99.9% उपयोगकर्ता एक चयन पर क्लिक करेंगे, इसलिए focusin घटना भी एक ऑनक्लिक आग लगती है।

राउंड प्राप्त करने के लिए, मैंने बंद कर दिया, और वर्तमान चयन-इन-फोकस पारित किया और तर्क के रूप में इसका मूल मूल्य है।लेकिन कुछ उपयोगकर्ता अपने कीबोर्ड का उपयोग करते हैं, और ये उपयोगकर्ता अक्सर मूल्य को बदलने के बिना अगले चयन बॉक्स पर टैब करते हैं। प्रत्येक बार एक नया ऑनक्लिक श्रोता बाध्यकारी ... मुझे विश्वास है कि है सभी e.type की जांच करने और उन्हें अलग से इलाज करने के लिए एक आसान तरीका होने के लिए है।
बस एक उदाहरण के रूप: एक अतिरिक्त onclick श्रोता के साथ कोड: सभी कोड पहले टुकड़ा के रूप में ही है, इसलिए मैं केवल case 'select': ब्लॉक

   case 'select': 
        self.attachEvent('onfocusout',(function(self,current) 
        { 
         return function(e) 
         { 
          e = e || window.event;//(IE... 
          var target = e.target || e.srcElement; 
          if (!(target === current)) 
          { 
           return; 
          } 
          self.detachEvent('onfocusout',arguments.callee);//(remove closure 
          return changeDelegator.apply(self,[e]); 
         }; 
        })(self,target)); 
        self.attachEvent('onclick',(function(self,current,oldVal) 
        { 
         return function(e) 
         { 
          e = e || window.event; 
          var target = e.target || e.srcElement; 
          if (target.tagName.toLowerCase() === 'option') 
          { 
           while(target.tagName.toLowerCase() !== 'select') 
           { 
            target = target.parentNode; 
           } 
          } 
          if (target !== current) 
          {//focus lost, onfocusout triggered anyway: 
           self.detachEvent('onclick',arguments.callee); 
           return; 
          } 
          var val = target.options[target.selectedIndex].innerHTML;//works best in all browsers 
          if (oldVal !== target.options[target.selectedIndex].innerHTML) 
          { 
           self.detachEvent('onclick',arguments.callee); 
           return target.fireEvent('onfocusout'); 
          } 
         }; 
        })(self,target,target.options[target.selectedIndex].innerHTML)); 
       default: return; 

उत्तर

2

ठीक है, मैं उस पर फिर से दरार थी, और मुझे (काम पर एक काफी सभ्य दृष्टिकोण लेकर आए हैं यह चाल किया था - मैं कोड मैंने लिखा दोहराने की कोशिश की है, लेकिन कुछ बियर के बाद यह कुछ त्रुटियाँ हो सकता है, लेकिन भावना एक ही रहता है)

window.attachEvent('onload',function ieLoad() 
{ 
    var mainDiv = document.getElementById('main');//main div, from here events will be delegated 
    var checks = mainDiv.getElementsByTagName('input');//node list of all inputs 
    var checkStates = {}; 
    for (var i=0;i<checks.length;i++) 
    { 
     if (checks[i].type === 'checkbox') 
     {//get their checked states on load, this object serves as a reference 
      checkStates[checks[i].id] = checks[i].checked; 
     } 
    } 
    mainDiv.attachEvent('onfocusin',(function(initState) 
    {//initState holds a reference to the checkStates object 
     return function(e) 
     { 
      e = e || window.event; 
      var target = e.target || e.srcElement; 
      //id of checkboxes used as key, so no checking for tagName or type required 
      if (!initState.hasOwnProperty(target.id) || target.checked === initState[target.id]) 
      {//don't call method if checkstate is unchanged, either. I'll explain in a minute 
       return e; 
      } 
      initState[target.id] = target.checked;//set new checked-state 
      changeDelegator.apply(target,[e]);//delegate 
     }; 
    })(checkStates)); 
    window.detachEvent('onload',ieLoad);//avoid mem-leak with onload handler! 
}); 

मुझे पता चला है कि दो बार रेडियो और चेक बॉक्स के लिए कुछ मामलों में Focusin घटनाओं आग। किसी ऑब्जेक्ट का उपयोग करना जो सभी चेकबॉक्सों के वास्तविक चेक किए गए राज्य रखता है, अलग-अलग हैंडलर से कम महंगा होता है, और यह तत्व के मूल्य को बदलने के बाद ही ईवेंट को ही प्रस्तुत करने की अनुमति देता है।

changeDelegator समारोह केवल आवश्यकता कहा जाता है, लेकिन शीघ्र समारोह है कि मैं यहाँ अब भी पोस्ट waaaay से अधिक मैं इसे करना चाहता था बुलाया जाता है, लेकिन इस दृष्टिकोण अभी भी बेहतर साबित व्यक्ति संचालकों-ले।

मैं चयन बाहर छोड़ दिया, लेकिन मैं उन्हें काम कर रहा है, भी बंद 2 वस्तुओं है मेरी कोड के पूर्ण संस्करण में (समान ले, गया, और मैं इसे बनाया है, तो मैं झंडा एक आईडी, सक्रिय कर सकता है आवश्यकता होने पर धुंधला घटना, और ग्राहक को पुनर्निर्देशित किया जाता है)।
रन के अंत में, भले ही मैंने कुछ नई चालें सीखी हैं, लेकिन इस अभ्यास से मैं जो मुख्य चीज लेता हूं वह आईई नामक चीज के उस भयानक, किरकिरा गोलेम का और भी गहरा घृणा है ... लेकिन अगर कोई अन्यथा कभी भी आईई में परिवर्तन घटनाओं को प्रतिनिधि बनाना चाहते हैं, जानते हैं कि यह है (लगभग) संभव

3

चिपकाने कर रहा हूँ जब मैं इस बात से सहमत बेहतर ही होने होगा कि कई श्रोताओं के बजाय पूरे फॉर्म पर एक ईवेंट श्रोता, प्रत्येक तत्व के लिए, आपको अपने निर्णय की लागत और लाभ का मूल्यांकन करना होगा। एक श्रोता का लाभ कम स्मृति पदचिह्न है। नकारात्मकता यह है कि आपको घटनाओं के लगभग एक ब्राउज़र के गलत कार्यान्वयन, निष्पादन समय में वृद्धि, घटना प्रकारों का दुरुपयोग, घटना सुनने वालों को बार-बार पंजीकरण और अनधिकृत करने के लिए ऐसी जटिल कोड चालें करनी पड़ती हैं, शायद कुछ उपयोगकर्ताओं को भ्रम पैदा हो सकती है।

लाभ पर वापस आना, स्मृति पदचिह्न इतना बड़ा नहीं है अगर आप सभी तत्वों के लिए श्रोता के रूप में एक ही कार्य को संलग्न करते हैं। और स्मृति कुछ ऐसा है जो मौजूदा कंप्यूटरों की कमी नहीं है।

भले ही यह आपके प्रश्न का उत्तर न दे, मैं आपको सलाह देता हूं कि आप इस काम को करने की कोशिश करना बंद कर दें, और इसके बजाय श्रोताओं को प्रत्येक फॉर्म तत्व पर संलग्न करें।

  1. आप इस बारे में सुनिश्चित कर रहे हैं:

    अपने अंक एक सा पता करने के लिए? मैंने the basic example from Microsoft's documentation की कोशिश की है, और ड्रॉपडाउन से किसी विकल्प पर क्लिक करने के बाद आईई 7 और आईई 8 दोनों onchange श्रोता को आग लगाते हैं। ऊपर/नीचे कुंजी के साथ चयन को बदलते समय भी यह आग लगती है।

  2. हालांकि यह सच है कि आप आसानी से प्रभावित चेकबॉक्स पर किसी लेबल पर किसी ईवेंट से कनेक्ट नहीं कर सकते हैं, तो आप ऐसा क्यों करना चाहेंगे? change ईवेंट किसी भी तरह से चेकबॉक्स पर ट्रिगर किया जाएगा, और आपको केवल उस पर ध्यान देना चाहिए। हालांकि, अगर आपको लेबल पर किसी ईवेंट से चेकबॉक्स में जाना होगा, तो आप इसे मैन्युअल रूप से कर सकते हैं। यदि ईवेंट लेबल को लक्षित करता है, तो आप जानते हैं कि लेबल किसी इनपुट से संबंधित है। लेबल का उपयोग करने के तरीके के आधार पर, आप या तो inputlabel के अंदर घोंसला वाले तत्व का चयन कर सकते हैं, या label की for विशेषता में मिली आईडी के साथ तत्व प्राप्त कर सकते हैं। चेक बॉक्स फिक्सिंग का

  3. एक तरह से परिवर्तन पर पिछले मान बग चेक बॉक्स पर एक this.blur()focus पर घटनाओं करना है।

  4. जब आप "हैंडलर" कहते हैं, तो आपका मतलब onfocusin ईवेंट हैंडलर, या changeDelegator है? एक टैब को पुनः सक्रिय करते समय focusin ईवेंट आग देखना सामान्य बात है। मुझे यकीन नहीं है कि घटना को एक से अधिक बार निकाल दिया गया है, इसलिए मैं अनुमान लगा रहा हूं: एक ऐसा फोकस हो सकता है जो सक्रिय इनपुट प्राप्त करता है; दूसरा फोकस हो सकता है कि दस्तावेज़ स्वयं प्राप्त करता है; मुझे नहीं पता कि तीसरा कॉल क्यों होता है। मुझे समझ में नहीं आता कि "क्या चेक किया गया राज्य वास्तव में बदल गया है, [...] अगर मैंने केवल एक बार चेकबॉक्स पर क्लिक किया है"।

+0

1. हां, मुझे इसके बारे में निश्चित है: परिवर्तन घटना आईई 8 में निकाल दी गई है, लेकिन यह बुलबुला नहीं है। यह [एक ज्ञात समस्या] (http://stackoverflow.com/questions/5146784/make-form-elements-onchange-bubble-in-internet-explorer) 2. परिवर्तन हैंडलर दोनों ही मामलों में कहा जाता है, जो वह नहीं है मुसीबत। हालांकि लेबल पर क्लिक करते समय, चेक किए गए राज्य को बदलने के बाद हैंडलर को कॉल किया जाता है, जबकि चेकबॉक्स सीधे क्लिक होने पर चेक की गई स्थिति बदलती जा रही है। तो यदि 'target.checked === true', क्या यह अभी चेक किया गया है, या यह अनचेक किया जा रहा है? कहने का कोई तरीका नहीं है। वर्णों से बाहर चल रहा है –

+0

3. धुंध और फोकस जोड़ना आईई को दुर्घटनाग्रस्त कर देता है: ध्यान दें कि, 'बदले' की वजह से बुलबुला नहीं है, मैं 'ऑनफोकसिन' और 'ऑनफोकसआउट' घटनाओं का उपयोग कर रहा हूं। हैंडलर blurs, और केंद्रित है, तो यह सिर्फ खुद infinitly 4. बुला पर रखेंगे और हैंडलर से मैं दोनों का मतलब: कडाई के साथ 'changeDelegator' सिर्फ एक समारोह है, लेकिन एक मैं संचालकों 'संदर्भ (' changeDelegator में कहते हैं। लागू करें (यह, [ई]); '), इसलिए मैं इसे वास्तविक हैंडलर का विस्तार/निरंतरता मानता हूं। मुझे पता है कि जब टैब _revived_ है, तो 'फोकसिन' निकाल दिया जाता है, लेकिन प्रतिनिधिमंडल फ़ंक्शन द्वारा इलाज की जाने वाली प्रत्येक घटना के लिए इसे निकाल दिया जाता है। अक्षर .... –

+0

आखिरी चीज़ से मेरा क्या मतलब है: मैं एक चेकबॉक्स पर क्लिक करता हूं (हैंडलर निकाल दिया जाता है, लेकिन चेक की गई स्थिति नहीं बदली जाती है!), अगर मैं दूसरी बार उस चेकबॉक्स पर क्लिक करता हूं, तो हैंडलर हैन नहीं कहा जाता है, लेकिन चेक की गई स्थिति सभी एक ही बदल जाती है। अगर मैं इसे दूसरी बार क्लिक नहीं करता हूं, लेकिन टैब स्विच करता हूं और फिर से वापस करता हूं, तो 'फोकसिन' ईवेंट उस चेकबॉक्स के लिए _not_ कहलाता है जिसे मैंने एक बार क्लिक किया था। सचमुच अजीब। प्रदर्शन मोर्चे पर: एक बड़ा अंतर है, खासकर जब _not_ इसे V8 पर चला रहा है। पूरे पृष्ठ पर प्रत्येक तत्व को जोड़ने से 333 तक बढ़ जाएगा (केवल उन्हें गिनें) elems! chars ... –

संबंधित मुद्दे