It's ok to be cute, but not too cute.
So, on twitter yesterday, I boldly announced:
Not that anyone needs another example of jQuery's live() function, but here ya go: http://bit.ly/7tWLof
I was all proud and stuff, messing around with jQuery is always fun. I didn't check the other browsers tho. I got home and I got curious if it actually worked in all browsers and it turns out, it does not. I wasn't too concerned about the code. It was a proof of concept for a discussion at work.
I wanted to fix it, but it wasn't going to be done last night. This morning, I spent some time fixing it and I have to say I learned some things. I learned that Firefox really wants me to be successful and allowed me to be cuter than I intended. IE / Chrome really doesn't like that. Looking back on what I was doing, I can't say that I really blame the other browsers - it did feel hackish when I wrote it.
I went about fixing this, but suddenly I felt blind without having Firebug installed in IE / Chrome. Chrome's javascript debugger / console really needs some work to be anywhere useful like Firebug. So, I knew that getfirebug.com had a 'lite' version available, so I went to go check it out. It turns out, that it is just as easy as typing:
<script type="text/javascript" src="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"></script>
When you add that to your HTML, it's like Firebug decided to follow you around like a little puppy regardless of what browser you're in. I'm considering uninstalling Firebug from Mozilla and making that part of my template shell that I can enable/disable at will. Now, not quite so blind, I set about fixing my script.
IE / Chrome really don't like it when you use the 'click' event on a select option. Mouse{down|up} works fine (except in IE). In the end, I stuck with click() for the select box itself, rather than the option (If you want bulletproof, use TexoTela's select plug-in). So, with that in mind, rewriting everything to grab the appropriate values and text was a no-brainer.
function addTag(){
var $tag = $(this);
var chosenValue = $tag.val();
var chosenOption = $('#'+$tag.attr('id') +' option[value='+chosenValue+']');
var chosenText = $(chosenOption).text();
var $span = $('<span id="tag_'+chosenValue+'">'+chosenText+' <a href="#" class="remove">X</a></span>');
$('#tags').append($span);
$(chosenOption).remove();
if($('#piclist option').length <= 0){ $(this).hide(); }
return false;
}
Now, the reverse... creating the option from the span was a little more challenging, but only because of the way I was building the span in the code above. I tried it many different ways, but having the anchor tag live inside the span felt, in my opinion, to be the cleanest. So, how does one get the text value of the span without including the "X" link? I'm sure I could have pulled out a regular expression, but in the end I opted to use clone() instead.
var parent_text = $parent.clone().children().remove().end().text();
I've also never used end() before either, so this was a little weird to me. So, the above is basically saying: clone the parent, traverse to the children (in this case, a href tag) and then remove it. Stop. Now tell me what the parent text is.
Perhaps there's an easier way to do all this. Regardless, I was able to get this working again in all browsers and that can be viewed on tags_example2.html. Now, one issue remains. Resorting the list appropriately. At this point, I'd probably just undo some code and let TexoTela's plug-in do majority of the work.
Btw, I left firebug lite on my 2nd example so that you can see what it looks like and how it works. Consider using it for your projects.