Reacting to URLs with HTML5 anchor/hash-tag/page-locaiton


#1

I’m using Meteor and Iron Router on client rendered reactive pages. I’d like to include anchors in text. I’ve read many other questions and even blog posts on this but they are old and the standard HTML5 method of writing the template does not seem to work.

Notice these are not necessarily triggered from inside the same page (an intra-page link), they may even be typed into the URL bar. I’d like to use them a lot so would appreciate something that doesn’t involve a router.js change for each one.

Can someone tell me what to do in my template/code to respond to any HTML5 anchor URL?


#2

I’m curious to know some other approaches as well. I’ve tried a few packages, but haven’t found one that worked consistently.

I use something like the following for templates where I am using an anchor in the url:

Template.myTemplate.onRendered(function() {
  if(window.location.hash) {
    $('.some.container').animate({ scrollTop: $(window.location.hash)[0].offsetTop + 40 }, 1000);
  }
});

#3

Wow, thanks for the fast reply!!

Sorry a bit of a Meteor noob, what is “.some.container”? What element of the template is this? Also is + 40 good for all? What do I base 40 on, nav/menu size?


#4

No worries. .some.container is the container you need to scroll. This could actually be something like $(window), if you are trying to scroll the entire page? 40 is based on a sticky nav that I use. And this is the template that wraps the content of the page, in my example.

So, I have a layout template that houses the menu template (for my nav) and the myTemplate that I referenced above, that is the content. If that makes sense?


#5

Gotit

Actually another reson I get confused is where do I put the code? Depends on my template nesting I bet. So if I use the same outer template for all “docs/”; a template like: <template name="docs">, would I put it there? In which case mytemplate is not named but is dynamic and has a page name:

<section class="docs-content">
  {{>Template.dynamic template=getTemplateName}}
</section>

Is the container "docs-content"? so the new code might be:

<section class="docs-content">
  {{>Template.dynamic template=getTemplateName;
    Template.template.onRendered(function() {
      if(window.location.hash) {
        $('.docs-content').animate({ scrollTop: $(window.location.hash)[0].offsetTop}, 1000);
      }
    });
  }}
</section>

The nav bar is above docs-content so no additional offset is needed? But the way you wrote it leads me to think I need to add to every page-specific leaf template?


#6

Yeah, it definitely would depend on your template nesting and when it makes sense to actually start scrolling the content. In my instance, I know that the timing is such that I can rely on the onRendered function for that specific template to know that my page is populated with the anchor I need to scroll to.

Your container could even vary by template, depending on your div structure. For instance, you could have a wrapper container with no overflow. In that case, you’d probably want to scroll secondContainer:

<div style="overflow: hidden;" class="mainContainer">
  <div class="secondContainer">
    <h2 id="section1">Section 1</h2>
  </div>
</div>

And yes, right now I include this block in every page template where I want this functionality. Not very DRY but it works and represents such a small piece of functionality that I can’t really justify putting a ton of time towards it right now.


#7

Thanks, given my ignorance, I’ll put it in every page for now. Much appreciated.