So I’m blogging more and posting more comments on blogs I read…which overall is a good thing. However, maintaining and following the conversations I get involved in via comments is super tedious. So I looked to my old friend Delicious for help in the matter.

I started by adding all the articles I’ve commented on to Delicious with appropriate tags plus two of my own homegrown tags: watching and contributed. Why two tags? Eventually I’d like to move articles off my “watching” list, but would still like a place to track down all the conversations I’ve “contributed” to.

Next, I wanted to be able to go to my “watching” tag in Delicious and quickly open up all the links. Hmmm…there’s not really a way to do that. So my buddy JS and I spent a half hour together and made our own. Here is the finished product that you can just drag into your “Bookmark Toolbar” on FF: DOAL: Delicious Open All Links

Now, anytime you are viewing a page in Delicious using FF, you can easily open all the links by clicking on that bookmark. (I don’t know what to tell you non-firefoxers…maybe someone in the comments can help you out.)

So, if you’re not a nerd, you should probably stop here. However, if you like Javascript, I’ll give you a quick walk through of what I did to get this thing going.

First, I went to my selected Delicious tag and opened up Firebug to start playing around. Using the inspect method, I see that the only “h4” tags on the page are the ones that house the links I want. Being a regular prototype user, here was my first attempt via the Firebug console: (Ok it’s not the first thing I typed, but my first real attempt)

$$('li.post h4 a').each(function(element) {window.open(element.href)});

Wow…that is good looking, sexy, one line JS! But it doesn’t work. For some reasons the “window.open” event wasn’t firing as expecting when inside the “each” function.

So I move to something like this:

var links = $$('li.post h4 a'); 
for(var i=0; i<links.length; i++) {
  window.open(links[i].href)
};

Ah the for loop…it’s been a while. This code works in Firebug, so I condense it to one line, put “javascript:” in front of it, paste it into the address bar, and hit enter. No go. ”$$” is not a function. Crap. Assuming prototype lives everywhere is a bad assumption. Let’s try to make it work without my favorite JS library.

var h4s = document.getElementsByTagName("h4"); 
for(var i=0; i<h4s.length; i++) {
  window.open(h4s[i].getElementsByTagName("a")[0].href)
}; 

Sweet. This working in the address bar, and opens up the right links, but it’s causing my Delicious page to go away. Let’s fix that.

var h4s = document.getElementsByTagName("h4"); 
for(var i=0; i<h4s.length; i++) {
  window.open(h4s[i].getElementsByTagName("a")[0].href)
}; 
window.refresh();

That’s better. Now all you do is right click in your bookmark toolbar, choose “New bookmark”, name it and insert the one line version of the code with “javascript:” in front of it and you have a Delicious extension!

I’m open to re-writes and suggestions for better efficiency, so if you’ve got ideas, let’s hear them.

I was knee deep in an old php form this week, trying to clean it up a bit, hiding and showing certain questions based on the responses of earlier questions. In addition this form had over 400 lines of JS validation that I had to turn on and off based on a questions visibility. Did I mention most of the fields and labels were stuck in a table?

(Ok…I can’t complain too much, it was marked up very nice and clean.)

So I’m hacking away at this validation and I need to only validate visible fields. So naturally I try something like this:

if($('fieldId').visible() && oldConditions) {
  throw an error;
}

Seemed pretty simple to me…until it wasn’t working. Fields that I could not see in my browser were still being validated. If I can’t see it, doesn’t that mean it is NOT visible.

According to prototype, I’m way off. The ‘visible’ method only tests THE SINGLE ELEMENT it is called on for the “style.display == ‘none’” without regard to that element’s ancestors. The problem was, my fields were visible, but the cells that contained them were not. What to do?

Extend prototpye of course! After a google and a quick read of a short article this is what I came up with:

Element.Methods.truelyVisible = function(element) {
  var visibleBoolean = element.visible();
  element.ancestors().each(function(el){ 
    if(!el.visible()) { visibleBoolean = false; }
  });
  return visibleBoolean;
};

Element.addMethods();

Quickly, it runs through an element’s ancestor’s checking them for visibility and then returning where the element can actually be seen or not. Now you can do $('elementId').truelyVisible() and get whether or not an element can actually be seen in the browser. Hope you enjoy!


PS. Looking at it a day later, it could probably be more efficient like this:

Element.Methods.truelyVisible = function(element) {
  var visibleBoolean = element.visible();
  if(visibleBoolean) {
    element.ancestors().each(function(el){ 
      if(!el.visible()) { visibleBoolean = false; }
    });
  }
  return visibleBoolean;
};

Element.addMethods();


PPS. It gets even better…I should blog code more often:

Element.Methods.truelyVisible = function(element) {
  return (element.visible() && !element.ancestors().any(function(el){ return !el.visible(); })) 
};

Element.addMethods();