Javascript ожидание появления элемента

How to wait until an element exists in JavaScript

To wait to do something until an element exists in the DOM, you can use JavaScript MutatationObserver API.

As the name suggests, it can be used to listen out for changes in the DOM. You can then fire a (callback) function in response to this.

First, select the area you want to monitor for changes. In this example, we monitor the entire DOM for changes:

/* Select a target to observe */ // Select the entire DOM for observing: const target = document.querySelector('body');

Next, create a new observer instance by calling new MutationObserver() . This accepts a callback function that runs when the change we are looking out for occurs.

When this callback function is run, we check if the DOM contains an element with an ID of new-div . If this is true, this element exists, and the message is logged to the console:

/* Create a new observer instance */ // Select the entire DOM for observing: const target = document.querySelector('body'); // Create a new observer instance: const observer = new MutationObserver(function() < if (document.getElementById('new-div')) < console.log("The new div was just appended!"); >>);

Next, create a configuration object, containing the property childList: true . This specifies that we want to observe for any changes in child elements (e.g. if a new one is added).

Читайте также:  Недостатки html мы php

Finally, call the observe method on the new observer instance, passing in the target (the DOM) and config (observe for changes in children).

/* Set configuration options and start the observer */ // Select the entire DOM for observing: const target = document.querySelector('body'); // Create a new observer instance: const observer = new MutationObserver(function() < if (document.getElementById('new-div')) < console.log("The new div was just appended!"); >>); // Set configuration object: const config = < childList: true >; // Start the observer observer.observe(target, config);

Try running this and nothing will happen. This is because every time there is a mutation in the DOM, the if statement is run but won’t be true.

But let’s now make it true after a slight delay, using setTimeout() :

/* Working example, observer for a new with ID 'new-div' */ // Select the entire DOM for observing: const target = document.querySelector('body'); // Create a new observer instance: const observer = new MutationObserver(function() < if (document.getElementById('new-div')) < console.log("The new div was just appended!"); // Do something with new div element observer.disconnect(); >>); // Set configuration object: const config = < childList: true >; // Start the observer observer.observe(target, config); // Create the mutation we are listening out for setTimeout(() => < const div = document.createElement('div'); div.id = 'new-div'; document.body.append(div); >,3000);

It is good practice to stop observing if you are no longer listening out for something.

You can do this by calling the disconnect method on the observer instance. It is still possible to start the observer again at a later time.

Источник

Как отследить появление новых элементов в DOM?

Есть div, в который по нажатию кнопки сторонним плагином добавляются новые элементы DOM (создаётся модальное окно), и после того как оно появилось, нужно сразу же произвести пару действий. Например, заменить значение в текстовом поле и изменить значение атрибута. Проблема в том, как отследить, что это текстовое поле появилось, и как изменить его атрибуты после того как оно появилось?

P.S. Лезть в плагин сторонний нет возможности, так как он обновляется и всё слетит после обновления.

mlnkv

// выбираем нужный элемент var target = document.querySelector('#some-id'); // если jQuery var target = $('#some-id')[0]; // создаем новый экземпляр наблюдателя var observer = new MutationObserver(function(mutations) < mutations.forEach(function(mutation) < console.log(mutation.type); >); >); // создаем конфигурации для наблюдателя var config = < attributes: true, childList: true, characterData: true >; // запускаем механизм наблюдения observer.observe(target, config); // позже, если надо, прекращаем наблюдение observer.disconnect();

А зачем городить столько нативного кода при наличии Jquery? Тем более просят наблюдать лишь за добавлением нового элемента.

Илья Шатохин: А чем вам тут jQuery поможет? тут обзервер, будет реагировать вообще на все. Вы же листенер навесили.

Сергей Протько: В смысле? В моем примере событие будет услышано только, когда в elem добавится другой элемент. Можете поиграть с консолью браузера. Под запрос топикстартера другое и не требуется.

Petroveg

Евгений Петров: У топикстартера просьба сильно проще, чем решение по вашей ссылке.
Также MutationObserver требует IE >= 11, а MutationEvent лишь >= 9 (хоть в вашем решении и есть полифил).

Petroveg

Я повторю то, что написал вам — не рекомендуется использовать Mutation Events, если клиент поддерживает MutationObserver. Если уровень подготовки ТС не слишком высок,это не означает, что ему надо предлагать не самый лучший вариант.

Евгений Петров: основная проблема MutationEvent — это попытка синхронно менять DOM в обработчике всплывающего Mutation события. Да, это может привести к зацикливанию или тормозам. Но топикстартер будет слушать DOMNodeInserted и не будет добавлять новые элементы (по его словам) в обработчике, только менять атрибуты, соответственно, его эта проблема tuj не коснется. А так вы конечно правы, сам я по возможности использую MutationObserver.

Источник

How to wait for DOM elements to show up in modern browsers

Senior Engineer Mindset cover

Remember how careful we all were of the DOM ready event a few years ago? Writing JavaScript code outside of a $(document).ready() callback was sacrilege. An offense of the highest order.

Then about two years ago somebody went «Whoa whoa, wait a minute. We don’t need all of that DOM ready nonsense. We can just put our JavaScript at the bottom»

And everyone was like, «Haha silly us, thinking that script tags belong in the header. They can go anywhere!»

