JavaScript:链接到隐藏容器中的锚点

huangapple go评论76阅读模式
英文:

Javascript: link to anchor in hidden container

问题

我有一个容器中的链接,另一个容器中的锚点默认隐藏。
当两个容器都显示时,链接可以正常工作,但当“锚点”容器隐藏时,链接不起作用。

我想要做的是:点击链接时,显示相关容器并跳转到锚点所在的位置。

以下是我尝试的代码,但成功有限(也可以查看这个Fiddle):

$(document).ready(function() {
  $(".toggle > *").hide();
  $(".toggle .header").show();
  $(".toggle .header").click(function() {
    $(this).parent().children().not(".header, .wy-table-responsive").toggle(400);
    $(this).parent().children(".wy-table-responsive").children().toggle(400);
    $(this).parent().children(".header").toggleClass("open");
    $(this).parent().children(".wy-table-responsive").toggleClass("open");
  });

  // 为指向隐藏部分锚点的 href 添加点击事件监听器
  $("a[href^='#']").click(function(event) {
    event.preventDefault(); // 阻止链接的默认行为
    var targetId = $(this).attr("href").substring(1); // 获取目标锚点的 id
    $(document.location.targetId).slideDown().prev().addClass('active');
  });
});
.toggle .header {
  display: block;
  clear: both;
}

.toggle .header p:before {
  content: " ▶ ";
}

