Has anybody ever built a widget to help with the process of tagging? I am in need of a tagger widget that aids my users in consistency. This is basically an autocomplete function but differs in that it needs to support addition and removal of items from a list and I cannot find anything to use as a guideline. As l a long time user of dojo I would like to write a custom widget, probably based on ComboBox to support this but would love to hear suggestions on how to make this happen efficiently.
Most big sites that handle this use a simple suggestion mechanism based on previously used tags and let the user handle deleting them manually from a single input box. I would like my widget to work just like this, except that my client wants to be able to choose from the suggestions BEFORE starting to type input and would like the ability to require only previously used tags.
Anybody?

Working (but hacked) implementaion
After some poking around I found enough evidence that this was not possibly using dojo's current widgets but that it would be easy enough to modify. Last night I hacked together a widget using ComboBox as a base. The code is ugly but it works. I would love to either get this cleaned up as a proper widget or the feature moved into the ComboBox core. Anybody out there willing to help me with this process?
This subject is also referenced at http://trac.dojotoolkit.org/ticket/2589
dojo.require("dijit.form.ComboBox"); dojo.require("dojo.data.ItemFileReadStore"); dojo.require("dijit.form.ValidationTextBox"); dojo.addOnLoad(function() { dojo.provide("dijit.quelib.Tagger"); dojo.declare( "dijit.quelib.Tagger", [dijit.form.ValidationTextBox, dijit.form.ComboBoxMixin], { delimiter: ",", _previousMatches: false, setValue: function (value) { if (this.delimiter && value.length != 0) { value = value+this.delimiter+" "; arguments[0] = this._addPreviousMatches(value); } this.inherited("setValue", arguments); }, _addPreviousMatches: function (text) { if (this._previousMatches) { if (!text.match(new RegExp("^"+this._previousMatches))) { text = this._previousMatches+text; } text = this._cleanupDelimiters(text); } return text; }, _cleanupDelimiters: function (text) { if (this.delimiter) { text = text.replace(new RegExp(" +"), " "); text = text.replace(new RegExp("^ *"+this.delimiter+"* *"), ""); text = text.replace(new RegExp(this.delimiter+" *"+this.delimiter), this.delimiter); } return text; }, _autoCompleteText: function (text) { arguments[0] = this._addPreviousMatches(text); this.inherited("_autoCompleteText", arguments); }, _startSearch: function (text) { text = this._cleanupDelimiters(text); var re = new RegExp("^.*"+this.delimiter+" *"); if (this._previousMatches = text.match(re)) { arguments[0] = text.replace(re, ""); } this.inherited("_startSearch", arguments); }, } ); });Added to dojox
As of r11639 this widget as been added to dojox under the name MultiComboBox. See http://trac.dojotoolkit.org/ticket/2589 for details and thanks to dante for getting this done.