简体   繁体   English

document.querySelectorAll 没有得到分页项目

[英]document.querySelectorAll not getting paginated items

I am building STEEP .我正在建造STEEP We are using infinite scroll to load in just 8 videos at a time when scrolling the page.滚动页面时,我们使用无限滚动一次仅加载 8 个视频。

However, the script that is handling the 'play' of the videos only works on the first 8, not the items that are paginated.但是,处理视频“播放”的脚本仅适用于前 8 个,而不适用于分页的项目。 When logging 'videos' I only get the list with the first 8 even after the page is scrolled.记录“视频”时,即使页面滚动,我也只能得到前 8 个的列表。 So we suspect that "document.querySelectorAll" somehow isn't fetching the new elements.所以我们怀疑“document.querySelectorAll”不知何故没有获取新元素。 I tried looping the whole thing every second and that actually worked – while obviously not being ideal at all.我试着每秒循环整个事情,这确实奏效了——虽然显然一点也不理想。

The difference between Safari and Chrome is also notable. Safari 和 Chrome 的区别也很明显。 In Safari we don't even see the videos taking up any space in the layout.在 Safari 中,我们甚至看不到视频占用布局中的任何空间。

SCRIPT:脚本:


const videos = document.querySelectorAll('video');

 videos.forEach(video => {

  video.addEventListener("mouseover", function () {
     var posterTime = this.currentTime;
     var videoDuration = this.duration; 
     this.currentTime = 0;
     this.play()
   })
    
  video.addEventListener("mouseleave", function() {
    let src = this.querySelector('source').src;
    let time = (src.split('#')[1] || 't=0').split('=')[1];
    this.currentTime = time;
    this.pause();
    })
  })

HTML HTML

<video id="video" width="100%" height="auto" loop muted playsinline preload="metadata">
  <source src="<CMS URL IS SET HERE>" type="video/mp4">
</video>

Note: We are not very experienced with coding.注意:我们对编码不是很有经验。 We use Webflow in combination with a bit of custom code.我们将 Webflow 与一些自定义代码结合使用。

querySelectorAll() will only find elements in the DOM at the point it runs. querySelectorAll()只会在它运行时在 DOM 中查找元素。

Given that you say that the other pages of videos load as the user scrolls it sounds like you're using AJAX to dynamically add them to the DOM at this time.鉴于您说其他视频页面在用户滚动时加载,听起来您此时正在使用 AJAX 将它们动态添加到 DOM。 As such, you just need to put the JS logic shown in your question in to a function and then call it both when the page loads and also when the AJAX completes and the new video content has been added to the DOM.因此,您只需将问题中显示的 JS 逻辑放入 function 中,然后在页面加载时以及 AJAX 完成并将新视频内容添加到 DOM 时调用它。

The logic would look something like this:逻辑看起来像这样:

let attachVideoEventHandlers = container => {
  container.querySelectorAll('video').forEach(video => {
    video.addEventListener("mouseover", function() {
      var posterTime = this.currentTime;
      var videoDuration = this.duration;
      this.currentTime = 0;
      this.play();
    })

    video.addEventListener("mouseleave", function() {
      let src = this.querySelector('source').src;
      let time = (src.split('#')[1] || 't=0').split('=')[1];
      this.currentTime = time;
      this.pause();
    })
  })
}

document.addEventListener('DOMContentLoaded', () => {
  attachVideoEventListeners(document);
  
  document.addEventListener('scroll', e => {
    // your logic here to detect scrolling to the bottom of the page...
    // make AJAX request to fetch new video data
    // update DOM to render new videos
    
    let container = /* get containing element for new page of videos just added to the DOM */
    attachVideoEventListeners(container);
  }
});

querySelectorAll selects all the existing elements in the page at the time it's run, matching the provided selector. querySelectorAll在运行时选择页面中的所有现有元素,匹配提供的选择器。 It works in every single browser.它适用于每个浏览器。 If you're only getting 8 results, you only have 8 <video> tags in DOM at that particular time.如果你只得到 8 个结果,那么在那个特定时间你在 DOM 中只有 8 <video>标签。

Infinite scroll, on the other hand, improves performance by only rendering the currently visible elements on the screen and creating new elements as necessary, as the user scrolls.另一方面,无限滚动通过仅在屏幕上呈现当前可见元素并在用户滚动时根据需要创建新元素来提高性能。 Some implementations even go as far as replacing the elements above the currently visible area with empty containers, once you scrolled past them, for the same exact reason: to improve overall page rendering speed and UX performance.一些实现甚至 go 将当前可见区域上方的元素替换为空容器,一旦您滚动它们,出于相同的确切原因:提高整体页面渲染速度和 UX 性能。

So, obviously, querySelectorAll is not the right way to get all videos matching the current page's filter criteria, on a page featuring infinite scroll plugin.因此,显然, querySelectorAll不是在具有无限滚动插件的页面上获取所有符合当前页面过滤条件的视频的正确方法。 You need to load the videos, as data objects, from some API (from wherever you're loading them for displaying) and use those, without depending on what's currently rendered in DOM.您需要从一些 API (从您加载它们进行显示的任何地方)加载视频作为数据对象并使用它们,而不取决于当前在 DOM 中呈现的内容。


