I came across the same issue - i needed it to show: enable/disable/ignore
Based on the icons available in jquery ui (http://jqueryui.com/themeroller/) I created following code (I know its not a plugin, but that wasnt necessary in my case):
The HTML I use is:
<input type="text" class="rotatestate" value="true"
data-state-style="cursor:pointer"
data-state-class="ui-icon"
data-state-values='[{"value":"true","class":"ui-icon-check","title":"title for true"},{"value":"false","class":"ui-icon-radio-off","title":"title for off"},{"value":"null","class":"ui-icon-cancel","title":"title for third state"}]'/>
The control takes the json array in data-state-values for as many states as you want to rotate through:
- value: the value that will be entered in the input
- class: css class(es) that the new span will have
- title: an optional title that will be set in the created span
It basically creates a <span class="data-state-class + classOfState" title="titleOfState">
element and on click updates it by cacling through the given value list.
I coded it so it even allows change through other means (i.e. setting the value of the input directly) and updates the "control" when the $("input").change(); event is triggered.
The jquery code that handles it:
/* rotatestate stontrol */
$("input.rotatestate", location).each(function(){
var states = $(this).attr("data-state-values");
var defaultClass = $(this).attr("data-state-class");
// no need to continue if there are no states
if(!states) {
return;
}
try {
states = JSON.parse(states);
} catch (ex) {
// do not need to continue if we cannot parse the states
return;
}
var stateControl = $("<span></span>");
if($(this).attr("data-state-style")) {
stateControl.attr("style", $(this).attr("data-state-style"));
}
stateControl.data("states", states);
stateControl.data("control", this);
stateControl.data("activeState", null);
$(this).data("control", stateControl);
if(defaultClass) {
stateControl.addClass(defaultClass);
}
// click on the control starts rotating
stateControl.click(function(){
var cState = $(this).data().activeState;
var cStates = $(this).data().states;
var control = $(this).data().control;
var newState = null;
if(cState != null) {
// go to the 'next' state
for(var i = 0; i < cStates.length; i++) {
if(cStates[i].value === cState.value) {
// last element
if(i === cStates.length - 1) {
newState = cStates[0];
} else {
newState = cStates[i+1];
}
break;
}
}
} else {
// no state yet - just set the first
newState = cStates[0];
}
$(control).attr("value", newState.value);
// trigger change
$(control).change();
});
// make sure to update state if the value is changed
$(this).change(function(){
var control = $($(this).data().control);
var cState = control.data().activeState;
var cStates = control.data().states;
if(cState != null) {
// remove "old state"
control.removeClass(cState['class']);
}
// add new State
var val = $(this).val();
$.each(cStates, function(){
if(this.value === val) {
control.data().activeState = this;
if(this.title) {
control.attr("title", this.title);
}
control.addClass(this['class']);
return false;
}
});
});
// trigger initial state
$(this).change();
$(this).after(stateControl);
$(this).hide();
});
The control is also part of my Form Controls Library on https://github.com/corinis/jsForm/wiki/Controls.