preventDefault
এবং stopPropagation
: কখন ব্যবহার করতে হবে এবং প্রতিটি পদ্ধতি ঠিক কী করে।
Event.stopPropagation() এবং Event.preventDefault()
জাভাস্ক্রিপ্ট ইভেন্ট হ্যান্ডলিং প্রায়ই সোজা। একটি সাধারণ (তুলনামূলকভাবে সমতল) এইচটিএমএল কাঠামোর সাথে কাজ করার সময় এটি বিশেষভাবে সত্য। ঘটনাগুলি যখন উপাদানগুলির একটি শ্রেণিবিন্যাসের মাধ্যমে ভ্রমণ (বা প্রচার) করে তখন জিনিসগুলি আরও কিছুটা জড়িত হয়। এটি সাধারণত হয় যখন ডেভেলপাররা তাদের সম্মুখীন হওয়া সমস্যার সমাধান করতে stopPropagation()
এবং/অথবা preventDefault()
এর জন্য পৌঁছায়। আপনি যদি কখনও নিজের মনে করে থাকেন "আমি শুধু preventDefault()
চেষ্টা করব এবং যদি এটি কাজ না করে তবে আমি stopPropagation()
চেষ্টা করব এবং যদি এটি কাজ না করে, আমি উভয়ই চেষ্টা করব," তাহলে এই নিবন্ধটি আপনার জন্য! প্রতিটি পদ্ধতি ঠিক কী করে, কখন কোনটি ব্যবহার করতে হবে তা আমি ব্যাখ্যা করব এবং অন্বেষণ করার জন্য আপনাকে বিভিন্ন কাজের উদাহরণ প্রদান করব। আমার লক্ষ্য আপনার বিভ্রান্তি একবার এবং সব জন্য শেষ করা.
যদিও আমরা খুব গভীরভাবে ডুব দেওয়ার আগে, জাভাস্ক্রিপ্টে সম্ভাব্য দুটি ধরণের ইভেন্ট পরিচালনার উপর সংক্ষিপ্তভাবে স্পর্শ করা গুরুত্বপূর্ণ (সমস্ত আধুনিক ব্রাউজারে যা হল—সংস্করণ 9 এর আগে ইন্টারনেট এক্সপ্লোরার ইভেন্ট ক্যাপচারিংকে মোটেও সমর্থন করে না)।
ইভেন্টিং শৈলী (ক্যাপচার এবং বুদবুদ)
সমস্ত আধুনিক ব্রাউজার ইভেন্ট ক্যাপচারিং সমর্থন করে, কিন্তু এটি খুব কমই ডেভেলপারদের দ্বারা ব্যবহৃত হয়। মজার বিষয় হল, এটিই ইভেন্টের একমাত্র রূপ যা নেটস্কেপ মূলত সমর্থন করেছিল। নেটস্কেপের সবচেয়ে বড় প্রতিদ্বন্দ্বী, মাইক্রোসফ্ট ইন্টারনেট এক্সপ্লোরার, ইভেন্ট ক্যাপচারিংকে মোটেও সমর্থন করেনি, বরং, শুধুমাত্র ইভেন্ট বুদবুদ নামক ইভেন্টের আরেকটি শৈলীকে সমর্থন করেছিল। যখন W3C গঠিত হয়, তখন তারা ইভেন্টের উভয় শৈলীতে যোগ্যতা খুঁজে পায় এবং ঘোষণা করে যে ব্রাউজারগুলির উভয়কেই সমর্থন করা উচিত, addEventListener
পদ্ধতিতে তৃতীয় প্যারামিটারের মাধ্যমে। মূলত, সেই প্যারামিটারটি ছিল একটি বুলিয়ান, কিন্তু সমস্ত আধুনিক ব্রাউজার তৃতীয় প্যারামিটার হিসাবে একটি options
অবজেক্টকে সমর্থন করে, যেটি আপনি ইভেন্ট ক্যাপচারিং ব্যবহার করতে চাইলে (অন্যান্য জিনিসগুলির মধ্যে) নির্দিষ্ট করতে ব্যবহার করতে পারেন:
someElement.addEventListener('click', myClickHandler, { capture: true | false });
নোট করুন যে options
অবজেক্টটি ঐচ্ছিক, যেমন এটির capture
সম্পত্তি। যদি উভয়টি বাদ দেওয়া হয়, capture
জন্য ডিফল্ট মান false
, যার অর্থ ইভেন্ট বুদবুদ ব্যবহার করা হবে।
ইভেন্ট ক্যাপচারিং
আপনার ইভেন্ট হ্যান্ডলার যদি "ক্যাপচারিং পর্বে শুনছেন" তাহলে এর অর্থ কী? এটি বোঝার জন্য, আমাদের জানতে হবে কিভাবে ঘটনার উৎপত্তি হয় এবং কিভাবে তারা ভ্রমণ করে। নিম্নলিখিতগুলি সমস্ত ইভেন্টের ক্ষেত্রে সত্য, এমনকি যদি আপনি, বিকাশকারী হিসাবে, এটিকে লাভবান না করেন, এটি সম্পর্কে যত্ন না করেন বা এটি সম্পর্কে ভাবেন।
সমস্ত ইভেন্ট উইন্ডোতে শুরু হয় এবং প্রথমে ক্যাপচারিং পর্বের মধ্য দিয়ে যায়। এর মানে হল যখন একটি ইভেন্ট পাঠানো হয়, এটি উইন্ডোটি শুরু করে এবং প্রথমে তার লক্ষ্য উপাদানের দিকে "নীচে" ভ্রমণ করে। আপনি শুধুমাত্র বুদবুদ পর্যায়ে শুনলেও এটি ঘটে। নিম্নলিখিত উদাহরণ মার্কআপ এবং জাভাস্ক্রিপ্ট বিবেচনা করুন:
<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 ক্লিক করা হয়েছিল" এবং তারপরে আমরা শেষ করেছি, তাই না? ভুল! আমরা মোটেই শেষ করিনি। প্রক্রিয়া চলতে থাকে, কিন্তু এখন এটি বুদবুদ পর্যায়ে পরিবর্তিত হয়।
ইভেন্ট বুদবুদ
ব্রাউজার জিজ্ঞাসা করবে:
"বাবলিং পর্বে কি #C
তে ক্লিক ইভেন্টের জন্য কিছু শোনা যাচ্ছে?" এখানে ঘনিষ্ঠ মনোযোগ দিন. ক্যাপচারিং এবং বুদবুদ উভয় পর্যায়েই ক্লিক (বা যেকোনো ইভেন্টের ধরন) শোনা সম্পূর্ণভাবে সম্ভব। এবং যদি আপনি উভয় পর্বে ইভেন্ট হ্যান্ডলারকে ওয়্যার আপ করে থাকেন (যেমন .addEventListener()
কে দুবার কল করে, একবার capture = true
এবং একবার capture = false
দিয়ে), তাহলে হ্যাঁ, উভয় ইভেন্ট হ্যান্ডলার একই উপাদানের জন্য একেবারে ফায়ার করবে। কিন্তু এটাও লক্ষ করা গুরুত্বপূর্ণ যে তারা বিভিন্ন পর্যায়ে ফায়ার করে (একটি ক্যাপচারিং পর্যায়ে এবং একটি বুদবুদ পর্যায়ে)।
এর পরে, ইভেন্টটি প্রচার করবে (আরো সাধারণভাবে "বুদবুদ" হিসাবে বলা হয় কারণ এটি মনে হয় যেন ইভেন্টটি DOM ট্রি থেকে "উপরে" ভ্রমণ করছে) তার মূল উপাদান, #B
, এবং ব্রাউজার জিজ্ঞাসা করবে: "বুদবুদ পর্বে #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"
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। #C
উপাদানে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
event.stopPropagation()
ইভেন্টের উৎপত্তি কোথায় এবং কিভাবে তারা DOM-এর মাধ্যমে ক্যাপচারিং ফেজ এবং বাবলিং ফেজ উভয়ের মাধ্যমে ভ্রমণ করে (অর্থাৎ প্রচার করে) তা বোঝার সাথে, আমরা এখন event.stopPropagation()
এর দিকে আমাদের মনোযোগ দিতে পারি।
stopPropagation()
পদ্ধতিটি (বেশিরভাগ) নেটিভ DOM ইভেন্টে কল করা যেতে পারে। আমি বলি "অধিকাংশ" কারণ এমন কয়েকটি আছে যার উপর এই পদ্ধতিতে কল করা কিছুই করবে না (কারণ ইভেন্টটি শুরুতে প্রচারিত হয় না)। focus
, blur
, load
, scroll
, এবং আরও কয়েকটির মতো ইভেন্টগুলি এই বিভাগে পড়ে৷ আপনি stopPropagation()
কল করতে পারেন তবে আকর্ষণীয় কিছুই ঘটবে না, যেহেতু এই ঘটনাগুলি প্রচার করে না।
কিন্তু stopPropagation
কি করে?
এটা করে, মোটামুটি, এটা কি বলে। আপনি যখন এটিকে কল করেন, তখন থেকে ইভেন্টটি যে কোনো উপাদানে প্রচার করা বন্ধ করে দেবে যা অন্যথায় ভ্রমণ করবে। এটি উভয় দিকের ক্ষেত্রেই সত্য (ক্যাপচারিং এবং বাবলিং)। সুতরাং আপনি যদি ক্যাপচারিং পর্বে যেকোন জায়গায় stopPropagation()
কল করেন, ইভেন্টটি কখনই টার্গেট ফেজ বা বুদবুদ পর্যায়ে পৌঁছাবে না। আপনি যদি এটিকে বুদবুদ পর্যায়ে কল করেন তবে এটি ইতিমধ্যেই ক্যাপচারিং পর্যায়ে চলে গেছে, তবে আপনি যে বিন্দুতে এটিকে কল করেছেন সেখান থেকে এটি "বাবলিং আপ" বন্ধ করবে।
আমাদের একই উদাহরণ মার্কআপে ফিরে আসা, আপনি কি মনে করেন, যদি আমরা #B
উপাদানে ক্যাপচারিং পর্যায়ে 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"
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। লাইভ ডেমোতে #C
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
বুদবুদ পর্যায়ে #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
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
আর একটা, শুধু মজা করার জন্য। যদি আমরা #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()
কে বলেছি, তাই সেই বিন্দুতে ইভেন্টের প্রচার বন্ধ হয়ে যাবে।
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। লাইভ ডেমোতে #C
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
এই লাইভ ডেমোগুলির যে কোনওটিতে, আমি আপনাকে চারপাশে খেলতে উত্সাহিত করি। শুধুমাত্র #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()
করে? এটা অনুরূপ কিছু করার মত শোনাচ্ছে. এটা করে?
আসলেই না। যদিও দুটি প্রায়শই বিভ্রান্ত হয়, তাদের আসলে একে অপরের সাথে খুব বেশি কিছু করার নেই। যখন আপনি আপনার মাথায় preventDefault()
দেখতে পান, তখন "ক্রিয়া" শব্দটি যোগ করুন। মনে করুন "ডিফল্ট অ্যাকশন প্রতিরোধ করুন।"
এবং আপনি জিজ্ঞাসা করতে পারেন ডিফল্ট কর্ম কি? দুর্ভাগ্যবশত, এর উত্তরটি পুরোপুরি পরিষ্কার নয় কারণ এটি প্রশ্নে উপাদান + ইভেন্ট সংমিশ্রণের উপর অত্যন্ত নির্ভরশীল। এবং বিষয়গুলিকে আরও বিভ্রান্তিকর করতে, কখনও কখনও কোনও ডিফল্ট অ্যাকশন নেই!
বোঝার জন্য একটি খুব সহজ উদাহরণ দিয়ে শুরু করা যাক। আপনি যখন একটি ওয়েব পৃষ্ঠায় একটি লিঙ্ক ক্লিক করেন তখন আপনি কি ঘটতে আশা করেন? স্পষ্টতই, আপনি আশা করেন যে ব্রাউজারটি সেই লিঙ্ক দ্বারা নির্দিষ্ট URL-এ নেভিগেট করবে। এই ক্ষেত্রে, উপাদানটি একটি অ্যাঙ্কর ট্যাগ এবং ইভেন্টটি একটি ক্লিক ইভেন্ট। সেই সংমিশ্রণে ( <a>
+ click
) লিঙ্কের href-এ নেভিগেট করার একটি "ডিফল্ট অ্যাকশন" রয়েছে। আপনি যদি ব্রাউজারটিকে সেই ডিফল্ট অ্যাকশনটি সম্পাদন করতে বাধা দিতে চান? অর্থাৎ, ধরুন আপনি <a>
এলিমেন্টের href
অ্যাট্রিবিউট দ্বারা নির্দিষ্ট URL-এ নেভিগেট করা থেকে ব্রাউজারকে আটকাতে চান? এটিই 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>
উপাদান + "জমা দিন" ইভেন্ট: এই সংমিশ্রণের জন্যpreventDefault()
একটি ফর্ম জমা হতে বাধা দেবে। যদি আপনি বৈধতা সম্পাদন করতে চান এবং কিছু ব্যর্থ হলে, আপনি শর্তসাপেক্ষে প্রিভেনড ডিফল্ট কল করতে পারেন যাতে ফর্ম জমা দেওয়া থেকে বিরত থাকে৷<a>
উপাদান + "ক্লিক" ইভেন্ট:preventDefault()
এই সংমিশ্রণের জন্য ব্রাউজারকে<a>
উপাদানের href বৈশিষ্ট্যে নির্দিষ্ট URL-এ নেভিগেট করতে বাধা দেয়।document
+ "মাউসহুইল" ইভেন্ট:preventDefault()
এই সংমিশ্রণের জন্য মাউসহুইল দিয়ে পৃষ্ঠা স্ক্রলিং প্রতিরোধ করে (যদিও কীবোর্ড দিয়ে স্ক্রোল করা এখনও কাজ করবে)।
↜ এর জন্যaddEventListener()
{ passive: false }
দিয়ে কল করতে হবে ।document
+ "কীডাউন" ইভেন্ট:preventDefault()
এই সংমিশ্রণের জন্য প্রাণঘাতী। এটি কীবোর্ড স্ক্রোলিং, ট্যাবিং এবং কীবোর্ড হাইলাইটিং প্রতিরোধ করে পৃষ্ঠাটিকে অনেকাংশে অকেজো করে দেয়।document
+ "মাউসডাউন" ইভেন্ট: এই সংমিশ্রণের জন্যpreventDefault()
মাউসের সাহায্যে টেক্সট হাইলাইট করা এবং অন্য যেকোন "ডিফল্ট" অ্যাকশনকে আটকাবে যা মাউস ডাউন দিয়ে আহ্বান করবে।<input>
element + "keypress" ইভেন্ট:preventDefault()
এই সংমিশ্রণের জন্য ব্যবহারকারীর দ্বারা টাইপ করা অক্ষরগুলিকে ইনপুট উপাদানে পৌঁছাতে বাধা দেবে (তবে এটি করবেন না; কদাচিৎ, যদি কখনও, এর জন্য একটি বৈধ কারণ থাকে)।document
+ "প্রসঙ্গমেনু" ইভেন্ট: এই সংমিশ্রণের জন্য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()
কেও বলি, যা আপনি মনে রাখবেন ডিফল্ট ক্রিয়াকে বাধা দেয়। তাই যেকোনো ডিফল্ট অ্যাকশন (যেমন মাউসহুইল স্ক্রোল, কীবোর্ড স্ক্রোল বা হাইলাইট বা ট্যাবিং, লিঙ্ক ক্লিক করা, প্রসঙ্গ মেনু প্রদর্শন ইত্যাদি) সবই প্রতিরোধ করা হয়, এইভাবে পৃষ্ঠাটিকে মোটামুটি অকেজো অবস্থায় ফেলে দেওয়া হয়।
লাইভ ডেমো
এই নিবন্ধ থেকে সমস্ত উদাহরণ আবার এক জায়গায় অন্বেষণ করতে, নীচে এমবেডেড ডেমো দেখুন।
স্বীকৃতি
আনস্প্ল্যাশে টম উইলসনের হিরো ছবি।
, preventDefault
এবং stopPropagation
: কখন ব্যবহার করতে হবে এবং প্রতিটি পদ্ধতি ঠিক কী করে।
Event.stopPropagation() এবং Event.preventDefault()
জাভাস্ক্রিপ্ট ইভেন্ট হ্যান্ডলিং প্রায়ই সোজা। একটি সাধারণ (তুলনামূলকভাবে সমতল) এইচটিএমএল কাঠামোর সাথে কাজ করার সময় এটি বিশেষভাবে সত্য। ঘটনাগুলি যখন উপাদানগুলির একটি শ্রেণিবিন্যাসের মাধ্যমে ভ্রমণ (বা প্রচার) করে তখন জিনিসগুলি আরও কিছুটা জড়িত হয়। এটি সাধারণত হয় যখন ডেভেলপাররা তাদের সম্মুখীন হওয়া সমস্যার সমাধান করতে stopPropagation()
এবং/অথবা preventDefault()
এর জন্য পৌঁছায়। আপনি যদি কখনও নিজের মনে করে থাকেন "আমি শুধু preventDefault()
চেষ্টা করব এবং যদি এটি কাজ না করে তবে আমি stopPropagation()
চেষ্টা করব এবং যদি এটি কাজ না করে, আমি উভয়ই চেষ্টা করব," তাহলে এই নিবন্ধটি আপনার জন্য! প্রতিটি পদ্ধতি ঠিক কী করে, কখন কোনটি ব্যবহার করতে হবে তা আমি ব্যাখ্যা করব এবং অন্বেষণ করার জন্য আপনাকে বিভিন্ন কাজের উদাহরণ প্রদান করব। আমার লক্ষ্য আপনার বিভ্রান্তি একবার এবং সব জন্য শেষ করা.
যদিও আমরা খুব গভীরভাবে ডুব দেওয়ার আগে, জাভাস্ক্রিপ্টে সম্ভাব্য দুটি ধরণের ইভেন্ট পরিচালনার উপর সংক্ষিপ্তভাবে স্পর্শ করা গুরুত্বপূর্ণ (সমস্ত আধুনিক ব্রাউজারে যা হল—সংস্করণ 9 এর আগে ইন্টারনেট এক্সপ্লোরার ইভেন্ট ক্যাপচারিংকে মোটেও সমর্থন করে না)।
ইভেন্টিং শৈলী (ক্যাপচার এবং বুদবুদ)
সমস্ত আধুনিক ব্রাউজার ইভেন্ট ক্যাপচারিং সমর্থন করে, কিন্তু এটি খুব কমই ডেভেলপারদের দ্বারা ব্যবহৃত হয়। মজার বিষয় হল, এটিই ইভেন্টের একমাত্র রূপ যা নেটস্কেপ মূলত সমর্থন করেছিল। নেটস্কেপের সবচেয়ে বড় প্রতিদ্বন্দ্বী, মাইক্রোসফ্ট ইন্টারনেট এক্সপ্লোরার, ইভেন্ট ক্যাপচারিংকে মোটেও সমর্থন করেনি, বরং, শুধুমাত্র ইভেন্ট বুদবুদ নামক ইভেন্টের আরেকটি শৈলীকে সমর্থন করেছিল। যখন W3C গঠিত হয়, তখন তারা ইভেন্টের উভয় শৈলীতে যোগ্যতা খুঁজে পায় এবং ঘোষণা করে যে ব্রাউজারগুলির উভয়কেই সমর্থন করা উচিত, addEventListener
পদ্ধতিতে তৃতীয় প্যারামিটারের মাধ্যমে। মূলত, সেই প্যারামিটারটি ছিল একটি বুলিয়ান, কিন্তু সমস্ত আধুনিক ব্রাউজার তৃতীয় প্যারামিটার হিসাবে একটি options
অবজেক্টকে সমর্থন করে, যেটি আপনি ইভেন্ট ক্যাপচারিং ব্যবহার করতে চাইলে (অন্যান্য জিনিসগুলির মধ্যে) নির্দিষ্ট করতে ব্যবহার করতে পারেন:
someElement.addEventListener('click', myClickHandler, { capture: true | false });
নোট করুন যে options
অবজেক্টটি ঐচ্ছিক, যেমন এটির capture
সম্পত্তি। যদি উভয়টি বাদ দেওয়া হয়, capture
জন্য ডিফল্ট মান false
, যার অর্থ ইভেন্ট বুদবুদ ব্যবহার করা হবে।
ইভেন্ট ক্যাপচারিং
আপনার ইভেন্ট হ্যান্ডলার যদি "ক্যাপচারিং পর্বে শুনছেন" তাহলে এর অর্থ কী? এটি বোঝার জন্য, আমাদের জানতে হবে কিভাবে ঘটনার উৎপত্তি হয় এবং কিভাবে তারা ভ্রমণ করে। নিম্নলিখিতগুলি সমস্ত ইভেন্টের ক্ষেত্রে সত্য, এমনকি যদি আপনি, বিকাশকারী হিসাবে, এটিকে লাভবান না করেন, এটি সম্পর্কে যত্ন না করেন বা এটি সম্পর্কে ভাবেন।
সমস্ত ইভেন্ট উইন্ডোতে শুরু হয় এবং প্রথমে ক্যাপচারিং পর্বের মধ্য দিয়ে যায়। এর মানে হল যখন একটি ইভেন্ট পাঠানো হয়, এটি উইন্ডোটি শুরু করে এবং প্রথমে তার লক্ষ্য উপাদানের দিকে "নীচে" ভ্রমণ করে। আপনি শুধুমাত্র বুদবুদ পর্যায়ে শুনলেও এটি ঘটে। নিম্নলিখিত উদাহরণ মার্কআপ এবং জাভাস্ক্রিপ্ট বিবেচনা করুন:
<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 ক্লিক করা হয়েছিল" এবং তারপরে আমরা শেষ করেছি, তাই না? ভুল! আমরা মোটেই শেষ করিনি। প্রক্রিয়া চলতে থাকে, কিন্তু এখন এটি বুদবুদ পর্যায়ে পরিবর্তিত হয়।
ইভেন্ট বুদবুদ
ব্রাউজার জিজ্ঞাসা করবে:
"বাবলিং পর্বে কি #C
তে ক্লিক ইভেন্টের জন্য কিছু শোনা যাচ্ছে?" এখানে ঘনিষ্ঠ মনোযোগ দিন. ক্যাপচারিং এবং বুদবুদ উভয় পর্যায়েই ক্লিক (বা যেকোনো ইভেন্টের ধরন) শোনা সম্পূর্ণভাবে সম্ভব। এবং যদি আপনি উভয় পর্বে ইভেন্ট হ্যান্ডলারকে ওয়্যার আপ করে থাকেন (যেমন .addEventListener()
কে দুবার কল করে, একবার capture = true
এবং একবার capture = false
দিয়ে), তাহলে হ্যাঁ, উভয় ইভেন্ট হ্যান্ডলার একই উপাদানের জন্য একেবারে ফায়ার করবে। কিন্তু এটাও লক্ষ করা গুরুত্বপূর্ণ যে তারা বিভিন্ন পর্যায়ে ফায়ার করে (একটি ক্যাপচারিং পর্যায়ে এবং একটি বুদবুদ পর্যায়ে)।
এর পরে, ইভেন্টটি প্রচার করবে (আরো সাধারণভাবে "বুদবুদ" হিসাবে বলা হয় কারণ এটি মনে হয় যেন ইভেন্টটি DOM ট্রি থেকে "উপরে" ভ্রমণ করছে) তার মূল উপাদান, #B
, এবং ব্রাউজার জিজ্ঞাসা করবে: "বুদবুদ পর্বে #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"
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। #C
উপাদানে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
event.stopPropagation()
ইভেন্টের উৎপত্তি কোথায় এবং কিভাবে তারা DOM-এর মাধ্যমে ক্যাপচারিং ফেজ এবং বাবলিং ফেজ উভয়ের মাধ্যমে ভ্রমণ করে (অর্থাৎ প্রচার করে) তা বোঝার সাথে, আমরা এখন event.stopPropagation()
এর দিকে আমাদের মনোযোগ দিতে পারি।
stopPropagation()
পদ্ধতিটি (বেশিরভাগ) নেটিভ DOM ইভেন্টে কল করা যেতে পারে। আমি বলি "অধিকাংশ" কারণ এমন কয়েকটি আছে যার উপর এই পদ্ধতিতে কল করা কিছুই করবে না (কারণ ইভেন্টটি শুরুতে প্রচারিত হয় না)। focus
, blur
, load
, scroll
, এবং আরও কয়েকটির মতো ইভেন্টগুলি এই বিভাগে পড়ে৷ আপনি stopPropagation()
কল করতে পারেন তবে আকর্ষণীয় কিছুই ঘটবে না, যেহেতু এই ঘটনাগুলি প্রচার করে না।
কিন্তু stopPropagation
কি করে?
এটা করে, মোটামুটি, এটা কি বলে। আপনি যখন এটিকে কল করেন, তখন থেকে ইভেন্টটি যে কোনো উপাদানে প্রচার করা বন্ধ করে দেবে যা অন্যথায় ভ্রমণ করবে। এটি উভয় দিকের ক্ষেত্রেই সত্য (ক্যাপচারিং এবং বাবলিং)। সুতরাং আপনি যদি ক্যাপচারিং পর্বে যেকোন জায়গায় stopPropagation()
কল করেন, ইভেন্টটি কখনই টার্গেট ফেজ বা বুদবুদ পর্যায়ে পৌঁছাবে না। আপনি যদি এটিকে বুদবুদ পর্যায়ে কল করেন তবে এটি ইতিমধ্যেই ক্যাপচারিং পর্যায়ে চলে গেছে, তবে আপনি যে বিন্দুতে এটিকে কল করেছেন সেখান থেকে এটি "বাবলিং আপ" বন্ধ করবে।
আমাদের একই উদাহরণ মার্কআপে ফিরে আসা, আপনি কি মনে করেন, যদি আমরা #B
উপাদানে ক্যাপচারিং পর্যায়ে 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"
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। লাইভ ডেমোতে #C
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
বুদবুদ পর্যায়ে #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
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
আর একটা, শুধু মজা করার জন্য। যদি আমরা #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()
কে বলেছি, তাই সেই বিন্দুতে ইভেন্টের প্রচার বন্ধ হয়ে যাবে।
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। লাইভ ডেমোতে #C
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
এই লাইভ ডেমোগুলির যে কোনওটিতে, আমি আপনাকে চারপাশে খেলতে উত্সাহিত করি। শুধুমাত্র #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()
করে? এটা অনুরূপ কিছু করার মত শোনাচ্ছে. এটা করে?
আসলেই না। যদিও দুটি প্রায়শই বিভ্রান্ত হয়, তাদের আসলে একে অপরের সাথে খুব বেশি কিছু করার নেই। যখন আপনি আপনার মাথায় preventDefault()
দেখতে পান, তখন "ক্রিয়া" শব্দটি যোগ করুন। মনে করুন "ডিফল্ট অ্যাকশন প্রতিরোধ করুন।"
এবং আপনি জিজ্ঞাসা করতে পারেন ডিফল্ট কর্ম কি? দুর্ভাগ্যবশত, এর উত্তরটি পুরোপুরি পরিষ্কার নয় কারণ এটি প্রশ্নে উপাদান + ইভেন্ট সংমিশ্রণের উপর অত্যন্ত নির্ভরশীল। এবং বিষয়গুলিকে আরও বিভ্রান্তিকর করতে, কখনও কখনও কোনও ডিফল্ট অ্যাকশন নেই!
বোঝার জন্য একটি খুব সহজ উদাহরণ দিয়ে শুরু করা যাক। আপনি যখন একটি ওয়েব পৃষ্ঠায় একটি লিঙ্ক ক্লিক করেন তখন আপনি কি ঘটতে আশা করেন? স্পষ্টতই, আপনি আশা করেন যে ব্রাউজারটি সেই লিঙ্ক দ্বারা নির্দিষ্ট URL-এ নেভিগেট করবে। এই ক্ষেত্রে, উপাদানটি একটি অ্যাঙ্কর ট্যাগ এবং ইভেন্টটি একটি ক্লিক ইভেন্ট। সেই সংমিশ্রণে ( <a>
+ click
) লিঙ্কের href-এ নেভিগেট করার একটি "ডিফল্ট অ্যাকশন" রয়েছে। আপনি যদি ব্রাউজারটিকে সেই ডিফল্ট অ্যাকশনটি সম্পাদন করতে বাধা দিতে চান? অর্থাৎ, ধরুন আপনি <a>
এলিমেন্টের href
অ্যাট্রিবিউট দ্বারা নির্দিষ্ট URL-এ নেভিগেট করা থেকে ব্রাউজারকে আটকাতে চান? এটিই 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>
উপাদান + "জমা দিন" ইভেন্ট: এই সংমিশ্রণের জন্যpreventDefault()
একটি ফর্ম জমা হতে বাধা দেবে। যদি আপনি বৈধতা সম্পাদন করতে চান এবং কিছু ব্যর্থ হলে, আপনি শর্তসাপেক্ষে প্রিভেনড ডিফল্ট কল করতে পারেন যাতে ফর্ম জমা দেওয়া থেকে বিরত থাকে৷<a>
উপাদান + "ক্লিক" ইভেন্ট:preventDefault()
এই সংমিশ্রণের জন্য ব্রাউজারকে<a>
উপাদানের href বৈশিষ্ট্যে নির্দিষ্ট URL-এ নেভিগেট করতে বাধা দেয়।document
+ "মাউসওহিল" ইভেন্ট: এই সংমিশ্রণের জন্যpreventDefault()
মাউসহিলের সাথে পৃষ্ঠা স্ক্রোলিংকে বাধা দেয় (কীবোর্ডের সাথে স্ক্রোলিং এখনও কার্যকর হবে)।
↜ এর জন্য{ passive: false }
সহaddEventListener()
কল করা দরকার }document
+ "কীডাউন" ইভেন্ট: এই সংমিশ্রণের জন্যpreventDefault()
প্রাণঘাতী। এটি পৃষ্ঠাটিকে মূলত অকেজো করে তোলে, কীবোর্ড স্ক্রোলিং, ট্যাবিং এবং কীবোর্ড হাইলাইটিং প্রতিরোধ করে।document
+ "মাউসডাউন" ইভেন্ট: এই সংমিশ্রণের জন্যpreventDefault()
মাউস এবং অন্য কোনও "ডিফল্ট" ক্রিয়া সহ পাঠ্য হাইলাইট করা রোধ করবে যা একজন মাউসকে নীচে নামিয়ে দেবে।<input>
এলিমেন্ট + "কীপ্রেস" ইভেন্ট: এই সংমিশ্রণের জন্যpreventDefault()
ব্যবহারকারী দ্বারা টাইপ করা অক্ষরগুলি ইনপুট উপাদানটিতে পৌঁছাতে বাধা দেবে (তবে এটি করবেন না; এর জন্য কোনও বৈধ কারণ যদি কখনও হয় তবে খুব কমই থাকে)।document
+ "কনটেক্সটম্যানু" ইভেন্ট: এই সংমিশ্রণের জন্য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()
কেও কল করি, যা আপনি স্মরণ করবেন ডিফল্ট ক্রিয়াটি প্রতিরোধ করে। সুতরাং যে কোনও ডিফল্ট ক্রিয়া (যেমন মাউসওয়েল স্ক্রোল, কীবোর্ড স্ক্রোল বা হাইলাইট বা ট্যাব্বিং, লিঙ্ক ক্লিক, প্রসঙ্গ মেনু প্রদর্শন ইত্যাদি) সমস্ত প্রতিরোধ করা হয়, এইভাবে পৃষ্ঠাটি মোটামুটি অকেজো অবস্থায় রেখে যায়।
লাইভ ডেমো
এই নিবন্ধটি থেকে আবার এক জায়গায় অন্বেষণ করতে, নীচে এম্বেড থাকা ডেমোটি দেখুন।
স্বীকৃতি
টম উইলসনের হিরো ইমেজটি আনস্প্ল্যাশে ।
, preventDefault
এবং stopPropagation
: কখন এবং প্রতিটি পদ্ধতি ঠিক কী করে তা ব্যবহার করবেন।
ইভেন্ট.স্টপপ্রোপ্যাগেশন () এবং ইভেন্ট.প্রভেন্টডেফাল্ট ()
জাভাস্ক্রিপ্ট ইভেন্ট হ্যান্ডলিং প্রায়শই সোজা। একটি সাধারণ (তুলনামূলকভাবে সমতল) এইচটিএমএল কাঠামোর সাথে কাজ করার সময় এটি বিশেষত সত্য। বিষয়গুলি কিছুটা আরও জড়িত হয়ে যায় যদিও ইভেন্টগুলি যখন উপাদানগুলির একটি শ্রেণিবিন্যাসের মাধ্যমে ভ্রমণ করে (বা প্রচার করছে)। এটি সাধারণত হয় যখন বিকাশকারীরা stopPropagation()
এবং/অথবা preventDefault()
এর জন্য তারা যে সমস্যাগুলি অনুভব করছেন তা সমাধান করার জন্য পৌঁছে যায়। যদি আপনি নিজেকে কখনও ভাবেন "আমি কেবল preventDefault()
চেষ্টা করে দেখি এবং যদি এটি কাজ না করে তবে আমি stopPropagation()
চেষ্টা করব এবং যদি এটি কাজ না করে তবে আমি উভয়ই চেষ্টা করব," তবে এই নিবন্ধটি আপনার জন্য! আমি প্রতিটি পদ্ধতি ঠিক কী করে তা ব্যাখ্যা করব, কখন কোনটি ব্যবহার করব এবং আপনাকে অন্বেষণ করার জন্য আপনাকে বিভিন্ন কাজের উদাহরণ সরবরাহ করব। আমার লক্ষ্য হ'ল একবার এবং সকলের জন্য আপনার বিভ্রান্তি শেষ করা।
যদিও আমরা খুব গভীরভাবে ডুব দেওয়ার আগে, জাভাস্ক্রিপ্টে দুটি ধরণের ইভেন্ট হ্যান্ডলিং সম্ভব (সমস্ত আধুনিক ব্রাউজারগুলিতে - সংস্করণ 9 এর পূর্বে ইন্টারনেট এক্সপ্লোরার ইভেন্টটি মোটেও সমর্থন করেনি) এ সংক্ষেপে স্পর্শ করা গুরুত্বপূর্ণ।
ইভেন্ট স্টাইল (ক্যাপচারিং এবং বুদবুদ)
সমস্ত আধুনিক ব্রাউজার ইভেন্ট ক্যাপচারকে সমর্থন করে তবে এটি খুব কমই বিকাশকারীরা ব্যবহার করে। মজার বিষয় হল, এটি ইভেন্টের একমাত্র রূপ যা নেটস্কেপ মূলত সমর্থিত। নেটস্কেপের বৃহত্তম প্রতিদ্বন্দ্বী, মাইক্রোসফ্ট ইন্টারনেট এক্সপ্লোরার, ইভেন্টটি মোটেও ক্যাপচারকে সমর্থন করেনি, বরং কেবল ইভেন্টের বুদবুদ নামে পরিচিত ইভেন্টের আরও একটি স্টাইলকে সমর্থন করেছিল। যখন ডাব্লু 3 সি গঠিত হয়েছিল, তারা ইভেন্টের উভয় স্টাইলে যোগ্যতা খুঁজে পেয়েছিল এবং ঘোষণা করেছিল যে ব্রাউজারগুলি addEventListener
পদ্ধতিতে তৃতীয় প্যারামিটারের মাধ্যমে উভয়কেই সমর্থন করা উচিত। মূলত, সেই প্যারামিটারটি কেবল একটি বুলিয়ান ছিল, তবে সমস্ত আধুনিক ব্রাউজারগুলি তৃতীয় প্যারামিটার হিসাবে একটি options
অবজেক্টকে সমর্থন করে, যা আপনি যদি ইভেন্ট ক্যাপচারিং বা না ব্যবহার করতে চান তবে আপনি নির্দিষ্ট করতে (অন্যান্য বিষয়গুলির মধ্যে) নির্দিষ্ট করতে ব্যবহার করতে পারেন:
someElement.addEventListener('click', myClickHandler, { capture: true | false });
নোট করুন যে options
অবজেক্টটি al চ্ছিক, যেমনটি এর capture
সম্পত্তি। যদি হয় বাদ দেওয়া হয় তবে capture
জন্য ডিফল্ট মানটি false
, যার অর্থ ইভেন্ট বুদবুদ ব্যবহার করা হবে।
ইভেন্ট ক্যাপচারিং
আপনার ইভেন্ট হ্যান্ডলার "ক্যাপচারিং পর্যায়ে শুনছেন" এর অর্থ কী? এটি বোঝার জন্য, ইভেন্টগুলি কীভাবে উত্পন্ন হয় এবং কীভাবে তারা ভ্রমণ করে তা আমাদের জানতে হবে। নিম্নলিখিতটি সমস্ত ইভেন্টগুলির ক্ষেত্রে সত্য, এমনকি যদি আপনি বিকাশকারী হিসাবে, এটি লাভ করবেন না, এটি সম্পর্কে যত্নশীল বা এটি সম্পর্কে চিন্তা করবেন না।
সমস্ত ইভেন্ট উইন্ডোতে শুরু হয় এবং প্রথমে ক্যাপচারিং পর্বের মধ্য দিয়ে যায়। এর অর্থ হ'ল যখন কোনও ইভেন্ট প্রেরণ করা হয়, এটি উইন্ডোটি শুরু করে এবং প্রথমে তার লক্ষ্য উপাদানটির দিকে "নীচের দিকে" ভ্রমণ করে। আপনি কেবল বুদবুদ পর্যায়ে শুনছেন এমনকি এটি ঘটে। নিম্নলিখিত উদাহরণটি মার্কআপ এবং জাভাস্ক্রিপ্ট বিবেচনা করুন:
<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
উপাদানটিতে ক্লিক ইভেন্টের জন্য কি কিছু শুনছেন?" এবার উত্তরটি "হ্যাঁ!" এই সংক্ষিপ্ত সময়টি যখন ইভেন্টটি লক্ষ্যমাত্রায় থাকে, তখন "লক্ষ্য পর্যায়" হিসাবে পরিচিত। এই মুহুর্তে, ইভেন্ট হ্যান্ডলারটি গুলি চালাবে, ব্রাউজারটি কনসোল করবে L ভুল! আমরা মোটেও সম্পন্ন করি না। প্রক্রিয়াটি অব্যাহত রয়েছে, তবে এখন এটি বুদবুদ পর্যায়ে পরিবর্তিত হয়।
ইভেন্ট বুদবুদ
ব্রাউজারটি জিজ্ঞাসা করবে:
"বুদবুদ পর্যায়ে #C
তে ক্লিক ইভেন্টের জন্য কি কিছু শুনছেন?" এখানে মনোযোগ দিন। ক্যাপচারিং এবং বুদবুদ উভয় পর্যায়ে ক্লিকগুলি (বা কোনও ইভেন্টের ধরণ) শুনতে সম্পূর্ণ সম্ভব। এবং যদি আপনি উভয় পর্যায়ে ইভেন্টের হ্যান্ডলারগুলি তারযুক্ত করে থাকেন (যেমন .addEventListener()
কল করে দুবার, একবার capture = true
এবং একবার capture = false
দিয়ে একবার), তবে হ্যাঁ, উভয় ইভেন্ট হ্যান্ডলারগুলি একই উপাদানটির জন্য একেবারে আগুন ধরিয়ে দেয়। তবে এটি লক্ষ করাও গুরুত্বপূর্ণ যে তারা বিভিন্ন পর্যায়ে গুলি চালায় (ক্যাপচারিং পর্যায়ে একটি এবং বুদবুদ পর্যায়ে একটি)।
এরপরে, ইভেন্টটি প্রচার করবে (আরও সাধারণভাবে "বুদ্বুদ" হিসাবে বলা হয়েছে কারণ দেখে মনে হচ্ছে ইভেন্টটি "ডোম ট্রি" আপ "ভ্রমণ করছে) তার পিতামাতার উপাদান, #B
, এবং ব্রাউজারটি জিজ্ঞাসা করবে:" বুদবুদ পর্যায়ে #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,
);
কনসোল আউটপুট নির্ভর করবে আপনি কোন উপাদানটি ক্লিক করেছেন তার উপর। আপনি যদি ডিওএম ট্রি ( #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"
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। #C
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
event.stopPropagation()
ইভেন্টগুলি কোথায় উদ্ভূত হয়েছে এবং কীভাবে তারা ক্যাপচারিং পর্ব এবং বুদবুদ পর্ব উভয় ক্ষেত্রেই ডোমের মাধ্যমে ভ্রমণ করে (অর্থাত্ প্রচার করে) তা বোঝার সাথে আমরা এখন event.stopPropagation()
।
stopPropagation()
পদ্ধতিটি (বেশিরভাগ) নেটিভ ডিওএম ইভেন্টগুলিতে কল করা যেতে পারে। আমি "সর্বাধিক" বলি কারণ এমন কয়েকটি রয়েছে যার উপরে এই পদ্ধতিটি কল করা কিছুই করবে না (কারণ ইভেন্টটি শুরু করার জন্য প্রচার করে না)। focus
, blur
, load
, scroll
এবং আরও কয়েকজনের মতো ইভেন্টগুলি এই বিভাগে পড়ে। আপনি stopPropagation()
কল করতে পারেন তবে আকর্ষণীয় কিছুই ঘটবে না, যেহেতু এই ইভেন্টগুলি প্রচার করে না।
তবে stopPropagation
কী করে?
এটি করে, বেশ অনেক কিছু, এটি যা বলে। আপনি যখন এটিকে কল করবেন, ইভেন্টটি সেদিক থেকে, অন্যথায় ভ্রমণ করবে এমন কোনও উপাদানগুলিতে প্রচার বন্ধ করে দেবে। এটি উভয় দিকের ক্ষেত্রে (ক্যাপচারিং এবং বুদবুদ) সত্য। সুতরাং আপনি যদি ক্যাপচারিং পর্বের যে কোনও জায়গায় stopPropagation()
কল করেন তবে ইভেন্টটি কখনই লক্ষ্য পর্যায়ে বা বুদবুদ পর্যায়ে তৈরি করবে না। আপনি যদি এটি বুদবুদ পর্যায়ে কল করেন তবে এটি ইতিমধ্যে ক্যাপচারিং পর্বের মধ্য দিয়ে চলে যাবে, তবে এটি আপনি যে বিন্দুতে বলেছিলেন তা থেকে "বুদবুদ" বন্ধ হয়ে যাবে।
আমাদের একই উদাহরণ মার্কআপে ফিরে আসা, আপনি কি মনে করেন যে #B
এলিমেন্টে ক্যাপচারিং পর্যায়ে আমরা যদি 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"
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। লাইভ ডেমোতে #C
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
বুদবুদ পর্যায়ে #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
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
আরও একটি, শুধু মজা জন্য। আমরা যদি #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
জন্য ইভেন্ট হ্যান্ডলার যেখানে আমরা লগ ইন "ক্যাপচারিং ফেজে #সি তে ক্লিক করুন" এখনও কার্যকর করে, তবে আমরা যেটিতে লগ ইন করুন "বুদবুদ পর্যায়ে #সি তে ক্লিক করুন" তা নয়। এটি নিখুঁত ধারণা করা উচিত। আমরা পূর্বের কাছ থেকে stopPropagation()
ডেকেছি, সুতরাং এটিই সেই পয়েন্ট যেখানে ইভেন্টটির প্রচার বন্ধ হবে।
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। লাইভ ডেমোতে #C
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
এই লাইভ ডেমোতে যে কোনও একটিতে, আমি আপনাকে চারপাশে খেলতে উত্সাহিত করি। কেবল #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()
কী করে? দেখে মনে হচ্ছে এটি অনুরূপ কিছু করে। এটা করে?
আসলেই না। দু'জন প্রায়শই বিভ্রান্ত হলেও তাদের একে অপরের সাথে আসলে খুব বেশি কিছু করার নেই। আপনি যখন আপনার মাথায় 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,
);
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। অ্যাভেট ব্রাদার্সের লিঙ্কটিতে ক্লিক করুন এবং কনসোল আউটপুটটি পর্যবেক্ষণ করুন (এবং আপনাকে অ্যাভেট ব্রাদার্স ওয়েবসাইটে পুনঃনির্দেশিত করা হয়নি)।
সাধারণত, অ্যাভেট ব্রাদার্স লেবেলযুক্ত লিঙ্কটিতে ক্লিক করার ফলে www.theavettbrothers.com
এ ব্রাউজ করা হবে। যদিও এই ক্ষেত্রে, আমরা <a>
উপাদানটিতে একটি ক্লিক ইভেন্ট হ্যান্ডলারকে ওয়্যার্ড করেছি এবং নির্দিষ্ট করেছি যে ডিফল্ট ক্রিয়াটি প্রতিরোধ করা উচিত। সুতরাং, যখন কোনও ব্যবহারকারী এই লিঙ্কটি ক্লিক করেন, তখন তারা কোথাও নেভিগেট করা হবে না, এবং পরিবর্তে কনসোলটি কেবল লগ করবে "সম্ভবত আমাদের পরিবর্তে এখানে তাদের কিছু সংগীত বাজানো উচিত?"
অন্যান্য কোন উপাদান/ইভেন্ট সংমিশ্রণগুলি আপনাকে ডিফল্ট ক্রিয়াটি রোধ করতে দেয়? আমি সম্ভবত তাদের সমস্ত তালিকাভুক্ত করতে পারি না এবং কখনও কখনও আপনাকে দেখার জন্য কেবল পরীক্ষা করতে হয়। তবে সংক্ষেপে, এখানে কয়েকটি রয়েছে:
<form>
এলিমেন্ট + "জমা দিন" ইভেন্ট: এই সংমিশ্রণের জন্যpreventDefault()
কোনও ফর্ম জমা দেওয়া থেকে বিরত রাখবে। এটি কার্যকর যদি আপনি বৈধতা সম্পাদন করতে চান এবং কিছু ব্যর্থ হওয়া উচিত, আপনি ফর্মটি জমা দেওয়া থেকে বিরত রাখতে শর্তসাপেক্ষে প্রিভেনডেফাল্টকে কল করতে পারেন।<a>
এলিমেন্ট + "ক্লিক করুন" ইভেন্ট:preventDefault()
এই সংমিশ্রণের জন্য ব্রাউজারটিকে<a>
এলিমেন্টের এইচআরইএফ অ্যাট্রিবিউটে নির্দিষ্ট করা ইউআরএলে নেভিগেট করতে বাধা দেয়।document
+ "মাউসওহিল" ইভেন্ট: এই সংমিশ্রণের জন্যpreventDefault()
মাউসহিলের সাথে পৃষ্ঠা স্ক্রোলিংকে বাধা দেয় (কীবোর্ডের সাথে স্ক্রোলিং এখনও কার্যকর হবে)।
↜ এর জন্য{ passive: false }
সহaddEventListener()
কল করা দরকার }document
+ "কীডাউন" ইভেন্ট: এই সংমিশ্রণের জন্যpreventDefault()
প্রাণঘাতী। এটি পৃষ্ঠাটিকে মূলত অকেজো করে তোলে, কীবোর্ড স্ক্রোলিং, ট্যাবিং এবং কীবোর্ড হাইলাইটিং প্রতিরোধ করে।document
+ "মাউসডাউন" ইভেন্ট: এই সংমিশ্রণের জন্যpreventDefault()
মাউস এবং অন্য কোনও "ডিফল্ট" ক্রিয়া সহ পাঠ্য হাইলাইট করা রোধ করবে যা একজন মাউসকে নীচে নামিয়ে দেবে।<input>
এলিমেন্ট + "কীপ্রেস" ইভেন্ট: এই সংমিশ্রণের জন্যpreventDefault()
ব্যবহারকারী দ্বারা টাইপ করা অক্ষরগুলি ইনপুট উপাদানটিতে পৌঁছাতে বাধা দেবে (তবে এটি করবেন না; এর জন্য কোনও বৈধ কারণ যদি কখনও হয় তবে খুব কমই থাকে)।document
+ "কনটেক্সটম্যানু" ইভেন্ট: এই সংমিশ্রণের জন্য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()
পৃষ্ঠাটি কী অকেজো করে তোলে তা নয় (কমপক্ষে বেশিরভাগ ক্ষেত্রে নয়)। They simply prevent events from getting where they would otherwise go.
তবে আমরা preventDefault()
কেও কল করি, যা আপনি স্মরণ করবেন ডিফল্ট ক্রিয়াটি প্রতিরোধ করে। সুতরাং যে কোনও ডিফল্ট ক্রিয়া (যেমন মাউসওয়েল স্ক্রোল, কীবোর্ড স্ক্রোল বা হাইলাইট বা ট্যাব্বিং, লিঙ্ক ক্লিক, প্রসঙ্গ মেনু প্রদর্শন ইত্যাদি) সমস্ত প্রতিরোধ করা হয়, এইভাবে পৃষ্ঠাটি মোটামুটি অকেজো অবস্থায় রেখে যায়।
লাইভ ডেমো
এই নিবন্ধটি থেকে আবার এক জায়গায় অন্বেষণ করতে, নীচে এম্বেড থাকা ডেমোটি দেখুন।
স্বীকৃতি
টম উইলসনের হিরো ইমেজটি আনস্প্ল্যাশে ।
, preventDefault
এবং stopPropagation
: কখন এবং প্রতিটি পদ্ধতি ঠিক কী করে তা ব্যবহার করবেন।
ইভেন্ট.স্টপপ্রোপ্যাগেশন () এবং ইভেন্ট.প্রভেন্টডেফাল্ট ()
জাভাস্ক্রিপ্ট ইভেন্ট হ্যান্ডলিং প্রায়শই সোজা। একটি সাধারণ (তুলনামূলকভাবে সমতল) এইচটিএমএল কাঠামোর সাথে কাজ করার সময় এটি বিশেষত সত্য। বিষয়গুলি কিছুটা আরও জড়িত হয়ে যায় যদিও ইভেন্টগুলি যখন উপাদানগুলির একটি শ্রেণিবিন্যাসের মাধ্যমে ভ্রমণ করে (বা প্রচার করছে)। এটি সাধারণত হয় যখন বিকাশকারীরা stopPropagation()
এবং/অথবা preventDefault()
এর জন্য তারা যে সমস্যাগুলি অনুভব করছেন তা সমাধান করার জন্য পৌঁছে যায়। যদি আপনি নিজেকে কখনও ভাবেন "আমি কেবল preventDefault()
চেষ্টা করে দেখি এবং যদি এটি কাজ না করে তবে আমি stopPropagation()
চেষ্টা করব এবং যদি এটি কাজ না করে তবে আমি উভয়ই চেষ্টা করব," তবে এই নিবন্ধটি আপনার জন্য! আমি প্রতিটি পদ্ধতি ঠিক কী করে তা ব্যাখ্যা করব, কখন কোনটি ব্যবহার করব এবং আপনাকে অন্বেষণ করার জন্য আপনাকে বিভিন্ন কাজের উদাহরণ সরবরাহ করব। আমার লক্ষ্য হ'ল একবার এবং সকলের জন্য আপনার বিভ্রান্তি শেষ করা।
যদিও আমরা খুব গভীরভাবে ডুব দেওয়ার আগে, জাভাস্ক্রিপ্টে দুটি ধরণের ইভেন্ট হ্যান্ডলিং সম্ভব (সমস্ত আধুনিক ব্রাউজারগুলিতে - সংস্করণ 9 এর পূর্বে ইন্টারনেট এক্সপ্লোরার ইভেন্টটি মোটেও সমর্থন করেনি) এ সংক্ষেপে স্পর্শ করা গুরুত্বপূর্ণ।
ইভেন্ট স্টাইল (ক্যাপচারিং এবং বুদবুদ)
সমস্ত আধুনিক ব্রাউজার ইভেন্ট ক্যাপচারকে সমর্থন করে তবে এটি খুব কমই বিকাশকারীরা ব্যবহার করে। মজার বিষয় হল, এটি ইভেন্টের একমাত্র রূপ যা নেটস্কেপ মূলত সমর্থিত। নেটস্কেপের বৃহত্তম প্রতিদ্বন্দ্বী, মাইক্রোসফ্ট ইন্টারনেট এক্সপ্লোরার, ইভেন্টটি মোটেও ক্যাপচারকে সমর্থন করেনি, বরং কেবল ইভেন্টের বুদবুদ নামে পরিচিত ইভেন্টের আরও একটি স্টাইলকে সমর্থন করেছিল। যখন ডাব্লু 3 সি গঠিত হয়েছিল, তারা ইভেন্টের উভয় স্টাইলে যোগ্যতা খুঁজে পেয়েছিল এবং ঘোষণা করেছিল যে ব্রাউজারগুলি addEventListener
পদ্ধতিতে তৃতীয় প্যারামিটারের মাধ্যমে উভয়কেই সমর্থন করা উচিত। মূলত, সেই প্যারামিটারটি কেবল একটি বুলিয়ান ছিল, তবে সমস্ত আধুনিক ব্রাউজারগুলি তৃতীয় প্যারামিটার হিসাবে একটি options
অবজেক্টকে সমর্থন করে, যা আপনি যদি ইভেন্ট ক্যাপচারিং বা না ব্যবহার করতে চান তবে আপনি নির্দিষ্ট করতে (অন্যান্য বিষয়গুলির মধ্যে) নির্দিষ্ট করতে ব্যবহার করতে পারেন:
someElement.addEventListener('click', myClickHandler, { capture: true | false });
নোট করুন যে options
অবজেক্টটি al চ্ছিক, যেমনটি এর capture
সম্পত্তি। যদি হয় বাদ দেওয়া হয় তবে capture
জন্য ডিফল্ট মানটি false
, যার অর্থ ইভেন্ট বুদবুদ ব্যবহার করা হবে।
ইভেন্ট ক্যাপচারিং
আপনার ইভেন্ট হ্যান্ডলার "ক্যাপচারিং পর্যায়ে শুনছেন" এর অর্থ কী? এটি বোঝার জন্য, ইভেন্টগুলি কীভাবে উত্পন্ন হয় এবং কীভাবে তারা ভ্রমণ করে তা আমাদের জানতে হবে। নিম্নলিখিতটি সমস্ত ইভেন্টগুলির ক্ষেত্রে সত্য, এমনকি যদি আপনি বিকাশকারী হিসাবে, এটি লাভ করবেন না, এটি সম্পর্কে যত্নশীল বা এটি সম্পর্কে চিন্তা করবেন না।
সমস্ত ইভেন্ট উইন্ডোতে শুরু হয় এবং প্রথমে ক্যাপচারিং পর্বের মধ্য দিয়ে যায়। এর অর্থ হ'ল যখন কোনও ইভেন্ট প্রেরণ করা হয়, এটি উইন্ডোটি শুরু করে এবং প্রথমে তার লক্ষ্য উপাদানটির দিকে "নীচের দিকে" ভ্রমণ করে। আপনি কেবল বুদবুদ পর্যায়ে শুনছেন এমনকি এটি ঘটে। নিম্নলিখিত উদাহরণটি মার্কআপ এবং জাভাস্ক্রিপ্ট বিবেচনা করুন:
<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
উপাদানটিতে ক্লিক ইভেন্টের জন্য কি কিছু শুনছেন?" এবার উত্তরটি "হ্যাঁ!" এই সংক্ষিপ্ত সময়টি যখন ইভেন্টটি লক্ষ্যমাত্রায় থাকে, তখন "লক্ষ্য পর্যায়" হিসাবে পরিচিত। এই মুহুর্তে, ইভেন্ট হ্যান্ডলারটি গুলি চালাবে, ব্রাউজারটি কনসোল করবে L ভুল! আমরা মোটেও সম্পন্ন করি না। প্রক্রিয়াটি অব্যাহত রয়েছে, তবে এখন এটি বুদবুদ পর্যায়ে পরিবর্তিত হয়।
ইভেন্ট বুদবুদ
ব্রাউজারটি জিজ্ঞাসা করবে:
"বুদবুদ পর্যায়ে #C
তে ক্লিক ইভেন্টের জন্য কি কিছু শুনছেন?" এখানে মনোযোগ দিন। ক্যাপচারিং এবং বুদবুদ উভয় পর্যায়ে ক্লিকগুলি (বা কোনও ইভেন্টের ধরণ) শুনতে সম্পূর্ণ সম্ভব। এবং যদি আপনি উভয় পর্যায়ে ইভেন্টের হ্যান্ডলারগুলি তারযুক্ত করে থাকেন (যেমন .addEventListener()
কল করে দুবার, একবার capture = true
এবং একবার capture = false
দিয়ে একবার), তবে হ্যাঁ, উভয় ইভেন্ট হ্যান্ডলারগুলি একই উপাদানটির জন্য একেবারে আগুন ধরিয়ে দেয়। তবে এটি লক্ষ করাও গুরুত্বপূর্ণ যে তারা বিভিন্ন পর্যায়ে গুলি চালায় (ক্যাপচারিং পর্যায়ে একটি এবং বুদবুদ পর্যায়ে একটি)।
এরপরে, ইভেন্টটি প্রচার করবে (আরও সাধারণভাবে "বুদ্বুদ" হিসাবে বলা হয়েছে কারণ দেখে মনে হচ্ছে ইভেন্টটি "ডোম ট্রি" আপ "ভ্রমণ করছে) তার পিতামাতার উপাদান, #B
, এবং ব্রাউজারটি জিজ্ঞাসা করবে:" বুদবুদ পর্যায়ে #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,
);
কনসোল আউটপুট নির্ভর করবে আপনি কোন উপাদানটি ক্লিক করেছেন তার উপর। আপনি যদি ডিওএম ট্রি ( #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"
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। #C
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
event.stopPropagation()
ইভেন্টগুলি কোথায় উদ্ভূত হয়েছে এবং কীভাবে তারা ক্যাপচারিং পর্ব এবং বুদবুদ পর্ব উভয় ক্ষেত্রেই ডোমের মাধ্যমে ভ্রমণ করে (অর্থাত্ প্রচার করে) তা বোঝার সাথে আমরা এখন event.stopPropagation()
।
stopPropagation()
পদ্ধতিটি (বেশিরভাগ) নেটিভ ডিওএম ইভেন্টগুলিতে কল করা যেতে পারে। আমি "সর্বাধিক" বলি কারণ এমন কয়েকটি রয়েছে যার উপরে এই পদ্ধতিটি কল করা কিছুই করবে না (কারণ ইভেন্টটি শুরু করার জন্য প্রচার করে না)। focus
, blur
, load
, scroll
এবং আরও কয়েকজনের মতো ইভেন্টগুলি এই বিভাগে পড়ে। আপনি stopPropagation()
কল করতে পারেন তবে আকর্ষণীয় কিছুই ঘটবে না, যেহেতু এই ইভেন্টগুলি প্রচার করে না।
তবে stopPropagation
কী করে?
এটি করে, বেশ অনেক কিছু, এটি যা বলে। আপনি যখন এটিকে কল করবেন, ইভেন্টটি সেদিক থেকে, অন্যথায় ভ্রমণ করবে এমন কোনও উপাদানগুলিতে প্রচার বন্ধ করে দেবে। এটি উভয় দিকের ক্ষেত্রে (ক্যাপচারিং এবং বুদবুদ) সত্য। সুতরাং আপনি যদি ক্যাপচারিং পর্বের যে কোনও জায়গায় stopPropagation()
কল করেন তবে ইভেন্টটি কখনই লক্ষ্য পর্যায়ে বা বুদবুদ পর্যায়ে তৈরি করবে না। আপনি যদি এটি বুদবুদ পর্যায়ে কল করেন তবে এটি ইতিমধ্যে ক্যাপচারিং পর্বের মধ্য দিয়ে চলে যাবে, তবে এটি আপনি যে বিন্দুতে বলেছিলেন তা থেকে "বুদবুদ" বন্ধ হয়ে যাবে।
আমাদের একই উদাহরণ মার্কআপে ফিরে আসা, আপনি কি মনে করেন যে #B
এলিমেন্টে ক্যাপচারিং পর্যায়ে আমরা যদি 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"
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। লাইভ ডেমোতে #C
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
বুদবুদ পর্যায়ে #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
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
আরও একটি, শুধু মজা জন্য। আমরা যদি #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
জন্য ইভেন্ট হ্যান্ডলার যেখানে আমরা লগ ইন "ক্যাপচারিং ফেজে #সি তে ক্লিক করুন" এখনও কার্যকর করে, তবে আমরা যেটিতে লগ ইন করুন "বুদবুদ পর্যায়ে #সি তে ক্লিক করুন" তা নয়। এটি নিখুঁত ধারণা করা উচিত। আমরা পূর্বের কাছ থেকে stopPropagation()
ডেকেছি, সুতরাং এটিই সেই পয়েন্ট যেখানে ইভেন্টটির প্রচার বন্ধ হবে।
আপনি নীচের লাইভ ডেমোতে এটির সাথে ইন্টারেক্টিভভাবে খেলতে পারেন। লাইভ ডেমোতে #C
উপাদানটিতে ক্লিক করুন এবং কনসোল আউটপুট পর্যবেক্ষণ করুন।
এই লাইভ ডেমোতে যে কোনও একটিতে, আমি আপনাকে চারপাশে খেলতে উত্সাহিত করি। কেবল #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()
বলে ডাকে এই কারণে কখনই চালায় না। If we had instead called e.stopPropagation()
, the third handler would still run.
event.preventDefault()
If stopPropagation()
prevents an event from traveling "downwards" (capturing) or "upwards" (bubbling), what then, does preventDefault()
do? It sounds like it does something similar. এটা করে?
আসলেই না। While the two are often confused, they actually don't have much to do with each other. When you see preventDefault()
, in your head, add the word "action." Think "prevent the default action."
And what is the default action you may ask? Unfortunately, the answer to that isn't quite as clear because it's highly dependent on the element + event combination in question. And to make matters even more confusing, sometimes there is no default action at all!
Let's begin with a very simple example to understand. What do you expect to happen when you click a link on a web page? Obviously, you expect the browser to navigate to the URL specified by that link. In this case, the element is an anchor tag and the event is a click event. That combination ( <a>
+ click
) has a "default action" of navigating to the link's href. What if you wanted to prevent the browser from performing that default action? That is, suppose you want to prevent the browser from navigating to the URL specified by the <a>
element's href
attribute? This is what preventDefault()
will do for you. এই উদাহরণ বিবেচনা করুন:
<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,
);
You can interactively play with this in the live demo below. Click the link The Avett Brothers and observe the console output (and the fact that you are not redirected to the Avett Brothers website).
Normally, clicking the link labelled The Avett Brothers would result in browsing to www.theavettbrothers.com
. In this case though, we've wired up a click event handler to the <a>
element and specified that the default action should be prevented. Thus, when a user clicks this link, they won't be navigated anywhere, and instead the console will simply log "Maybe we should just play some of their music right here instead?"
What other element/event combinations allow you to prevent the default action? I cannot possibly list them all, and sometimes you have to just experiment to see. But briefly, here are a few:
<form>
element + "submit" event:preventDefault()
for this combination will prevent a form from submitting. This is useful if you want to perform validation and should something fail, you can conditionally call preventDefault to stop the form from submitting.<a>
element + "click" event:preventDefault()
for this combination prevents the browser from navigating to the URL specified in the<a>
element's href attribute.document
+ "mousewheel" event:preventDefault()
for this combination prevents page scrolling with the mousewheel (scrolling with keyboard would still work though).
↜ This requires callingaddEventListener()
with{ passive: false }
.document
+ "keydown" event:preventDefault()
for this combination is lethal. It renders the page largely useless, preventing keyboard scrolling, tabbing, and keyboard highlighting.document
+ "mousedown" event:preventDefault()
for this combination will prevent text highlighting with the mouse and any other "default" action that one would invoke with a mouse down.<input>
element + "keypress" event:preventDefault()
for this combination will prevent characters typed by the user from reaching the input element (but don't do this; there is rarely, if ever, a valid reason for it).document
+ "contextmenu" event:preventDefault()
for this combination prevents the native browser context menu from appearing when a user right-clicks or long-presses (or any other way in which a context menu might appear).
This is not an exhaustive list by any means, but hopefully it gives you a good idea of how preventDefault()
can be used.
A fun practical joke?
What happens if you stopPropagation()
and preventDefault()
in the capturing phase, starting at the document? উচ্ছ্বাস আসে! The following code snippet will render any web page just about completely useless:
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 });
I don't really know why you'd ever want to do this (except maybe to play a joke on someone), but it is useful to think about what's happening here, and realize why it creates the situation it does.
All events originate at window
, so in this snippet, we're stopping, dead in their tracks, all click
, keydown
, mousedown
, contextmenu
, and mousewheel
events from ever getting to any elements that might be listening for them. We also call stopImmediatePropagation
so that any handlers wired up to the document after this one, will be thwarted as well.
Note that stopPropagation()
and stopImmediatePropagation()
aren't (at least not mostly) what render the page useless. They simply prevent events from getting where they would otherwise go.
But we also call preventDefault()
, which you'll recall prevents the default action . So any default actions (like mousewheel scroll, keyboard scroll or highlight or tabbing, link clicking, context menu display, etc.) are all prevented, thus leaving the page in a fairly useless state.
লাইভ ডেমো
To explore all the examples from this article again in one place, check out the embedded demo below.
স্বীকৃতি
Hero image by Tom Wilson on Unsplash .