.toggle .header.open p:before {
  content: " ▼ ";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<div class="toggle docutils container">
  <div class="header docutils container">
    <p><strong>Keywords</strong></p>
  </div>
  <pre class="literal-block">
    <a class="reference internal" href="#ref1"><span class="std std-ref">ref1</span></a> value = 1
    <a class="reference internal" href="#ref2"><span class="std std-ref">is_planar</span></a> value= 2
  </pre>
</div>

<div class="toggle docutils container">
  <div class="header docutils container">
    <p><strong>Anchors</strong></p>
  </div>
  <p id="ref1">ref1 anchor</p>
  <p id="ref2">ref2 anchor</p>
</div>

这段代码使用了jQuery来实现所需的功能。希望这对你有帮助。

英文:

I have links in a container with anchors in another container hidden by default.
When both container are showing, the link works without problem, but when the "Anchors" container is hidden, the link does not work.

What I would like to do : on the click of the link, show the relative container and go to the line of the anchor.

Here is what I did, without much success (also as a Fiddle):

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

$(document).ready(function() {
  $(&quot;.toggle &gt; *&quot;).hide();
  $(&quot;.toggle .header&quot;).show();
  $(&quot;.toggle .header&quot;).click(function() {
    $(this).parent().children().not(&quot;.header, .wy-table-responsive&quot;).toggle(400);
    $(this).parent().children(&quot;.wy-table-responsive&quot;).children().toggle(400);
    $(this).parent().children(&quot;.header&quot;).toggleClass(&quot;open&quot;);
    $(this).parent().children(&quot;.wy-table-responsive&quot;).toggleClass(&quot;open&quot;);
  });

  // Add click event listeners to links with href pointing to anchors in hidden section
  $(&quot;a[href^=&#39;#&#39;]&quot;).click(function(event) {
    event.preventDefault(); // Prevent default behavior of link
    var targetId = $(this).attr(&quot;href&quot;).substring(1); // Get the id of the target anchor
    $(document.location.targetId).slideDown().prev().addClass(&#39;active&#39;);
  });
});

<!-- language: lang-css -->

.toggle .header {
  display: block;
  clear: both;
}

.toggle .header p:before {
  content: &quot; ▶ &quot;;
}

.toggle .header.open p:before {
  content: &quot; ▼ &quot;;
}

<!-- language: lang-html -->

&lt;script src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;toggle docutils container&quot;&gt;
  &lt;div class=&quot;header docutils container&quot;&gt;
    &lt;p&gt;&lt;strong&gt;Keywords&lt;/strong&gt;&lt;/p&gt;
  &lt;/div&gt;
  &lt;pre class=&quot;literal-block&quot;&gt;
&lt;a class=&quot;reference internal&quot; href=&quot;#ref1&quot;&gt;&lt;span class=&quot;std std-ref&quot;&gt;ref1&lt;/span&gt;&lt;/a&gt; value = 1
&lt;a class=&quot;reference internal&quot; href=&quot;#ref2&quot;&gt;&lt;span class=&quot;std std-ref&quot;&gt;is_planar&lt;/span&gt;&lt;/a&gt;  value= 2
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;toggle docutils container&quot;&gt;
  &lt;div class=&quot;header docutils container&quot;&gt;
    &lt;p&gt;&lt;strong&gt;Anchors&lt;/strong&gt;&lt;/p&gt;
  &lt;/div&gt;
  &lt;p id=&quot;ref1&quot;&gt;ref1 anchor
    &lt;p id=&quot;ref2&quot;&gt;ref2 anchor
&lt;/div&gt;

<!-- end snippet -->

答案1

得分: 1

看起来有一些相对较小的问题:

  1. 你从 targetId 中移除了 #,但是如果你要将其与 $() 一起使用来按ID查找某个元素,你需要保留它,因为它表示ID选择器。
  2. $(document.location.targetId) 查找 document.location 上名为 targetId 的属性,然后使用其值作为 $ 的参数。我认为你想要使用你刚刚创建并填充的 targetId 变量。
  3. 你实际上没有滚动到任何地方,只是向下滑动。

我通过以下方式修复了这些问题,不移除 #,只是使用 $(targetId) 来获取元素,并在 slideDown 的完成回调中使用内置的 "smooth" 动画将目标滚动到视图中:

$(document).ready(function() {
  $(".toggle > *").hide();
  $(".toggle .header").show();
  $(".toggle .header").click(function() {
    $(this).parent().children().not(".header, .wy-table-responsive").toggle(400);
    $(this).parent().children(".wy-table-responsive").children().toggle(400);
    $(this).parent().children(".header").toggleClass("open");
    $(this).parent().children(".wy-table-responsive").toggleClass("open");
  });

  // Add click event listeners to links with href pointing to anchors in hidden section
  $("a[href^='#']").click(function(event) {
    event.preventDefault(); // 阻止链接的默认行为
    var targetId = $(this).attr("href"); // 获取目标锚点的ID
    var target = $(targetId);
    target
      .slideDown(() => {
        target[0].scrollIntoView({ behavior: "smooth" });
      })
      .prev()
      .addClass('active');
  });
});

我还在它们之间插入了一个元素,以便我们可以看到滚动。

(另外,你没有关闭段落标签。我知道大多数情况下你不需要关闭它们,但它会影响格式化程序 [以及其他人阅读你的代码的思维],我建议你关闭它们。我在上面已经这样做了。)

英文:

Looks like there were a couple of relatively-minor problems:

  1. You were removing the # from targetId, but if you're going to use it with $() to look something up by ID, you need that as it's what indicates an ID selector.
  2. $(document.location.targetId) looks for a property called targetId on document.location, then uses its value as the argument to $. I think you wanted to just use the targetId variable you'd just created and filled in.
  3. You weren't actually scrolling to anything, just sliding it down.

I've fixed that below by not stripping the #, just using $(targetId) to get the element, and using the completion callback for slideDown to scroll the target into view (using the built-in "smooth" animation):

<!-- begin snippet: js hide: false console: false babel: false -->

<!-- language: lang-js -->

$(document).ready(function() {
  $(&quot;.toggle &gt; *&quot;).hide();
  $(&quot;.toggle .header&quot;).show();
  $(&quot;.toggle .header&quot;).click(function() {
    $(this).parent().children().not(&quot;.header, .wy-table-responsive&quot;).toggle(400);
    $(this).parent().children(&quot;.wy-table-responsive&quot;).children().toggle(400);
    $(this).parent().children(&quot;.header&quot;).toggleClass(&quot;open&quot;);
    $(this).parent().children(&quot;.wy-table-responsive&quot;).toggleClass(&quot;open&quot;);
  });

  // Add click event listeners to links with href pointing to anchors in hidden section
  $(&quot;a[href^=&#39;#&#39;]&quot;).click(function(event) {
    event.preventDefault(); // Prevent default behavior of link
    var targetId = $(this).attr(&quot;href&quot;); // Get the id of the target anchor
    var target = $(targetId);
    target
      .slideDown(() =&gt; {
        target[0].scrollIntoView({ behavior: &quot;smooth&quot; });
      })
      .prev()
      .addClass(&#39;active&#39;);
  });
});

<!-- language: lang-css -->

.toggle .header {
  display: block;
  clear: both;
}

.toggle .header p:before {
  content: &quot; ▶ &quot;;
}

.toggle .header.open p:before {
  content: &quot; ▼ &quot;;
}

<!-- language: lang-html -->

&lt;script src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;toggle docutils container&quot;&gt;
  &lt;div class=&quot;header docutils container&quot;&gt;
    &lt;p&gt;&lt;strong&gt;Keywords&lt;/strong&gt;&lt;/p&gt;
  &lt;/div&gt;
  &lt;pre class=&quot;literal-block&quot;&gt;
&lt;a class=&quot;reference internal&quot; href=&quot;#ref1&quot;&gt;&lt;span class=&quot;std std-ref&quot;&gt;ref1&lt;/span&gt;&lt;/a&gt; value = 1
&lt;a class=&quot;reference internal&quot; href=&quot;#ref2&quot;&gt;&lt;span class=&quot;std std-ref&quot;&gt;is_planar&lt;/span&gt;&lt;/a&gt;  value= 2
&lt;/pre&gt;
&lt;/div&gt;

&lt;div style=&quot;height: 50em&quot;&gt;A bunch of space so we can see scrolling&lt;/div&gt;

&lt;div class=&quot;toggle docutils container&quot;&gt;
  &lt;div class=&quot;header docutils container&quot;&gt;
    &lt;p&gt;&lt;strong&gt;Anchors&lt;/strong&gt;&lt;/p&gt;
  &lt;/div&gt;
  &lt;p id=&quot;ref1&quot;&gt;ref1 anchor&lt;/p&gt;
  &lt;p id=&quot;ref2&quot;&gt;ref2 anchor&lt;/p&gt;
&lt;/div&gt;

<!-- end snippet -->

I also inserted an element between them so we could see the scrolling.

(Also, you weren't closing your paragraphs tags. I realize you don't have to much of the time, but it messes with formatters [and with the minds of other people reading your code], I suggest doing it. I've done it above.)

huangapple
  • 本文由 发表于 2023年5月24日 17:59:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76322281.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定