Basically, all I needed was to be able to say "This list of stuff is only allowed to have one thing selected at once", while showing the active selection with css.
As a first attempt, I wrote the following little bit of javascript:
function UniqueSelection(id) {
function toggle() {
UniqueSelection.active.className = "inactive";
this.className = "active";
UniqueSelection.active = this;
}
var listItems = document.getElementById(id).getElementsByTagName('li');
for(var i = 0; i < listItems.length; i++) {
listItems[i].onclick = toggle;
if(listItems[i].className == 'active'){
UniqueSelection.active = listItems[i];
}
}
}
Which works, but has one big flaw: you can only have one UniqueSelection at a time, and is a pretty ugly solution anyhow.
The following code allows you to have as many UniqueSelection elements as you want, and is shorter, clearer code:
function UniqueSelection(id) {
var listItems = document.getElementById(id).getElementsByTagName('li');
function toggle() {
for(var i = 0; i < listItems.length; i++) {
listItems[i].className = 'inactive';
}
this.className = 'active';
}
for(var i = 0; i < listItems.length; i++) {
listItems[i].onclick = toggle;
}
}
This does have some downsides - for one, it might have a visible delay on long lists. For two, you can't have multiple class names on your 'li' elements. For my purposes, this is fine - and I think that if you're using ul's in a semantic manner, it shouldn't be a problem.
The code above does show some interesting things about javascripts scoping rules though.
Update:
With a couple more lines of code, we can allow for both lists where a selection must be unique and a selection must be active, and lists where a selection must be unique, but where the current selection can be turned off without making another one:
function UniqueSelection(id, allowToggle) {
var listItems = document.getElementById(id).getElementsByTagName('li');
function choose() {
for(var i = 0; i < listItems.length; i++) {
if(listItems[i] != this)
listItems[i].className = 'inactive';
}
if(allowToggle && this.className == 'active') {
this.className = 'inactive';
}else{
this.className = 'active';
}
}
for(var i = 0; i < listItems.length; i++) {
listItems[i].onclick = choose;
}
}
Update 2: The above function clobbers the onclick attribute, and in some cases I need it to not do so. Getting it to not clobber is turning out to be frustrating though. . .
Update 3: Got it working, through a bit of education and head-banging. The new code and an explanation of what was going on deserves it's own post though. Will write it up later.
No comments:
Post a Comment