preventDefault
और stopPropagation
: इनका इस्तेमाल कब करना चाहिए और हर तरीका क्या करता है.
Event.stopPropagation() और Event.preventDefault()
JavaScript में इवेंट हैंडलिंग करना अक्सर आसान होता है. यह खास तौर पर तब सही होता है, जब एचटीएमएल स्ट्रक्चर आसान (तुलनात्मक रूप से फ़्लैट) हो. हालांकि, जब इवेंट, एलिमेंट के क्रम में आगे बढ़ते हैं, तो चीज़ें थोड़ी ज़्यादा जटिल हो जाती हैं. आम तौर पर, डेवलपर को जब कोई समस्या आती है, तो वे उसे हल करने के लिए stopPropagation()
और/या preventDefault()
का इस्तेमाल करते हैं. अगर आपने कभी सोचा है कि "मैं सिर्फ़ preventDefault()
आज़माऊंगा और अगर यह काम नहीं करता है, तो मैं stopPropagation()
आज़माऊंगा और अगर यह भी काम नहीं करता है, तो मैं दोनों को आज़माऊंगा," तो यह लेख आपके लिए है! हम आपको बताएंगे कि हर तरीका क्या करता है और किस तरीके का इस्तेमाल कब करना चाहिए. साथ ही, हम आपको काम करने वाले कई उदाहरण देंगे, ताकि आप उन्हें एक्सप्लोर कर सकें. मेरा मकसद, आपके भ्रम को हमेशा के लिए दूर करना है.
हालांकि, इससे पहले कि हम इस बारे में ज़्यादा जानकारी दें, यह जानना ज़रूरी है कि JavaScript में दो तरह के इवेंट हैंडलिंग मुमकिन हैं. ये सभी आधुनिक ब्राउज़र में काम करते हैं. Internet Explorer के वर्शन 9 से पहले, इवेंट कैप्चर करने की सुविधा उपलब्ध नहीं थी.
इवेंटिंग स्टाइल (कैप्चर करना और बबल करना)
सभी मॉडर्न ब्राउज़र, इवेंट कैप्चर करने की सुविधा के साथ काम करते हैं. हालांकि, डेवलपर इसका इस्तेमाल बहुत कम करते हैं.
दिलचस्प बात यह है कि Netscape ने शुरुआत में सिर्फ़ इसी तरह के इवेंट को सपोर्ट किया था. Netscape का सबसे बड़ा प्रतिस्पर्धी, Microsoft Internet Explorer, इवेंट कैप्चर करने की सुविधा के साथ काम नहीं करता था. हालांकि, यह इवेंट बब्लिंग नाम की इवेंटिंग की एक अन्य स्टाइल के साथ काम करता था. W3C के गठन के समय, उन्हें इवेंटिंग के दोनों स्टाइल में फ़ायदे दिखे. इसलिए, उन्होंने यह एलान किया कि ब्राउज़र को दोनों स्टाइल के साथ काम करना चाहिए. इसके लिए, addEventListener
तरीके में तीसरा पैरामीटर इस्तेमाल किया जाना चाहिए. पहले, यह पैरामीटर सिर्फ़ बूलियन था. हालांकि, सभी आधुनिक ब्राउज़र, तीसरे पैरामीटर के तौर पर options
ऑब्जेक्ट का इस्तेमाल करने की सुविधा देते हैं. इसका इस्तेमाल करके, यह तय किया जा सकता है कि आपको इवेंट कैप्चरिंग का इस्तेमाल करना है या नहीं. इसके अलावा, और भी कई काम किए जा सकते हैं:
someElement.addEventListener('click', myClickHandler, { capture: true | false });
ध्यान दें कि options
ऑब्जेक्ट और इसकी capture
प्रॉपर्टी का इस्तेमाल करना ज़रूरी नहीं है. अगर इनमें से किसी एक को शामिल नहीं किया जाता है, तो capture
के लिए डिफ़ॉल्ट वैल्यू false
होती है. इसका मतलब है कि इवेंट बब्लिंग का इस्तेमाल किया जाएगा.
इवेंट कैप्चर करना
अगर आपका इवेंट हैंडलर "कैप्चरिंग फ़ेज़ में सुन रहा है", तो इसका क्या मतलब है? इसे समझने के लिए, हमें यह जानना होगा कि इवेंट कैसे जनरेट होते हैं और वे कैसे ट्रैवल करते हैं. सभी इवेंट के लिए यह जानकारी सही है. भले ही, डेवलपर के तौर पर आपने इसका इस्तेमाल न किया हो, इस पर ध्यान न दिया हो या इसके बारे में न सोचा हो.
सभी इवेंट, विंडो से शुरू होते हैं और सबसे पहले कैप्चरिंग फ़ेज़ से गुज़रते हैं. इसका मतलब है कि जब कोई इवेंट भेजा जाता है, तो वह विंडो शुरू करता है और अपने टारगेट एलिमेंट की ओर "नीचे की ओर" जाता है. सबसे पहले. ऐसा तब भी होता है, जब सिर्फ़ बब्लिंग फ़ेज़ में सुना जा रहा हो. मार्कअप और JavaScript का यह उदाहरण देखें:
<html>
<body>
<div id="A">
<div id="B">
<div id="C"></div>
</div>
</div>
</body>
</html>
document.getElementById('C').addEventListener(
'click',
function (e) {
console.log('#C was clicked');
},
true,
);
जब कोई उपयोगकर्ता एलिमेंट #C
पर क्लिक करता है, तो window
से शुरू होने वाला एक इवेंट भेजा जाता है. इसके बाद, यह इवेंट इसके डिसेंडेंट में इस तरह से दिखेगा:
window
=> document
=> <html>
=> <body>
=> और इसी तरह, जब तक यह टारगेट तक नहीं पहुंच जाता.
इससे कोई फ़र्क़ नहीं पड़ता कि window
या document
या <html>
एलिमेंट या <body>
एलिमेंट (या टारगेट तक पहुंचने के रास्ते में मौजूद कोई अन्य एलिमेंट) पर क्लिक इवेंट के लिए कुछ भी नहीं सुना जा रहा है. इवेंट अब भी window
पर जनरेट होता है और ऊपर बताए गए तरीके से ही आगे बढ़ता है.
हमारे उदाहरण में, क्लिक इवेंट प्रॉपगेट होगा. यह एक ज़रूरी शब्द है, क्योंकि यह सीधे तौर पर stopPropagation()
तरीके से जुड़ा है. इसके बारे में इस दस्तावेज़ में बाद में बताया जाएगा. यह window
से लेकर टारगेट एलिमेंट (इस मामले में, #C
) तक, window
और #C
के बीच मौजूद हर एलिमेंट के ज़रिए होगा.
इसका मतलब है कि क्लिक इवेंट window
पर शुरू होगा और ब्राउज़र ये सवाल पूछेगा:
"क्या कैप्चरिंग फ़ेज़ में, window
पर क्लिक इवेंट को सुना जा रहा है?" ऐसा होने पर, सही इवेंट हैंडलर ट्रिगर होंगे. हमारे उदाहरण में, कुछ भी नहीं है. इसलिए, कोई भी हैंडलर ट्रिगर नहीं होगा.
इसके बाद, इवेंट document
तक पहुंचेगा और ब्राउज़र पूछेगा: "क्या कैप्चरिंग फ़ेज़ में, document
पर क्लिक इवेंट को कोई सुन रहा है?" ऐसा होने पर, सही इवेंट हैंडलर ट्रिगर हो जाएंगे.
इसके बाद, इवेंट <html>
एलिमेंट तक पहुंचेगा और ब्राउज़र पूछेगा: "क्या कैप्चरिंग फ़ेज़ में, <html>
एलिमेंट पर क्लिक करने के लिए कोई इवेंट लिसनर मौजूद है?" ऐसा होने पर, सही इवेंट हैंडलर ट्रिगर होंगे.
इसके बाद, इवेंट <body>
एलिमेंट तक प्रॉपगेट होगा. ब्राउज़र पूछेगा: "क्या कैप्चरिंग फ़ेज़ में, <body>
एलिमेंट पर क्लिक इवेंट को सुनने के लिए कोई फ़ंक्शन मौजूद है?" ऐसा होने पर, सही इवेंट हैंडलर ट्रिगर होंगे.
इसके बाद, इवेंट #A
एलिमेंट में प्रॉपगेट होगा. ब्राउज़र फिर से पूछेगा: "क्या कैप्चरिंग फ़ेज़ में #A
पर क्लिक इवेंट को कोई सुन रहा है? अगर हां, तो इवेंट हैंडलर ट्रिगर हो जाएंगे.
इसके बाद, इवेंट प्रॉपगेट होकर #B
एलिमेंट तक पहुंच जाएगा. साथ ही, वही सवाल पूछा जाएगा.
आखिर में, इवेंट अपने टारगेट तक पहुंच जाएगा और ब्राउज़र पूछेगा: "क्या कैप्चरिंग फ़ेज़ में #C
एलिमेंट पर क्लिक इवेंट को सुना जा रहा है?" इस बार जवाब है "हाँ!" जब इवेंट टारगेट पर होता है, तो इस छोटे से समय को "टारगेट फ़ेज़" कहा जाता है. इस समय, इवेंट हैंडलर ट्रिगर होगा. ब्राउज़र, console.log "#C was clicked" करेगा. इसके बाद, हम पूरा कर लेंगे, है न?
गलत! अभी हमें और भी बहुत कुछ करना है. यह प्रोसेस जारी रहती है. हालांकि, अब यह बब्लिंग फ़ेज़ में बदल जाती है.
इवेंट बबलिंग
ब्राउज़र आपसे यह पूछेगा:
"क्या बब्लिंग फ़ेज़ में, #C
पर क्लिक इवेंट को सुना जा रहा है?" यहाँ ध्यान दें.
दोनों कैप्चरिंग और बब्लिंग फ़ेज़ में, क्लिक (या किसी भी तरह के इवेंट) को सुना जा सकता है. अगर आपने दोनों फ़ेज़ में इवेंट हैंडलर को वायर किया है (उदाहरण के लिए, .addEventListener()
को दो बार कॉल करके, एक बार capture = true
के साथ और एक बार capture = false
के साथ), तो हां, दोनों इवेंट हैंडलर एक ही एलिमेंट के लिए ट्रिगर होंगे. हालांकि, यह ध्यान रखना भी ज़रूरी है कि ये अलग-अलग फ़ेज़ में ट्रिगर होते हैं. एक कैप्चरिंग फ़ेज़ में और दूसरा बब्लिंग फ़ेज़ में.
इसके बाद, इवेंट अपने पैरंट एलिमेंट #B
तक प्रॉपगेट होगा. इसे आम तौर पर "बबल" कहा जाता है, क्योंकि ऐसा लगता है कि इवेंट DOM ट्री में "ऊपर" की ओर जा रहा है. इसके बाद, ब्राउज़र यह पूछेगा: "क्या बबलिंग फ़ेज़ में #B
पर क्लिक इवेंट के लिए कोई लिसनर मौजूद है?" हमारे उदाहरण में, कुछ भी नहीं है. इसलिए, कोई भी हैंडलर ट्रिगर नहीं होगा.
इसके बाद, इवेंट #A
तक पहुंच जाएगा. साथ ही, ब्राउज़र यह सवाल पूछेगा: "क्या बब्लिंग फ़ेज़ में, #A
पर क्लिक इवेंट को सुना जा रहा है?"
इसके बाद, इवेंट <body>
पर बब्ल होगा: "क्या बब्लिंग फ़ेज़ में <body>
एलिमेंट पर क्लिक इवेंट के लिए कोई लिसनर मौजूद है?"
इसके बाद, <html>
एलिमेंट: "क्या बब्लिंग फ़ेज़ में, <html>
एलिमेंट पर क्लिक इवेंट को कोई सुन रहा है?
इसके बाद, document
: "क्या बब्लिंग फ़ेज़ में document
पर क्लिक इवेंट को सुनने के लिए कोई प्रोसेस चल रही है?"
आखिर में, window
: "क्या बब्लिंग फ़ेज़ में विंडो पर क्लिक इवेंट के लिए कोई लिसनर मौजूद है?"
वाह! यह एक लंबा सफ़र था और हमारा इवेंट शायद अब बहुत थका हुआ है, लेकिन यकीन मानिए, हर इवेंट को इसी तरह के सफ़र से गुज़रना पड़ता है! ज़्यादातर मामलों में, इस बात पर ध्यान नहीं दिया जाता, क्योंकि डेवलपर आम तौर पर सिर्फ़ एक इवेंट फ़ेज़ में दिलचस्पी रखते हैं. आम तौर पर, यह बब्लिंग फ़ेज़ होता है.
इवेंट कैप्चरिंग, इवेंट बब्लिंग, और इवेंट लॉगिंग के साथ कुछ समय बिताएं. साथ ही, हैंडलर के ट्रिगर होने पर कंसोल में कुछ नोट लॉग करें. किसी इवेंट के पाथ को देखना बहुत मददगार होता है. यहां एक ऐसा उदाहरण दिया गया है जो दोनों फ़ेज़ में हर एलिमेंट को सुनता है.
<html>
<body>
<div id="A">
<div id="B">
<div id="C"></div>
</div>
</div>
</body>
</html>
document.addEventListener(
'click',
function (e) {
console.log('click on document in capturing phase');
},
true,
);
// document.documentElement == <html>
document.documentElement.addEventListener(
'click',
function (e) {
console.log('click on <html> in capturing phase');
},
true,
);
document.body.addEventListener(
'click',
function (e) {
console.log('click on <body> in capturing phase');
},
true,
);
document.getElementById('A').addEventListener(
'click',
function (e) {
console.log('click on #A in capturing phase');
},
true,
);
document.getElementById('B').addEventListener(
'click',
function (e) {
console.log('click on #B in capturing phase');
},
true,
);
document.getElementById('C').addEventListener(
'click',
function (e) {
console.log('click on #C in capturing phase');
},
true,
);
document.addEventListener(
'click',
function (e) {
console.log('click on document in bubbling phase');
},
false,
);
// document.documentElement == <html>
document.documentElement.addEventListener(
'click',
function (e) {
console.log('click on <html> in bubbling phase');
},
false,
);
document.body.addEventListener(
'click',
function (e) {
console.log('click on <body> in bubbling phase');
},
false,
);
document.getElementById('A').addEventListener(
'click',
function (e) {
console.log('click on #A in bubbling phase');
},
false,
);
document.getElementById('B').addEventListener(
'click',
function (e) {
console.log('click on #B in bubbling phase');
},
false,
);
document.getElementById('C').addEventListener(
'click',
function (e) {
console.log('click on #C in bubbling phase');
},
false,
);
कंसोल आउटपुट इस बात पर निर्भर करेगा कि आपने किस एलिमेंट पर क्लिक किया है. अगर आपको DOM ट्री में "सबसे गहरे" एलिमेंट (#C
एलिमेंट) पर क्लिक करना है, तो आपको ये सभी इवेंट हैंडलर ट्रिगर होते हुए दिखेंगे. सीएसएस स्टाइलिंग की मदद से, यह साफ़ तौर पर पता चलता है कि कौनसे एलिमेंट का क्या काम है. यहां कंसोल आउटपुट #C
एलिमेंट (स्क्रीनशॉट के साथ) दिया गया है:
"click on document in capturing phase"
"click on <html> in capturing phase"
"click on <body> in capturing phase"
"click on #A in capturing phase"
"click on #B in capturing phase"
"click on #C in capturing phase"
"click on #C in bubbling phase"
"click on #B in bubbling phase"
"click on #A in bubbling phase"
"click on <body> in bubbling phase"
"click on <html> in bubbling phase"
"click on document in bubbling phase"
event.stopPropagation()
इवेंट कहां से शुरू होते हैं और कैप्चरिंग फ़ेज़ और बब्लिंग फ़ेज़, दोनों में DOM के ज़रिए कैसे आगे बढ़ते हैं (यानी कि कैसे फैलते हैं), यह समझने के बाद अब हम event.stopPropagation()
पर ध्यान दे सकते हैं.
stopPropagation()
तरीके को (ज़्यादातर) नेटिव DOM इवेंट पर कॉल किया जा सकता है. मैंने "ज़्यादातर" इसलिए कहा है, क्योंकि कुछ ऐसे इवेंट भी होते हैं जिन पर इस तरीके को कॉल करने से कोई फ़र्क़ नहीं पड़ता. ऐसा इसलिए होता है, क्योंकि इवेंट शुरू होने पर भी आगे नहीं बढ़ता है. focus
, blur
, load
, scroll
, और कुछ अन्य इवेंट इस कैटगरी में आते हैं. stopPropagation()
को कॉल किया जा सकता है, लेकिन इससे कोई फ़र्क़ नहीं पड़ेगा, क्योंकि ये इवेंट आगे नहीं बढ़ते हैं.
हालांकि, stopPropagation
क्या करता है?
यह टूल, जैसा इसका नाम है वैसा ही काम करता है. इसे कॉल करने पर, इवेंट उस समय से उन सभी एलिमेंट में नहीं दिखेगा जिनमें वह आम तौर पर दिखता है. यह दोनों दिशाओं (कैप्चरिंग और बब्लिंग) के लिए सही है. इसलिए, अगर आपने कैप्चरिंग फ़ेज़ में stopPropagation()
को कॉल किया है, तो इवेंट कभी भी टारगेट फ़ेज़ या बब्लिंग फ़ेज़ तक नहीं पहुंचेगा. अगर आपने इसे बब्लिंग फ़ेज़ में कॉल किया है, तो यह पहले ही कैप्चरिंग फ़ेज़ से गुज़र चुका होगा. हालांकि, इसे कॉल करने के बाद, यह "बबल अप" होना बंद हो जाएगा.
हम अपने पिछले उदाहरण वाले मार्कअप पर वापस आते हैं. आपको क्या लगता है कि अगर हम stopPropagation()
एलिमेंट पर कैप्चरिंग फ़ेज़ में stopPropagation()
को कॉल करें, तो क्या होगा?#B
इससे यह आउटपुट मिलेगा:
"click on document in capturing phase"
"click on <html> in capturing phase"
"click on <body> in capturing phase"
"click on #A in capturing phase"
"click on #B in capturing phase"
क्या बब्लिंग फ़ेज़ में #A
पर इवेंट को आगे बढ़ने से रोका जा सकता है? इससे यह आउटपुट मिलेगा:
"click on document in capturing phase"
"click on <html> in capturing phase"
"click on <body> in capturing phase"
"click on #A in capturing phase"
"click on #B in capturing phase"
"click on #C in capturing phase"
"click on #C in bubbling phase"
"click on #B in bubbling phase"
"click on #A in bubbling phase"
एक और, सिर्फ़ मज़े के लिए. अगर हम #C
के लिए, टारगेट फ़ेज़ में stopPropagation()
को कॉल करते हैं, तो क्या होता है?
याद रखें कि "टारगेट फ़ेज़" उस समयावधि को कहते हैं जब इवेंट अपने टारगेट पर होता है. इससे यह आउटपुट मिलेगा:
"click on document in capturing phase"
"click on <html> in capturing phase"
"click on <body> in capturing phase"
"click on #A in capturing phase"
"click on #B in capturing phase"
"click on #C in capturing phase"
ध्यान दें कि #C
के लिए इवेंट हैंडलर, जिसमें हम "कैप्चरिंग फ़ेज़ में #C पर क्लिक करें" लॉग करते हैं, अब भी काम करता है. हालांकि, जिसमें हम "बबलिंग फ़ेज़ में #C पर क्लिक करें" लॉग करते हैं वह काम नहीं करता. इससे आपको पूरी जानकारी मिल जाएगी. हमने stopPropagation()
को यहां से कॉल किया था. इसलिए, इवेंट का डेटा यहीं से आगे नहीं भेजा जाएगा.
हमारा सुझाव है कि आप इनमें से किसी भी लाइव डेमो को आज़माएं. सिर्फ़ #A
एलिमेंट या सिर्फ़ body
एलिमेंट पर क्लिक करके देखें. यह अनुमान लगाने की कोशिश करें कि आगे क्या होगा. इसके बाद, देखें कि आपका अनुमान सही है या नहीं. इस समय, आपको सटीक अनुमान लगाने में मदद मिल सकती है.
event.stopImmediatePropagation()
यह अजीब और कम इस्तेमाल किया जाने वाला तरीका क्या है? यह stopPropagation
से मिलता-जुलता है. हालांकि, यह तरीका सिर्फ़ तब लागू होता है, जब आपने एक एलिमेंट से एक से ज़्यादा इवेंट हैंडलर कनेक्ट किए हों. साथ ही, यह इवेंट को डिसेंडेंट (कैप्चर करना) या ऐनसेस्टर (बबलिंग) तक पहुंचने से रोकने के बजाय, सिर्फ़ एक एलिमेंट से कनेक्ट किए गए एक से ज़्यादा इवेंट हैंडलर पर लागू होता है. addEventListener()
में मल्टीकास्ट स्टाइल की इवेंटिंग काम करती है. इसलिए, किसी इवेंट हैंडलर को एक से ज़्यादा बार किसी एक एलिमेंट से जोड़ा जा सकता है. ऐसा होने पर, (ज़्यादातर ब्राउज़र में) इवेंट हैंडलर उसी क्रम में एक्ज़ीक्यूट होते हैं जिस क्रम में उन्हें सेट अप किया गया था. stopImmediatePropagation()
को कॉल करने से, बाद के किसी भी हैंडलर को ट्रिगर होने से रोका जा सकता है. नीचे दिए गए उदाहरण पर ध्यान दें:
<html>
<body>
<div id="A">I am the #A element</div>
</body>
</html>
document.getElementById('A').addEventListener(
'click',
function (e) {
console.log('When #A is clicked, I shall run first!');
},
false,
);
document.getElementById('A').addEventListener(
'click',
function (e) {
console.log('When #A is clicked, I shall run second!');
e.stopImmediatePropagation();
},
false,
);
document.getElementById('A').addEventListener(
'click',
function (e) {
console.log('When #A is clicked, I would have run third, if not for stopImmediatePropagation');
},
false,
);
ऊपर दिए गए उदाहरण से, कंसोल में यह आउटपुट मिलेगा:
"When #A is clicked, I shall run first!"
"When #A is clicked, I shall run second!"
ध्यान दें कि तीसरा इवेंट हैंडलर कभी नहीं चलता, क्योंकि दूसरा इवेंट हैंडलर e.stopImmediatePropagation()
को कॉल करता है. अगर हमने e.stopPropagation()
को कॉल किया होता, तो तीसरा हैंडलर अब भी चलता.
event.preventDefault()
अगर stopPropagation()
किसी इवेंट को "नीचे की ओर" (कैप्चर करना) या "ऊपर की ओर" (बबलिंग) जाने से रोकता है, तो preventDefault()
क्या करता है? इसकी आवाज़ भी कुछ ऐसी ही है. Does
it?
दरअसल ऐसा नहीं है. हालांकि, इन दोनों को अक्सर एक ही मान लिया जाता है, लेकिन असल में ये एक-दूसरे से अलग हैं.
जब आपको preventDefault()
दिखे, तो अपने दिमाग़ में "कार्रवाई" शब्द जोड़ें. "डिफ़ॉल्ट ऐक्शन को रोकना" के बारे में सोचें.
इसके अलावा, आपसे डिफ़ॉल्ट कार्रवाई के बारे में क्या पूछा जा सकता है? माफ़ करें, इस सवाल का जवाब साफ़ तौर पर नहीं दिया जा सकता, क्योंकि यह सवाल में दिए गए एलिमेंट और इवेंट के कॉम्बिनेशन पर निर्भर करता है. समस्या को और ज़्यादा उलझाने के लिए, कभी-कभी कोई डिफ़ॉल्ट ऐक्शन नहीं होता!
इसे समझने के लिए, आइए एक बहुत ही आसान उदाहरण से शुरुआत करें. किसी वेब पेज पर मौजूद लिंक पर क्लिक करने पर, आपको क्या दिखने की उम्मीद है? ज़ाहिर है, आपको उम्मीद होगी कि ब्राउज़र उस लिंक में दिए गए यूआरएल पर जाएगा.
इस मामले में, एलिमेंट एक ऐंकर टैग है और इवेंट एक क्लिक इवेंट है. इस कॉम्बिनेशन (<a>
+ click
) की "डिफ़ॉल्ट कार्रवाई" लिंक के एचआरईएफ़ पर नेविगेट करना है. अगर आपको ब्राउज़र को डिफ़ॉल्ट कार्रवाई करने से रोकना है, तो क्या करें? उदाहरण के लिए, मान लें कि आपको ब्राउज़र को <a>
एलिमेंट के href
एट्रिब्यूट में दिए गए यूआरएल पर जाने से रोकना है. preventDefault()
आपके लिए यह काम करेगा. इस उदाहरण से समझें:
<a id="avett" href="https://www.theavettbrothers.com/welcome">The Avett Brothers</a>
document.getElementById('avett').addEventListener(
'click',
function (e) {
e.preventDefault();
console.log('Maybe we should just play some of their music right here instead?');
},
false,
);
आम तौर पर, The Avett Brothers लेबल वाले लिंक पर क्लिक करने से, www.theavettbrothers.com
पर ब्राउज़ किया जाता है. हालांकि, इस मामले में हमने <a>
एलिमेंट के लिए, क्लिक इवेंट हैंडलर को वायर अप किया है. साथ ही, यह तय किया है कि डिफ़ॉल्ट कार्रवाई को रोका जाना चाहिए. इसलिए, जब कोई उपयोगकर्ता इस लिंक पर क्लिक करेगा, तो उसे कहीं भी रीडायरेक्ट नहीं किया जाएगा. इसके बजाय, कंसोल सिर्फ़ "क्या हमें यहां उनका कुछ संगीत चलाना चाहिए?" लॉग करेगा.
कौनसे अन्य एलिमेंट/इवेंट कॉम्बिनेशन की मदद से, डिफ़ॉल्ट कार्रवाई को रोका जा सकता है? इन सभी को एक साथ नहीं दिखाया जा सकता. इसलिए, आपको खुद ही एक्सपेरिमेंट करके देखना होगा. हालांकि, यहां कुछ के बारे में बताया गया है:
<form>
एलिमेंट + "submit" इवेंट: इस कॉम्बिनेशन के लिएpreventDefault()
, फ़ॉर्म को सबमिट होने से रोकेगा. अगर आपको पुष्टि करनी है और कोई गड़बड़ी होती है, तो यह आपके काम आ सकता है. ऐसे में, फ़ॉर्म सबमिट होने से रोकने के लिए, preventDefault को कॉल किया जा सकता है.<a>
एलिमेंट + "click" इवेंट: इस कॉम्बिनेशन के लिएpreventDefault()
, ब्राउज़र को<a>
एलिमेंट के href एट्रिब्यूट में दिए गए यूआरएल पर नेविगेट करने से रोकता है.document
+ "mousewheel" इवेंट: इस कॉम्बिनेशन के लिएpreventDefault()
, माउस के पहिए से पेज को स्क्रोल करने से रोकता है. हालांकि, कीबोर्ड से स्क्रोल करने की सुविधा अब भी काम करेगी.
↜ इसके लिए,{ passive: false }
के साथaddEventListener()
को कॉल करना ज़रूरी है.document
+ "keydown" इवेंट: इस कॉम्बिनेशन के लिएpreventDefault()
का इस्तेमाल करना खतरनाक है. इससे पेज का ज़्यादातर हिस्सा बेकार हो जाता है. साथ ही, कीबोर्ड से स्क्रोल करने, टैब करने, और कीबोर्ड को हाइलाइट करने की सुविधा काम नहीं करती.document
+ "mousedown" इवेंट: इस कॉम्बिनेशन के लिएpreventDefault()
का इस्तेमाल करने से, माउस से टेक्स्ट हाइलाइट नहीं किया जा सकेगा. साथ ही, माउस डाउन करके की जाने वाली कोई भी "डिफ़ॉल्ट" कार्रवाई नहीं की जा सकेगी.<input>
एलिमेंट + "keypress" इवेंट: इस कॉम्बिनेशन के लिएpreventDefault()
, उपयोगकर्ता के टाइप किए गए वर्णों को इनपुट एलिमेंट तक पहुंचने से रोकेगा. हालांकि, ऐसा न करें. ऐसा करने की कोई मान्य वजह नहीं होती.document
+ "contextmenu" इवेंट: इस कॉम्बिनेशन के लिएpreventDefault()
, उपयोगकर्ता के राइट क्लिक करने या देर तक दबाए रखने (या किसी अन्य तरीके से कॉन्टेक्स्ट मेन्यू दिखने पर) पर, नेटिव ब्राउज़र के कॉन्टेक्स्ट मेन्यू को दिखने से रोकता है.
यह पूरी सूची नहीं है. हालांकि, हमें उम्मीद है कि इससे आपको preventDefault()
के इस्तेमाल के बारे में अच्छी जानकारी मिल गई होगी.
कोई मज़ेदार प्रैक्टिकल जोक?
अगर दस्तावेज़ से शुरू करके, कैप्चर करने के दौरान stopPropagation()
और preventDefault()
किया जाता है, तो क्या होता है? इसके बाद, हंसी-मज़ाक शुरू हो जाता है! नीचे दिया गया कोड स्निपेट, किसी भी वेब पेज को पूरी तरह से बेकार बना देगा:
function preventEverything(e) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
}
document.addEventListener('click', preventEverything, true);
document.addEventListener('keydown', preventEverything, true);
document.addEventListener('mousedown', preventEverything, true);
document.addEventListener('contextmenu', preventEverything, true);
document.addEventListener('mousewheel', preventEverything, { capture: true, passive: false });
हमें नहीं पता कि आपको ऐसा क्यों करना चाहिए (शायद किसी के साथ मज़ाक करने के लिए), लेकिन यह समझना ज़रूरी है कि यहाँ क्या हो रहा है और यह स्थिति क्यों पैदा हो रही है.
सभी इवेंट window
से शुरू होते हैं. इसलिए, इस स्निपेट में हम click
, keydown
, mousedown
, contextmenu
, और mousewheel
इवेंट को किसी भी ऐसे एलिमेंट तक पहुंचने से रोक रहे हैं जो उन्हें सुन रहा हो. हम stopImmediatePropagation
को भी कॉल करते हैं, ताकि इस दस्तावेज़ के बाद वायर किए गए किसी भी हैंडलर को भी रोका जा सके.
ध्यान दें कि stopPropagation()
और stopImmediatePropagation()
की वजह से, पेज काम का नहीं रहता. हालांकि, ऐसा हमेशा नहीं होता. ये कुकी, इवेंट को उस जगह पर जाने से रोकती हैं जहां वे आम तौर पर जाते हैं.
हालांकि, हम preventDefault()
को भी कॉल करते हैं. आपको याद होगा कि इससे डिफ़ॉल्ट कार्रवाई नहीं होती है. इसलिए, डिफ़ॉल्ट कार्रवाइयों (जैसे कि माउस व्हील से स्क्रोल करना, कीबोर्ड से स्क्रोल करना या हाइलाइट करना या टैब करना, लिंक पर क्लिक करना, कॉन्टेक्स्ट मेन्यू दिखाना वगैरह) को रोका जाता है. इस वजह से, पेज किसी काम का नहीं रह जाता.
Acknowledgements
Unsplash पर टॉम विल्सन की हीरो इमेज.