Nowadays, no JavaScript ever goes in a $(document).ready() callback. Our scripts’ hair flows in the wind as they ride through the glen firing arrows into the sunset. Khem.

Anyway, the point is. We’ve all but forgotten about the DOM ready event. By the time our scripts run, the whole DOM is already there and we don’t have to worry about accessing elements that don’t exist.

That is, until we start rendering our elements with JavaScript.

Building DOM with JS can mess things up

In an ideal world, you’d wholly rely on your fancy framework to build the DOM. Backbone, Angular, CanJS, React, anything really. They’re all smart enough to keep you from doing stupid things.

But sometimes you’re still going to do something stupid. Like, you’ll have some init code that needs an element for some reason or another. In my case, I needed to set its width based on some stuff in local storage.

However, for whatever reason deep inside your legacy code, your init function gets called before the element you need is rendered. This can happen because you’re doing ugly things with your framework, like, setTimeout(foo, 100); // this solves a render loop conflict . Or as often happens, the element depends on a different component, and your framework decides on the wrong order of rendering.

Frameworks are fickle like that. They really really like to pretend everything renders at the same time, but in reality it renders in a loop.

And then you’re tempted to write something like this:

function try ()
if (!$("#element").size())
setTimeout(try, 500); // give everything some time to render
>
>

And it works. It really does. As long as you keep looking at it.

But modern browsers are tricky. When the tab isn’t in focus, or your user’s computer is running slow, or whatever, that timeout won’t have enough time.

You see, browsers these days are trying desperately to conserve batteries and generally be nice to computers. When a tab isn’t in focus, the JavaScript slows down. Timeouts start acting funny, and you should forget all about any rendering happening.

You’ll notice this easiest when switching to your app’s tab. It shows the old content. Then flashes. Then re-renders.

Really really really annoying for testing because you can no longer browse HackerNews while your app takes its 20 seconds to reload. But really useful for users.

Please don’t ask why the app I’m working on takes 20 seconds to reload.

But anyway, you’ve hit upon the problem of DOM elements not being there when your code needs them. No matter how long the delay in that setTimeout, the element still isn’t there.

«A-ha! DOM ready! I need the DOM ready!», you think.

Nope. The DOM is long since ready by the your script runs. I’ve tried that.

Turns out what you’re looking for is requestAnimationFrame . It’s normally used to make animation less jittery because it syncs your JavaScript’s rendering with the browser’s rendering. Normally about 60 hertz.

But it’s also how the browser tells your code that it’s still waiting. That things haven’t been rendered because the user isn’t there and there’s nobody to look at your stuff.

So instead of that setTimeout, you should do something like this:

function try()
if (!$("#element").size())
window.requestAnimationFrame(try);
>else
$("#element").do_some_stuff();
>
>;

Yup, no timeouts. At first glance it looks like this code is going to poll the DOM every 60th of a second to see if the element is there yet.

But in practice it only ever retries once. Because no matter what, by the next render frame, whether it comes in a 60th of a second, or a minute, the element will have been rendered.

And that’s how you properly wait for DOM elements to show up in modern browsers. I nearly tore my hair out before I figured it out.

Did you enjoy this article?

Learned something new?
Read more Software Engineering Lessons from Production

I write articles with real insight into the career and skills of a modern software engineer. «Raw and honest from the heart!» as one reader described them. Fueled by lessons learned over 20 years of building production code for side-projects, small businesses, and hyper growth startups. Both successful and not.

Software Engineering Lessons from Production

Join Swizec’s Newsletter and get insightful emails 💌 on mindsets, tactics, and technical skills for your career. Real lessons from building production software. No bullshit.

«Man, love your simple writing! Yours is the only newsletter I open and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. 👌»

~ Ashish Kumar

Senior Engineer Mindset cover

Senior Mindset Book

Get promoted, earn a bigger salary, work for top companies

Have a burning question that you think I can answer? Hit me up on twitter and I’ll do my best.

Who am I and who do I help? I’m Swizec Teller and I turn coders into engineers with «Raw and honest from the heart!» writing. No bullshit. Real insights into the career and skills of a modern software engineer.

Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help 👉 swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.

Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers 👉 ServerlessHandbook.dev

Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization

Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections

Want to brush up on modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog

Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com

By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️

Источник

Javascript — wait for DOM or element to load.

Nikita Kazakov

Javascript is asynchronous and a common pain-point is running a script before a DOM element on the page has loaded.

One way to handle this is by adding a listener to the document which listens for the DOMEContentLoaded event.

document.addEventListener("DOMContentLoaded", function() // Code here waits to run until the DOM is loaded. >); 

In complicated scenarios — when several elements on the page are loading data via AJAX — the above script doesn’t work.

I use the snippet below to check when a specific DOM element is present on the page and then run code. I took it from Volomike at Stack Overflow.

 const isElementLoaded = async selector =>  while ( document.querySelector(selector) === null)  await new Promise( resolve => requestAnimationFrame(resolve) ) > return document.querySelector(selector); >; // I'm checking for a specific class .file-item and then running code. You can also check for an id or an element. isElementLoaded('.file-item').then((selector) =>  // Run code here. >); 

This code is clever as it loops looking for a specific selector and returns a promise.

Источник

Оцените статью