Rails/JavaScript issue

Hey all,

I have an application.js file in my javascripts folder of my Ruby on
Rails application. The javascript is just a typical hide/show tabs
effect, so when the user clicks on one link, the corresponding div is
revealed and the other divs are hidden. Two pages require the
javascript. However, while one page displays content of no tabs onload,
the other page displays the content of the first tab onload. So the page
that displays the content of no tab onload works fine. However, the page
that displays the content of first tab onload is not working. I get the
following error in FireBug:

document.getElementById(“tabs”) is NULL
var tabListItems = document.getElementById(“tabs”).childNodes;

I think the issue is I’m calling multiple functions on page load (and
hence since the one page doesn’t have a tabs id it doesn’t know what to
do), even though I only need one function for each of the pages. But I
wuld like to keep this tab effect in the same file. So I don’t know what
to do. Thanks for anyone’s response:

window.onload = init;

var tabLinks = new Array();
var contentDivs = new Array();

function init() {
  initProduct();
  initAbout();
}

function initProduct() {
  var tabListItems = document.getElementById("tabs").childNodes;
  for(var i=0; i < tabListItems.length; i++) {
    if(tabListItems[i].nodeName == "LI") {
      var tabLink = getFirstChildWithTagName(tabListItems[i], "A");
      var id = getHash(tabLink.getAttribute("href"));
      tabLinks[id] = tabLink;
      contentDivs[id] = document.getElementById(id);
      tabLinks[id].className = "";
      contentDivs[id].className = "tabContent hide";
      tabLinks[id].onclick = showTab;
      tabLinks[id].onfocus = function() { this.blur() };
    }
  }
}

function initAbout() {
  var tabListItems = document.getElementById("tabAbout").childNodes;
  for(var i=0; i < tabListItems.length; i++) {
    if(tabListItems[i].nodeName == "LI") {
      tabLink = getFirstChildWithTagName(tabListItems[i], "A")
      id = getHash(tabLink.getAttribute("href"));
      tabLinks[id] = tabLink;
      contentDivs[id] = document.getElementById(id);
    }
  }
  var i = 0;
  for(var id in tabLinks) {
    tabLinks[id].onclick = showTab;
    tabLinks[id].onfocus = function() { this.blur() }
    if(i == 0) {
      tabLinks[id].className = "selected"
    }
    i++
  }
  var i = 0;
  for(var id in contentDivs) {
    if(i != 0) {
      contentDivs[id].className = "tabContent hide";
    }
    i++
  }
}

function showTab() {
  document.getElementById("product").className = "tabContent hide"
  var selectedId = getHash(this.getAttribute("href"));

  for(id in contentDivs) {
    if(id == selectedId) {
      tabLinks[id].className = "selected";
      contentDivs[id].className = "tabContent";
    }
    else {
      tabLinks[id].className = "";
      contentDivs[id].className = "tabContent hide";
    }
  }

  return false;
}



function getFirstChildWithTagName(element, tagName) {
  for(var i=0; i < element.childNodes.length; i++) {
    if(element.childNodes[i].nodeName == tagName) {
      return element.childNodes[i];
    }
  }
}

function getHash(url) {
  var hashPos = url.lastIndexOf("#");
  return url.substring(hashPos + 1);
}

On Sun, May 23, 2010 at 2:21 PM, John M. [email protected]
wrote:

document.getElementById(“tabs”) is NULL
var tabListItems = document.getElementById(“tabs”).childNodes;

I think the issue is I’m calling multiple functions on page load (and
hence since the one page doesn’t have a tabs id it doesn’t know what to
do), even though I only need one function for each of the pages. But I
wuld like to keep this tab effect in the same file. So I don’t know what
to do.

  1. check the battery in your watch; it’s so not 1997 anymore. :slight_smile:

window.onload = init;

That line looks resurrected from a seriously ancient tutorial – read
up on EventListeners to understand why it’s a poor approach, and
how you should be invoking your functions.

  1. defensive coding: you can either test first to see if there is an
    element with the ID “tabs” or you can wrap the whole thing in
    a try/catch block.

function initProduct() {
var tabListItems = document.getElementById(“tabs”).childNodes;
// …
}

  1. Either way, it’s strictly a JS question and has nothing to do with
    Rails.

FWIW,

Hassan S. ------------------------ [email protected]
twitter: @hassan

In my initial post, I did say there was an element with an id of tabs,
but that it was part of another page and not the page the error occured
on. However,the same js file is being used for both pages. So that’s the
issue I’m trying to resolve here.

Also I don’t think the getElementById() method was around in 1997.

On Sun, May 23, 2010 at 3:27 PM, John M. [email protected]
wrote:

In my initial post, I did say there was an element with an id of tabs,
but that it was part of another page and not the page the error occured
on. However,the same js file is being used for both pages. So that’s the
issue I’m trying to resolve here.

Yes, and I just explained how to do that. More than one way, actually.

And it still has nothing to do with Rails :slight_smile:


Hassan S. ------------------------ [email protected]
twitter: @hassan

On Sun, May 23, 2010 at 3:31 PM, John M. [email protected]
wrote:

Also I don’t think the getElementById() method was around in 1997.

? Uh, well. I explicitly referenced the line

window.onload = init;

so, that has what now to do with getElementById ? :slight_smile:


Hassan S. ------------------------ [email protected]
twitter: @hassan