From fe977620ccc9fd7b06d95e150cbbc582468ad014 Mon Sep 17 00:00:00 2001 From: Saiful Date: Sat, 6 Mar 2021 13:22:02 +0600 Subject: [PATCH 1/8] translate styles and classes --- .../08-styles-and-classes/article.md | 183 +++++++++--------- 1 file changed, 91 insertions(+), 92 deletions(-) diff --git a/2-ui/1-document/08-styles-and-classes/article.md b/2-ui/1-document/08-styles-and-classes/article.md index 9154d43d6..c09573908 100644 --- a/2-ui/1-document/08-styles-and-classes/article.md +++ b/2-ui/1-document/08-styles-and-classes/article.md @@ -1,37 +1,37 @@ -# Styles and classes +# Styles এবং classes -Before we get into JavaScript's ways of dealing with styles and classes -- here's an important rule. Hopefully it's obvious enough, but we still have to mention it. +জাভাস্ক্রিপ্টের সাহায্যে style এবং class নিয়ে কাজ করার সময় আমাদের কিছু গুরুত্বপূর্ণ রুল জেনে রাখা উচিত। যদিও আমাদের কাছে অনেক কিছু সুস্পষ্ট, তারপরও কিছু বিষয় জেনে রাখা উচিত। -There are generally two ways to style an element: +দুইটি উপায়ে আমরা এলিমেন্টে স্ট্যাইল করতে পারি: -1. Create a class in CSS and add it: `
` -2. Write properties directly into `style`: `
`. +1. CSS ক্লাস এর মাধ্যমে: `
` +2. সরাসরি `style` প্রপার্টির মাধ্যমে : `
`। -JavaScript can modify both classes and `style` properties. +জাভাস্ক্রিপ্টের মাধ্যমে ক্লাস এবং `style` প্রপার্টিকে উভয়ভাবে আমরা পরিবর্তন করতে পারি। -We should always prefer CSS classes to `style`. The latter should only be used if classes "can't handle it". +তবে আমাদের `style` এর জন্য CSS ক্লাস ব্যবহার করাই বেশি উপযোগী। তবে যদি ক্লাসের মাধ্যমে সম্পূর্ন ব্যাপারটি কন্ট্রোল করতে না পারি তাহলে দ্বিতীয়টির মাধ্যমে করা উচিত। -For example, `style` is acceptable if we calculate coordinates of an element dynamically and want to set them from JavaScript, like this: +যেমন, আমরা জাভাস্ক্রিপ্টের মাধ্যমে ডায়নামিক্যালি কো-অর্ডিনেট ক্যালকুলেশন করে `style` এ সেট করতে পারি, এভাবে: ```js -let top = /* complex calculations */; -let left = /* complex calculations */; +let top = /* জটিল ক্যালকুলেশন */; +let left = /* জটিল ক্যালকুলেশন */; -elem.style.left = left; // e.g '123px', calculated at run-time -elem.style.top = top; // e.g '456px' +elem.style.left = left; // যেমন '123px', রানটাইমে ক্যালকুলেশন +elem.style.top = top; // যেমন '456px' ``` -For other cases, like making the text red, adding a background icon -- describe that in CSS and then add the class (JavaScript can do that). That's more flexible and easier to support. +অন্যান্য ক্ষেত্রে, যেমন টেক্সট কালার লাল, বা আইকন পরিবর্তন ইত্যাদি আমরা জাভাস্ক্রিপ্টের মাধ্যমে *CSS class* সংযুক্ত করণের দ্বারা করতে পারি। এটি আরো বেশি সহজ এবং উপযোগী। -## className and classList +## className এবং classList -Changing a class is one of the most often used actions in scripts. +জাভাস্ক্রিপ্টের মাধ্যমে আমরা প্রায়সই ক্লাসের নাম পরিবর্তন করে থাকি। -In the ancient time, there was a limitation in JavaScript: a reserved word like `"class"` could not be an object property. That limitation does not exist now, but at that time it was impossible to have a `"class"` property, like `elem.class`. +পূর্বে জাভাস্ক্রিপ্টের কিছু সীমাবদ্ধতা ছিল: `"class"` একটি রিসার্ভড ওয়ার্ড হওয়ায় এটি অবজেক্টের প্রপার্টি হতে পারত না। তবে সীমাবদ্ধতাটি এখন আর নেই, কিন্তু অই সময় `"class"` নামের প্রপার্টি অ্যাসাইন করা সম্ভব হত নাহ, যেমন `elem.class`। -So for classes the similar-looking property `"className"` was introduced: the `elem.className` corresponds to the `"class"` attribute. +ক্লাসের জন্য আমাদের অনুরূপ একটি প্রপার্টি ছিল `"className"`: `elem.className` দ্বারা `"class"` অ্যাট্রিবিউটকে নির্দেশ করে। -For instance: +উদাহরণস্বরূপ: ```html run @@ -41,19 +41,19 @@ For instance: ``` -If we assign something to `elem.className`, it replaces the whole string of classes. Sometimes that's what we need, but often we want to add/remove a single class. +যদি আমরা `elem.className` এ কিছু অ্যাসাইন করি তাহলে এটি সম্পূর্ন ক্লাস স্ট্রিংটিকে রিপ্লেস করে। মাঝে মাঝে আমাদের এটি দরকার হয়, কিন্তু বেশিরভাগ সময় আমাদের একটি সিংগেল ক্লাস সংযুক্ত/বাদ দেয়া লাগে। -There's another property for that: `elem.classList`. +এজন্য আমাদের আরেকটি প্রপার্টি আছে: `elem.classList`। -The `elem.classList` is a special object with methods to `add/remove/toggle` a single class. +`elem.classList` একটি স্পেশাল অবজেক্ট যার কিছু মেথড আছে `add/remove/toggle`। -For instance: +উদাহরণস্বরূপ: ```html run ``` -This property is rarely used, because such assignment removes all existing styles: it does not add, but replaces them. May occasionally delete something needed. But we can safely use it for new elements, when we know we won't delete an existing style. +প্রপার্টিটি কদাচিৎ ব্যবহার হয়, কেননা এর ফলে বিদ্যমান সকল স্ট্যাইল রিমুভ হয়ে যায়: এটি পুরনো স্ট্যাইল টিকে সম্পুর্ন পরিবর্তন করে দেয়, এর ফলে অনেক সময় আমাদের প্রয়োজনীয় স্ট্যাইলও ডিলিট হয়ে যায়। তবে নতুন কোন এলিমেন্টে একাধিক স্ট্যাইল সেটের জন্য এটি উপযোগী, যখন আমরা জানি প্রয়োজনীয় কোন স্ট্যাইল এখনো সেট হয়নি। -The same can be accomplished by setting an attribute: `div.setAttribute('style', 'color: red...')`. +আমরা এভাবেও করতে পারি: `div.setAttribute('style', 'color: red...')`। ```` ## Mind the units -Don't forget to add CSS units to values. +CSS ইউনিট ভ্যালু লিখতে ভুলবেন না। -For instance, we should not set `elem.style.top` to `10`, but rather to `10px`. Otherwise it wouldn't work: +উদাহরণস্বরূপ, আমাদের `elem.style.top` কে শুধুমাত্র `10` দ্বারা লিখলে হবে না, তার পরিবর্তে ইউনিট লিখা লাগবে যেমন `10px`। অন্যথায় এটি কাজ করবে না: ```html run height=100 ``` ```` -```smart header="Styles applied to `:visited` links are hidden!" -Visited links may be colored using `:visited` CSS pseudoclass. +```smart header="Styles applied to `:visited` লিংক অদৃশ্য!" +ভিজিটেড লিংক সমূহ হয়তবা CSS pseudoclass `:visited` এর জন্য একটি কালার দেখায়। -But `getComputedStyle` does not give access to that color, because otherwise an arbitrary page could find out whether the user visited a link by creating it on the page and checking the styles. +কিন্তু `getComputedStyle` এটি কোন কালারের মান রিটার্ন করে না কারণ এটির অ্যাক্সেস থাকে না, কেননা একটি স্বতন্ত্র পেজে স্ট্যাইল যাচাইয়ের মাধ্যমে সহজেই জানা যাবে কোন কোন পেজ ভিজিট করা হয়েছে। -JavaScript may not see the styles applied by `:visited`. And also, there's a limitation in CSS that forbids applying geometry-changing styles in `:visited`. That's to guarantee that there's no side way for an evil page to test if a link was visited and hence to break the privacy. +তাই জাভাস্ক্রিপ্টের মাধ্যমে `:visited` এর মান জানা সম্ভব না। এটি আমাদের গোপনীয়তার নিশ্চয়তা প্রদান করে। ``` -## Summary +## সারাংশ -To manage classes, there are two DOM properties: +ক্লাস ম্যানিপুলেসনের জন্য, দুটি DOM প্রপার্টি আছে: -- `className` -- the string value, good to manage the whole set of classes. -- `classList` -- the object with methods `add/remove/toggle/contains`, good for individual classes. +- `className` -- ক্লাস অ্যাট্রিবিউটের সকল ক্লাস স্ট্রিং হিসেবে রিটার্ন করে, এলিমেন্টের সকল ক্লাসের জন্য এটি উপযোগী। +- `classList` -- একটি অবজেক্ট যার মেথডসমূহ `add/remove/toggle/contains`, সিংগেল ক্লাসের জন্য উপযোগী। -To change the styles: +স্ট্যাইল পরিবর্তনের জন্য: -- The `style` property is an object with camelCased styles. Reading and writing to it has the same meaning as modifying individual properties in the `"style"` attribute. To see how to apply `important` and other rare stuff -- there's a list of methods at [MDN](mdn:api/CSSStyleDeclaration). +- `style` প্রপার্টি একটি অবজেক্ট যার প্রপার্টি সমূহ ক্যামেল কেসের হয়ে থাকে। প্রতিটি একক প্রপার্টি পড়তে এবং অ্যাসাইন করতে এটি উপযোগী। কিভাবে আমরা `important` এবং অন্যান্য কদাচিৎ ব্যবহৃত বিষয়গুলো ব্যবহার করতে পারি -- তা জানতে এটি দেখুন [MDN](mdn:api/CSSStyleDeclaration)। +- `style.cssText` এর সাহায্যে আমরা একাধিক `"style"` অ্যাট্রিবিউট সেট করতে পারি। -- The `style.cssText` property corresponds to the whole `"style"` attribute, the full string of styles. +কোন এলিমেন্টের প্রয়োগকৃত সর্বশেষ সকল স্ট্যাইল জানতে: -To read the resolved styles (with respect to all classes, after all CSS is applied and final values are calculated): - -- The `getComputedStyle(elem, [pseudo])` returns the style-like object with them. Read-only. +- `getComputedStyle(elem, [pseudo])` সকল প্রপার্টি রিটার্ন করবে. এটি Read-only। From e8c8c0695ce391c5d095a228f4787372ad60f9b2 Mon Sep 17 00:00:00 2001 From: Saiful Date: Sat, 6 Mar 2021 13:22:20 +0600 Subject: [PATCH 2/8] translate task --- .../2-create-notification/task.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/2-ui/1-document/08-styles-and-classes/2-create-notification/task.md b/2-ui/1-document/08-styles-and-classes/2-create-notification/task.md index 60930cb6c..6d5694d5c 100644 --- a/2-ui/1-document/08-styles-and-classes/2-create-notification/task.md +++ b/2-ui/1-document/08-styles-and-classes/2-create-notification/task.md @@ -2,14 +2,14 @@ importance: 5 --- -# Create a notification +# নোটিফিকেশন তৈরি -Write a function `showNotification(options)` that creates a notification: `
` with the given content. The notification should automatically disappear after 1.5 seconds. +`showNotification(options)` নামের একটি ফাংশন লিখুন যা একটি নোটিফিকেশন দেখাবে: `
`। নোটিফিকেশনটি ১.৫ সেকেন্ড পর অদৃশ্য হবে। -The options are: +options হবে: ```js -// shows an element with the text "Hello" near the right-top of the window +// "Hello" টেক্সট সহকারে একটি এলিমেন্ট দেখাবে window এর উপরের ডান কোণায় showNotification({ top: 10, // 10px from the top of the window (by default 0px) right: 10, // 10px from the right edge of the window (by default 0px) @@ -21,4 +21,4 @@ showNotification({ [demo src="solution"] -Use CSS positioning to show the element at given top/right coordinates. The source document has the necessary styles. +CSS পজিশনিং স্ট্যাইল ব্যবহার করুন top/right এর জন্য। From 0a71143aa7a5e25f87d95eac4db4e4b30169a6fd Mon Sep 17 00:00:00 2001 From: Saiful Date: Tue, 9 Mar 2021 13:26:26 +0600 Subject: [PATCH 3/8] translate content --- .../01-introduction-browser-events/article.md | 222 +++++++++--------- 1 file changed, 110 insertions(+), 112 deletions(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index 19394e49e..018ede551 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -1,56 +1,56 @@ -# Introduction to browser events +# browser events এর সূচনা -*An event* is a signal that something has happened. All DOM nodes generate such signals (but events are not limited to DOM). +*event* হল কোন কিছু ঘটার একটি সংকেত। সকল DOM নোড এই ধরণের সংকেত জেনারেট করতে পারে(কিন্তু event শুধুমাত্র এর মধ্যই সীমাবদ্ধ না)। -Here's a list of the most useful DOM events, just to take a look at: +নিচে গুরুত্বপূর্ণ কিছু DOM ইভেন্ট নিয়ে আলোচনা করা হল: **Mouse events:** -- `click` -- when the mouse clicks on an element (touchscreen devices generate it on a tap). -- `contextmenu` -- when the mouse right-clicks on an element. -- `mouseover` / `mouseout` -- when the mouse cursor comes over / leaves an element. -- `mousedown` / `mouseup` -- when the mouse button is pressed / released over an element. -- `mousemove` -- when the mouse is moved. +- `click` -- যখন কোন এলিমেন্টে ক্লিক করা হয় (টাচস্ক্রীন ডিভাইসে ট্যাপ করলে)। +- `contextmenu` -- এলিমেন্টে মাউসের ডানের বাটনটি ক্লিক হলে। +- `mouseover` / `mouseout` -- কোন এলিমেন্টে মাউসের কার্সর আসলে অথবা এলিমেন্ট হতে ছেড়ে গেলে। +- `mousedown` / `mouseup` -- যখন কোন একটি এলিমেন্টে মাউস বাটন ক্লিক হয় বা ছাড়া হয়। +- `mousemove` -- যখন মাউস নাড়াচড়া করা হয়। **Keyboard events:** -- `keydown` and `keyup` -- when a keyboard key is pressed and released. +- `keydown` এবং `keyup` -- যখন কি-বোর্ডে কোন বাটন প্রেস হয়, এবং বাটন প্রেস সম্পন্ন হয়। **Form element events:** -- `submit` -- when the visitor submits a `
`. -- `focus` -- when the visitor focuses on an element, e.g. on an ``. +- `submit` -- যখন কোন একটি `` সাবমিট হয়। +- `focus` -- যখন কোন একটি এলিমেন্টে ফোকাস হয় যেমন, ``। **Document events:** -- `DOMContentLoaded` -- when the HTML is loaded and processed, DOM is fully built. +- `DOMContentLoaded` -- যখন DOM সম্পূর্ণ বিল্ট হয় এবং HTML লোড প্রসেসড হয়। **CSS events:** -- `transitionend` -- when a CSS-animation finishes. +- `transitionend` -- যখন একটি CSS-animation সম্পন্ন হয়। -There are many other events. We'll get into more details of particular events in next chapters. +এছাড়াও আরো অনেক ইভেন্ট আছে। পরবর্তী অধ্যায় সমূহে আমরা আরো বিস্তারিত জানব। ## Event handlers -To react on events we can assign a *handler* -- a function that runs in case of an event. +ইভেন্টগুলো কিভাবে সংগঠিত হবে তা অ্যাসাইন করা হয় *handler* দ্বারা -- এটি একটি ফাংশন। -Handlers are a way to run JavaScript code in case of user actions. +হ্যান্ডেলার হল ইউজারের চাহিদামত জাভাস্ক্রিপ্ট কোড রান করার একটি উপায়, অন্য কথায় ইভেন্ট সংগঠিত হলে যে ফাংশনটি কল হয়। -There are several ways to assign a handler. Let's see them, starting from the simplest one. +বিভিন্নভাবে আমরা হ্যান্ডেলার অ্যাসাইন করতে পারি। চলুন, সবচেয়ে সহজটি দিয়ে শুরু করি। ### HTML-attribute -A handler can be set in HTML with an attribute named `on`. +অ্যাট্রিবিউট আকারে হ্যান্ডেলার `on` সেট করা। -For instance, to assign a `click` handler for an `input`, we can use `onclick`, like here: +যেমন, `input` এ একটি `click` হ্যান্ডেলার অ্যাসাইন করতে, আমরা `onclick` ব্যবহার করতে পারি, এভাবে: ```html run ``` -On mouse click, the code inside `onclick` runs. +মাউস ক্লিক হলে, `onclick` এর মধ্যের কোড রান হবে। -Please note that inside `onclick` we use single quotes, because the attribute itself is in double quotes. If we forget that the code is inside the attribute and use double quotes inside, like this: `onclick="alert("Click!")"`, then it won't work right. +দয়া করে মনে রাখুন `onclick` এর মধ্যে আমাদের একক উদ্ধৃতি চিহ্ন *''* ব্যবহার করা লাগবে, কেননা অ্যাট্রিবিউটটি যুগল উদ্ধৃতি চিহ্ন *""* দ্বারা লিখা হয়েছে। যদি আমরা উভয়ই যুগল উদ্ধৃতি চিহ্ন ব্যবহার করি, এভাবে: `onclick="alert("Click!")"`, তাহলে এটি কাজ করবে না। -An HTML-attribute is not a convenient place to write a lot of code, so we'd better create a JavaScript function and call it there. +HTML-attribute এ অনেক কোড লিখা তেমন সুবিধাজনক না। সুতরাং আমাদের জন্য সুবিধাজনক হবে আলাদা ফাংশনে কোড লিখে তাদের কল করলে। -Here a click runs the function `countRabbits()`: +**onclick এর মাধ্যমে ফাংশন কল** `countRabbits()`: ```html autorun height=50 ``` -If the handler is assigned using an HTML-attribute then the browser reads it, creates a new function from the attribute content and writes it to the DOM property. +অ্যাট্রিবিটের সাহায্যে লিখিত হ্যান্ডেলারটি, একটি নতুন ফাংশন তৈরি করে এবং DOM প্রপার্টিতে এটি সেট করে। -So this way is actually the same as the previous one. +সুতরাং এটি পূর্ববর্তী টির মত কাজ করে। -These two code pieces work the same: +নিচের দুটি কোডের কাজ একই: -1. Only HTML: +1. শুধুমাত্র HTML: ```html autorun height=50 @@ -107,30 +107,30 @@ These two code pieces work the same: ``` -In the first example, the HTML attribute is used to initialize the `button.onclick`, while in the second example -- the script, that's all the difference. +প্রথম উদাহরণটিতে, অ্যাট্রিবিউটটি `button.onclick` ইনিশিয়ালাইজ করে, যেখানে দ্বিতীয় উদাহরণটি একটি -- স্ক্রিপ্ট, এটিই মূল পার্থক্য। -**As there's only one `onclick` property, we can't assign more than one event handler.** +**এক্ষেত্রে শুধুমাত্র একটি `onclick` প্রপার্টি থাকবে, সুতরাং আমরা একের অধিক হ্যান্ডেলার সেট করতে পারব না।** -In the example below adding a handler with JavaScript overwrites the existing handler: +নিচের উদাহরণটিতে দেখুন স্ক্রিপ্টের ফাংশনটি অ্যাট্রিবিউট হ্যান্ডেলারকে ওভাররাইট করে: ```html run height=50 autorun ``` -To remove a handler -- assign `elem.onclick = null`. + হ্যান্ডেলার রিমুভ করতে -- `elem.onclick = null`। -## Accessing the element: this +## this এর মাধ্যমে এলিমেন্টকে অ্যাক্সেস -The value of `this` inside a handler is the element. The one which has the handler on it. +হ্যান্ডেলারের মধ্যে `this` দ্বারা এলিমেন্টটিকে মির্দেশ করে। অর্থাৎ যে এলিমেন্টটি হ্যান্ডেলারে লিখা হয়েছে। -In the code below `button` shows its contents using `this.innerHTML`: +নিচের কোডটি রান হলে এটি `button` এর কন্টেন্টটি দেখাবে `this.innerHTML`: ```html height=50 autorun @@ -138,9 +138,9 @@ In the code below `button` shows its contents using `this.innerHTML`: ## Possible mistakes -If you're starting to work with events -- please note some subtleties. +যখন আমরা ইভেন্ট নিয়ে কোন কাজ করব --আমাদের কিছু ব্যপার মনে রাখতে হবে। -We can set an existing function as a handler: +আমরা কোন এক্সিটিং ফাংশনকে এভাবে হ্যান্ডেলার হিসেবে সেট করতে পারি: ```js function sayThanks() { @@ -150,93 +150,91 @@ function sayThanks() { elem.onclick = sayThanks; ``` -But be careful: the function should be assigned as `sayThanks`, not `sayThanks()`. +কিন্তু সাবধান! আমাদের ফাংশনটি এভাবে অ্যাসাইন করতে হবে `sayThanks`, `sayThanks()` কাজ করবে না। ```js -// right +// সঠিক button.onclick = sayThanks; -// wrong +// ভুল button.onclick = sayThanks(); ``` -If we add parentheses, then `sayThanks()` becomes is a function call. So the last line actually takes the *result* of the function execution, that is `undefined` (as the function returns nothing), and assigns it to `onclick`. That doesn't work. +যদি আমরা প্যারেন্টেসিস সহকারে লিখি, তাহলে `sayThanks()` একটি ফাংশন কল হবে। শেষেরটি *result*ঠিসেবে নতুন আরেকটি ফাংশন এক্সিকিউশন হিসেবে নেয়, যা `undefined`, এবং এটি `onclick` অ্যাসাইন করে। তাই এটি কাজ করবে না। -...On the other hand, in the markup we do need the parentheses: +...আবার অন্যদিকে, এলিমেন্ট হতে কল করলে প্যারেন্টেসিস সহকারে করতে হবে: ```html ``` -The difference is easy to explain. When the browser reads the attribute, it creates a handler function with body from the attribute content. - -So the markup generates this property: +এটি নিচের কোডটি দেখলে আমরা সহজেই বুঝতে পারব, ব্রাউজার অ্যাট্রিবিউট হতে কন্টেন্ট নিয়ে ফাংশনটিকে এভাবে কল করে: ```js button.onclick = function() { *!* - sayThanks(); // <-- the attribute content goes here + sayThanks(); // <-- অ্যাট্রিবিউটের কন্টেন্ট এখানে সেট হয় */!* }; ``` -**Don't use `setAttribute` for handlers.** +**হ্যান্ডেলার সেট করতে `setAttribute` ব্যবহার করবেন না** -Such a call won't work: +এটি কাজ করবে না: ```js run no-beautify -// a click on will generate errors, -// because attributes are always strings, function becomes a string +// বডিতে ক্লিক করলে ইরোর দেখাবে, +// কেননা অ্যাট্রিবিউট সমূহ সর্বদা স্ট্রিং হিসেবে সেট হয় document.body.setAttribute('onclick', function() { alert(1) }); ``` -**DOM-property case matters.** +**DOM-property এর ক্ষেত্রে কেস গুরুত্বপূর্ন** -Assign a handler to `elem.onclick`, not `elem.ONCLICK`, because DOM properties are case-sensitive. +হ্যান্ডেলার অ্যাসাইন করতে `elem.onclick` কাজ করবে, কিন্তু `elem.ONCLICK` কাজ করবে না, কেননা DOM প্রপার্টি সমূহ কেস-সেনসিটিভ। ## addEventListener -The fundamental problem of the aforementioned ways to assign handlers -- we can't assign multiple handlers to one event. +উপরোল্লিখিত নিয়ম অনুযায়ী হ্যান্ডেলার অ্যাসাইনের মূল সমস্যা হল -- আমরা একাধিক হ্যান্ডেলার অ্যাসাইন করতে পারব না। -Let's say, one part of our code wants to highlight a button on click, and another one wants to show a message on the same click. +যেমন ধরা যাক, আমরা বাটন ক্লিকে আমরা তা হাইলাইট করতে চায়, এবং তারপর ঐ ক্লিকে একটি মেসেজ দেখাব। -We'd like to assign two event handlers for that. But a new DOM property will overwrite the existing one: +আমরা এজন্য দুটি হ্যান্ডেলার অ্যাসাইন করতে চাই। কিন্তু DOM প্রপার্টি বিদ্যমান হ্যান্ডেলারকে নতুনটি দ্বারা প্রতিস্থাপন করে দেয়: ```js no-beautify input.onclick = function() { alert(1); } // ... -input.onclick = function() { alert(2); } // replaces the previous handler +input.onclick = function() { alert(2); } // পূর্ববর্তী হ্যান্ডেলারকে নতুনটি দ্বারা প্রতিস্থাপন ``` -Developers of web standards understood that long ago and suggested an alternative way of managing handlers using special methods `addEventListener` and `removeEventListener`. They are free of such a problem. +এজন্য ডেভলাপাররা এই সমস্যা সমাধানের জন্য আরো দুটি বিশেষ মেথড নিয়ে আসে `addEventListener` এবং `removeEventListener`। এদের সাহায্যে আমরা এই সমস্যার সমাধান করতে পারি। -The syntax to add a handler: +হ্যান্ডেলার অ্যাসাইনের সিনট্যাক্সটি হল: ```js element.addEventListener(event, handler, [options]); ``` `event` -: Event name, e.g. `"click"`. +: ইভেন্টের নাম, যেমন `"click"`। `handler` -: The handler function. +: হ্যান্ডেলার ফাংশন `options` -: An additional optional object with properties: - - `once`: if `true`, then the listener is automatically removed after it triggers. - - `capture`: the phase where to handle the event, to be covered later in the chapter . For historical reasons, `options` can also be `false/true`, that's the same as `{capture: false/true}`. - - `passive`: if `true`, then the handler will not call `preventDefault()`, we'll explain that later in . +: কিছু ঐচ্ছিক প্রপার্টির একটি অবজেক্ট: + - `once`: যদি `true` হয়, তাহলে এটি একবার কল হওয়ার পর স্বয়ংক্রিয়ভাবে রিমুভ হয়ে যাবে। + - `capture`: এই ব্যাপারে আমরা পরবর্তী অধ্যায়ে জানব । তবে জেনে রাখুন, `options` টি `false/true` হতে পারে, অর্থাৎ `{capture: false/true}`। + - `passive`: যদি `true` হয়, তাহলে হ্যান্ডেলার `preventDefault()` কে কল করবে না, আরো বিস্তারিত জানব এই অধ্যায়ে । -To remove the handler, use `removeEventListener`: +হ্যান্ডেলার রিমুভের জন্য, `removeEventListener`: ```js element.removeEventListener(event, handler, [options]); ``` -````warn header="Removal requires the same function" -To remove a handler we should pass exactly the same function as was assigned. +````warn header="রিমুভ করা যায় একই ফাংশনকে" +হ্যান্ডেলারকে ফাংশনকে রিমুভের জন্য অ্যাসাইকৃত ফাংশনটিই পাস করতে হবে। -This doesn't work: +এটি কাজ করবে না: ```js no-beautify elem.addEventListener( "click" , () => alert('Thanks!')); @@ -244,9 +242,9 @@ elem.addEventListener( "click" , () => alert('Thanks!')); elem.removeEventListener( "click", () => alert('Thanks!')); ``` -The handler won't be removed, because `removeEventListener` gets another function -- with the same code, but that doesn't matter, as it's a different function object. +হ্যান্ডেলার রিমুভ কাজ করবে না, কেননা `removeEventListener` ফাংশনটি একই কোডের আরেকটি ফাংশন, কিন্তু এটি কোন ব্যাপার না, কেননা এটি ভিন্ন ফাংশন অবজেক্ট। -Here's the right way: +এটি কাজ করবে: ```js function handler() { @@ -258,10 +256,10 @@ input.addEventListener("click", handler); input.removeEventListener("click", handler); ``` -Please note -- if we don't store the function in a variable, then we can't remove it. There's no way to "read back" handlers assigned by `addEventListener`. +সুতরাং আমরা বলতে পারি -- কোন ধরণের অ্যানোনিমাস ফাংশনকে আমরা রিমুভ করতে পারব না। ```` -Multiple calls to `addEventListener` allow to add multiple handlers, like this: +`addEventListener` এর মাধ্যমে একাধিক হ্যান্ডেলার কল করার উপায়টি, এমন: ```html run no-beautify @@ -283,78 +281,78 @@ Multiple calls to `addEventListener` allow to add multiple handlers, like this: ``` -As we can see in the example above, we can set handlers *both* using a DOM-property and `addEventListener`. But generally we use only one of these ways. +উপরের উদাহরণে আমরা দেখছি, আমরা DOM-property এবং `addEventListener` এর মাধ্যমে হ্যান্ডেলার অ্যাসাইন করছি। তবে সাধারণত আমরা যেকোন এক উপায়ে হ্যান্ডেলার সেট করব। -````warn header="For some events, handlers only work with `addEventListener`" -There exist events that can't be assigned via a DOM-property. Only with `addEventListener`. +````warn header="কিছু ইভেন্ট আছে শুধু `addEventListener` এর সাথে কাজ করে" +কিছু ইভেন্ট আছে যারা DOM-property এর সাথে কাজ করে না, শুধুমাত্র `addEventListener` এর মাধ্যমে কাজ করে। -For instance, the `DOMContentLoaded` event, that triggers when the document is loaded and DOM is built. +যেমন, `DOMContentLoaded` ইভেন্ট, এটি ট্রিগার হয় যখন সম্পূর্ন DOM লোড হয়ে DOM অবজেক্টটি তৈরি হয়। ```js -// will never run +// এটি রান হবে না document.onDOMContentLoaded = function() { alert("DOM built"); }; ``` ```js -// this way it works +// এটি কাজ করবে document.addEventListener("DOMContentLoaded", function() { alert("DOM built"); }); ``` -So `addEventListener` is more universal. Although, such events are an exception rather than the rule. +সুতরাং `addEventListener` আরো বেশি সুবিধাজনক। এছাড়াও, এই ধরণের ইভেন্ট সমূহ কিছু ব্যতিক্রম। ```` ## Event object -To properly handle an event we'd want to know more about what's happened. Not just a "click" or a "keydown", but what were the pointer coordinates? Which key was pressed? And so on. +ইভেন্ট নিয়ে কাজ করার সময় আমাদের অনেক ব্যাপার জানা লাগে, এটি শুধু "ক্লিক" বা "কী প্রেসে" সীমাবদ্ধ না, আমাদের জানা লাগতে পারে কোন কী প্রেস করা হয়েছে বা কোন স্থানাংকে মাউস ক্লিক হয়েছে। -When an event happens, the browser creates an *event object*, puts details into it and passes it as an argument to the handler. +যখন কোন ইভেন্ট সংগঠিত হয়, ব্রাউজার *event object* তৈরি করে, এবং সকল বিস্তারিত প্রপার্টি নিয়ে *event object* টি হ্যান্ডেলারে পাস হয়। -Here's an example of getting pointer coordinates from the event object: +এখানে কোন স্থানাংকে মাউস ক্লিক হয়েছে তার একটি উদাহরণ দেখানো হল: ```html run ``` -Some properties of `event` object: +`event` অবজেক্ট এর কিছু প্রপার্টি: `event.type` -: Event type, here it's `"click"`. +: ইভেন্ট টাইপ, এখানে এটি `"click"`। `event.currentTarget` -: Element that handled the event. That's exactly the same as `this`, unless the handler is an arrow function, or its `this` is bound to something else, then we can get the element from `event.currentTarget`. +: যে এলিমেন্টে ইভেন্টটি সংগঠিত হয়। এটি এলিমেন্টের `this` এর মত, যতক্ষন হ্যান্ডেলারটি অ্যারো ফাংশনের সাহায্যে কল করা হয়, অন্যথায় `this` অন্য কোন কনট্যাক্স কে বুঝায়। `event.clientX / event.clientY` -: Window-relative coordinates of the cursor, for pointer events. +: windows এর সাপেক্ষে কার্সরের স্থানাংক। -There are more properties. Many of them depend on the event type: keyboard events have one set of properties, pointer events - another one, we'll study them later when we come to different events in details. +এছাড়াও আরো অনেক প্রপার্টি আছে। বেশিরভাগ ইভেন্টের ধরণের উপর নির্ভর করে: কী-বোর্ড ইভেন্টের প্রপার্টি এক ধরণের, পয়েন্টার ইভেন্টের প্রপার্টি অন্য ধরণের, পরবর্তী অধ্যায় সমূহে আমরা ইভেন্টের ধরণ অনুযায়ী বিস্তারিত জানব। -````smart header="The event object is also available in HTML handlers" -If we assign a handler in HTML, we can also use the `event` object, like this: +````smart header="HTML অ্যাট্রিবিউট হ্যান্ডেলারেও ইভেন্ট অবজেক্ট অ্যাক্সেস করা যায়" +যদি আমরা HTML এ কোন হ্যান্ডেলার অ্যাসাইন করি, আমরা `event` অবজেক্টটি এভাবে ব্যবহার করতে পারি: ```html autorun height=60 ``` -That's possible because when the browser reads the attribute, it creates a handler like this: `function(event) { alert(event.type) }`. That is: its first argument is called `"event"`, and the body is taken from the attribute. +এটি সম্ভব হয় কেননা যখন ব্রাউজার অ্যাট্রিবিউট হতে হ্যান্ডেলার ফাংশনটি এভাবে তৈরি করে: `function(event) { alert(event.type) }`। সুতরাং প্রথম আর্গুমেন্টটি হয় `"event"`। ```` ## Object handlers: handleEvent -We can assign not just a function, but an object as an event handler using `addEventListener`. When an event occurs, its `handleEvent` method is called. +আমরা চাইলে `addEventListener` এ কোন অবজেক্টকেও হ্যান্ডেলার হিসেবে পাস করতে পারি। যখন কোন ইভেন্ট সংগঠিত হয়, এটি `handleEvent` মেথডকে কল করে। -For instance: +যেমন: ```html run @@ -371,9 +369,9 @@ For instance: ``` -As we can see, when `addEventListener` receives an object as the handler, it calls `obj.handleEvent(event)` in case of an event. +এক্ষেত্রে আমরা দেখছি, `addEventListener` হ্যান্ডেলার হিসেবে একটি অবজেক্ট নিচ্ছে, এবং এক্ষেত্রে এটি `obj.handleEvent(event)` কে কল করে। -We could also use a class for that: +আমরা চাইলে ES-6 class সিনট্যাক্স ব্যবহার করতে পারি: ```html run @@ -401,9 +399,9 @@ We could also use a class for that: ``` -Here the same object handles both events. Please note that we need to explicitly setup the events to listen using `addEventListener`. The `menu` object only gets `mousedown` and `mouseup` here, not any other types of events. +এখানে একটি অবজেক্টকে আমরা উভয়ই ইভেন্টের হ্যান্ডেলার হিসেবে ব্যবহার করছি। দয়া করে নোট করুন `addEventListener` এর জন্য আমাদের অবজেক্টটিকে সঠিকভাবে সেটাপ করতে হবে। এক্ষেত্রে `menu` অবজেক্টটি শুধুমাত্র `mousedown` এবং `mouseup` এর সাথে কাজ করবে, অন্যান্য ইভেন্টের জন্য এটি কাজ করবে না। -The method `handleEvent` does not have to do all the job by itself. It can call other event-specific methods instead, like this: +আমরা `handleEvent` মেথডটিকে চাইলে এভাবে ডায়নামিক্যালি ব্যবহার করতে পারি: ```html run @@ -431,22 +429,22 @@ The method `handleEvent` does not have to do all the job by itself. It can call ``` -Now event handlers are clearly separated, that may be easier to support. +এখানে আমরা হ্যান্ডেলার ফাংশনকে আলাদা করে নিলাম, কোডটি পড়তে এবং পরিবর্তন করা সহজ হবে। -## Summary +## সারাংশ -There are 3 ways to assign event handlers: +তিনভাবে আমরা ইভেন্ট হ্যান্ডেলার অ্যাসাইন করতে পারি: -1. HTML attribute: `onclick="..."`. -2. DOM property: `elem.onclick = function`. -3. Methods: `elem.addEventListener(event, handler[, phase])` to add, `removeEventListener` to remove. +1. HTML attribute: `onclick="..."`। +2. DOM property: `elem.onclick = function`। +3. মেথডের সাহায্যে: `elem.addEventListener(event, handler[, phase])` হ্যান্ডেলার সংযুক্ত করতে, `removeEventListener` হ্যান্ডেলার রিমুভ করতে। -HTML attributes are used sparingly, because JavaScript in the middle of an HTML tag looks a little bit odd and alien. Also can't write lots of code in there. +HTML attribute এর সাহায্যে ইভেন্ট খুব কম লিখা হয়, কেননা HTML এ জাভাস্ক্রিপ্ট দেখতে বিদঘুটে লাগে। এছাড়াও আমরা অনেক কোড একসাথে লিখতে পারি না। -DOM properties are ok to use, but we can't assign more than one handler of the particular event. In many cases that limitation is not pressing. +আমরা DOM প্রপার্টির সাহায্যে হ্যান্ডেলার অ্যাসাইন করতে পারি, কিন্তু এর একটি সীমাবদ্ধতা আছে, আমরা শুধুমাত্র একটি হ্যান্ডেলার অ্যাসাইন করতে পারি। -The last way is the most flexible, but it is also the longest to write. There are few events that only work with it, for instance `transitionend` and `DOMContentLoaded` (to be covered). Also `addEventListener` supports objects as event handlers. In that case the method `handleEvent` is called in case of the event. +এবং শেষেরটি ব্যবহার আমাদের জন্য সুবিধাজনক, তবে এটি অন্য দুটি থেকে দেখতে কিছুটা বড়। এছাড়াও কিছু ইভেন্ট আছে যা এটি ছাড়া অন্য কোনভাবে কাজ করবে না, যেমন `transitionend` এবং `DOMContentLoaded` (যা পরবর্তীতে আমরা দেখব)। এছাড়াও `addEventListener` হ্যান্ডেলার হিসেবে অবজেক্ট নিতে পারে। এক্ষেত্রে এটি ডায়নামিক্যালি `handleEvent` মেথড কে কল করে। -No matter how you assign the handler -- it gets an event object as the first argument. That object contains the details about what's happened. +আপনি যেভাবেই হ্যান্ডেলার অ্যাসাইন করুন না কেন -- প্রথম আর্গুমেন্টটি সর্বদা একটি *event object* হয়। যা ইভেন্ট সম্পর্কিত সকল তথ্য ধারণ করে। -We'll learn more about events in general and about different types of events in the next chapters. +এছাড়াও আমরা নির্দিষ্ট ইভেন্ট সম্পর্কিত বিস্তারিত পরবর্তী অধ্যায় সমূহে জানব। From c97f02972ca48768ea3221c350fdb744b91b4970 Mon Sep 17 00:00:00 2001 From: Saiful Date: Thu, 11 Mar 2021 02:12:43 +0600 Subject: [PATCH 4/8] translate bubbling --- .../02-bubbling-and-capturing/article.md | 170 +++++++++--------- 1 file changed, 85 insertions(+), 85 deletions(-) diff --git a/2-ui/2-events/02-bubbling-and-capturing/article.md b/2-ui/2-events/02-bubbling-and-capturing/article.md index e203a4eb4..f4e8aa497 100644 --- a/2-ui/2-events/02-bubbling-and-capturing/article.md +++ b/2-ui/2-events/02-bubbling-and-capturing/article.md @@ -1,8 +1,8 @@ -# Bubbling and capturing +# Bubbling এবং capturing -Let's start with an example. +একটি উদাহরণ দিয়ে শুরু করা যাক। -This handler is assigned to `
`, but also runs if you click any nested tag like `` or ``: +`
` এর মধ্যে একটি হ্যান্ডেলার অ্যাসাইন করলাম, কিন্তু যদি `` বা `` এ ক্লিক করা হয় তাহলেও এটি রান করবে: ```html autorun height=60
@@ -10,15 +10,15 @@ This handler is assigned to `
`, but also runs if you click any nested tag l
``` -Isn't it a bit strange? Why does the handler on `
` run if the actual click was on ``? +এটি কিছুটা অদ্ভুত না? কেন `` ক্লিকে `
` এর হ্যান্ডেলারটি রান হয়? ## Bubbling -The bubbling principle is simple. +এর প্রধান কারণ *bubbling*। -**When an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors.** +**যখন কোন এলিমেন্টে ইভেন্ট সংগঠিত হয়, প্রথমে এলিমেন্টটির হ্যান্ডেলার রান হবে, তারপর তার প্যারেন্টটি রান হবে, এভাবে তার উপরের এলিমেন্টটি রান হবে** -Let's say we have 3 nested elements `FORM > DIV > P` with a handler on each of them: +দেখা যাক আমাদের ৩ টি নেস্টেড এলিমেন্ট `FORM > DIV > P` আছে এবং তাদের প্রতিটিতে একটি হ্যান্ডেলার আছে: ```html run autorun - - - - The red text - - -``` - -...কিন্তু আমাদের যদি মার্জিন `20px` বাড়ানো লাগে তাহলে কি করব? এজন্য আমাদের বর্তমান ভ্যালু জানা দরকার। - -এজন্য আরেকটি মেথড আছে: `getComputedStyle`. - -সিন্ট্যাক্স হবে: - -```js -getComputedStyle(element, [pseudo]) -``` - -element -: এলিমেন্ট হল যার মান পড়া দরকার - -pseudo -: এটি প্রয়োজন হয় যদি সুডো মান জানা লাগে, যেমন `::before`। এটি ঐচ্ছিক। - -রেজাল্ট হবে style প্রপার্টি সমূহের অবজেক্ট, অনেকটা `elem.style` এর মত, তবে এখন এটি এলিমেন্টের সর্বশেষ মানটি পাবে। - -উদাহরণস্বরূপ: - -```html run height=100 - - - - - - - - -``` - -```smart header="Computed এবং resolved ভ্যালু" -এর দুটি ধারণা আছে [CSS](https://drafts.csswg.org/cssom/#resolved-values): - -1. *CSS cascade* এর ফলে *computed* স্ট্যাইল এর মান পাব আমরা সকল CSS রুলস এবং CSS ইনহেরিটেন্স অ্যাপ্লাই হওয়ার পর। যেমন `height:1em` অথবা `font-size:125%`। -2. *resolved* এর মান পাব এলিমেন্টে সর্বশেষ রুলস অ্যাপ্লাই হওয়ার পর। যেমন `1em` অথবা `125%` মানসমূহ আপেক্ষিক। ব্রাউজার *computed* মানটি নেয় এবং সকল সকল ইউনিটকে পরমমানে নির্দিষ্ট করে, যেমন: `height:20px` বা `font-size:16px`। জ্যামিতিক প্রপার্টিসমূহের মান ভগ্নাংশ আকারে হতে পারে, যেমন `width:50.5px`। - -পূর্বে `getComputedStyle` শুধুমাত্র *computed* স্ট্যাইল এর মানটি রিটার্ন করত, কিন্তু বর্তমানে এটি আরো সুবিধাজনক, *resolved* কৃতমান রিটার্ন করে। - -সুতরাং বর্তমানে `getComputedStyle` *resolved* কৃতমান রিটার্ন করে, সাধারণত জ্যামিতিক প্রপার্টিসমূহকে `px` এ রিটার্ন করে। -``` - -````warn header="`getComputedStyle` এ সম্পূর্ণ প্রপার্টির নাম প্রয়োজন" -আমাদের অবশ্যই প্রপার্টির মান হুবহু লিখা উচিত, যেমন *padding*, *margin* বা *border* এর বদলে যথাক্রমে `paddingLeft`, `marginTop` বা `borderTopWidth` লিখতে হবে। অন্যথায় এটি সর্বদা সঠিক মান দিবে তা নিশ্চিত নয়। - -যেমন, যদি আমরা `paddingLeft/paddingTop` এর মান জানতে চাই, তাহলে আমরা কি `getComputedStyle(elem).padding` এর মান পাব? এর কোন স্ট্যান্ডার্ড রুল নাই। - -এটি ব্রাউজার অনুযায়ী অসংগতি আচরণ করে, যেমন (Chrome) এ দেখাবে `10px` এবং (Firefox) -- কোন মান দেখাবে না: - -```html run - - -``` -```` - -```smart header="Styles applied to `:visited` লিংক অদৃশ্য!" -ভিজিটেড লিংক সমূহ হয়তবা CSS pseudoclass `:visited` এর জন্য একটি কালার দেখায়। - -কিন্তু `getComputedStyle` এটি কোন কালারের মান রিটার্ন করে না কারণ এটির অ্যাক্সেস থাকে না, কেননা একটি স্বতন্ত্র পেজে স্ট্যাইল যাচাইয়ের মাধ্যমে সহজেই জানা যাবে কোন কোন পেজ ভিজিট করা হয়েছে। - -তাই জাভাস্ক্রিপ্টের মাধ্যমে `:visited` এর মান জানা সম্ভব না। এটি আমাদের গোপনীয়তার নিশ্চয়তা প্রদান করে। -``` - -## সারাংশ - -ক্লাস ম্যানিপুলেসনের জন্য, দুটি DOM প্রপার্টি আছে: - -- `className` -- ক্লাস অ্যাট্রিবিউটের সকল ক্লাস স্ট্রিং হিসেবে রিটার্ন করে, এলিমেন্টের সকল ক্লাসের জন্য এটি উপযোগী। -- `classList` -- একটি অবজেক্ট যার মেথডসমূহ `add/remove/toggle/contains`, সিংগেল ক্লাসের জন্য উপযোগী। - -স্ট্যাইল পরিবর্তনের জন্য: - -- `style` প্রপার্টি একটি অবজেক্ট যার প্রপার্টি সমূহ ক্যামেল কেসের হয়ে থাকে। প্রতিটি একক প্রপার্টি পড়তে এবং অ্যাসাইন করতে এটি উপযোগী। কিভাবে আমরা `important` এবং অন্যান্য কদাচিৎ ব্যবহৃত বিষয়গুলো ব্যবহার করতে পারি -- তা জানতে এটি দেখুন [MDN](mdn:api/CSSStyleDeclaration)। -- `style.cssText` এর সাহায্যে আমরা একাধিক `"style"` অ্যাট্রিবিউট সেট করতে পারি। - -কোন এলিমেন্টের প্রয়োগকৃত সর্বশেষ সকল স্ট্যাইল জানতে: - -- `getComputedStyle(elem, [pseudo])` সকল প্রপার্টি রিটার্ন করবে. এটি Read-only। From 2cdc1715d7aadb896feda6e5e8992e15082339ac Mon Sep 17 00:00:00 2001 From: Mohammad Saiful Islam Date: Tue, 30 Mar 2021 20:31:56 +0600 Subject: [PATCH 7/8] Delete article.md --- .../01-introduction-browser-events/article.md | 450 ------------------ 1 file changed, 450 deletions(-) delete mode 100644 2-ui/2-events/01-introduction-browser-events/article.md diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md deleted file mode 100644 index 018ede551..000000000 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ /dev/null @@ -1,450 +0,0 @@ -# browser events এর সূচনা - -*event* হল কোন কিছু ঘটার একটি সংকেত। সকল DOM নোড এই ধরণের সংকেত জেনারেট করতে পারে(কিন্তু event শুধুমাত্র এর মধ্যই সীমাবদ্ধ না)। - -নিচে গুরুত্বপূর্ণ কিছু DOM ইভেন্ট নিয়ে আলোচনা করা হল: - -**Mouse events:** -- `click` -- যখন কোন এলিমেন্টে ক্লিক করা হয় (টাচস্ক্রীন ডিভাইসে ট্যাপ করলে)। -- `contextmenu` -- এলিমেন্টে মাউসের ডানের বাটনটি ক্লিক হলে। -- `mouseover` / `mouseout` -- কোন এলিমেন্টে মাউসের কার্সর আসলে অথবা এলিমেন্ট হতে ছেড়ে গেলে। -- `mousedown` / `mouseup` -- যখন কোন একটি এলিমেন্টে মাউস বাটন ক্লিক হয় বা ছাড়া হয়। -- `mousemove` -- যখন মাউস নাড়াচড়া করা হয়। - -**Keyboard events:** -- `keydown` এবং `keyup` -- যখন কি-বোর্ডে কোন বাটন প্রেস হয়, এবং বাটন প্রেস সম্পন্ন হয়। - -**Form element events:** -- `submit` -- যখন কোন একটি `` সাবমিট হয়। -- `focus` -- যখন কোন একটি এলিমেন্টে ফোকাস হয় যেমন, ``। - -**Document events:** -- `DOMContentLoaded` -- যখন DOM সম্পূর্ণ বিল্ট হয় এবং HTML লোড প্রসেসড হয়। - -**CSS events:** -- `transitionend` -- যখন একটি CSS-animation সম্পন্ন হয়। - -এছাড়াও আরো অনেক ইভেন্ট আছে। পরবর্তী অধ্যায় সমূহে আমরা আরো বিস্তারিত জানব। - -## Event handlers - -ইভেন্টগুলো কিভাবে সংগঠিত হবে তা অ্যাসাইন করা হয় *handler* দ্বারা -- এটি একটি ফাংশন। - -হ্যান্ডেলার হল ইউজারের চাহিদামত জাভাস্ক্রিপ্ট কোড রান করার একটি উপায়, অন্য কথায় ইভেন্ট সংগঠিত হলে যে ফাংশনটি কল হয়। - -বিভিন্নভাবে আমরা হ্যান্ডেলার অ্যাসাইন করতে পারি। চলুন, সবচেয়ে সহজটি দিয়ে শুরু করি। - -### HTML-attribute - -অ্যাট্রিবিউট আকারে হ্যান্ডেলার `on` সেট করা। - -যেমন, `input` এ একটি `click` হ্যান্ডেলার অ্যাসাইন করতে, আমরা `onclick` ব্যবহার করতে পারি, এভাবে: - -```html run - -``` - -মাউস ক্লিক হলে, `onclick` এর মধ্যের কোড রান হবে। - -দয়া করে মনে রাখুন `onclick` এর মধ্যে আমাদের একক উদ্ধৃতি চিহ্ন *''* ব্যবহার করা লাগবে, কেননা অ্যাট্রিবিউটটি যুগল উদ্ধৃতি চিহ্ন *""* দ্বারা লিখা হয়েছে। যদি আমরা উভয়ই যুগল উদ্ধৃতি চিহ্ন ব্যবহার করি, এভাবে: `onclick="alert("Click!")"`, তাহলে এটি কাজ করবে না। - -HTML-attribute এ অনেক কোড লিখা তেমন সুবিধাজনক না। সুতরাং আমাদের জন্য সুবিধাজনক হবে আলাদা ফাংশনে কোড লিখে তাদের কল করলে। - -**onclick এর মাধ্যমে ফাংশন কল** `countRabbits()`: - -```html autorun height=50 - - - -``` - -আমরা জানি অ্যাট্রিবিউট কেস-সেনসিটিভ না, সুতরাং `ONCLICK`, `onClick` এবং `onCLICK`... সব কাজ করবে তবে আদর্শ হল সর্বদা ছোট হাতের লিখা: `onclick`। - -### DOM property - -আমরা DOM প্রপার্টির মাধ্যমেও হ্যান্ডেলার অ্যাসাইন করতে পারি `on`। - -যেমন, `elem.onclick`: - -```html autorun - - -``` - -অ্যাট্রিবিটের সাহায্যে লিখিত হ্যান্ডেলারটি, একটি নতুন ফাংশন তৈরি করে এবং DOM প্রপার্টিতে এটি সেট করে। - -সুতরাং এটি পূর্ববর্তী টির মত কাজ করে। - -নিচের দুটি কোডের কাজ একই: - -1. শুধুমাত্র HTML: - - ```html autorun height=50 - - ``` -2. HTML + JS: - - ```html autorun height=50 - - - ``` - -প্রথম উদাহরণটিতে, অ্যাট্রিবিউটটি `button.onclick` ইনিশিয়ালাইজ করে, যেখানে দ্বিতীয় উদাহরণটি একটি -- স্ক্রিপ্ট, এটিই মূল পার্থক্য। - -**এক্ষেত্রে শুধুমাত্র একটি `onclick` প্রপার্টি থাকবে, সুতরাং আমরা একের অধিক হ্যান্ডেলার সেট করতে পারব না।** - -নিচের উদাহরণটিতে দেখুন স্ক্রিপ্টের ফাংশনটি অ্যাট্রিবিউট হ্যান্ডেলারকে ওভাররাইট করে: - -```html run height=50 autorun - - -``` - - হ্যান্ডেলার রিমুভ করতে -- `elem.onclick = null`। - -## this এর মাধ্যমে এলিমেন্টকে অ্যাক্সেস - -হ্যান্ডেলারের মধ্যে `this` দ্বারা এলিমেন্টটিকে মির্দেশ করে। অর্থাৎ যে এলিমেন্টটি হ্যান্ডেলারে লিখা হয়েছে। - -নিচের কোডটি রান হলে এটি `button` এর কন্টেন্টটি দেখাবে `this.innerHTML`: - -```html height=50 autorun - -``` - -## Possible mistakes - -যখন আমরা ইভেন্ট নিয়ে কোন কাজ করব --আমাদের কিছু ব্যপার মনে রাখতে হবে। - -আমরা কোন এক্সিটিং ফাংশনকে এভাবে হ্যান্ডেলার হিসেবে সেট করতে পারি: - -```js -function sayThanks() { - alert('Thanks!'); -} - -elem.onclick = sayThanks; -``` - -কিন্তু সাবধান! আমাদের ফাংশনটি এভাবে অ্যাসাইন করতে হবে `sayThanks`, `sayThanks()` কাজ করবে না। - -```js -// সঠিক -button.onclick = sayThanks; - -// ভুল -button.onclick = sayThanks(); -``` - -যদি আমরা প্যারেন্টেসিস সহকারে লিখি, তাহলে `sayThanks()` একটি ফাংশন কল হবে। শেষেরটি *result*ঠিসেবে নতুন আরেকটি ফাংশন এক্সিকিউশন হিসেবে নেয়, যা `undefined`, এবং এটি `onclick` অ্যাসাইন করে। তাই এটি কাজ করবে না। - -...আবার অন্যদিকে, এলিমেন্ট হতে কল করলে প্যারেন্টেসিস সহকারে করতে হবে: - -```html - -``` - -এটি নিচের কোডটি দেখলে আমরা সহজেই বুঝতে পারব, ব্রাউজার অ্যাট্রিবিউট হতে কন্টেন্ট নিয়ে ফাংশনটিকে এভাবে কল করে: -```js -button.onclick = function() { -*!* - sayThanks(); // <-- অ্যাট্রিবিউটের কন্টেন্ট এখানে সেট হয় -*/!* -}; -``` - -**হ্যান্ডেলার সেট করতে `setAttribute` ব্যবহার করবেন না** - -এটি কাজ করবে না: - -```js run no-beautify -// বডিতে ক্লিক করলে ইরোর দেখাবে, -// কেননা অ্যাট্রিবিউট সমূহ সর্বদা স্ট্রিং হিসেবে সেট হয় -document.body.setAttribute('onclick', function() { alert(1) }); -``` - -**DOM-property এর ক্ষেত্রে কেস গুরুত্বপূর্ন** - -হ্যান্ডেলার অ্যাসাইন করতে `elem.onclick` কাজ করবে, কিন্তু `elem.ONCLICK` কাজ করবে না, কেননা DOM প্রপার্টি সমূহ কেস-সেনসিটিভ। - -## addEventListener - -উপরোল্লিখিত নিয়ম অনুযায়ী হ্যান্ডেলার অ্যাসাইনের মূল সমস্যা হল -- আমরা একাধিক হ্যান্ডেলার অ্যাসাইন করতে পারব না। - -যেমন ধরা যাক, আমরা বাটন ক্লিকে আমরা তা হাইলাইট করতে চায়, এবং তারপর ঐ ক্লিকে একটি মেসেজ দেখাব। - -আমরা এজন্য দুটি হ্যান্ডেলার অ্যাসাইন করতে চাই। কিন্তু DOM প্রপার্টি বিদ্যমান হ্যান্ডেলারকে নতুনটি দ্বারা প্রতিস্থাপন করে দেয়: - -```js no-beautify -input.onclick = function() { alert(1); } -// ... -input.onclick = function() { alert(2); } // পূর্ববর্তী হ্যান্ডেলারকে নতুনটি দ্বারা প্রতিস্থাপন -``` - -এজন্য ডেভলাপাররা এই সমস্যা সমাধানের জন্য আরো দুটি বিশেষ মেথড নিয়ে আসে `addEventListener` এবং `removeEventListener`। এদের সাহায্যে আমরা এই সমস্যার সমাধান করতে পারি। - -হ্যান্ডেলার অ্যাসাইনের সিনট্যাক্সটি হল: - -```js -element.addEventListener(event, handler, [options]); -``` - -`event` -: ইভেন্টের নাম, যেমন `"click"`। - -`handler` -: হ্যান্ডেলার ফাংশন - -`options` -: কিছু ঐচ্ছিক প্রপার্টির একটি অবজেক্ট: - - `once`: যদি `true` হয়, তাহলে এটি একবার কল হওয়ার পর স্বয়ংক্রিয়ভাবে রিমুভ হয়ে যাবে। - - `capture`: এই ব্যাপারে আমরা পরবর্তী অধ্যায়ে জানব । তবে জেনে রাখুন, `options` টি `false/true` হতে পারে, অর্থাৎ `{capture: false/true}`। - - `passive`: যদি `true` হয়, তাহলে হ্যান্ডেলার `preventDefault()` কে কল করবে না, আরো বিস্তারিত জানব এই অধ্যায়ে । - -হ্যান্ডেলার রিমুভের জন্য, `removeEventListener`: - -```js -element.removeEventListener(event, handler, [options]); -``` - -````warn header="রিমুভ করা যায় একই ফাংশনকে" -হ্যান্ডেলারকে ফাংশনকে রিমুভের জন্য অ্যাসাইকৃত ফাংশনটিই পাস করতে হবে। - -এটি কাজ করবে না: - -```js no-beautify -elem.addEventListener( "click" , () => alert('Thanks!')); -// .... -elem.removeEventListener( "click", () => alert('Thanks!')); -``` - -হ্যান্ডেলার রিমুভ কাজ করবে না, কেননা `removeEventListener` ফাংশনটি একই কোডের আরেকটি ফাংশন, কিন্তু এটি কোন ব্যাপার না, কেননা এটি ভিন্ন ফাংশন অবজেক্ট। - -এটি কাজ করবে: - -```js -function handler() { - alert( 'Thanks!' ); -} - -input.addEventListener("click", handler); -// .... -input.removeEventListener("click", handler); -``` - -সুতরাং আমরা বলতে পারি -- কোন ধরণের অ্যানোনিমাস ফাংশনকে আমরা রিমুভ করতে পারব না। -```` - -`addEventListener` এর মাধ্যমে একাধিক হ্যান্ডেলার কল করার উপায়টি, এমন: - -```html run no-beautify - - - -``` - -উপরের উদাহরণে আমরা দেখছি, আমরা DOM-property এবং `addEventListener` এর মাধ্যমে হ্যান্ডেলার অ্যাসাইন করছি। তবে সাধারণত আমরা যেকোন এক উপায়ে হ্যান্ডেলার সেট করব। - -````warn header="কিছু ইভেন্ট আছে শুধু `addEventListener` এর সাথে কাজ করে" -কিছু ইভেন্ট আছে যারা DOM-property এর সাথে কাজ করে না, শুধুমাত্র `addEventListener` এর মাধ্যমে কাজ করে। - -যেমন, `DOMContentLoaded` ইভেন্ট, এটি ট্রিগার হয় যখন সম্পূর্ন DOM লোড হয়ে DOM অবজেক্টটি তৈরি হয়। - -```js -// এটি রান হবে না -document.onDOMContentLoaded = function() { - alert("DOM built"); -}; -``` - -```js -// এটি কাজ করবে -document.addEventListener("DOMContentLoaded", function() { - alert("DOM built"); -}); -``` -সুতরাং `addEventListener` আরো বেশি সুবিধাজনক। এছাড়াও, এই ধরণের ইভেন্ট সমূহ কিছু ব্যতিক্রম। -```` - -## Event object - -ইভেন্ট নিয়ে কাজ করার সময় আমাদের অনেক ব্যাপার জানা লাগে, এটি শুধু "ক্লিক" বা "কী প্রেসে" সীমাবদ্ধ না, আমাদের জানা লাগতে পারে কোন কী প্রেস করা হয়েছে বা কোন স্থানাংকে মাউস ক্লিক হয়েছে। - -যখন কোন ইভেন্ট সংগঠিত হয়, ব্রাউজার *event object* তৈরি করে, এবং সকল বিস্তারিত প্রপার্টি নিয়ে *event object* টি হ্যান্ডেলারে পাস হয়। - -এখানে কোন স্থানাংকে মাউস ক্লিক হয়েছে তার একটি উদাহরণ দেখানো হল: - -```html run - - - -``` - -`event` অবজেক্ট এর কিছু প্রপার্টি: - -`event.type` -: ইভেন্ট টাইপ, এখানে এটি `"click"`। - -`event.currentTarget` -: যে এলিমেন্টে ইভেন্টটি সংগঠিত হয়। এটি এলিমেন্টের `this` এর মত, যতক্ষন হ্যান্ডেলারটি অ্যারো ফাংশনের সাহায্যে কল করা হয়, অন্যথায় `this` অন্য কোন কনট্যাক্স কে বুঝায়। - -`event.clientX / event.clientY` -: windows এর সাপেক্ষে কার্সরের স্থানাংক। - -এছাড়াও আরো অনেক প্রপার্টি আছে। বেশিরভাগ ইভেন্টের ধরণের উপর নির্ভর করে: কী-বোর্ড ইভেন্টের প্রপার্টি এক ধরণের, পয়েন্টার ইভেন্টের প্রপার্টি অন্য ধরণের, পরবর্তী অধ্যায় সমূহে আমরা ইভেন্টের ধরণ অনুযায়ী বিস্তারিত জানব। - -````smart header="HTML অ্যাট্রিবিউট হ্যান্ডেলারেও ইভেন্ট অবজেক্ট অ্যাক্সেস করা যায়" -যদি আমরা HTML এ কোন হ্যান্ডেলার অ্যাসাইন করি, আমরা `event` অবজেক্টটি এভাবে ব্যবহার করতে পারি: - -```html autorun height=60 - -``` - -এটি সম্ভব হয় কেননা যখন ব্রাউজার অ্যাট্রিবিউট হতে হ্যান্ডেলার ফাংশনটি এভাবে তৈরি করে: `function(event) { alert(event.type) }`। সুতরাং প্রথম আর্গুমেন্টটি হয় `"event"`। -```` - - -## Object handlers: handleEvent - -আমরা চাইলে `addEventListener` এ কোন অবজেক্টকেও হ্যান্ডেলার হিসেবে পাস করতে পারি। যখন কোন ইভেন্ট সংগঠিত হয়, এটি `handleEvent` মেথডকে কল করে। - -যেমন: - - -```html run - - - -``` - -এক্ষেত্রে আমরা দেখছি, `addEventListener` হ্যান্ডেলার হিসেবে একটি অবজেক্ট নিচ্ছে, এবং এক্ষেত্রে এটি `obj.handleEvent(event)` কে কল করে। - -আমরা চাইলে ES-6 class সিনট্যাক্স ব্যবহার করতে পারি: - - -```html run - - - -``` - -এখানে একটি অবজেক্টকে আমরা উভয়ই ইভেন্টের হ্যান্ডেলার হিসেবে ব্যবহার করছি। দয়া করে নোট করুন `addEventListener` এর জন্য আমাদের অবজেক্টটিকে সঠিকভাবে সেটাপ করতে হবে। এক্ষেত্রে `menu` অবজেক্টটি শুধুমাত্র `mousedown` এবং `mouseup` এর সাথে কাজ করবে, অন্যান্য ইভেন্টের জন্য এটি কাজ করবে না। - -আমরা `handleEvent` মেথডটিকে চাইলে এভাবে ডায়নামিক্যালি ব্যবহার করতে পারি: - -```html run - - - -``` - -এখানে আমরা হ্যান্ডেলার ফাংশনকে আলাদা করে নিলাম, কোডটি পড়তে এবং পরিবর্তন করা সহজ হবে। - -## সারাংশ - -তিনভাবে আমরা ইভেন্ট হ্যান্ডেলার অ্যাসাইন করতে পারি: - -1. HTML attribute: `onclick="..."`। -2. DOM property: `elem.onclick = function`। -3. মেথডের সাহায্যে: `elem.addEventListener(event, handler[, phase])` হ্যান্ডেলার সংযুক্ত করতে, `removeEventListener` হ্যান্ডেলার রিমুভ করতে। - -HTML attribute এর সাহায্যে ইভেন্ট খুব কম লিখা হয়, কেননা HTML এ জাভাস্ক্রিপ্ট দেখতে বিদঘুটে লাগে। এছাড়াও আমরা অনেক কোড একসাথে লিখতে পারি না। - -আমরা DOM প্রপার্টির সাহায্যে হ্যান্ডেলার অ্যাসাইন করতে পারি, কিন্তু এর একটি সীমাবদ্ধতা আছে, আমরা শুধুমাত্র একটি হ্যান্ডেলার অ্যাসাইন করতে পারি। - -এবং শেষেরটি ব্যবহার আমাদের জন্য সুবিধাজনক, তবে এটি অন্য দুটি থেকে দেখতে কিছুটা বড়। এছাড়াও কিছু ইভেন্ট আছে যা এটি ছাড়া অন্য কোনভাবে কাজ করবে না, যেমন `transitionend` এবং `DOMContentLoaded` (যা পরবর্তীতে আমরা দেখব)। এছাড়াও `addEventListener` হ্যান্ডেলার হিসেবে অবজেক্ট নিতে পারে। এক্ষেত্রে এটি ডায়নামিক্যালি `handleEvent` মেথড কে কল করে। - -আপনি যেভাবেই হ্যান্ডেলার অ্যাসাইন করুন না কেন -- প্রথম আর্গুমেন্টটি সর্বদা একটি *event object* হয়। যা ইভেন্ট সম্পর্কিত সকল তথ্য ধারণ করে। - -এছাড়াও আমরা নির্দিষ্ট ইভেন্ট সম্পর্কিত বিস্তারিত পরবর্তী অধ্যায় সমূহে জানব। From 44b952332c2b82901dd290418fbb032fb3b2dd63 Mon Sep 17 00:00:00 2001 From: Saiful Date: Tue, 27 Apr 2021 05:29:10 +0600 Subject: [PATCH 8/8] fixed --- .../2-create-notification/task.md | 24 + .../08-styles-and-classes/article.md | 303 ++++++++++++ .../01-introduction-browser-events/article.md | 452 ++++++++++++++++++ 3 files changed, 779 insertions(+) create mode 100644 2-ui/1-document/08-styles-and-classes/2-create-notification/task.md create mode 100644 2-ui/1-document/08-styles-and-classes/article.md create mode 100644 2-ui/2-events/01-introduction-browser-events/article.md diff --git a/2-ui/1-document/08-styles-and-classes/2-create-notification/task.md b/2-ui/1-document/08-styles-and-classes/2-create-notification/task.md new file mode 100644 index 000000000..60930cb6c --- /dev/null +++ b/2-ui/1-document/08-styles-and-classes/2-create-notification/task.md @@ -0,0 +1,24 @@ +importance: 5 + +--- + +# Create a notification + +Write a function `showNotification(options)` that creates a notification: `
` with the given content. The notification should automatically disappear after 1.5 seconds. + +The options are: + +```js +// shows an element with the text "Hello" near the right-top of the window +showNotification({ + top: 10, // 10px from the top of the window (by default 0px) + right: 10, // 10px from the right edge of the window (by default 0px) + html: "Hello!", // the HTML of notification + className: "welcome" // an additional class for the div (optional) +}); +``` + +[demo src="solution"] + + +Use CSS positioning to show the element at given top/right coordinates. The source document has the necessary styles. diff --git a/2-ui/1-document/08-styles-and-classes/article.md b/2-ui/1-document/08-styles-and-classes/article.md new file mode 100644 index 000000000..9154d43d6 --- /dev/null +++ b/2-ui/1-document/08-styles-and-classes/article.md @@ -0,0 +1,303 @@ +# Styles and classes + +Before we get into JavaScript's ways of dealing with styles and classes -- here's an important rule. Hopefully it's obvious enough, but we still have to mention it. + +There are generally two ways to style an element: + +1. Create a class in CSS and add it: `
` +2. Write properties directly into `style`: `
`. + +JavaScript can modify both classes and `style` properties. + +We should always prefer CSS classes to `style`. The latter should only be used if classes "can't handle it". + +For example, `style` is acceptable if we calculate coordinates of an element dynamically and want to set them from JavaScript, like this: + +```js +let top = /* complex calculations */; +let left = /* complex calculations */; + +elem.style.left = left; // e.g '123px', calculated at run-time +elem.style.top = top; // e.g '456px' +``` + +For other cases, like making the text red, adding a background icon -- describe that in CSS and then add the class (JavaScript can do that). That's more flexible and easier to support. + +## className and classList + +Changing a class is one of the most often used actions in scripts. + +In the ancient time, there was a limitation in JavaScript: a reserved word like `"class"` could not be an object property. That limitation does not exist now, but at that time it was impossible to have a `"class"` property, like `elem.class`. + +So for classes the similar-looking property `"className"` was introduced: the `elem.className` corresponds to the `"class"` attribute. + +For instance: + +```html run + + + +``` + +If we assign something to `elem.className`, it replaces the whole string of classes. Sometimes that's what we need, but often we want to add/remove a single class. + +There's another property for that: `elem.classList`. + +The `elem.classList` is a special object with methods to `add/remove/toggle` a single class. + +For instance: + +```html run + + + +``` + +So we can operate both on the full class string using `className` or on individual classes using `classList`. What we choose depends on our needs. + +Methods of `classList`: + +- `elem.classList.add/remove("class")` -- adds/removes the class. +- `elem.classList.toggle("class")` -- adds the class if it doesn't exist, otherwise removes it. +- `elem.classList.contains("class")` -- checks for the given class, returns `true/false`. + +Besides, `classList` is iterable, so we can list all classes with `for..of`, like this: + +```html run + + + +``` + +## Element style + +The property `elem.style` is an object that corresponds to what's written in the `"style"` attribute. Setting `elem.style.width="100px"` works the same as if we had in the attribute `style` a string `width:100px`. + +For multi-word property the camelCase is used: + +```js no-beautify +background-color => elem.style.backgroundColor +z-index => elem.style.zIndex +border-left-width => elem.style.borderLeftWidth +``` + +For instance: + +```js run +document.body.style.backgroundColor = prompt('background color?', 'green'); +``` + +````smart header="Prefixed properties" +Browser-prefixed properties like `-moz-border-radius`, `-webkit-border-radius` also follow the same rule: a dash means upper case. + +For instance: + +```js +button.style.MozBorderRadius = '5px'; +button.style.WebkitBorderRadius = '5px'; +``` +```` + +## Resetting the style property + +Sometimes we want to assign a style property, and later remove it. + +For instance, to hide an element, we can set `elem.style.display = "none"`. + +Then later we may want to remove the `style.display` as if it were not set. Instead of `delete elem.style.display` we should assign an empty string to it: `elem.style.display = ""`. + +```js run +// if we run this code, the will blink +document.body.style.display = "none"; // hide + +setTimeout(() => document.body.style.display = "", 1000); // back to normal +``` + +If we set `style.display` to an empty string, then the browser applies CSS classes and its built-in styles normally, as if there were no such `style.display` property at all. + +````smart header="Full rewrite with `style.cssText`" +Normally, we use `style.*` to assign individual style properties. We can't set the full style like `div.style="color: red; width: 100px"`, because `div.style` is an object, and it's read-only. + +To set the full style as a string, there's a special property `style.cssText`: + +```html run +
Button
+ + +``` + +This property is rarely used, because such assignment removes all existing styles: it does not add, but replaces them. May occasionally delete something needed. But we can safely use it for new elements, when we know we won't delete an existing style. + +The same can be accomplished by setting an attribute: `div.setAttribute('style', 'color: red...')`. +```` + +## Mind the units + +Don't forget to add CSS units to values. + +For instance, we should not set `elem.style.top` to `10`, but rather to `10px`. Otherwise it wouldn't work: + +```html run height=100 + + + +``` + +Please note: the browser "unpacks" the property `style.margin` in the last lines and infers `style.marginLeft` and `style.marginTop` from it. + +## Computed styles: getComputedStyle + +So, modifying a style is easy. But how to *read* it? + +For instance, we want to know the size, margins, the color of an element. How to do it? + +**The `style` property operates only on the value of the `"style"` attribute, without any CSS cascade.** + +So we can't read anything that comes from CSS classes using `elem.style`. + +For instance, here `style` doesn't see the margin: + +```html run height=60 no-beautify + + + + + + The red text + + +``` + +...But what if we need, say, to increase the margin by `20px`? We would want the current value of it. + +There's another method for that: `getComputedStyle`. + +The syntax is: + +```js +getComputedStyle(element, [pseudo]) +``` + +element +: Element to read the value for. + +pseudo +: A pseudo-element if required, for instance `::before`. An empty string or no argument means the element itself. + +The result is an object with styles, like `elem.style`, but now with respect to all CSS classes. + +For instance: + +```html run height=100 + + + + + + + + +``` + +```smart header="Computed and resolved values" +There are two concepts in [CSS](https://drafts.csswg.org/cssom/#resolved-values): + +1. A *computed* style value is the value after all CSS rules and CSS inheritance is applied, as the result of the CSS cascade. It can look like `height:1em` or `font-size:125%`. +2. A *resolved* style value is the one finally applied to the element. Values like `1em` or `125%` are relative. The browser takes the computed value and makes all units fixed and absolute, for instance: `height:20px` or `font-size:16px`. For geometry properties resolved values may have a floating point, like `width:50.5px`. + +A long time ago `getComputedStyle` was created to get computed values, but it turned out that resolved values are much more convenient, and the standard changed. + +So nowadays `getComputedStyle` actually returns the resolved value of the property, usually in `px` for geometry. +``` + +````warn header="`getComputedStyle` requires the full property name" +We should always ask for the exact property that we want, like `paddingLeft` or `marginTop` or `borderTopWidth`. Otherwise the correct result is not guaranteed. + +For instance, if there are properties `paddingLeft/paddingTop`, then what should we get for `getComputedStyle(elem).padding`? Nothing, or maybe a "generated" value from known paddings? There's no standard rule here. + +There are other inconsistencies. As an example, some browsers (Chrome) show `10px` in the document below, and some of them (Firefox) -- do not: + +```html run + + +``` +```` + +```smart header="Styles applied to `:visited` links are hidden!" +Visited links may be colored using `:visited` CSS pseudoclass. + +But `getComputedStyle` does not give access to that color, because otherwise an arbitrary page could find out whether the user visited a link by creating it on the page and checking the styles. + +JavaScript may not see the styles applied by `:visited`. And also, there's a limitation in CSS that forbids applying geometry-changing styles in `:visited`. That's to guarantee that there's no side way for an evil page to test if a link was visited and hence to break the privacy. +``` + +## Summary + +To manage classes, there are two DOM properties: + +- `className` -- the string value, good to manage the whole set of classes. +- `classList` -- the object with methods `add/remove/toggle/contains`, good for individual classes. + +To change the styles: + +- The `style` property is an object with camelCased styles. Reading and writing to it has the same meaning as modifying individual properties in the `"style"` attribute. To see how to apply `important` and other rare stuff -- there's a list of methods at [MDN](mdn:api/CSSStyleDeclaration). + +- The `style.cssText` property corresponds to the whole `"style"` attribute, the full string of styles. + +To read the resolved styles (with respect to all classes, after all CSS is applied and final values are calculated): + +- The `getComputedStyle(elem, [pseudo])` returns the style-like object with them. Read-only. diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md new file mode 100644 index 000000000..19394e49e --- /dev/null +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -0,0 +1,452 @@ +# Introduction to browser events + +*An event* is a signal that something has happened. All DOM nodes generate such signals (but events are not limited to DOM). + +Here's a list of the most useful DOM events, just to take a look at: + +**Mouse events:** +- `click` -- when the mouse clicks on an element (touchscreen devices generate it on a tap). +- `contextmenu` -- when the mouse right-clicks on an element. +- `mouseover` / `mouseout` -- when the mouse cursor comes over / leaves an element. +- `mousedown` / `mouseup` -- when the mouse button is pressed / released over an element. +- `mousemove` -- when the mouse is moved. + +**Keyboard events:** +- `keydown` and `keyup` -- when a keyboard key is pressed and released. + +**Form element events:** +- `submit` -- when the visitor submits a ``. +- `focus` -- when the visitor focuses on an element, e.g. on an ``. + +**Document events:** +- `DOMContentLoaded` -- when the HTML is loaded and processed, DOM is fully built. + +**CSS events:** +- `transitionend` -- when a CSS-animation finishes. + +There are many other events. We'll get into more details of particular events in next chapters. + +## Event handlers + +To react on events we can assign a *handler* -- a function that runs in case of an event. + +Handlers are a way to run JavaScript code in case of user actions. + +There are several ways to assign a handler. Let's see them, starting from the simplest one. + +### HTML-attribute + +A handler can be set in HTML with an attribute named `on`. + +For instance, to assign a `click` handler for an `input`, we can use `onclick`, like here: + +```html run + +``` + +On mouse click, the code inside `onclick` runs. + +Please note that inside `onclick` we use single quotes, because the attribute itself is in double quotes. If we forget that the code is inside the attribute and use double quotes inside, like this: `onclick="alert("Click!")"`, then it won't work right. + +An HTML-attribute is not a convenient place to write a lot of code, so we'd better create a JavaScript function and call it there. + +Here a click runs the function `countRabbits()`: + +```html autorun height=50 + + + +``` + +As we know, HTML attribute names are not case-sensitive, so `ONCLICK` works as well as `onClick` and `onCLICK`... But usually attributes are lowercased: `onclick`. + +### DOM property + +We can assign a handler using a DOM property `on`. + +For instance, `elem.onclick`: + +```html autorun + + +``` + +If the handler is assigned using an HTML-attribute then the browser reads it, creates a new function from the attribute content and writes it to the DOM property. + +So this way is actually the same as the previous one. + +These two code pieces work the same: + +1. Only HTML: + + ```html autorun height=50 + + ``` +2. HTML + JS: + + ```html autorun height=50 + + + ``` + +In the first example, the HTML attribute is used to initialize the `button.onclick`, while in the second example -- the script, that's all the difference. + +**As there's only one `onclick` property, we can't assign more than one event handler.** + +In the example below adding a handler with JavaScript overwrites the existing handler: + +```html run height=50 autorun + + +``` + +To remove a handler -- assign `elem.onclick = null`. + +## Accessing the element: this + +The value of `this` inside a handler is the element. The one which has the handler on it. + +In the code below `button` shows its contents using `this.innerHTML`: + +```html height=50 autorun + +``` + +## Possible mistakes + +If you're starting to work with events -- please note some subtleties. + +We can set an existing function as a handler: + +```js +function sayThanks() { + alert('Thanks!'); +} + +elem.onclick = sayThanks; +``` + +But be careful: the function should be assigned as `sayThanks`, not `sayThanks()`. + +```js +// right +button.onclick = sayThanks; + +// wrong +button.onclick = sayThanks(); +``` + +If we add parentheses, then `sayThanks()` becomes is a function call. So the last line actually takes the *result* of the function execution, that is `undefined` (as the function returns nothing), and assigns it to `onclick`. That doesn't work. + +...On the other hand, in the markup we do need the parentheses: + +```html + +``` + +The difference is easy to explain. When the browser reads the attribute, it creates a handler function with body from the attribute content. + +So the markup generates this property: +```js +button.onclick = function() { +*!* + sayThanks(); // <-- the attribute content goes here +*/!* +}; +``` + +**Don't use `setAttribute` for handlers.** + +Such a call won't work: + +```js run no-beautify +// a click on will generate errors, +// because attributes are always strings, function becomes a string +document.body.setAttribute('onclick', function() { alert(1) }); +``` + +**DOM-property case matters.** + +Assign a handler to `elem.onclick`, not `elem.ONCLICK`, because DOM properties are case-sensitive. + +## addEventListener + +The fundamental problem of the aforementioned ways to assign handlers -- we can't assign multiple handlers to one event. + +Let's say, one part of our code wants to highlight a button on click, and another one wants to show a message on the same click. + +We'd like to assign two event handlers for that. But a new DOM property will overwrite the existing one: + +```js no-beautify +input.onclick = function() { alert(1); } +// ... +input.onclick = function() { alert(2); } // replaces the previous handler +``` + +Developers of web standards understood that long ago and suggested an alternative way of managing handlers using special methods `addEventListener` and `removeEventListener`. They are free of such a problem. + +The syntax to add a handler: + +```js +element.addEventListener(event, handler, [options]); +``` + +`event` +: Event name, e.g. `"click"`. + +`handler` +: The handler function. + +`options` +: An additional optional object with properties: + - `once`: if `true`, then the listener is automatically removed after it triggers. + - `capture`: the phase where to handle the event, to be covered later in the chapter . For historical reasons, `options` can also be `false/true`, that's the same as `{capture: false/true}`. + - `passive`: if `true`, then the handler will not call `preventDefault()`, we'll explain that later in . + +To remove the handler, use `removeEventListener`: + +```js +element.removeEventListener(event, handler, [options]); +``` + +````warn header="Removal requires the same function" +To remove a handler we should pass exactly the same function as was assigned. + +This doesn't work: + +```js no-beautify +elem.addEventListener( "click" , () => alert('Thanks!')); +// .... +elem.removeEventListener( "click", () => alert('Thanks!')); +``` + +The handler won't be removed, because `removeEventListener` gets another function -- with the same code, but that doesn't matter, as it's a different function object. + +Here's the right way: + +```js +function handler() { + alert( 'Thanks!' ); +} + +input.addEventListener("click", handler); +// .... +input.removeEventListener("click", handler); +``` + +Please note -- if we don't store the function in a variable, then we can't remove it. There's no way to "read back" handlers assigned by `addEventListener`. +```` + +Multiple calls to `addEventListener` allow to add multiple handlers, like this: + +```html run no-beautify + + + +``` + +As we can see in the example above, we can set handlers *both* using a DOM-property and `addEventListener`. But generally we use only one of these ways. + +````warn header="For some events, handlers only work with `addEventListener`" +There exist events that can't be assigned via a DOM-property. Only with `addEventListener`. + +For instance, the `DOMContentLoaded` event, that triggers when the document is loaded and DOM is built. + +```js +// will never run +document.onDOMContentLoaded = function() { + alert("DOM built"); +}; +``` + +```js +// this way it works +document.addEventListener("DOMContentLoaded", function() { + alert("DOM built"); +}); +``` +So `addEventListener` is more universal. Although, such events are an exception rather than the rule. +```` + +## Event object + +To properly handle an event we'd want to know more about what's happened. Not just a "click" or a "keydown", but what were the pointer coordinates? Which key was pressed? And so on. + +When an event happens, the browser creates an *event object*, puts details into it and passes it as an argument to the handler. + +Here's an example of getting pointer coordinates from the event object: + +```html run + + + +``` + +Some properties of `event` object: + +`event.type` +: Event type, here it's `"click"`. + +`event.currentTarget` +: Element that handled the event. That's exactly the same as `this`, unless the handler is an arrow function, or its `this` is bound to something else, then we can get the element from `event.currentTarget`. + +`event.clientX / event.clientY` +: Window-relative coordinates of the cursor, for pointer events. + +There are more properties. Many of them depend on the event type: keyboard events have one set of properties, pointer events - another one, we'll study them later when we come to different events in details. + +````smart header="The event object is also available in HTML handlers" +If we assign a handler in HTML, we can also use the `event` object, like this: + +```html autorun height=60 + +``` + +That's possible because when the browser reads the attribute, it creates a handler like this: `function(event) { alert(event.type) }`. That is: its first argument is called `"event"`, and the body is taken from the attribute. +```` + + +## Object handlers: handleEvent + +We can assign not just a function, but an object as an event handler using `addEventListener`. When an event occurs, its `handleEvent` method is called. + +For instance: + + +```html run + + + +``` + +As we can see, when `addEventListener` receives an object as the handler, it calls `obj.handleEvent(event)` in case of an event. + +We could also use a class for that: + + +```html run + + + +``` + +Here the same object handles both events. Please note that we need to explicitly setup the events to listen using `addEventListener`. The `menu` object only gets `mousedown` and `mouseup` here, not any other types of events. + +The method `handleEvent` does not have to do all the job by itself. It can call other event-specific methods instead, like this: + +```html run + + + +``` + +Now event handlers are clearly separated, that may be easier to support. + +## Summary + +There are 3 ways to assign event handlers: + +1. HTML attribute: `onclick="..."`. +2. DOM property: `elem.onclick = function`. +3. Methods: `elem.addEventListener(event, handler[, phase])` to add, `removeEventListener` to remove. + +HTML attributes are used sparingly, because JavaScript in the middle of an HTML tag looks a little bit odd and alien. Also can't write lots of code in there. + +DOM properties are ok to use, but we can't assign more than one handler of the particular event. In many cases that limitation is not pressing. + +The last way is the most flexible, but it is also the longest to write. There are few events that only work with it, for instance `transitionend` and `DOMContentLoaded` (to be covered). Also `addEventListener` supports objects as event handlers. In that case the method `handleEvent` is called in case of the event. + +No matter how you assign the handler -- it gets an event object as the first argument. That object contains the details about what's happened. + +We'll learn more about events in general and about different types of events in the next chapters.