diff --git a/1-js/01-getting-started/1-intro/article.md b/1-js/01-getting-started/1-intro/article.md index f8b58f81..35879ad6 100644 --- a/1-js/01-getting-started/1-intro/article.md +++ b/1-js/01-getting-started/1-intro/article.md @@ -28,9 +28,9 @@ Different engines have different "codenames", for example: - [Gecko](https://en.wikipedia.org/wiki/Gecko_(software)) -- in Firefox. - ...There are other codenames like "Trident", "Chakra" for different versions of IE, "ChakraCore" for Microsoft Edge, "Nitro" and "SquirrelFish" for Safari etc. -These terms above are good to remember, because they are used in developer articles in the internet. We'll use them too. For instance, if "a feature X is supported by V8", then it probably works in Chrome and Opera. +The terms above are good to remember, because they are used in developer articles in the internet. We'll use them too. For instance, if "a feature X is supported by V8", then it probably works in Chrome and Opera. -```smart header="How the engines work?" +```smart header="How engines work?" Engines are complicated. But the basics are easy. @@ -38,7 +38,7 @@ Engines are complicated. But the basics are easy. 2. The engine (embedded if it's a browser) reads the script ("parses") and converts ("compiles") it to the machine language. 3. And then it runs, pretty fast. -The engine applies optimizations on every stage of the process. It even watches the script as it runs, analyzes the data which flows through it and applies optimizations to the machine-code basing on that knowledge. +The engine applies optimizations on every stage of the process. It even watches the script as it runs, analyzes the data which flows through it and applies optimizations to the machine-code basing on that knowledge. That's why the code runs fast. ``` ## What can in-browser JavaScript do? @@ -57,7 +57,7 @@ For instance, in-browser JavaScript is able to: - Get and set cookies, ask questions to the visitor, show messages. - Remember the data on the browser side ("local storage"). -## What can in-browser JavaScript NOT do? +## What in-browser JavaScript can NOT do? JavaScript abilities in the browser are limited for the sake of the user's safety. The aim is to prevent an evil webpage from accessing private information or harming the user's data. @@ -89,9 +89,9 @@ There are at least *three* great things about JavaScript: + Supported by all major browsers and enabled by default. ``` -Combined, these 3 things only exist in JavaScript and no other browser technology. +Combined, these 3 things exist only in JavaScript and no other browser technology. -That's what makes JavaScript unique. That's why it is the most widespread way of creating browser interfaces. +That's what makes JavaScript unique. That's why it's the most widespread tool to create browser interfaces. While planning to learn a new technology, it's beneficial to check its perspectives. So let's move on to the modern trends that include new languages and browser abilities. diff --git a/1-js/01-getting-started/2-code-editors/article.md b/1-js/01-getting-started/2-code-editors/article.md index 2b9f016a..d2120eb9 100644 --- a/1-js/01-getting-started/2-code-editors/article.md +++ b/1-js/01-getting-started/2-code-editors/article.md @@ -10,14 +10,14 @@ There are two archetypes: IDE and lightweight editors. Many people feel comforta The term [IDE](https://en.wikipedia.org/wiki/Integrated_development_environment) (Integrated Development Environment) means a powerful editor with many features that usually operates on a "whole project". As said, that's not just an editor, but a full-scale "development environment". -An IDE loads the project (can be many files), and then allows to navigate between files, provides autocompletion based on the whole project, integrates with version management system (like [git](https://git-scm.com/)), with testing environment and other "project-level" stuff. +An IDE loads the project (can be many files), and then allows navigation between files, provides autocompletion based on the whole project, integrates with version management system (like [git](https://git-scm.com/)), with testing environment and other "project-level" stuff. If you haven't considered selecting an IDE, look at the following variants: - IntelliJ editors: [WebStorm](http://www.jetbrains.com/webstorm/) for frontend development and [PHPStorm (PHP)](http://www.jetbrains.com/phpstorm/), [IDEA (Java)](http://www.jetbrains.com/idea/), [RubyMine (Ruby)](http://www.jetbrains.com/ruby/) and other if you need additional languages. - Visual Studio is fine if you're a .NET developer, and a free version is available ([Visual Studio Community](https://www.visualstudio.com/vs/community/)) - Eclipse-based products, like [Aptana](http://www.aptana.com/) and Zend Studio. -- [Komodo IDE](http://www.activestate.com/komodo-ide) and it's lightweight free version [Komodo Edit](http://www.activestate.com/komodo-edit). +- [Komodo IDE](http://www.activestate.com/komodo-ide) and its lightweight free version [Komodo Edit](http://www.activestate.com/komodo-edit). - [Netbeans](http://netbeans.org/). All of the IDEs listed above are available on both Windows and Mac, and the IDEs other than Visual Studio are also available on Linux. diff --git a/1-js/02-first-steps/01-hello-world/article.md b/1-js/02-first-steps/01-hello-world/article.md index daecf9b7..3307f1a6 100644 --- a/1-js/02-first-steps/01-hello-world/article.md +++ b/1-js/02-first-steps/01-hello-world/article.md @@ -37,7 +37,7 @@ For instance: ``` ```online -You can run the example clicking on a "Play" button in it's right-top corner. +You can run the example by clicking on the "Play" button in its right-top corner. ``` The ` ``` -Unlike `innerHTML`, writing to `outerHTML` does not change the element. Instead, it replaces it as a whole in the outer context. Yeah, sounds strange, and strange it is. Take a look. +**Beware: unlike `innerHTML`, writing to `outerHTML` does not change the element. Instead, it replaces it as a whole in the outer context.** + +Yeah, sounds strange, and strange it is, that's why we make a separate note about it here. Take a look. Consider the example: 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 a3ee986d..6e39eae2 100644 --- a/2-ui/2-events/02-bubbling-and-capturing/article.md +++ b/2-ui/2-events/02-bubbling-and-capturing/article.md @@ -108,11 +108,11 @@ Sometimes `event.stopPropagation()` creates hidden pitfalls that later may becom For instance: -1. We create a nested menu. Each submenu handles clicks on its elements and calls `stopPropagation` so that outer parts don't trigger. -2. Later we decide to catch clicks inside the whole window, to track users' behavior (where people click). Some counters do that. Usually a counter code does that by `document.addEventListener('click'…)`. -3. Our counter won't work over the area where clicks are stopped by `stopPropagation`. We've got a "dead zone". +1. We create a nested menu. Each submenu handles clicks on its elements and calls `stopPropagation` so that outer menu don't trigger. +2. Later we decide to catch clicks on the whole window, to track users' behavior (where people click). Some analytic systems do that. Usually the code uses `document.addEventListener('click'…)` to catch all clicks. +3. Our analytic won't work over the area where clicks are stopped by `stopPropagation`. We've got a "dead zone". -There's usually no real need to prevent the bubbling. One of them is to use custom events, we'll cover them later. Also we can write our data into the `event` object in one handler and read it in another one, so we can pass to handlers on parents information about the processing below. +There's usually no real need to prevent the bubbling. A task that seemingly requires that may be solved by other means. One of them is to use custom events, we'll cover them later. Also we can write our data into the `event` object in one handler and read it in another one, so we can pass to handlers on parents information about the processing below. ``` @@ -138,14 +138,14 @@ Handlers added using `on`-property or using HTML attributes or using `add To catch an event on the capturing phase, we need to set the 3rd argument of `addEventListener` to `true`. -Actually, there are two possible values for that optional last argument: +There are two possible values for that optional last argument: - If it's `false` (default), then the handler is set on the bubbling phase. - If it's `true`, then the handler is set on the capturing phase. Note that while formally there are 3 phases, the 2nd phase ("target phase": the event reached the element) is not handled separately: handlers on both capturing and bubbling phases trigger at that phase. -Handlers on the target element trigger last on the capturing state, and then trigger first on the bubbling stage. +If one puts a handler on the target element -- it triggers last on the capturing state, and first on the bubbling stage. Let's see it in action: diff --git a/2-ui/3-event-details/10-onload-ondomcontentloaded/article.md b/2-ui/3-event-details/10-onload-ondomcontentloaded/article.md index 1e3ba766..92a6618b 100644 --- a/2-ui/3-event-details/10-onload-ondomcontentloaded/article.md +++ b/2-ui/3-event-details/10-onload-ondomcontentloaded/article.md @@ -238,7 +238,7 @@ Page lifecycle events: - All scripts are executed except those that are external with `async` or `defer` - Images and other resources may still continue loading. - `load` event on `window` triggers when the page and all resources are loaded. We rarely use it, because there's usually no need to wait for so long. -- `beforeload` event on `window` triggers when the user wants to leave the page. If it returns a string, the browser shows a question whether the user really wants to leave or not. +- `beforeunload` event on `window` triggers when the user wants to leave the page. If it returns a string, the browser shows a question whether the user really wants to leave or not. - `unload` event on `window` triggers when the user is finally leaving, in the handler we can only do simple things that do not involve delays or asking a user. Because of that limitation, it's rarely used. - `document.readyState` is the current state of the document, changes can be tracked in the `readystatechange` event: - `loading` -- the document is loading. diff --git a/3-animation/3-js-animation/article.md b/3-animation/3-js-animation/article.md index f91f72e6..0b119563 100644 --- a/3-animation/3-js-animation/article.md +++ b/3-animation/3-js-animation/article.md @@ -15,11 +15,11 @@ And if we increase it in `setInterval`, by making 50 small changes per second, t The pseudo-code can look like this: ```js -let fps = 50; // 50 frames per second +let delay = 1000 / 50; // in 1 second 50 frames let timer = setInterval(function() { if (animation complete) clearInterval(timer); else increase style.left -}, 1000 / fps) +}, delay) ``` More complete example of the animation: @@ -54,13 +54,13 @@ Click for the demo: ## requestAnimationFrame -Let's imagine we have several simultaneous animations. +Let's imagine we have several animations running simultaneously. If we run them separately, each one with its own `setInterval(..., 20)`, then the browser would have to repaint much more often than every `20ms`. Each `setInterval` triggers once per `20ms`, but they are independent, so we have several independent runs within `20ms`. -These several independent actions should be grouped together, because it's easier for the browser to redraw things once per `20ms`. +These several independent redraws should be grouped together, to make it easier for the browser. In other words, this: @@ -80,11 +80,11 @@ setInterval(animate2, 20); setInterval(animate3, 20); ``` -There's one more thing to keep in mind. Sometimes when CPU is overloaded or for other reasons it may be better to trigger redraws less often. Not 20, but maybe 200ms. +There's one more thing to keep in mind. Sometimes when CPU is overloaded, or there are other reasons to redraw less often. For instance, if the browser tab is hidden, then there's totally no point in drawing. There's a standard [Animation timing](http://www.w3.org/TR/animation-timing/) that provides the function `requestAnimationFrame`. -It addresses all those issues and even more. +It addresses all these issues and even more. The syntax: ```js diff --git a/4-frames-and-windows/03-cross-window-communication/article.md b/4-frames-and-windows/03-cross-window-communication/article.md index 3c502b77..15394969 100644 --- a/4-frames-and-windows/03-cross-window-communication/article.md +++ b/4-frames-and-windows/03-cross-window-communication/article.md @@ -10,28 +10,30 @@ The idea is that if we have two windows open: one from `john-smith.com`, and ano Two URLs are said to have the "same origin" if they have the same protocol, domain and port. -These URLs have the same origin: +These URLs all share the same origin: - `http://site.com` - `http://site.com/` - `http://site.com/my/page.html` -These ones are not: +These ones do not: -- `http://www.site.com` (another domain: `www.` matters) -- `http://site.org` (another domain: `.org` matters) -- `https://site.com` (another protocol: `https`) -- `http://site.com:8080` (another port: `8080`) +- http://www.site.com (another domain: `www.` matters) +- http://site.org (another domain: `.org` matters) +- https://site.com (another protocol: `https`) +- http://site.com:8080 (another port: `8080`) If we have a reference to another window (a popup or iframe), and that window comes from the same origin, then we can do everything with it. -Otherwise, we can only change its location. Please note: not *read*, but modify it, redirect it to another place. That's possible, because such action does not reveal any data. Also such windows windows may exchange messages. Soon about that later. +If it comes from another origin, then we can only change its location. Please note: not *read* the location, but *modify* it, redirect it to another place. That's safe, because the URL may contain sensitive parameters, so reading it from another origin is prohibited, but changing is not. + +Also such windows windows may exchange messages. Soon about that later. ````warn header="Exclusion: subdomains may be same-origin" There's an important exclusion in the same-origin policy. -If windows share the same second-level domain, for instance `john.site.com`, `peter.site.com` and `site.com`, and assign to `document.domain` their common second-level domain `site.com`, then limitations are removed. +If windows share the same second-level domain, for instance `john.site.com`, `peter.site.com` and `site.com`, we can use JavaScript to assign to `document.domain` their common second-level domain `site.com`. Then these windows are treated as having the same origin. In other words, all such documents (including the one from `site.com`) should have the code: @@ -40,49 +42,51 @@ document.domain = 'site.com'; ``` Then they can interact without limitations. + +That's only possible for pages with the same second-level domain. ```` -## Managing iframes +## Accessing an iframe contents -An ` ``` @@ -98,7 +102,7 @@ The `iframe.onload` event is actually the same as `iframe.contentWindow.onload`. ...But `iframe.onload` is always available, while `iframe.contentWindow.onload` needs the same origin. ``` -And here's an example with the same origin: +And now an example with the same origin. We can do anything with the embedded window: ```html run @@ -111,7 +115,7 @@ And here's an example with the same origin: ``` -### Wait until the iframe loads +### Please wait until the iframe loads When an iframe is created, it immediately has a document. But that document is different from the one that finally loads into it! @@ -126,6 +130,7 @@ Here, look: iframe.onload = function() { let newDoc = iframe.contentDocument; *!* + // the loaded document is not the same as initial! alert(oldDoc == newDoc); // false */!* }; @@ -134,9 +139,9 @@ Here, look: That's actually a well-known pitfall for novice developers. We shouldn't work with the document immediately, because that's the *wrong document*. If we set any event handlers on it, they will be ignored. -...But the `onload` event triggers when the whole iframe with all resources is loaded. What if we want to act sooner, on `DOMContentLoaded`? +...But the `onload` event triggers when the whole iframe with all resources is loaded. What if we want to act sooner, on `DOMContentLoaded` of the embedded document? -We can try to catch the moment when a new document appears, and then setup necessary handlers, like this: +That's not possible if the iframe comes from another origin. But for the same origin we can try to catch the moment when a new document appears, and then setup necessary handlers, like this: ```html run @@ -148,19 +153,19 @@ We can try to catch the moment when a new document appears, and then setup neces let timer = setInterval(() => { if (iframe.contentDocument == oldDoc) return; - // yeah, now set handlers and do whatever we want - clearInterval(timer); - + // new document, let's set handlers iframe.contentDocument.addEventListener('DOMContentLoaded', () => { iframe.contentDocument.body.prepend('Hello, world!'); }); + + clearInterval(timer); // cancel setInterval, don't need it any more }, 100); ``` Let me know in comments if you know a better solution here. -### window.frames +## window.frames An alternative way to get a window object for `