32

I'm working on a simple application which is single page based (due to project restrictions) and has dynamic content. I understand the dynamic content alright but what I don't understand is how to set-up a script that changes the html of a div when the hash value in the URL changes.

I need a JavaScript script to work as such:

Url: http://foo.com/foo.html div contents: <h1>Hello World</h1>

Url: http://foo.com/foo.html#foo div contents: <h1>Foo</h1>

How would this work?

Please help! Thanks.

Nagendra Rao
  • 7,016
  • 5
  • 54
  • 92
user115422
  • 4,662
  • 10
  • 26
  • 38
  • Have a look at [sammy](https://github.com/quirkey/sammy). – Brad Christie Feb 20 '13 at 01:25
  • @Bradchristie ok, i'll take a look but ideally i want to avoid using plugins much... is it possible with just jQuery? – user115422 Feb 20 '13 at 01:26
  • Let's look at it realistically. Either you spend the additional time writing something that does what a library does, or you just use the library and move on. You're already using jQuery (a library) because you presumably want the flexibility and not have to write it yourself. Plus sammy lets you insert placeholders and template the incoming hash (very flexible) – Brad Christie Feb 20 '13 at 01:31
  • @BradChristie, understood, i just need to see an example... im a bit messed up :( – user115422 Feb 20 '13 at 01:33

3 Answers3

77

You can listen to the hashchange event:

$(window).on('hashchange',function(){ 
    $('h1').text(location.hash.slice(1));
});
Ram
  • 143,282
  • 16
  • 168
  • 197
  • ok, this may seem like a stupid question but does this go at the end of the body or in the head because I always get confused in this regard? – user115422 Feb 20 '13 at 01:27
  • @RPM so in the head? Thanks :) – user115422 Feb 20 '13 at 01:29
  • 7
    I _believe_ that assumes HTML5's [`window.onhashchange`](http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#event-hashchange) event exists. this isn't a native event of jquery i don't believe and therefore you're looking at either using a plugin to generate a trigger, or only accept those supporting the [fairly new event](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange). – Brad Christie Feb 20 '13 at 01:30
  • @BradChristie, can you show me an example using the plugin because this isnt working for me :( – user115422 Feb 20 '13 at 01:31
5

personally, I'd use sammy which gives you the flexibility to template the hashtag (add placeholders and be able to read them back). e.g.

<script src="/path/to/jquery.js"></script>
<script src="/path/to/sammy.js"></script>
<script>
  $(function(){
      // Use sammy to detect hash changes
      $.sammy(function(){
          // bind to #:page where :page can be some value
          // we're expecting and can be retrieved with this.params
          this.get('#:page',function(){
              // load some page using ajax in to an simple container
              $('#container').load('/partial/'+this.params['page']+'.html');
          });
      }).run();
  });
</script>

<a href="#foo">Load foo.html</a>
<a href="#bar">Load bar.html</a>

An example can be found here: http://jsfiddle.net/KZknm/1/

Brad Christie
  • 100,477
  • 16
  • 156
  • 200
0

Suppose we have list of items, each items has a hash tag as #id

const markup = `
        <li>
            <a class="results__link" href="#${recipe.recipe_id}">
                <figure class="results__fig">
                    <img src="${recipe.image_url}" alt="${limitRecipeTitle(recipe.title)}">
                </figure>
                <div class="results__data">
                    <h4 class="results__name">${recipe.title}</h4>
                    <p class="results__author">${recipe.publisher}</p>
                </div>
            </a>
        </li>
    `;

Now when a user click on any of those list item or reload (http://localhost:8080/#47746) an item with hash tag, hash event will be fired. To recive the fired hash event we must register hash event listener in our app.js

//jquery: 
['hashchange', 'load'].forEach(event => $(window).on(event, controlRecipe));
//js:
['hashchange', 'load'].forEach(event => window.addEventListener(event, controlRecipe));

catch the id in your controlRecipe function

const controlRecipe = async ()=>{
//jq
  const id =  $(window)..location.hash.replace('#','');
//js
  const id = window.location.hash.replace('#','');
  if(id){
    //console.log(id);
    state.recipe = new Recipe(id);
    try {
      await state.recipe.getRecipe();
      state.recipe.calcTime();
      state.recipe.calcServings();
      console.log(state.recipe);
    } catch (error) {
      alert(error);
    }
  }
}
Rafiq
  • 8,987
  • 4
  • 35
  • 35