Javascript:为博客文章创建多读/少读功能

时间:2021-04-05 00:57:21

标签: javascript this

早些时候发布了这个,但在意识到一个不适用于我的代码的限制之前,将回复标记为“答案”。重新发布我的问题。

JS 新手。我正在从头开始创建博客,并尝试实现“阅读更多/阅读更少”按钮。我能够在一篇博客文章中实现这一点,但是如果我尝试将相同的类添加到其他博客文章中,显然会出现问题,因为这样该函数将无法确定要对哪些对象进行操作。

我最接近让它工作的是另一个用户提供的这个解决方案:

function readMoreFunction(buttonIndex) {
    var dots = document.getElementsByClassName("dots")[buttonIndex];
    var contentText = document.getElementsByClassName("content")[buttonIndex];
    var btnText = document.getElementsByClassName("buttonReadMore")[buttonIndex];
    
    if (dots.style.display === "none") {
      dots.style.display = "inline";
      btnText.innerHTML = "Read More";
      contentText.style.display = "none";
    } else {
      dots.style.display = "none";
      btnText.innerHTML = "Read Less";
      contentText.style.display = "inline";
    }
  }
.content{
  display: none;
}
<p><strong>Blog Title</strong></p>

<p>Here is an example of the short snippet I want to show by default. <span class="dots">...</span></p>
<span class="content">
<p>Here is the longer text I want to show after the user clicks Read More.</p>
</span>
<button onclick="readMoreFunction(0)" class="buttonReadMore">Read More</button>

<p><strong>Blog Title 2</strong></p>

<p>Here is another short snippet I want to show by default for the second blog post. <span class="dots">...</span></p>
<span class="content">
<p>Here is the longer text I want to show after the user clicks Read More on the second blog post.</p>
</span>
<button onclick="readMoreFunction(1)" class="buttonReadMore">Read More</button>

基本上,当用户点击“阅读更多”时,省略号消失,隐藏的内容现在显示,按钮变为“阅读更少”。当他们点击“阅读更少”时,省略号将重新插入较短的片段部分,再次隐藏完整内容,按钮变回“阅读更多”。

问题是,我们通过一个索引号,当我们通过readMoreFunction(0)时会找到页面上“dots”类的第一个实例,当我们通过时,“dots”类的第二个实例通过readMoreFunction(1)等。所以你会发现,如果你把上面HTML中的(0)和(1)切换了,代码就不能正常工作了。单击“博客 1”阅读更多按钮将尝试展开“博客 2”,因为它正在寻找“点”类的第二个实例。

这意味着每次我在顶部添加一个新的博客文章时,我都需要更新在我所有博客文章中传递的索引号,以便最近的(顶部)文章现在是 (0) 并且第二篇文章现在是(1),通过我可能拥有的数百篇博客文章,这是不合理的。

如何编写一个函数,使“阅读更多/阅读更少”按钮独立运行所有不同的博客文章?我试图通过 this 中的 readMoreFunction,但无法弄清楚如何引用具有特定 id 或类名的前一个元素(以便它可以获取具有id“点”等)。我只能弄清楚如何使用 this.previousElementSibling;

引用最直接的前一个元素

你们能帮我指出正确的方向吗?

3 个答案:

答案 0 :(得分:1)

如果您可以随意编辑 html 标记,建议将每个博客内容包含在一个父元素中。

通过从父元素开始搜索类名,可以唯一标识按钮对应的每个元素。

function readMoreFunction(el) {
    var parent = el.closest(".wrapper")
    var dots = parent.querySelector(".dots");
    var contentText = parent.querySelector(".content");
    var btnText = parent.querySelector(".buttonReadMore");
    
    if (dots.style.display === "none") {
      dots.style.display = "inline";
      btnText.innerHTML = "Read More";
      contentText.style.display = "none";
    } else {
      dots.style.display = "none";
      btnText.innerHTML = "Read Less";
      contentText.style.display = "inline";
    }
  }
.content{
  display: none;
}
<div class="wrapper">
<p><strong>Blog Title</strong></p>

<p>Here is an example of the short snippet I want to show by default. <span class="dots">...</span></p>
<span class="content">
<p>Here is the longer text I want to show after the user clicks Read More.</p>
</span>
<button onclick="readMoreFunction(this)" class="buttonReadMore">Read More</button>
</div>

<div class="wrapper">
<p><strong>Blog Title 2</strong></p>

<p>Here is another short snippet I want to show by default for the second blog post. <span class="dots">...</span></p>
<span class="content">
<p>Here is the longer text I want to show after the user clicks Read More on the second blog post.</p>
</span>
<button onclick="readMoreFunction(this)" class="buttonReadMore">Read More</button>
</div>

答案 1 :(得分:1)

您可以在所有按钮内使用事件:onclick="readMoreFunction(event)"

然后在您的函数中,您使用 event.target 作为点击按钮的引用,并根据您的 HTML 标记从那里导航。

function readMoreFunction(event) {
  var dots = event.target.previousElementSibling.previousElementSibling.querySelector(".dots")
  var contentText = event.target.previousElementSibling
  var btnText = event.target

  if (dots.style.display === "none") {
    dots.style.display = "inline";
    btnText.innerHTML = "Read More";
    contentText.style.display = "none";
  } else {
    dots.style.display = "none";
    btnText.innerHTML = "Read Less";
    contentText.style.display = "inline";
  }
}
.content {
  display: none;
}
<p><strong>Blog Title</strong></p>

<p>Here is an example of the short snippet I want to show by default. <span class="dots">...</span></p>
<span class="content">
  <p>Here is the longer text I want to show after the user clicks Read More.</p>
</span>
<button onclick="readMoreFunction(event)" class="buttonReadMore">Read More</button>

<p><strong>Blog Title 2</strong></p>

<p>Here is another short snippet I want to show by default for the second blog post. <span class="dots">...</span>
</p>
<span class="content">
  <p>Here is the longer text I want to show after the user clicks Read More on the second blog post.</p>
</span>
<button onclick="readMoreFunction(event)" class="buttonReadMore">Read More</button>

答案 2 :(得分:1)

尝试将每个帖子包装在一个容器中,然后仅像下面那样通过该容器访问子项,这样您就永远不会遇到此类问题。

function readMoreFunction() {
    var parent = event.target.parentElement;
    var dots = parent.getElementsByClassName("dots")[0];
    var contentText = parent.getElementsByClassName("content")[0];
    var btnText = parent.getElementsByClassName("buttonReadMore")[0];
    
    if (dots.style.display === "none") {
      dots.style.display = "inline";
      btnText.innerHTML = "Read More";
      contentText.style.display = "none";
    } else {
      dots.style.display = "none";
      btnText.innerHTML = "Read Less";
      contentText.style.display = "inline";
    }
  }
.content{
  display: none;
}
<div class="conainer-post">
<p><strong>Blog Title</strong></p>

<p>Here is an example of the short snippet I want to show by default. <span class="dots">...</span></p>
<span class="content">
<p>Here is the longer text I want to show after the user clicks Read More.</p>
</span>
<button onclick="readMoreFunction()" class="buttonReadMore">Read More</button>
</div>

<div class="conainer-post">
<p><strong>Blog Title 2</strong></p>

<p>Here is another short snippet I want to show by default for the second blog post. <span class="dots">...</span></p>
<span class="content">
<p>Here is the longer text I want to show after the user clicks Read More on the second blog post.</p>
</span>
<button onclick="readMoreFunction()" class="buttonReadMore">Read More</button>
</div>