diff --git a/1-js/03-code-quality/01-debugging-chrome/head.html b/1-js/03-code-quality/01-debugging-chrome/head.html index e990ced8..f219b0af 100644 --- a/1-js/03-code-quality/01-debugging-chrome/head.html +++ b/1-js/03-code-quality/01-debugging-chrome/head.html @@ -1,8 +1,8 @@ \ No newline at end of file + diff --git a/2-ui/1-document/1-browser-environment/article.md b/2-ui/1-document/1-browser-environment/article.md index 39573e16..ce6fe0ba 100644 --- a/2-ui/1-document/1-browser-environment/article.md +++ b/2-ui/1-document/1-browser-environment/article.md @@ -97,8 +97,8 @@ CSSOM specification : Describes styles, manipulations with them and their binding to documents, see . HTML specification -: Describes HTML language and also BOM (browser object model) -- various browser functions: `setTimeout`, `alert`, `location` and so on, see . +: Describes HTML language (tags etc) and also BOM (browser object model) -- various browser functions: `setTimeout`, `alert`, `location` and so on, see . It takes DOM specification and extends it with many additional properties and methods. Now we'll get down to learning DOM, because the document plays the central role in the UI, and working with it is the most complex part. -Please note the links above, because there's so many stuff to learn, it's impossible to cover and remember everything. When you'd like to read about a property or a method -- can go , but looking up the corresponding spec is even better. Longer to read, but will make your fundamental knowledge stronger. +Please note the links above, because there's so many stuff to learn, it's impossible to cover and remember everything. When you'd like to read about a property or a method -- can go , but looking up the corresponding spec may be better. Longer to read, but will make your fundamental knowledge stronger. diff --git a/2-ui/1-document/1-browser-environment/windowObjects.png b/2-ui/1-document/1-browser-environment/windowObjects.png index c44b9ab8..81803bd0 100644 Binary files a/2-ui/1-document/1-browser-environment/windowObjects.png and b/2-ui/1-document/1-browser-environment/windowObjects.png differ diff --git a/2-ui/1-document/1-browser-environment/windowObjects@2x.png b/2-ui/1-document/1-browser-environment/windowObjects@2x.png index d79481db..e6dae7c3 100644 Binary files a/2-ui/1-document/1-browser-environment/windowObjects@2x.png and b/2-ui/1-document/1-browser-environment/windowObjects@2x.png differ diff --git a/2-ui/1-document/2-dom-nodes/1-body-from-head/solution.md b/2-ui/1-document/2-dom-nodes/1-body-from-head/solution.md deleted file mode 100644 index 1618f182..00000000 --- a/2-ui/1-document/2-dom-nodes/1-body-from-head/solution.md +++ /dev/null @@ -1,20 +0,0 @@ -Выведет `null`, так как на момент выполнения скрипта тег `` ещё не обработан браузером. - -Попробуйте в действии: - -```html run - - - - - - - - Привет, мир! - - - -``` - diff --git a/2-ui/1-document/2-dom-nodes/1-body-from-head/task.md b/2-ui/1-document/2-dom-nodes/1-body-from-head/task.md deleted file mode 100644 index 1b271f05..00000000 --- a/2-ui/1-document/2-dom-nodes/1-body-from-head/task.md +++ /dev/null @@ -1,26 +0,0 @@ -importance: 5 - ---- - -# Что выведет этот alert? - -Что выведет `alert`? - -```html - - - -*!* - -*/!* - - - - Привет, мир! - - - -``` - diff --git a/2-ui/1-document/2-dom-nodes/article.md b/2-ui/1-document/2-dom-nodes/article.md index 9de936f0..8230231f 100644 --- a/2-ui/1-document/2-dom-nodes/article.md +++ b/2-ui/1-document/2-dom-nodes/article.md @@ -69,10 +69,13 @@ var node = {"name":"HTML","nodeType":1,"children":[{"name":"HEAD","nodeType":1," drawHtmlTree(node, 'div.domtree', 690, 210); -```smart -From here on, spaces and line-breaks on DOM pictures will only be shown for "space-only" nodes that have no other text. +```smart header="Starting/ending spaces and line breaks are usually not shown in DOM tools" +Tools working with DOM usually do not show spaces at start/end of the text and line-breaks between nodes. That's because they are mainly used to decorate HTML, and do not affect (in most cases) how it is shown. + +On our DOM pictures we'll omit them too where they are not important, to keep things short. ``` + ## Autocorrection If the browser encounters malformed HTML, it automatically corrects it when making DOM. @@ -83,7 +86,7 @@ Like, if the HTML file is a single word `"Hello"`, the browser will wrap it into **While generating DOM, browser automatically processes errors in the document, closes tags and so on.** -Such a document: +Such an "invalid" document: ```html no-beautify