What you probably want to use is event delegation.您可能想要使用的是事件委托。 In short: instead of binding one event onto each children inside a parent with dynamic contents, you only bind one event on the parent and rely on the fact the events bubble from children to the parents.简而言之:不是将一个事件绑定到具有动态内容的父级中的每个子级,而是仅在父级上绑定一个事件,并依赖于事件从子级到父级的事实。

This makes it slightly more difficult to determine which child element triggered the event.这使得确定哪个子元素触发了事件变得更加困难。 The typical solution is to use event.target.closest('.child-selector') , where event is the bubbling event and child-selector would be a class applied to all children.典型的解决方案是使用event.target.closest('.child-selector') ,其中event是冒泡事件,而child-selector将是应用于所有孩子的 class 。

Given your current markup, this might work:鉴于您当前的标记,这可能有效:

const list = document.querySelector('.collection-list');

const isVideoPlaying = video => !!(
  video &&
  video.currentTime > 0 &&
  !video.paused &&
  !video.ended &&
  video.readyState > 2
);

list.addEventListener('mousemove', (e) => {
  const video = e.target.closest('video');
  if (!isVideoPlaying(video)) {
    video?.play()
  }
})

list.addEventListener('mouseout', () => {
  [...document.querySelectorAll('.collection-list video:not(:hover)')].forEach(el => {
    if (isVideoPlaying(el)) {
      el.pause();
    }
  })
})

