1

My 'about' page uses a div content switch method (by Bill Posters) that allows me to put the mission, contact, etc, in the same container. It works really well until I try to link into a specific tab from another page. E.g., I have '/about/#mission' or '/about/#contact' that ends up linking to the first 'about' option of the content switch box rather than the correct option. I'd like a user to be able to click on 'Contact Us' from the homepage and get directed straight to the contact tab.

I've tried and tried to tweak the html and the jquery (even experimented with double anchors which I'm pretty sure is not a thing), I've added cookie recognition (doesn't quite work if the user hasn't accessed the page yet...), and I've searched forums extensively. Any ideas what I'm doing wrong or if there's a better way to do this? I'm guessing I'm making the issue much more complicated than necessary, but I'm pretty new to coding and, among other things, may not be using the correct search language.

I'd really appreciate any help!! I'm not married to this particular content switch method and am happy to try something else. Thanks very much!

Sara

function switchContent(obj) {

    obj = (!obj) ? 'sub1' : obj;

    var contentDivs =    document.getElementById('container').getElementsByTagName('div');
    for (i=0; i<contentDivs.length; i++) {
        if (contentDivs[i].id && contentDivs[i].id.indexOf('sub') != -1) {
            contentDivs[i].className = 'hide';
        }
    }
    document.getElementById(obj).className = '';

}


<div id="container">

<div id="sub1">content 1</div>
<div id="sub2" class="hide">content 2</div>
<div id="sub3" class="hide">content 3</div>

<div id="navigation">
    <a href="#" class="mininav" onclick="switchContent('sub1');   return false;">link 1</a>
    <a href="#" class="mininav" onclick="switchContent('sub2'); return false;">link 2</a>
    <a href="#" class="mininav" onclick="switchContent('sub3'); return false;">link 3</a>
</div>

Sara
  • 13
  • 3

1 Answers1

0

Simply check the fragment identifier value in the location string. Pass the object we want to change in based on some conditional parameters.

if(window.location.hash){
    //fragment identifier such as '#mission', or '#about' has been found
    var sub = '',
        hsh = window.location.hash.split('#')[1]; // get string without # sign

    switch(hsh){
        case 'mission' :
            sub = 'sub1';
            break;
        case 'contact' :
            sub = 'sub2';
            break;
    }
    switchContent(sub);
}

In the above, we check for the fragment identifier. If found, we build a switch statement to prepare a string. Once we're done with the switch, we pass the string to the function which will in turn fire the content loader.

Ensure this code runs inside $(document).ready(function(){ }): otherwise the DOM elements may not be available.

Note: I would suggest changing this to build a more relationship friendly design pattern. Where the fragment identifier and the element containing the markup share some common string, such as a data attribute. <div data-rel="contact" id="sub1">. If this is done, then we no longer need to build a switch statement where we have to manually assign to a variable. If you're open to a more dynamic and fluid method, I'll be happy to build you out an example, just respond below.

Here's a more fluid method.

We should build relationships so we can keep things more sane. Let's take a look at how we should change the content divs.

<div class="info" id="mission">content 1</div>
<div class="info" id="about">content 2</div>
<div class="info" id="contact">content 3</div>

You'll see we modified the ids so they have a special relationship with not only the content inside, but the fragment identifier we're trying to work with. This way, we can reference that information back in our conditional statement that checks for the hash existence. We also added a new class, info which will allow us to make the code cleaner.

Now, let's clean up that content switcher function. Before, we were using a ternary operator to check if the obj exists and if not, assigning some arbitrary string to it; let's not do that.

function switchContent(did){
    $('.info').hide(0); //hide all the elements.
    $('div[id='+did+']').show();  //show only what we want!
}

That's it for our content switcher! Now let's build our conditional statement for the existence of the hash tag.

$(function(){
    if(window.location.hash){
        switchContent(window.location.hash.split('#')[1]);
    }  
});

We've shortened the code, and made it more fluid. In the above, we've wrapped our conditional check within the ready function, so that we know elements exist, and the page will work as intended.

Now let's clean up our anchors so they'll work even if there's no javascript enabled.

<a href="#mission" class="mininav">link 1</a>
<a href="#about" class="mininav">link 2</a>
<a href="#contact" class="mininav">link 3</a>

Great. Now that's much cleaner. No messy inline click functions or random string identifiers. Let's make it work.

$('#navigation a').click(function(e){
    e.preventDefault(); //we don't want the default jumping behavior
    switchContent($(this).prop('href').split('#')[1]);
});

Easy and clean! We capture the click event, stop the default behavior, then pass the href without the # sign to the function to switch our content! that's it!

Ohgodwhy
  • 49,779
  • 11
  • 80
  • 110
  • Yes for sure! I'd be VERY happy to include something more fluid. I really appreciate it, thanks a lot! – Sara Jan 12 '13 at 19:23
  • @Sara It's all there now. Let me know if you have any questions; sorry it took so long. – Ohgodwhy Jan 12 '13 at 19:37
  • Wow, this looks fantastic! What sort of user do I need to become to give out gold badges?? I particularly appreciate the help b/c I have no tech background and can only get so far with my books (i.e. I'd like to keep from tearing out all of my hair). THANK YOU for taking the time to simplify & write out the code!! – Sara Jan 13 '13 at 00:51
  • @Sara gold badges are earned by participating in the community, they're given out when you reach common achievements; so unfortunately you can't do that :) I don't mind helping and clarifying at all. Hopefully users in the future will find this post helpful as well. – Ohgodwhy Jan 13 '13 at 00:56
  • FYI--Since the hide/show commands are placed within the switchContent f(x), I wasn't able to hide any of the content blocks until first clicking on one of the links. Anytime the page was reloaded, all of the content would show. Not sure if the following fix is the best, but it worked for me: before the switchContent f(x), I put $('.info').hide(); $('#mission').show() with 'mission' representing the id for content 1. – Sara Jan 13 '13 at 21:57
  • @Sara - I would just simply do `.info { display:none}` in your CSS declarations. Then create an else statement here: `if(window.location.hash){ //code above } else { $('.mission').show() }` – Ohgodwhy Jan 13 '13 at 22:34