PageRenderTime 141ms CodeModel.GetById 61ms app.highlight 14ms RepoModel.GetById 50ms app.codeStats 0ms

/web-app/js/tagit.js

http://github.com/jdmr/mateo
JavaScript | 253 lines | 167 code | 35 blank | 51 comment | 35 complexity | 577f541633b67b216e10c0884a091de8 MD5 | raw file
  1/*
  2 * INFORMATION
  3 * ---------------------------
  4 * Owner:     jquery.webspirited.com
  5 * Developer: Matthew Hailwood
  6 * ---------------------------
  7 *
  8 * CHANGELOG:
  9 * ---------------------------
 10 * 1.1
 11 * Fixed bug 01
 12 * 1.2
 13 * Added select option
 14 * * hidden select so tags may be submitted via normal form.
 15 * 1.3
 16 * Fixed bug 02
 17 * 1.4
 18 * Fixed bug 03
 19 * Fixed bug 04
 20 *
 21 * ---------------------------
 22 * Bug Fix Credits:
 23 * --
 24 * * Number: 01
 25 * * Bug:  Clicking autocomplete option does not add it to the array
 26 * * Name: Ed <tastypopsicle.com>
 27 * --
 28 * * Number: 02
 29 * * Bug: Unable to give select a name
 30 * * Name: Ed <tastypopsicle.com>
 31 * --
 32 * * Number 03
 33 * * Bug: reference to incorrect variable (tagArray vs tagsArray)
 34 * * Name: claudio <unknown>
 35 * --
 36 * * Number 04
 37 * * Bug: console.log() left in code
 38 * * Name: claudio <unknown>
 39 */
 40
 41(function($) {
 42    $.widget("ui.tagit", {
 43
 44        // default options
 45        options: {
 46            tagSource:   [],
 47            triggerKeys: ['enter', 'space', 'comma', 'tab'],
 48            initialTags: [],
 49            minLength:   1,
 50            select:      false
 51
 52        },
 53
 54        _keys: {
 55            backspace: 8,
 56            enter:     13,
 57            space:     32,
 58            comma:     44,
 59            tab:       9
 60        },
 61
 62        //initialization function
 63        _create: function() {
 64
 65            var self = this;
 66            this.tagsArray = [];
 67            this.timer = null;
 68
 69            //add class "tagit" for theming
 70            this.element.addClass("tagit");
 71
 72            //add any initial tags added through html to the array
 73            this.element.children('li').each(function() {
 74                self.options.initialTags.push($(this).text());
 75            });
 76
 77            //add the html input
 78            this.element.html('<li class="tagit-new"><input class="tagit-input" type="text" /></li>');
 79
 80            this.input = this.element.find(".tagit-input");
 81
 82            //setup click handler
 83            $(this.element).click(function(e) {
 84                if ($(e.target).hasClass('tagit-close')) {
 85                    // Removes a tag when the little 'x' is clicked.
 86                    $(e.target).parent().remove();
 87                    var text = $(e.target).parent().text();
 88                    self._popTag(text.substr(0, text.length - 1));
 89                }
 90                else {
 91                    self.input.focus();
 92                }
 93            });
 94
 95            //setup autcomplete handler
 96            var os = this.options.select;
 97            this.options.appendTo = this.element;
 98            this.options.source = this.options.tagSource;
 99            this.options.select = function(event, ui) {
100                clearTimeout(self.timer);
101                self._addTag(ui.item.value);
102                return false;
103            }
104            this.input.autocomplete(this.options);
105            this.options.select = os;
106
107            //setup keydown handler
108            this.input.keydown(function(e) {
109                var lastLi = self.element.children(".tagit-choice:last");
110                if (e.which == self._keys.backspace)
111                    return self._backspace(lastLi);
112
113                if (self._isInitKey(e.which)) {
114                    e.preventDefault();
115                    if ($(this).val().length >= self.options.minLength)
116                        self._addTag($(this).val());
117                }
118
119                if (lastLi.hasClass('selected'))
120                    lastLi.removeClass('selected');
121
122                self.lastKey = e.which;
123            });
124
125            //setup blur handler
126            this.input.blur(function(e) {
127                var v = $(this).val();
128                this.timer = setTimeout(function(){
129                    self._addTag(v);
130                }, 50000);
131                console.log(this.timer);
132
133                $(this).val('');
134                return false;
135            });
136
137            //define missing trim function for strings
138            String.prototype.trim = function() {
139                return this.replace(/^\s+|\s+$/g, "");
140            };
141
142            if (this.options.select) {
143                this.element.after('<select class="tagit-hiddenSelect" name="'+this.element.attr('name')+'" multiple="multiple"></select>');
144                this.select = this.element.siblings('.tagit-hiddenSelect');
145            }
146            this._initialTags();
147
148        },
149
150        _popSelect: function(text) {
151            this.select.children('option[value="' + text + '"]').remove();
152        }
153        ,
154
155        _addSelect: function(value) {
156            this.select.append('<option selected="selected" value="' + value + '">' + value + '</option>');
157        }
158        ,
159
160        _popTag: function(text) {
161            $.inArray(text, this.tagsArray);
162            if (text == undefined) {
163                text = this.tagsArray.pop();
164            }
165            else {
166                var index = ($.inArray(text, this.tagsArray) == -1 ? this.tagsArray.length - 1 : $.inArray(text, this.tagsArray));
167                this.tagsArray.splice(index, 1);
168            }
169            if (this.options.select)
170                this._popSelect(text);
171        }
172        ,
173
174        _addTag: function(value) {
175            this.input.val("");
176            value = value.replace(/,+$/, "");
177            value = value.trim();
178            if (value == "" || this._exists(value))
179                return false;
180
181            var tag = "";
182            tag = '<li class="tagit-choice">' + value + '<a class="tagit-close">x</a></li>';
183            $(tag).insertBefore(this.input.parent());
184            this.input.val("");
185            this.tagsArray.push(value);
186            if (this.options.select)
187                this._addSelect(value);
188            return true;
189        }
190        ,
191
192        _exists: function(value) {
193            if (this.tagsArray.length == 0 || $.inArray(value, this.tagsArray) == -1)
194                return false;
195            return true;
196        }
197        ,
198
199        _isInitKey : function(keyCode) {
200            var keyName = "";
201            for (var key in this._keys)
202                if (this._keys[key] == keyCode)
203                    keyName = key
204
205            if ($.inArray(keyName, this.options.triggerKeys) != -1)
206                return true;
207            return false;
208        }
209        ,
210
211        _removeTag: function() {
212            this._popTag();
213            this.element.children(".tagit-choice:last").remove();
214        }
215        ,
216
217        _backspace: function(li) {
218            if (this.input.val() == "") {
219                // When backspace is pressed, the last tag is deleted.
220                if (this.lastKey == this._keys.backspace) {
221                    this._popTag();
222                    li.remove();
223                    this.lastKey = null;
224                } else {
225                    li.addClass('selected');
226                    this.lastKey = this._keys.backspace;
227                }
228            }
229            return true;
230        }
231        ,
232
233        _initialTags: function() {
234            if (this.options.initialTags.length != 0) {
235                for (var i in this.options.initialTags)
236                    if (!this._exists(this.options.initialTags[i]))
237                        this._addTag(this.options.initialTags[i]);
238            }
239        }
240        ,
241
242        tags: function() {
243            return this.tagsArray;
244        }
245        ,
246
247        destroy: function() {
248            $.Widget.prototype.destroy.apply(this, arguments); // default destroy
249            this.tagsArray = [];
250        }
251
252    });
253})(jQuery);