Add a pretty tag autocompleter to the ajax event edit form
authorMichael J. Rubinsky <mrubinsk@horde.org>
Fri, 3 Apr 2009 00:45:52 +0000 (20:45 -0400)
committerMichael J. Rubinsky <mrubinsk@horde.org>
Fri, 3 Apr 2009 05:52:11 +0000 (01:52 -0400)
kronolith/index.php
kronolith/js/src/kronolith.js
kronolith/js/src/taggerAutoCompleter.js
kronolith/lib/Imple/TagAutoCompleter.php
kronolith/templates/index/index.inc
kronolith/themes/screen.css

index dab2406..aab60d2 100644 (file)
@@ -65,4 +65,12 @@ require KRONOLITH_TEMPLATES . '/index/index.inc';
 Kronolith::includeScriptFiles();
 Kronolith::outputInlineScript();
 $notification->notify(array('listeners' => array('javascript')));
+Kronolith_Imple::factory('TagAutoCompleter',
+     array('box' => 'kronolithTagACBox',
+           'triggerId' => 'kronolithTagACTrigger',
+           'tags' => 'kronolithEventTags',
+           'container' => 'kronolithTagACContainer'
+           //'existing' => array('tag1', 'tag2'),
+           //'debug' => true
+           ));
 echo "</body>\n</html>";
index ad24aa6..37f8bf6 100644 (file)
@@ -1024,6 +1024,7 @@ KronolithCore = {
 
             case 'kronolithEventCancel':
                 this._closeRedBox();
+                // TODO: Need to clear the tagger fields.
                 e.stop();
                 return;
 
@@ -1105,8 +1106,7 @@ KronolithCore = {
                 e.stop();
                 return;
             } else if (elt.hasClassName('kronolithEventTag')) {
-                var etags = $F('kronolithEventTags');
-                $('kronolithEventTags').value = (etags ? etags + ', ' :  '') + elt.getText();
+                $('kronolithTagACTrigger').forceTaggerUpdate(elt.getText());
                 e.stop();
                 return;
             }
index 4e15399..d57f47d 100644 (file)
@@ -2,19 +2,25 @@ var KronolithTagger = Class.create({
         initialize: function(params)
         {
             this.p = params;
-            $(this.p.trigger).observe('keydown', this._onKeyDown.bindAsEventListener(this));
             
+            trigger = $(this.p.trigger);
+            trigger.observe('keydown', this._onKeyDown.bindAsEventListener(this));
+            trigger.forceTaggerUpdate = function(item) {
+                this.addNewTagNode(item);
+            }.bind(this);
             // Make sure the right dom elements are styled correctly.
-            $(this.p.container).addClassName('listItem tagACContainer');
-            $(this.p.trigger).addClassName('showTag');
+            $(this.p.container).addClassName('kronolithACListItem kronolithTagACContainer');
             
             // Make sure the p.tags element is hidden
-            if (!params.debug) {
+            if (!this.p.debug) {
                 $(this.p.tags).hide();
             }
             
             // Set the updateElement callback
-            params.params.updateElement = this._updateElement.bind(this);
+            this.p.params.updateElement = this._updateElement.bind(this);
+            
+            // Look for clicks on the box to simulate clicking in an input box
+            $(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);
@@ -54,8 +60,8 @@ var KronolithTagger = Class.create({
         
         addNewTagNode: function(value)
         {
-            var newTag = new Element('li', {class: 'listItem tagListItem'}).update(value);
-            var x = new Element('img', {class: 'tagRemove', src:this.p.URI_IMG_HORDE + "/delete-small.png"});
+            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"});
             x.observe('click', this._removeTag.bindAsEventListener(this));
             newTag.insert(x);
             $(this.p.container).insert({before: newTag});
index 09d5eb8..0014c6c 100644 (file)
@@ -33,7 +33,7 @@ class Kronolith_Imple_TagAutoCompleter extends Kronolith_Imple
 
     /**
      * Attach the Imple object to a javascript event.
-     * Assume that if the 'container' parameter is empty then we want a
+     * Assume that if the 'box' parameter is empty then we want a
      * traditional autocompleter, otherwise we get a spiffy pretty one.
      *
      */
@@ -43,7 +43,7 @@ class Kronolith_Imple_TagAutoCompleter extends Kronolith_Imple
         parent::attach();
         Horde::addScriptFile('autocomplete.js', 'horde', true);
 
-        if ($pretty = !empty($this->_params['container'])) {
+        if ($pretty = !empty($this->_params['box'])) {
             Horde::addScriptFile('taggerAutoCompleter.js', 'kronolith', true);
         }
         $this->_params['uri'] =  Horde::url($GLOBALS['registry']->get('webroot', 'kronolith') . '/imple.php?imple=TagAutoCompleter/input=' . rawurlencode($this->_params['triggerId']), true);
@@ -69,7 +69,8 @@ class Kronolith_Imple_TagAutoCompleter extends Kronolith_Imple
         $params[] = '{' . implode(',', $js_params) . '}';
 
         if ($pretty) {
-            $js_vars = array('resultsId' => $this->_params['resultsId'],
+            $js_vars = array('box' => $this->_params['box'],
+                             'resultsId' => $this->_params['resultsId'],
                              'uri' => $this->_params['uri'],
                              'selectedTags' => array(),
                              'trigger' => $this->_params['triggerId'],
@@ -77,12 +78,8 @@ class Kronolith_Imple_TagAutoCompleter extends Kronolith_Imple
                              'container' => $this->_params['container'],
                              'URI_IMG_HORDE' => $registry->getImageDir('horde'),
                              'params' => $params);
-            // These are optional
-            if ($this->_params['debug']) {
-                $js_vars['debug'] = $this->_params['debug'];
-            }
 
-            if ($this->_params['existing']) {
+            if (!empty($this->_params['existing'])) {
                 $js_vars['existing'] = $this->_params['existing'];
             }
 
index dd78e4f..04b231f 100644 (file)
 
 <div>
   <label for="id_tags"><?php echo _("Tags") ?></label><br />
-  <textarea name="tags" id="kronolithEventTags" rows="2" class="kronolithLongField"></textarea>
+  <div id="kronolithTagACBox" class="kronolithLongField">
+   <ul class="kronolithTagACList">
+    <li id="kronolithTagACContainer" class="kronolithACListItem kronolithTagACContainer"><input name="kronolithTagACTrigger" id="kronolithTagACTrigger" type="text" /></li>
+   </ul>
+   <div id="kronolithTagACTrigger_results" class="autocomplete"></div>
+  </div>
+  <input type="hidden" id="kronolithEventTags" name="tags" />
+  <span id="kronolithTagACTrigger_loading_img" style="display:none;"><?php echo Horde::img('loading.gif', _("Loading...")) ?></span>
 </div>
 
 <div id="kronolithEventTopTags"></div>
index 1971a34..80f093b 100644 (file)
@@ -1245,9 +1245,64 @@ li.panel-tags {
     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");
     border-color: #807b00;
     color: #000;
-}
+}
\ No newline at end of file