2

I'm writing a small documentation, html being like:

<dl class="commands">
  <dt id="commandA">Command A</dt>
  <dd class="description">This command makes you happy.</dd>
  <dt id="commandB">Command B</dt>
  <dd class="description">This command makes you even happier.</dd>
</dl>

I thought it would be nice if accessing mydoc.html#commandA highlights where the description for command A is written, and wrote the following JavaScript:

(function(){
  window.addEventListener('load', emphCmd);
  
  function emphCmd(){
    var loc = window.location.href;
    if (/\.html#.*$/.test(loc)){
      var cmd = loc.split("#")[1]; // "commandA" for mydoc.html#commandA
      var cmdElm = document.getElementById(cmd);
      if (cmdElm !== null){ // if element with that id is found,
        cmdElm.style.backgroundColor = "#eeeeaa"; // highlight its background.
      }
    }
  }
})();

This works, but only when the page is loaded (well, of course. I said do this on load). The cases where this script does nothing includes : i) when I manually add #commandA to the address bar in the browser and press Enter (without F5 --- reloading) ii) Jumping within page with <a> tag.

I want it to be highlighted in either case. For the <a href="#commandA">, I could probablyanchor.addEventListener('click',emphCmd), although that does not seem very neat.

Is there an event for these "jumping within page"? If not, what are the good ways to achieve this effect?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Yosh
  • 2,512
  • 3
  • 24
  • 30
  • 2
    I think the `scroll` event is what you want. – Barmar Oct 17 '14 at 03:34
  • @Barmar That event fires just by scrolling, right? Although that won't cause problems in this case because what's after `#` is always checked, am I right to understand that there is no special ways for "jumping, not scrolling"? – Yosh Oct 17 '14 at 03:38
  • I'm not totally sure. I think it might fire for anything that causes the window to reposition, not just using the scrollbar. Try it and see if it works. – Barmar Oct 17 '14 at 03:39
  • 2
    Your requirement is just highlight the targeted part (the part is jumped to), so in this case you don't need to listen to any event, just add the style for `:target` in CSS to highlight it like this: http://jsfiddle.net/wfszzx2k/ – King King Oct 17 '14 at 03:39
  • 1
    @KingKing Wow, CSS3 literally rocks. I can accept as the answer if you post that alongside with `scroll` (or any other good) event.. – Yosh Oct 17 '14 at 03:43
  • it's OK. In fact I could not think of any event pinpointing exactly your desired event, so anyway the demo I posted is just a work-around (a beautiful one). – King King Oct 17 '14 at 03:59
  • @KingKing Will you be posting an answer? This is an interesting enough problem to solve that I wouldn't mind creating a community wiki post, if you won't be posting an answer. – Tieson T. Oct 17 '14 at 04:49
  • ok, you can freely make a wiki post. – King King Oct 17 '14 at 04:58
  • 1
    Why this is not helpful? http://stackoverflow.com/questions/2161906/handle-url-anchor-change-event-in-js – GramThanos Oct 19 '14 at 03:23
  • @ThanasisGrammatopoulos This IS helpful, I just couldn't find it --- I didn't come up with digging around hash, not movement. Although using css seems cleaner in this specific use case, `hashchange` event is the more general solution. Will you add that to the answer? – Yosh Oct 19 '14 at 06:26

1 Answers1

2

There isn't one single event that would cover your use-case, but since you're just attempting to style a targeted element, you can actually leverage the :target CSS pseudo-class. The MDN documentation has a pretty good description and some examples:

URIs with fragment identifiers link to a certain element within the document, known as the target element. For instance, here is a URI pointing to an anchor named section2: http://example.com/folder/document.html#section2 The anchor can be any element with an id attribute, e.g. <h1 id="section2"> in our example. The target element h1 can be represented by the :target pseudo-class.

The :target pseudo-class also works with named anchors (i.e. <a name="some-id-value"></a>), so it's backward-compatible with older markup. You will notice, though, that using a named anchor is not 100% the same - the targeted item receives the rule, and an anchor is an inline element.

Here's @KingKing's example, included as a code snippet:

:target {
  background: #eeeeaa;
}
<a href="#commandA">Command A</a>
<a href="#commandB">Command B</a>
<a href="#commandC">Command C</a>
<dl class="commands">
  <dt id="commandA">Command A</dt>
  <dd class="description">This command makes you happy.</dd>
  <dt id="commandB">Command B</dt>
  <dd class="description">This command makes you even happier.</dd>
  <dt><a name="commandC">Command C</a></dt>
  <dd class="description">This command makes you sad, since it's using a named anchor.</dd>
</dl>

The one caveat is that IE8 and under do not support the :target selector. You can get around that by using a polyfill such as Selectivir or IE9.js.

Tieson T.
  • 20,774
  • 6
  • 77
  • 92