I wrote a class for making ‘pretty’ select boxes. As you can see, the script simply hides each select box, and replaces it with a DIV that acts as the opener for a sucker-fish style drop down menu. Upon selecting an element, the script updates the value of the hidden select box and calls an ‘on_change’ callback. (I know, it’s been done before, but I needed a standalone script and figured it would be good to stretch my non-framework muscles.)
In any case, the script works like a charm in FF, but breaks in IE7/8 and Safari 3 (no way, right?). IE throws this error:
Webpage error details
User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Timestamp: Thu, 26 Mar 2009 17:53:54 UTC
Message: Expected identifier
Line: 78
Char: 28
Code: 0
URI: http://00.00.00.00/js_object/object.js
And Safari gives me nothing. Here’s the code:
var Suckah = {
select_class: 'neat_select',
init: function(attr)
{
for(prop in attr) this[prop] = attr[prop];
elems = this.get_elements_by_class(this.select_class);
for(i in elems)
{
if(elems*.type == 'select-one')
{
this.hide_elem(elems*);
this.build_dropdown(elems*);
}
}
},
hide_elem: function(elem)
{
elem.style.position = 'absolute';
elem.style.top = '-60000px';
},
build_dropdown: function(orig)
{
var dropdown_container = document.createElement('div');
dropdown_container.innerHTML = '<span class="label">' + orig.options[orig.selectedIndex].innerHTML + '</span>';
this.add_class(dropdown_container, 'dropdown_container');
var dropdown_menu = document.createElement('ul');
dropdown_menu.style.display = 'none';
this.add_class(dropdown_menu, 'dropdown_menu');
orig.parentNode.insertBefore(dropdown_container, orig.nextSibling);
dropdown_container.appendChild(dropdown_menu);
for(var i = 0; i <= orig.options.length - 1; i++)
{
var new_opt = document.createElement('li');
new_opt.innerHTML = orig.options*.innerHTML;
dropdown_menu.appendChild(new_opt);
}
var click_target;
var opener = null;
var closer = null;
dropdown_container.addEventListener('select', function(e) {return false; }, false);
dropdown_container.addEventListener('click', function(e) { dropdown_menu.style.display = 'block'; }, false);
window.addEventListener('mousedown', function(e)
{
if(!e) var e = window.event;
if(e.target) click_target = e.target;
else if(e.srcElement) click_target = e.srcElement;
if(click_target.nodeType == 3) click_target = click_target.parentNode;
if(click_target != dropdown_container && click_target != dropdown_menu && click_target.parentNode != dropdown_menu)
{
dropdown_menu.style.display = 'none';
}
else if(click_target.parentNode == dropdown_menu)
{
for(var i = 0; i <= orig.options.length - 1; i++)
{
if(orig.options*.innerHTML == click_target.innerHTML) orig.options*.selected = true;
}
dropdown_container.getElementsByTagName('span')[0].innerHTML = '<span>' + click_target.innerHTML + '</span>';
dropdown_menu.style.display = 'none';
Suckah.on_change(orig);
}
}, false);
},
on_change: function(orig)
{
return false;
},
add_class: function(elem, class)
{
if(elem.className == false)
{
elem.className = class;
}
else
{
new_class_name = elem.className;
new_class_name += " ";
new_class_name += class;
elem.className = new_class_name;
}
},
get_elements_by_class: function(classname, node)
{
if(!node) node = document.getElementsByTagName("body")[0];
var a = [];
var re = new RegExp('\\b' + classname + '\\b');
var els = node.getElementsByTagName("*");
for(var i=0,j=els.length; i<j; i++)
if(re.test(els*.className))a.push(els*);
return a;
}
}
And the init code:
Suckah.init({
on_change: function(orig) {
//window.location = orig.options[orig.selectedIndex].value;
}
});
I’ve also attached a zip file with the source. Any of you have any clue what the problem is? (God I hate IE error debugging…)
Also, I’m sure there are likely to be several incompatibilities other than what error is currently thrown… If you see anything else that may be an issue, feel free to point it out.