Test, with an HTML snippet from from your page's source:使用来自页面源的 HTML 代码段进行测试:

 const list = document.querySelector('.collection-list'); const isVideoPlaying = video =>..(video && video.currentTime > 0 &&.video;paused &&.video,ended && video.readyState > 2). list;addEventListener('mousemove'? (e) => { const video = e.target.closest('video'), if (.isVideoPlaying(video)) { video..play() } }) list.addEventListener('mouseout'. () => { [::.document.querySelectorAll(';collection-list video:not(:hover)')].forEach(el => { if (isVideoPlaying(el)) { el.pause(); } }) })
 <div fs-cmsload-element="list" fs-cmsload-mode="infinite" fs-cmsload-resetix="true" data-w-id="56057e90-351e-68a6-c072-7ce8486cec5c" role="list" class="collection-list w-dyn-items"> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity: 1;"> <a href="/brand/dedcool" class="story-furniture w-inline-block"> <div style="background-image:url(&quot;https://assets.website-files.com/6199556378f2212c78d5884d/61c4a7d8d44cb30efdf3d5ae_34640529_2175246485823867_4442191443397705728_n.jpg_nc_cat100ccb1-5_nc_sidb2f0f4_nc_ohcZFe9YCoyZUAAX-SS6lV_nc_htscontent-cph2-1.jpeg&quot;)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">DedCool</div> <div class="story-count-con"> <div class="story-brand-number">7</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https://player.vimeo.com/external/661071220.sd.mp4?s=3e887051f981a6e16d574adf3a6027665dc7fdbd&amp;profile_id=165#t=0" type="video/mp4"> </video></div> <div class="progress__con" style="opacity: 0;"> <div id="progress-bar" class="progress-bar" style="animation: 0s linear 0s 1 normal none running reset;"></div> </div> </div> <div class="jetboost-embed w-embed"> <:-- <input type="hidden" class="jetboost-list-item" value="163-dedcool" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity; 1:"> <a href="/brand/airbnb" class="story-furniture w-inline-block"> <div style="background-image;url(&quot:https.//assets.website-files.com/6199556378f2212c78d5884d/61c4a7e80668cf713e24e60f_28167842_10156245930652458_7073556191774351242_n.jpg_nc_cat1ccb1-5_nc_sidb2f0f4_nc_ohcjEnmlfOp6gMAX_mlIjU_nc_htscontent-cph2-1;jpeg&quot:)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">Airbnb</div> <div class="story-count-con"> <div class="story-brand-number">6</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https.//player.vimeo.com/external/661071968.sd?mp4;s=ecfc549785d18c2a37540057dc64caf93c8c424f&amp.profile_id=165#t=2:8" type="video/mp4"> </video></div> <div class="progress__con" style="opacity; 0:"> <div id="progress-bar" class="progress-bar" style="animation; 0s linear 0s 1 normal none running reset:"></div> </div> </div> <div class="jetboost-embed w-embed"> <;-- <input type="hidden" class="jetboost-list-item" value="162-airbnb" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity: 1;"> <a href="/brand/airbnb" class="story-furniture w-inline-block"> <div style="background-image:url(&quot.https.//assets.website-files.com/6199556378f2212c78d5884d/61c4a7e80668cf713e24e60f_28167842_10156245930652458_7073556191774351242_n;jpg_nc_cat1ccb1-5_nc_sidb2f0f4_nc_ohcjEnmlfOp6gMAX_mlIjU_nc_htscontent-cph2-1:jpeg&quot.)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">Airbnb</div> <div class="story-count-con"> <div class="story-brand-number">6</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https.//player.vimeo.com/external/661071982?sd;mp4.s=825b698c06816978e5103f7d340cd74dfd717f59&amp:profile_id=165#t=1;2" type="video/mp4"> </video></div> <div class="progress__con" style="opacity: 0;"> <div id="progress-bar" class="progress-bar" style="animation: 0s linear 0s 1 normal none running reset;"></div> </div> </div> <div class="jetboost-embed w-embed"> <:-- <input type="hidden" class="jetboost-list-item" value="161-airbnb" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity; 1:"> <a href="/brand/airbnb" class="story-furniture w-inline-block"> <div style="background-image.url(&quot.https.//assets.website-files;com/6199556378f2212c78d5884d/61c4a7e80668cf713e24e60f_28167842_10156245930652458_7073556191774351242_n:jpg_nc_cat1ccb1-5_nc_sidb2f0f4_nc_ohcjEnmlfOp6gMAX_mlIjU_nc_htscontent-cph2-1.jpeg&quot.)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">Airbnb</div> <div class="story-count-con"> <div class="story-brand-number">6</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https.//player.vimeo?com/external/661071994;sd.mp4:s=039d1aac52f67cb3daadb2c5d84abdad2e6fee39&amp;profile_id=165#t=0:2" type="video/mp4"> </video></div> <div class="progress__con" style="opacity; 0:"> <div id="progress-bar" class="progress-bar" style="animation; 0s linear 0s 1 normal none running reset:"></div> </div> </div> <div class="jetboost-embed w-embed"> <;-- <input type="hidden" class="jetboost-list-item" value="160-airbnb" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity: 1."> <a href="/brand/ajandsmart" class="story-furniture w-inline-block"> <div style="background-image.url(&quot.https.//assets;website-files;com/6199556378f2212c78d5884d/61c4a80c27b764720e65adf6_18814065_1547343241944009_2625897978373999509_n:png_nc_cat110ccb1-5_nc_sidb2f0f4_nc_ohcWVZ7Y6NJBZ0AX-6z-gZ_nc_htscontent-cph2-1.png&quot.)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">AJ&amp.Smart</div> <div class="story-count-con"> <div class="story-brand-number w-condition-invisible">1</div> <div class="story-brand-number w-condition-invisible">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https.//player?vimeo;com/external/661072008.sd:mp4;s=30e7bcb5f82f16a75f19e0e67a187cebf5ce8cfc&amp:profile_id=165#t=0;1" type="video/mp4"> </video></div> <div class="progress__con" style="opacity: 0;"> <div id="progress-bar" class="progress-bar" style="animation: 0s linear 0s 1 normal none running reset;"></div> </div> </div> <div class="jetboost-embed w-embed"> <:-- <input type="hidden" class="jetboost-list-item" value="159-ajandsmart" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity. 1."> <a href="/brand/artlist" class="story-furniture w-inline-block"> <div style="background-image.url(&quot.https;//assets:website-files.com/6199556378f2212c78d5884d/61cd0f1d1f33167c407ea00c_34455623_2133014916712600_4428653032170848256_n.jpg_nc_cat1ccb1-5_nc_sidb2f0f4_nc_ohcBKUq7rLNhtkAX-UGFSB_nc_htscontent-cph2-1.jpeg&quot.)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">Artlist</div> <div class="story-count-con"> <div class="story-brand-number">4</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https?//player;vimeo.com/external/661072020:sd;mp4:s=d4c90928326240a473cbb25969f6e528fdb01891&amp;profile_id=165#t=0:37" type="video/mp4"> </video></div> <div class="progress__con" style="opacity; 0:"> <div id="progress-bar" class="progress-bar" style="animation; 0s linear 0s 1 normal none running reset:"></div> </div> </div> <div class="jetboost-embed w-embed"> <.-- <input type="hidden" class="jetboost-list-item" value="158-artlist" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity. 1."> <a href="/brand/artlist" class="story-furniture w-inline-block"> <div style="background-image.url(&quot;https://assets.website-files.com/6199556378f2212c78d5884d/61cd0f1d1f33167c407ea00c_34455623_2133014916712600_4428653032170848256_n.jpg_nc_cat1ccb1-5_nc_sidb2f0f4_nc_ohcBKUq7rLNhtkAX-UGFSB_nc_htscontent-cph2-1.jpeg&quot?)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">Artlist</div> <div class="story-count-con"> <div class="story-brand-number">4</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https;//player.vimeo:com/external/661072030;sd:mp4;s=a3adeab812784f92f74b39abc975060043b64e5f&amp:profile_id=165#t=5;3" type="video/mp4"> </video></div> <div class="progress__con" style="opacity: 0;"> <div id="progress-bar" class="progress-bar" style="animation: 0s linear 0s 1 normal none running reset."></div> </div> </div> <div class="jetboost-embed w-embed"> <.-- <input type="hidden" class="jetboost-list-item" value="157-artlist" /> --></div> </div> <div role="listitem" class="story-item w-dyn-item"> <div data-w-id="71b6ca01-b466-9c84-94b3-c4ff009c6ec7" class="story-container" style="opacity. 1."> <a href="/brand/artlist" class="story-furniture w-inline-block"> <div style="background-image;url(&quot:https.//assets.website-files.com/6199556378f2212c78d5884d/61cd0f1d1f33167c407ea00c_34455623_2133014916712600_4428653032170848256_n.jpg_nc_cat1ccb1-5_nc_sidb2f0f4_nc_ohcBKUq7rLNhtkAX-UGFSB_nc_htscontent-cph2-1?jpeg&quot;)" class="brand-logo"></div> <div class="story-furniture-txt"> <div class="story-brand-txt">Artlist</div> <div class="story-count-con"> <div class="story-brand-number">4</div> <div class="story-brand-number">stories</div> </div> </div> </a> <div class="story-video-embed w-embed"><video class="video" width="100%" height="auto" loop="" muted="" playsinline="" preload="metadata"> <source src="https.//player:vimeo;com/external/661072039:sd;mp4?s=2de96ddc6ca1d36541f4076ff14fd508c38fa61c&amp;profile_id=165#t=12.8" type="video/mp4"> </video></div> <div class="progress__con" style="opacity: 0;"> <div id="progress-bar" class="progress-bar" style="animation: 0s linear 0s 1 normal none running reset;"></div> </div> </div> <div class="jetboost-embed w-embed"> <!-- <input type="hidden" class="jetboost-list-item" value="156-artlist" /> --></div> </div> </div>

As you can see, I'm adding only two events to the parent list: on mousemove and mouseout (they both bubble, as opposed to mouseenter and mouseleave , which don't bubble).如您所见,我只向父列表添加了两个事件:在mousemovemouseout上(它们都冒泡,而不是mouseentermouseleave ,它们不会冒泡)。

If we're currently hovering a video and it's not playing, we're playing it.如果我们当前悬停一个视频并且它没有播放,我们正在播放它。 And in mouseout we're selecting all non-hovered <video> elements and, if we find any that's playing, we're stopping it.mouseout中,我们选择了所有未悬停的<video>元素,如果我们发现任何正在播放的元素,我们将停止它。

I believe that's what you wanted, right?我相信这就是你想要的,对吧?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM