:hover does not match, because the position of the tooltip changes depending on the mouse cursor. Event delegation is also not suitable - it is too expensive to listen to mouseover and mouseleave for all elements on the page. This is where live extensions come into play. DOM.extend("[title]", { constructor: function() { var tooltip = DOM.create("span.custom-title"); // textContent // title tooltip.set("textContent", this.get("title")).hide(); this // tooltip .set("title", null) // .data("tooltip", tooltip) // .on("mouseenter", this.onMouseEnter, ["clientX", "clientY"]) .on("mouseleave", this.onMouseLeave) // DOM .append(tooltip); }, onMouseEnter: function(x, y) { this.data("tooltip").style({left: x, top: y}).show(); }, onMouseLeave: function() { this.data("tooltip").hide(); } }); .custom-title selector in CSS: .custom-title { position: fixed; border: 1px solid #faebcc; background: #faf8f0; } title attribute are added to the page. They will be picked up by the extension without calling any initializing function .Decorators, unlike other sections of Web Components, do not yet have a specification.
setInterval and setTimeout . It was a cool thing, but now ... something like a bad practice. Native animations will always be smoother: they are usually faster, require less energy and simply do not appear in browsers that do not support them.animate method in better-dom: only show , hide and toggle . To capture the state of a hidden item in the CSS library uses the standardized attribute aria-hidden . .custom-title { position: fixed; border: 1px solid #faebcc; background: #faf8f0; /* */ opacity: 1; -webkit-transition: opacity 0.5s; transition: opacity 0.5s; } .custom-title[aria-hidden=true] { opacity: 0; } show and hide attribute, aria-hidden changes its value to false or true . This is enough to show the animation means CSS. body.append("<ul><li class='list-item'></li><li class='list-item'></li><li class='list-item'></li></ul>"); body.append("ul>li.list-item*3"); :lang and :before . Take a look at the code below: [data-i18n="hello"]:before { content: "Hello Maksim!"; } [data-i18n="hello"]:lang(ru):before { content: " !"; } content property changes according to the current language, which is determined by the value of the lang attribute for the html element. Using the data-i18n attribute, we can use a more general entry: [data-i18n]:before { content: attr(data-i18n); } [data-i18n="Hello Maksim!"]:lang(ru):before { content: " !"; } i18n and DOM.importStrings . The first is used to update the data-i18n attribute with the corresponding value, and the second locates strings for a particular language. label.i18n("Hello Maksim!"); // label "Hello Maksim!" DOM.importStrings("ru", "Hello Maksim!", " !"); // "ru", label " !" label.set("lang", "ru"); // label " !" ${param} variables to the key string: label.i18n("Hello ${user}!", {user: "Maksim"}); // label "Hello Maksim!" <a href="/chemerisuk/better-dom" id="foo" data-test="test">better-dom</a> var link = document.getElementById("foo"); link.href; // => "https://github.com/chemerisuk/better-dom" link.getAttribute("href"); // => "/chemerisuk/better-dom" link["data-test"]; // => undefined link.getAttribute("data-test"); // => "test" link.href = "abc"; link.href; // => "https://github.com/abc" link.getAttribute("href"); // => "abc" var link = DOM.find("#foo"); link.get("href"); // => "https://github.com/chemerisuk/better-dom" link.set("href", "abc"); link.get("href"); // => "https://github.com/abc" link.get("data-attr"); // => "test" checked , selected , etc.) you can simply use true or false . Changing these properties on the element updates the corresponding attribute (native behavior). var button = document.getElementById("foo"); button.addEventListener("click", function(e) { handleButtonClick(e.button); }, false); var button = DOM.find("#foo"); button.on("click", handleButtonClick, ["button"]); ["target", "defaultPrevented"] , so there is no need to add the last argument to read these properties: button.on("click", function(target, canceled) { // }); on and off methods. button._handleButtonClick = function() { alert("click!"); }; button.on("click", "_handleButtonClick"); button.fire("click"); // "clicked" button._handleButtonClick = null; button.fire("click"); // click() , focus() , submit() etc., which are present in the standard and have different behavior in browsers. The only way to call them is to use the fire method, which executes the default behavior when none of the handlers returned false : link.fire("click"); // link.on("click", function() { return false; }); link.fire("click"); // map , filter , some , etc. They allow you to conduct operations on collections in a standardized form. As a result, there are today projects like Underscore or Lo-Dash , which allow you to use these methods in older browsers.each (differs from forEach in that it returns this instead of undefined )someeverymapfilterreduce[Right] var urls, activeLi, linkText; urls = menu.findAll("a").map(function(el) { return el.get("href"); }); activeLi = menu.children().filter(function(el) { return el.hasClass("active"); }); linkText = menu.children().reduce(function(memo, el) { return memo || el.hasClass("active") && el.find("a").get() }, false); $return falsefind and findAll$ (dollar) is “magic”. The name consisting of only one character is not very clear; the function looks like an operator built into the language. That is why inexperienced developers simply call it wherever it is needed.$ is a rather complicated function . Its frequent execution, especially inside events such as mousemove or scroll , can be the cause of poor UI responsiveness.$ . This is because the library syntax contributes to this coding style. $("a"); // => , “a” $("<a>"); // => <a> jQuery find[All] and DOM.create . The find[All] methods are used to search for elements by a CSS selector. DOM.create creates new elements in memory. Function names clearly state what these functions do. var links = $("a"); links[0].on("click", function() { ... }); // ! $(links[0]).on("click", function() { ... }); // $() within an iteration function. Therefore, the developer must always remember with what object he works: native or a wrapper, despite the fact that the library is used to work with the DOM.legacy method. var foo = DOM.find("#foo"); foo.legacy(function(node) { // Hammer swipe Hammer(node).on("swipe", function(e) { // swipe }); }); return false in event listeners. In accordance with W3C standards, this value should, in most cases, override the default behavior. In jQuery, return false additionally stops event delegation !stopPropagation() call itself can create compatibility problems, since he breaks the possibility of other listeners to do their work in the occurrence of such an eventreturn false inside an event handler only causes preventDefault() , as expected.querySelector and querySelectorAll . The difference between them is that the first one stops the search after the first match.find method that uses querySelectorAll in general. To date, there is no method here that would use querySelector to find only the first matching element.find and findAll . They allow you to use querySelector optimization above. To estimate the potential gain, I made a sample by the number of entries in the source code of the last commercial project:find - 103 matches in 11 filesfindAll - 14 matches in 4 filesfind method is much more popular. This means that querySelector optimization takes place in most cases, so it can give a tangible gain in code performance on the client.Source: https://habr.com/ru/post/209140/
All Articles