Hello @@ -92,14 +95,14 @@ Such a document:

  • Dad ``` -...Will make a respectable DOM, as the browser knows how to read tags (from the spec): +...Will become a normal DOM, as the browser read tags and restores the missing parts:
    ````warn header="Tables always have ``" @@ -120,7 +123,7 @@ var node = {"name":"TABLE","nodeType":1,"children":[{"name":"TBODY","nodeType":1 drawHtmlTree(node, 'div.domtree', 600, 200); -Do you see? The `` has appeared out of nowhere. Should keep in mind while working with tables to evade surprises. +You see? The `` has appeared out of nowhere. Should keep in mind while working with tables to evade surprises. ```` ## Other node types @@ -155,49 +158,76 @@ Here we see a new tree node type -- *comment node*. We may think -- why a comment is added to the DOM? It doesn't affect the visual representation anyway. But there's a rule -- if something's in HTML, then it also must be in the DOM tree. -**Everything in HTML has its place in DOM.** +**Everything in HTML, even comments, becomes a part of DOM.** -Even the `` directive at the very beginning of HTML is also a DOM node. It's in the DOM tree right before ``. The pictures above don't show that fact, because we are not going to touch that node, but it's there. +Even the `` directive at the very beginning of HTML is also a DOM node. It's in the DOM tree right before ``. We are not going to touch that node, but it's there. The `document` object that represents the whole document is, formally, a DOM node as well. -There are 12 node types. In practice we only work with 4 of them: +There are [12 node types](https://dom.spec.whatwg.org/#node). In practice we mainly work with 4 of them: 1. `document` -- the "entry point" into DOM. 2. element nodes -- HTML-tags, the tree building blocks. 3. text nodes -- they contain text. 4. comments -- sometimes we can put the information there, that won't be shown, but JS can read it from DOM. -If you want to explore how DOM changes with the document, please consider the [Live DOM Viewer](http://software.hixie.ch/utilities/js/live-dom-viewer/). Just type in/modify the document, and it will show up DOM at instant. +## See it yourself -## Power of DOM +To see the DOM structure in real-time, try [Live DOM Viewer](http://software.hixie.ch/utilities/js/live-dom-viewer/). Just type in the document, and it will show up DOM at instant. -Why besides nice pictures do we need DOM? To manipulate the page -- read the information from HTML, create and modify elements. +## In the browser inspector -The `` node is accessible as `document.documentElement`, and `` -- as `document.body`. +Another way to explore DOM is to use browser developer tools. Actually, that's what we use when developing. -Then we can do something with the node. +To do so, open the web-page [elks.html](elks.html), turn on browser developer tools and switch to Elements tab. -Like changing the color: -```js run -document.body.style.background = 'yellow'; -alert('The body is now yellow'); +Should look like this: -// return back in 3 seconds -setTimeout(() => document.body.style.background = '', 3000); -``` +![](elks.png) -...But actually much more. +So you can see the DOM, click on elements, see the details about them and so on. -In the next chapters we're going to learn it. +Please note that the DOM structure show in developer tools is simplified. Text nodes are shown just as text. And there are no "blank" (space only) text nodes at all. That's fine, because most of time we are interested in element nodes. + +Clicking the button allows to choose a node from the webpage using a mouse (or alike) and "inspect" it. Works great when we have a huge HTML page and would like to see the DOM of a particular place in it. + +Another way to do it would be just right-clicking on a webpage and selecting "Inspect element" in the context menu. + +![](inspect.png) + +The right part has tabs: +- Styles -- to see CSS applied to the current element rule by rule, including built-in rules (gray). Almost everything can be edited at-place including the dimensions/margins/paddings of the box below. +- Computed -- to see CSS applied to the element by property: for each property we can see a rule that gives it (including CSS inheritance and such). +- ...there are other less used tabs as well. + +The best way to study them is to click around. Again, please note that most values are in-place editable. + +## Interaction with console + +As we explore the DOM, open/close nodes, we also may want to apply Javascript to it. Like get a node and some code on it, to see how it works. There are few tips to travel between nodes in Elements tab and the console. + +Press `key:Esc` -- it will open console right below the Elements tab. + +Now, the most recently selected element is available as `$0`, the previous one as `$1` etc. + +We can run commands on them, like `$0.style.background = 'red'` here: + +![](domconsole0.png) + +From the other side, if we're in console and have a node in a variable, then we can use the command `inspect(node)` to see it in the Elements pane. Or we can just output it and explore "at-place". + +![](domconsole1.png) + +From the next chapter on we'll study how to access and modify the DOM using Javascript. The browser developer tools are the great help in debugging things. ## Summary -- DOM-модель -- это внутреннее представление HTML-страницы в виде дерева. -- Все элементы страницы, включая теги, текст, комментарии, являются узлами DOM. -- У элементов DOM есть свойства и методы, которые позволяют изменять их. -- IE8- не генерирует пробельные узлы. +An HTML/XML document are represented inside the browser as the DOM tree. -Кстати, DOM-модель используется не только в JavaScript, это известный способ представления XML-документов. +- Tags become element nodes and form the structure. +- Text becomes text nodes. +- ...etc, everything in HTML has its place in DOM, even comments. -В следующих главах мы познакомимся с DOM более плотно. +We can use developer tools to inspect DOM and modify it manually. There's an extensive documentation about Chrome developer tools at , but the best way to learn it is to click here and there, see various menus: most options are obvious. And then later, when you know most stuff, read the docs and pick up the rest. + +DOM nodes have properties and methods that allow to modify them. We'll get down to it in further chapters. diff --git a/2-ui/1-document/2-dom-nodes/domconsole0.png b/2-ui/1-document/2-dom-nodes/domconsole0.png new file mode 100644 index 00000000..121c11d7 Binary files /dev/null and b/2-ui/1-document/2-dom-nodes/domconsole0.png differ diff --git a/2-ui/1-document/2-dom-nodes/domconsole0@2x.png b/2-ui/1-document/2-dom-nodes/domconsole0@2x.png new file mode 100644 index 00000000..a8953395 Binary files /dev/null and b/2-ui/1-document/2-dom-nodes/domconsole0@2x.png differ diff --git a/2-ui/1-document/2-dom-nodes/domconsole1.png b/2-ui/1-document/2-dom-nodes/domconsole1.png new file mode 100644 index 00000000..c04f015c Binary files /dev/null and b/2-ui/1-document/2-dom-nodes/domconsole1.png differ diff --git a/2-ui/1-document/2-dom-nodes/domconsole1@2x.png b/2-ui/1-document/2-dom-nodes/domconsole1@2x.png new file mode 100644 index 00000000..95871113 Binary files /dev/null and b/2-ui/1-document/2-dom-nodes/domconsole1@2x.png differ diff --git a/2-ui/1-document/2-dom-nodes/elks.html b/2-ui/1-document/2-dom-nodes/elks.html new file mode 100644 index 00000000..7d29f3d4 --- /dev/null +++ b/2-ui/1-document/2-dom-nodes/elks.html @@ -0,0 +1,11 @@ + + + + The truth about elks. +
      +
    1. An elk is a smart
    2. + +
    3. ...and cunning animal!
    4. +
    + + diff --git a/2-ui/1-document/2-dom-nodes/elks.png b/2-ui/1-document/2-dom-nodes/elks.png new file mode 100644 index 00000000..03177c40 Binary files /dev/null and b/2-ui/1-document/2-dom-nodes/elks.png differ diff --git a/2-ui/1-document/2-dom-nodes/elks@2x.png b/2-ui/1-document/2-dom-nodes/elks@2x.png new file mode 100644 index 00000000..e8a15bd5 Binary files /dev/null and b/2-ui/1-document/2-dom-nodes/elks@2x.png differ diff --git a/2-ui/1-document/2-dom-nodes/head.html b/2-ui/1-document/2-dom-nodes/head.html new file mode 100644 index 00000000..d61883c2 --- /dev/null +++ b/2-ui/1-document/2-dom-nodes/head.html @@ -0,0 +1,8 @@ + diff --git a/2-ui/1-document/2-dom-nodes/inspect.png b/2-ui/1-document/2-dom-nodes/inspect.png new file mode 100644 index 00000000..075cf930 Binary files /dev/null and b/2-ui/1-document/2-dom-nodes/inspect.png differ diff --git a/2-ui/1-document/2-dom-nodes/inspect@2x.png b/2-ui/1-document/2-dom-nodes/inspect@2x.png new file mode 100644 index 00000000..8743dd29 Binary files /dev/null and b/2-ui/1-document/2-dom-nodes/inspect@2x.png differ diff --git a/1-js/03-code-quality/01-debugging-chrome/statusbarButtonGlyphs.svg b/2-ui/1-document/2-dom-nodes/statusbarButtonGlyphs.svg similarity index 100% rename from 1-js/03-code-quality/01-debugging-chrome/statusbarButtonGlyphs.svg rename to 2-ui/1-document/2-dom-nodes/statusbarButtonGlyphs.svg diff --git a/2-ui/1-document/2-dom-nodes/toolbarButtonGlyphs.svg b/2-ui/1-document/2-dom-nodes/toolbarButtonGlyphs.svg new file mode 100644 index 00000000..5bdf20a8 --- /dev/null +++ b/2-ui/1-document/2-dom-nodes/toolbarButtonGlyphs.svg @@ -0,0 +1,1035 @@ + +image/svg+xml \ No newline at end of file diff --git a/2-ui/1-document/3-dom-navigation/1-dom-children/solution.md b/2-ui/1-document/3-dom-navigation/1-dom-children/solution.md new file mode 100644 index 00000000..decfa62c --- /dev/null +++ b/2-ui/1-document/3-dom-navigation/1-dom-children/solution.md @@ -0,0 +1,27 @@ +There are many ways, for instance: + + +The `
    ` DOM node: + +```js +document.body.firstElementChild +// or +document.body.children[0] +// or (the first node is space, so we take 2nd) +document.body.childNodes[1] +``` + +The `
      ` DOM node: + +```js +document.body.lastElementChild +// or +document.body.children[1] +``` + +The second `
    • ` (with Pete): + +```js +// get
        , and then get its last element child +document.body.lastElementChild.lastElementChild +``` diff --git a/2-ui/1-document/3-dom-navigation/1-dom-children/task.md b/2-ui/1-document/3-dom-navigation/1-dom-children/task.md new file mode 100644 index 00000000..4a9e741a --- /dev/null +++ b/2-ui/1-document/3-dom-navigation/1-dom-children/task.md @@ -0,0 +1,24 @@ +importance: 5 + +--- + +# DOM children + +For the page: + +```html + + +
        Users:
        +
          +
        • John
        • +
        • Pete
        • +
        + + +``` + +How to access: +- The `
        ` DOM node? +- The `
          ` DOM node? +- The second `
        • ` (with Pete)? diff --git a/2-ui/1-document/3-dom-navigation/3-navigation-links-which-null/solution.md b/2-ui/1-document/3-dom-navigation/3-navigation-links-which-null/solution.md new file mode 100644 index 00000000..e962eb66 --- /dev/null +++ b/2-ui/1-document/3-dom-navigation/3-navigation-links-which-null/solution.md @@ -0,0 +1,4 @@ +1. Yes, true. The element `elem.lastChild` is always the last one, it has no `nextSibling`, so if there are children, then yes. +2. No, wrong, because `elem.children[0]` is the first child among elements. But there may be non-element nodes before it. So `previousSibling` may be a text node. + +Please note that for both cases if there are no children, then there will be an error. For instance, if `elem.lastChild` is `null`, we can't access `elem.lastChild.nextSibling`. diff --git a/2-ui/1-document/3-dom-navigation/3-navigation-links-which-null/task.md b/2-ui/1-document/3-dom-navigation/3-navigation-links-which-null/task.md new file mode 100644 index 00000000..235e83a0 --- /dev/null +++ b/2-ui/1-document/3-dom-navigation/3-navigation-links-which-null/task.md @@ -0,0 +1,10 @@ +importance: 5 + +--- + +# The sibling question + +If `elem` -- is an arbitrary DOM element node... + +- Is it true that `elem.lastChild.nextSibling` is always `null`? +- Is it true that `elem.children[0].previousSibling` is always `null` ? diff --git a/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/solution.md b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/solution.md new file mode 100644 index 00000000..f2aa8630 --- /dev/null +++ b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/solution.md @@ -0,0 +1 @@ +We'll be using `rows` and `cells` properties to access diagonal table cells. diff --git a/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/solution.view/index.html b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/solution.view/index.html new file mode 100644 index 00000000..91e80566 --- /dev/null +++ b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/solution.view/index.html @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          1:12:13:14:15:1
          1:22:23:24:25:2
          1:32:33:34:35:3
          1:42:43:44:45:4
          1:52:53:54:55:5
          + + + diff --git a/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/source.view/index.html b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/source.view/index.html new file mode 100644 index 00000000..ad835f9f --- /dev/null +++ b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/source.view/index.html @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          1:12:13:14:15:1
          1:22:23:24:25:2
          1:32:33:34:35:3
          1:42:43:44:45:4
          1:52:53:54:55:5
          + + + diff --git a/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/task.md b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/task.md new file mode 100644 index 00000000..23be59fc --- /dev/null +++ b/2-ui/1-document/3-dom-navigation/4-select-diagonal-cells/task.md @@ -0,0 +1,18 @@ +importance: 5 + +--- + +# Select all diagonal cells + +Write the code to paint all diagonal table cells in red. + +You'll need to get all diagonal `` from the `` and paint them using the code: + +```js +// td should be the reference to the table cell +td.style.backgroundColor = 'red'; +``` + +The result should be: + +[iframe src="solution" height=180] diff --git a/2-ui/1-document/3-dom-navigation/article.md b/2-ui/1-document/3-dom-navigation/article.md new file mode 100644 index 00000000..c4dc022c --- /dev/null +++ b/2-ui/1-document/3-dom-navigation/article.md @@ -0,0 +1,284 @@ +libs: + - d3 + - domtree + +--- + + +# DOM Navigation + +DOM allows to do anything with HTML-element and its contents, but first we need to reach it. + +All operations on DOM start with the `document` object. From it we can access any node. + +[cut] + +Here's a picture of links that allow to walk between DOM nodes: + +![](dom-links.png) + +Let's discuss them in more detail. + +## On top: documentElement and body + +The topmost tree nodes are available directly as `document` properties: + +`` = `document.documentElement` +: The topmost document node is `document.documentElement`. That's DOM node of `` tag. + +`` = `document.body` +: Another widely used DOM node is the `` element -- `document.body`. + +`` = `document.head` +: The `` tag is available as `document.head`. + +````warn header="There's a catch: `document.body` can be `null`" +A script cannot access an element that doesn't exist at the moment of running. + +In particular, if a script is inside ``, then `document.body` is unavailable, because the browser did not reach it yet. + +So, in the example below `alert` will show `null`: + +```html run + + + + + + + + + + + + +``` +```` + +```smart header="In the DOM world `null` is actively used" +In the DOM, the value meaning "no such node" is `null`, not `undefined`. +``` + +## Children: childNodes, firstChild, lastChild + +There are two tree terms that we'll use: + +- **Child nodes (or children)** -- elements that are nested exactly 1 level below the given one. For instance, `` and `` are children of `` element. +- **Descendants** -- all elements that are nested in the given one, including children, their children and so on. That is: the DOM subtree. + +The `childNodes` collection provides access to all child nodes, including text nodes. + +The example below shows children of `document.body`: + +```html run + + +
          Begin
          + +
            +
          • Information
          • +
          + +
          End
          + + + ...more stuff... + + +``` + +Please note an interesting detail here. If we run the example above, the last element shown is ` + ... + + +``` + +## More links, tables [#dom-navigation-tables] + +Till now we described the basic navigation properties. Certain DOM element types may provide more, specific to their type, for better convenience. + +Tables are a great example and important particular case of that. + +`
          ` elements support these properties: +- `table.rows` -- the collection of `` elements of the table. +- `table.caption/tHead/tFoot` -- references to elements ``, ``. +- `table.tBodies` -- the collection of `` elements (can be many according to the standard). + +``, ``, `` elements provide: +- `tbody.rows` -- the collection of `` inside them. + +``: +- `tr.cells` -- the collection of ``. +- `tr.sectionRowIndex` -- the number of the given `` inside the enclosing `/`. +- `tr.rowIndex` -- the number of the `` in the table. + +``. + +An example of usage: + +```html run height=100 +
          `, `
          ` and `` cells inside the given `
          ` and ``: +- `td.cellIndex` -- the number of the cell inside the enclosing `
          + + + + + + +
          onetwo
          threefour
          + + +``` + +The specification: [tabular data](https://html.spec.whatwg.org/multipage/tables.html). + +There are also additional navigation properties for HTML forms. We'll look at them later when start working with forms. + +# Summary + +The main navigation sets are: + +- `parentNode`, `childNodes`, `firstChild`, `lastChild`, `previousSibling`, `nextSibling` -- for all nodes. +- `parentElement`, `children`, `firstElementChild`, `lastElementChild`, `previousElementSibling`, `nextElementSibling` -- if we take only element nodes into account. + +Some types of DOM elements, e.g. tables, provide additional properties and collections to access their content. diff --git a/2-ui/1-document/3-dom-navigation/dom-links-elements.png b/2-ui/1-document/3-dom-navigation/dom-links-elements.png new file mode 100644 index 00000000..f7eef5d1 Binary files /dev/null and b/2-ui/1-document/3-dom-navigation/dom-links-elements.png differ diff --git a/2-ui/1-document/3-dom-navigation/dom-links-elements@2x.png b/2-ui/1-document/3-dom-navigation/dom-links-elements@2x.png new file mode 100644 index 00000000..cf4e220c Binary files /dev/null and b/2-ui/1-document/3-dom-navigation/dom-links-elements@2x.png differ diff --git a/2-ui/1-document/3-dom-navigation/dom-links.png b/2-ui/1-document/3-dom-navigation/dom-links.png new file mode 100644 index 00000000..25b25b37 Binary files /dev/null and b/2-ui/1-document/3-dom-navigation/dom-links.png differ diff --git a/2-ui/1-document/3-dom-navigation/dom-links@2x.png b/2-ui/1-document/3-dom-navigation/dom-links@2x.png new file mode 100644 index 00000000..84cd33d4 Binary files /dev/null and b/2-ui/1-document/3-dom-navigation/dom-links@2x.png differ diff --git a/2-ui/1-document/3-dom-navigation/head.html b/2-ui/1-document/3-dom-navigation/head.html new file mode 100644 index 00000000..5d763505 --- /dev/null +++ b/2-ui/1-document/3-dom-navigation/head.html @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/2-ui/1-document/5-searching-elements-dom/1-find-elements/solution.md b/2-ui/1-document/5-searching-elements-dom/1-find-elements/solution.md new file mode 100644 index 00000000..9842595f --- /dev/null +++ b/2-ui/1-document/5-searching-elements-dom/1-find-elements/solution.md @@ -0,0 +1,27 @@ +Есть много вариантов решения, вот некоторые из них: + +```js +// 1 +document.getElementById('age-table').getElementsByTagName('label'); + +// 2 +document.getElementById('age-table').getElementsByTagName('td')[0]; +// в современных браузерах можно одним запросом: +var result = document.querySelector('#age-table td'); + +// 3 +document.getElementsByTagName('form')[1]; + +// 4 +document.querySelector('form[name="search"]'); + +// 5 +document.querySelector('form[name="search"] input') + +// 6 +document.getElementsByName("info[0]")[0]; + +// 7 +document.querySelector('form[name="search-person"] [name="info[0]"]'); +``` + diff --git a/2-ui/1-document/5-searching-elements-dom/1-find-elements/table.html b/2-ui/1-document/5-searching-elements-dom/1-find-elements/table.html new file mode 100644 index 00000000..3484bc0c --- /dev/null +++ b/2-ui/1-document/5-searching-elements-dom/1-find-elements/table.html @@ -0,0 +1,48 @@ + + + + + + + + +
          + + +
          + +
          + +
          + Поиск по посетителям: + + + + + + + + + + + +
          Возраст: + + + +
          Дополнительно: + + + +
          + + +
          + + + \ No newline at end of file diff --git a/2-ui/1-document/5-searching-elements-dom/1-find-elements/task.md b/2-ui/1-document/5-searching-elements-dom/1-find-elements/task.md new file mode 100644 index 00000000..6cbdbfa9 --- /dev/null +++ b/2-ui/1-document/5-searching-elements-dom/1-find-elements/task.md @@ -0,0 +1,20 @@ +importance: 4 + +--- + +# Поиск элементов + +Ниже находится документ с таблицей и формой. + +Найдите (получите в переменную) в нём: + +1. Все элементы `label` внутри таблицы. Должно быть 3 элемента. +2. Первую ячейку таблицы (со словом `"Возраст"`). +3. Вторую форму в документе. +4. Форму с именем `search`, без использования её позиции в документе. +5. Элемент `input` в форме с именем `search`. Если их несколько, то нужен первый. +6. Элемент с именем `info[0]`, без точного знания его позиции в документе. +7. Элемент с именем `info[0]`, внутри формы с именем `search-person`. + +Используйте для этого консоль браузера, открыв страницу [table.html](table.html) в отдельном окне. + diff --git a/2-ui/1-document/5-searching-elements-dom/2-tree-info/solution.md b/2-ui/1-document/5-searching-elements-dom/2-tree-info/solution.md new file mode 100644 index 00000000..615c88d7 --- /dev/null +++ b/2-ui/1-document/5-searching-elements-dom/2-tree-info/solution.md @@ -0,0 +1,18 @@ +Сделаем цикл по узлам `
        • `: + +```js +var lis = document.getElementsByTagName('li'); + +for (i = 0; i < lis.length; i++) { + ... +} +``` + +В цикле для каждого `lis[i]` можно получить текст, используя свойство `firstChild`. Ведь первым в `
        • ` является как раз текстовый узел, содержащий текст названия. + +Также можно получить количество потомков, используя `lis[i].getElementsByTagName('li')`. + +Напишите код с этой подсказкой. + +Если уж не выйдет -- тогда откройте решение. + diff --git a/2-ui/1-document/5-searching-elements-dom/2-tree-info/solution.view/index.html b/2-ui/1-document/5-searching-elements-dom/2-tree-info/solution.view/index.html new file mode 100644 index 00000000..e9b5d644 --- /dev/null +++ b/2-ui/1-document/5-searching-elements-dom/2-tree-info/solution.view/index.html @@ -0,0 +1,66 @@ + + + + + + + + + +
            +
          • Животные +
              +
            • Млекопитающие +
                +
              • Коровы
              • +
              • Ослы
              • +
              • Собаки
              • +
              • Тигры
              • +
              +
            • +
            • Другие +
                +
              • Змеи
              • +
              • Птицы
              • +
              • Ящерицы
              • +
              +
            • +
            +
          • +
          • Рыбы +
              +
            • Аквариумные +
                +
              • Гуппи
              • +
              • Скалярии
              • +
              + +
            • +
            • Морские +
                +
              • Морская форель
              • +
              +
            • +
            +
          • +
          + + + + + + \ No newline at end of file diff --git a/2-ui/1-document/5-searching-elements-dom/2-tree-info/source.view/index.html b/2-ui/1-document/5-searching-elements-dom/2-tree-info/source.view/index.html new file mode 100644 index 00000000..2f45460c --- /dev/null +++ b/2-ui/1-document/5-searching-elements-dom/2-tree-info/source.view/index.html @@ -0,0 +1,54 @@ + + + + + + + + + +
            +
          • Животные +
              +
            • Млекопитающие +
                +
              • Коровы
              • +
              • Ослы
              • +
              • Собаки
              • +
              • Тигры
              • +
              +
            • +
            • Другие +
                +
              • Змеи
              • +
              • Птицы
              • +
              • Ящерицы
              • +
              +
            • +
            +
          • +
          • Рыбы +
              +
            • Аквариумные +
                +
              • Гуппи
              • +
              • Скалярии
              • +
              + +
            • +
            • Морские +
                +
              • Морская форель
              • +
              +
            • +
            +
          • +
          + + + + + + \ No newline at end of file diff --git a/2-ui/1-document/5-searching-elements-dom/2-tree-info/task.md b/2-ui/1-document/5-searching-elements-dom/2-tree-info/task.md new file mode 100644 index 00000000..c1fdc1db --- /dev/null +++ b/2-ui/1-document/5-searching-elements-dom/2-tree-info/task.md @@ -0,0 +1,15 @@ +importance: 5 + +--- + +# Дерево + +Есть дерево из тегов `
            /
          • `. + +Напишите код, который для каждого элемента `
          • ` выведет: + +1. Текст непосредственно в нём (без подразделов). +2. Количество вложенных в него элементов `
          • ` -- всех, с учётом вложенных. + +[demo src="solution"] + diff --git a/2-ui/1-document/5-searching-elements-dom/article.md b/2-ui/1-document/5-searching-elements-dom/article.md new file mode 100644 index 00000000..4f4bf3f2 --- /dev/null +++ b/2-ui/1-document/5-searching-elements-dom/article.md @@ -0,0 +1,323 @@ +# Searching: getElement*, querySelector* and others + +DOM navigation properties are great when elements are close to each other. What if they are not? How to get an arbitrary element of the page? + +There are additional searching methods for that. +[cut] + +## document.getElementById or just id + +If an element has the `id` attribute, then there's a global variable by the name from that `id`. + +We can use it to access the element, like this: + +```html run +
            +
            Element
            +
            + + +``` + +The behavior is described [in the specification](http://www.whatwg.org/specs/web-apps/current-work/#dom-window-nameditem), but it is supported mainly for compatibility, because relies on global variables. The browser tries to help us by mixing namespaces of JS and DOM, but there may be conflicts. + +The better alternative is to use a special method `document.getElementById(id)`. + +For instance: + +```html run +
            +
            Element
            +
            + + +``` + +```smart header="There must be only one" +By the specification the value of `id` must be unique. There may be only one element in the document with the given `id`. + +If there are multiple elements with the same `id`, then the behavior is unpredictable. The browser may return any of them at random. So please stick to the rule and keep `id` unique. +``` + +I will often use `id` to directly reference an element in examples, but that's only to keep things short. In real life `document.getElementById` is definitely the preferred method. + +## getElementsBy* + +There are also other methods of this kind: + +`elem.getElementsByTagName(tag)` looks for elements with the given tag and returns the collection of them. The `tag` can also be `*` for any. + +For instance: +```js +// get all divs in the document +let divs = document.getElementsByTagName('div'); +``` + +Unlike `getElementById` that can be called only on `document`, this method can look inside any element. + +Let's find all `input` inside the table: + +```html run height=50 + + + + + + +
            Your age: + + + +
            + + +``` + +```warn header="Don't forget the `\"s\"` letter!" +Novice developers sometimes forget the letter `"s"`. That is, they try to call `getElementByTagName` instead of getElementsByTagName. + +The `"s"` letter is only absent in `getElementById`, because we look for a single element. But `getElementsByTagName` returns a collection. +``` + +````warn header="It returns a collection, not an element!" +Another widespread novice mistake is to write like: + +```js +// doesn't work +document.getElementsByTagName('input').value = 5; +``` + +That won't work, because we take a *collection* of inputs and assign the value to it, rather to elements inside it. + +We should either iterate over the collection or get an element by the number, and then assign, like this: + +```js +// should work (if there's an input) +document.getElementsByTagName('input')[0].value = 5; +``` +```` + +Other methods: + +- `document.getElementsByName(name)` returns elements with the given `name` attribute. Rarely used. +- `elem.getElementsByClassName(className)` returns elements that have the given CSS class. Elements may have other classes too. + +For instance: + +```html run height=50 +
            +
            Article
            +
            Long article
            +
            + + +``` + +## querySelectorAll [#querySelectorAll] + +Now the heavy artillery. + +The call to `elem.querySelectorAll(css)` returns all elements inside `elem` matching the given CSS selector. That's the most often used and powerful method. + +Here we look for all `
          • ` elements that are last children: + +```html run +
              +
            • The
            • +
            • test
            • +
            +
              +
            • has
            • +
            • passed
            • +
            + +``` + +```smart header="Can use pseudo-classes as well" +Pseudo-classes in the CSS selector like `:hover` and `:active` are also supported. For instance, `document.querySelectorAll(':hover')` will return the collection with elements that the pointer is over now (in nesting order: from the outmost `` to the most nested one). +``` + +## querySelector [#querySelector] + +The call to `elem.querySelector(css)` returns the first element for the given CSS selector. + +In other words, the result is the same as `elem.querySelectorAll(css)[0]`, but that's looking for *all* elements and picking the first, much slower than only looking for the first one. + +## matches + +Previous methods were searching the DOM. + +The [elem.matches(css)](http://dom.spec.whatwg.org/#dom-element-matches) does not look for anything, it merely checks if `elem` fits the CSS-selector. It returns `true` or `false`. + +The method comes handy when we are walking over elements (like in array or something) and trying to filter those that interest us. + +For instance: + +```html run +... +... + + +``` + +## closest + +The method `elem.closest(css)` looks the nearest ancestor (parent or his parent and so on) that matches the CSS-selector. The `elem` itself is also included in the search. + +In other words, the method `closest` goes up from the element and checks each of them. If it matches, then stops the search and returns it. + +For instance: + +```html run +
              +
            • Chapter I +
                +
              • Chapter 1.1
              • +
              • Chapter 1.2
              • +
              +
            • +
            + + +``` + +## XPath в современных браузерах + +Для полноты картины рассмотрим ещё один способ поиска, который обычно используется в XML. Это язык запросов XPath. + +Он очень мощный, во многом мощнее CSS, но сложнее. Например, запрос для поиска элементов `H2`, содержащих текст `"XPath"`, будет выглядеть так: `//h2[contains(., "XPath")]`. + +Все современные браузеры, кроме IE, поддерживают XPath с синтаксисом, близким к [описанному в MDN](https://developer.mozilla.org/en/XPath). + +Найдем заголовки с текстом `XPath` в текущем документе: + +```js run no-beautify +var result = document.evaluate("//h2[contains(., 'XPath')]", document.documentElement, null, + XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + +for (var i = 0; i < result.snapshotLength; i++) { + alert( result.snapshotItem(i).outerHTML ); +} +``` + +IE тоже поддерживает XPath, но эта поддержка не соответствует стандарту и работает только для XML-документов, например, полученных с помощью `XMLHTTPRequest` (AJAX). Для обычных же HTML-документов XPath в IE не поддерживается. + +Так как XPath сложнее и длиннее CSS, то используют его очень редко. + +## Итого + +Есть 6 основных методов поиска элементов DOM: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            МетодИщет по...Ищет внутри элемента?Поддержка
            getElementByIdid-везде
            getElementsByNamename-везде
            getElementsByTagNameтег или '*'везде
            getElementsByClassNameклассукроме IE8-
            querySelectorCSS-селекторвезде
            querySelectorAllCSS-селекторвезде
            + +Практика показывает, что в 95% ситуаций достаточно `querySelector/querySelectorAll`. Хотя более специализированные методы `getElement*` работают чуть быстрее, но разница в миллисекунду-другую редко играет роль. + +Кроме того: + +- Есть метод `elem.matches(css)`, который проверяет, удовлетворяет ли элемент CSS-селектору. Он поддерживается большинством браузеров в префиксной форме (`ms`, `moz`, `webkit`). +- Метод `elem.closest(css)` ищет ближайший элемент выше по иерархии DOM, подходящий под CSS-селектор css. Сам элемент тоже включается в поиск. +- Язык запросов XPath поддерживается большинством браузеров, кроме IE, даже 9-й версии, но `querySelector` удобнее. Поэтому XPath используется редко. diff --git a/contributors.md b/contributors.md new file mode 100644 index 00000000..ee3c4661 --- /dev/null +++ b/contributors.md @@ -0,0 +1,13 @@ + +The file lists people who made significant contributions to the project: + +
              +
            • Alexey Maximov @amaxcz (admin)
            • +
            • Alexey Shisterov (tutorial)
            • +
            • Anton Vernogor @smmurf (markup)
            • +
            • Artem Beztsenny @bezart (design)
            • +
            • Илья Кантор @iliakan (tutorial, code)
            • +
            • Юрий Ткаченко @tyv (markup)
            • +
            + +The project exists for a long time, I might have missed someone. If you expect to find yourself in the list, but you're not -- please mail me at mk@javascript.ru. diff --git a/figures.sketch b/figures.sketch index e5ef8b74..baf67eee 100644 Binary files a/figures.sketch and b/figures.sketch differ