{
this.p = params;
- trigger = $(this.p.trigger);
+ // Array to hold the currently selected tags to ease with removing
+ // them, assuring no duplicates etc..
+ this.selectedTags = [];
+
+ // The outter most box, the "fake" input element.
+ if (typeof this.p.box == 'undefined') {
+ this.p.box = this.p.box = 'HordeACBox';
+ }
+ if (typeof this.p.boxClass == 'undefined') {
+ this.p.boxClass = 'hordeACBox';
+ }
+
+ // The class for the ul. li will have a *Item and *Member class
+ // added to them.
+ if (typeof this.p.listClass == 'undefined') {
+ this.p.listClass = 'hordeACList';
+ }
+
+ // Class for the actual input element.
+ if (typeof this.p.growingInputClass == 'undefined') {
+ this.p.growingInputClass = 'hordeACTrigger';
+ }
+ if (typeof this.p.triggerContainer == 'undefined') {
+ this.p.triggerContainer = 'hordeACTriggerContainer';
+ }
+
+ // p.tags is now the hidden input field, while p.trigger will
+ // contain the "real" input element's name attribute.
+ this.p.tags = this.p.trigger;
+ this.p.trigger = this.p.trigger + 'real';
+
+ this.buildStructure();
+
+ var trigger = $(this.p.trigger);
trigger.observe('keydown', this._onKeyDown.bindAsEventListener(this));
// Bind this object to the trigger so we can call it's methods
// from client code.
- trigger.kronolithTagger = this;
-
- // Make sure the right dom elements are styled correctly.
- $(this.p.container).addClassName('kronolithACListItem kronolithTagACContainer');
+ //trigger.kronolithTagger = this;
+ $(this.p.tags).tagger = this;
// Make sure the p.tags element is hidden
if (!this.p.debug) {
$(this.p.box).observe('click', function() {$(this.p.trigger).focus()}.bindAsEventListener(this));
// Create the underlaying Autocompleter
- new Ajax.Autocompleter(params.trigger, params.resultsId, params.uri, params.params);
+ this.p.uri = this.p.uri + '/input=' + this.p.trigger;
+ new Ajax.Autocompleter(this.p.trigger, this.p.trigger + '_results', this.p.uri, this.p.params);
// Prepopulate the tags and the container elements?
if (typeof this.p.existing != 'undefined') {
{
// TODO: Resize the trigger field to fill the current line?
// Clear any existing values
- if (this.p.selectedTags.length) {
- $('kronolithTagACBox').select('li.kronolithTagACListItem').each(function(item) {this.removeTagNode(item) }.bind(this));
+ if (this.selectedTags.length) {
+ $(this.p.box).select('li.' + this.p.listClass + 'Item').each(function(item) {this.removeTagNode(item) }.bind(this));
}
// Clear the hidden tags field
},
+ buildStructure: function()
+ {
+ // Build the outter box
+ var box = new Element('div', {id: this.p.box, 'class': this.p.boxClass});
+
+ // The results div - where the autocomplete choices are placed.
+ var results = new Element('div', {id: this.p.trigger + '_results', 'class': 'autocomplete'});
+
+ // The list - where the choosen items are placed as <li> nodes
+ var list = new Element('ul', {'class': this.p.listClass});
+
+ // The input element and the <li> wraper
+ var inputListItem = new Element('li', {'class': this.p.listClass + 'Member',
+ 'id': this.p.triggerContainer});
+
+ var growingInput = new Element('input', {'class': this.p.growingInputClass,
+ 'id': this.p.trigger,
+ 'name': this.p.trigger,
+ 'autocomplete':'off'});
+
+ inputListItem.update(growingInput);
+ list.update(inputListItem);
+ box.update(list);
+ box.insert(results);
+
+ // Replace the single input element with the new structure and
+ // move the old element into the structure while making sure it's
+ // hidden. (Use the long form to play nice with Opera)
+ oldTrigger = Element.replace($(this.p.tags), box);
+ box.insert(oldTrigger);
+
+ },
+
_onKeyDown: function(e)
{
// Check for a comma
addNewTagNode: function(value)
{
// Don't add if it's already present.
- for (var x = 0, len = this.p.selectedTags.length; x < len; x++) {
- if (this.p.selectedTags[x] == value) {
+ for (var x = 0, len = this.selectedTags.length; x < len; x++) {
+ if (this.selectedTags[x] == value) {
return;
}
}
- var newTag = new Element('li', {class: 'kronolithACListItem kronolithTagACListItem'}).update(value);
- var x = new Element('img', {class: 'kronolithTagACRemove', src:this.p.URI_IMG_HORDE + "/delete-small.png"});
+ var newTag = new Element('li', {class: this.p.listClass + 'Member ' + this.p.listClass + 'Item'}).update(value);
+ var x = new Element('img', {class: 'hordeACItemRemove', src:this.p.URI_IMG_HORDE + "/delete-small.png"});
x.observe('click', this._removeTagHandler.bindAsEventListener(this));
newTag.insert(x);
- $(this.p.container).insert({before: newTag});
+ $(this.p.triggerContainer).insert({before: newTag});
$(this.p.trigger).value = '';
// Add to hidden input field.
}
// ...and keep the selectedTags array up to date.
- this.p.selectedTags.push(value);
+ this.selectedTags.push(value);
},
removeTagNode: function(item)
{
var value = item.collectTextNodesIgnoreClass('informal');
- for (var x = 0, len = this.p.selectedTags.length; x < len; x++) {
- if (this.p.selectedTags[x] == value) {
- this.p.selectedTags.splice(x, 1);
+ for (var x = 0, len = this.selectedTags.length; x < len; x++) {
+ if (this.selectedTags[x] == value) {
+ this.selectedTags.splice(x, 1);
}
}
item.remove();
{
item = Event.element(e).up();
this.removeTagNode(item);
- $(this.p.tags).value = this.p.selectedTags.join(',');
+ $(this.p.tags).value = this.selectedTags.join(',');
}
});
\ No newline at end of file
/**
* Attach the Imple object to a javascript event.
- * Assume that if the 'box' parameter is empty then we want a
+ * If the 'pretty' parameter is empty then we want a
* traditional autocompleter, otherwise we get a spiffy pretty one.
*
*/
parent::attach();
Horde::addScriptFile('autocomplete.js', 'horde', true);
- if ($pretty = !empty($this->_params['box'])) {
+ if ($pretty = !empty($this->_params['pretty'])) {
Horde::addScriptFile('taggerAutoCompleter.js', 'kronolith', true);
+ $this->_params['uri'] = Horde::url($GLOBALS['registry']->get('webroot', 'kronolith') . '/imple.php?imple=TagAutoCompleter', true);
+ } else {
+ $this->_params['uri'] = Horde::url($GLOBALS['registry']->get('webroot', 'kronolith') . '/imple.php?imple=TagAutoCompleter/input=' . rawurlencode($this->_params['triggerId']), true);
}
- $this->_params['uri'] = Horde::url($GLOBALS['registry']->get('webroot', 'kronolith') . '/imple.php?imple=TagAutoCompleter/input=' . rawurlencode($this->_params['triggerId']), true);
if (!$pretty) {
$params = array(
$params[] = '{' . implode(',', $js_params) . '}';
if ($pretty) {
- $js_vars = array('box' => $this->_params['box'],
- 'resultsId' => $this->_params['resultsId'],
+ $js_vars = array('boxClass' => 'hordeACBox kronolithLongField',
'uri' => $this->_params['uri'],
- 'selectedTags' => array(),
'trigger' => $this->_params['triggerId'],
- 'tags' => $this->_params['tags'],
- 'container' => $this->_params['container'],
'URI_IMG_HORDE' => $registry->getImageDir('horde'),
'params' => $params);
$js_vars['existing'] = $this->_params['existing'];
}
- $script = array('new KronolithTagger(' . Horde_Serialize::serialize($js_vars, Horde_Serialize::JSON, NLS::getCharset()) . ')');
+ $script = array('new KronolithTagger(' . Horde_Serialize::serialize($js_vars, Horde_Serialize::JSON, NLS::getCharset()) . ')');
} else {
$script = array('new Ajax.Autocompleter(' . implode(',', $params) . ')');
}
/* to be removed */
div.c1 {
- color: #336600;
+ color: #336600;
}
div.c2 {
- color: #1a5587;
+ color: #1a5587;
}
div.c3 {
- color: #d38a23;
+ color: #d38a23;
}
div.c4 {
- color: #4b2a16;
+ color: #4b2a16;
}
div.c1.kronolithEventFull {
- background-color: #336600 !important;
+ background-color: #336600 !important;
}
div.c2.kronolithEventFull {
- background-color: #1a5587 !important;
+ background-color: #1a5587 !important;
}
div.c3.kronolithEventFull {
- background-color: #d38a23 !important;
+ background-color: #d38a23 !important;
}
div.c4.kronolithEventFull {
- background-color: #4b2a16 !important;
+ background-color: #4b2a16 !important;
}
#kronolithAddEvents span {
text-decoration: underline;
}
-#kronolithTagACBox {
- background:white none repeat scroll 0 0;
- border:1px solid #666699;
- cursor:default;
- /*overflow:hidden;*/
- text-align:left;
- min-height: 58px;
-}
-
-.kronolithTagACList {
- display:block;
- overflow:hidden;
- width:100%;
- cursor:default;
- list-style-type:none;
- margin:0;
- padding:0;
-}
-
-.kronolithACListItem {
- display:inline-block;
- font-size:90%;
- padding:2px 1px 1px 2px;
- height: 17px;
- white-space:nowrap;
-}
-
-.kronolithTagACListItem {
- background-color:lightblue;
- border:1px solid #C0C0C0;
- -moz-border-radius-bottomleft:4px;
- -moz-border-radius-bottomright:4px;
- -moz-border-radius-topleft:4px;
- -moz-border-radius-topright:4px;
- margin:5px;
-}
-
-#kronolithTagACTrigger {
- background:transparent none repeat scroll 0 0;
- border:0 none;
- display:inline;
- position:static;
- width:80px;
-}
-
-.kronolithTagACContainer {
- height:18px;
- margin:2px;
- padding:2px 2px 2px 0;
-}
-
-.kronolithTagACRemove:hover {
- cursor:pointer;
-}
-
#hordeAlerts div.kronolith-sticky, #hordeAlerts div.kronolith-sticky {
background-color: #ebe20c;
background-image: url("graphics/warning.png");