PageRenderTime 179ms CodeModel.GetById 65ms RepoModel.GetById 3ms 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. (function($) {
  41. $.widget("ui.tagit", {
  42. // default options
  43. options: {
  44. tagSource: [],
  45. triggerKeys: ['enter', 'space', 'comma', 'tab'],
  46. initialTags: [],
  47. minLength: 1,
  48. select: false
  49. },
  50. _keys: {
  51. backspace: 8,
  52. enter: 13,
  53. space: 32,
  54. comma: 44,
  55. tab: 9
  56. },
  57. //initialization function
  58. _create: function() {
  59. var self = this;
  60. this.tagsArray = [];
  61. this.timer = null;
  62. //add class "tagit" for theming
  63. this.element.addClass("tagit");
  64. //add any initial tags added through html to the array
  65. this.element.children('li').each(function() {
  66. self.options.initialTags.push($(this).text());
  67. });
  68. //add the html input
  69. this.element.html('<li class="tagit-new"><input class="tagit-input" type="text" /></li>');
  70. this.input = this.element.find(".tagit-input");
  71. //setup click handler
  72. $(this.element).click(function(e) {
  73. if ($(e.target).hasClass('tagit-close')) {
  74. // Removes a tag when the little 'x' is clicked.
  75. $(e.target).parent().remove();
  76. var text = $(e.target).parent().text();
  77. self._popTag(text.substr(0, text.length - 1));
  78. }
  79. else {
  80. self.input.focus();
  81. }
  82. });
  83. //setup autcomplete handler
  84. var os = this.options.select;
  85. this.options.appendTo = this.element;
  86. this.options.source = this.options.tagSource;
  87. this.options.select = function(event, ui) {
  88. clearTimeout(self.timer);
  89. self._addTag(ui.item.value);
  90. return false;
  91. }
  92. this.input.autocomplete(this.options);
  93. this.options.select = os;
  94. //setup keydown handler
  95. this.input.keydown(function(e) {
  96. var lastLi = self.element.children(".tagit-choice:last");
  97. if (e.which == self._keys.backspace)
  98. return self._backspace(lastLi);
  99. if (self._isInitKey(e.which)) {
  100. e.preventDefault();
  101. if ($(this).val().length >= self.options.minLength)
  102. self._addTag($(this).val());
  103. }
  104. if (lastLi.hasClass('selected'))
  105. lastLi.removeClass('selected');
  106. self.lastKey = e.which;
  107. });
  108. //setup blur handler
  109. this.input.blur(function(e) {
  110. var v = $(this).val();
  111. this.timer = setTimeout(function(){
  112. self._addTag(v);
  113. }, 50000);
  114. console.log(this.timer);
  115. $(this).val('');
  116. return false;
  117. });
  118. //define missing trim function for strings
  119. String.prototype.trim = function() {
  120. return this.replace(/^\s+|\s+$/g, "");
  121. };
  122. if (this.options.select) {
  123. this.element.after('<select class="tagit-hiddenSelect" name="'+this.element.attr('name')+'" multiple="multiple"></select>');
  124. this.select = this.element.siblings('.tagit-hiddenSelect');
  125. }
  126. this._initialTags();
  127. },
  128. _popSelect: function(text) {
  129. this.select.children('option[value="' + text + '"]').remove();
  130. }
  131. ,
  132. _addSelect: function(value) {
  133. this.select.append('<option selected="selected" value="' + value + '">' + value + '</option>');
  134. }
  135. ,
  136. _popTag: function(text) {
  137. $.inArray(text, this.tagsArray);
  138. if (text == undefined) {
  139. text = this.tagsArray.pop();
  140. }
  141. else {
  142. var index = ($.inArray(text, this.tagsArray) == -1 ? this.tagsArray.length - 1 : $.inArray(text, this.tagsArray));
  143. this.tagsArray.splice(index, 1);
  144. }
  145. if (this.options.select)
  146. this._popSelect(text);
  147. }
  148. ,
  149. _addTag: function(value) {
  150. this.input.val("");
  151. value = value.replace(/,+$/, "");
  152. value = value.trim();
  153. if (value == "" || this._exists(value))
  154. return false;
  155. var tag = "";
  156. tag = '<li class="tagit-choice">' + value + '<a class="tagit-close">x</a></li>';
  157. $(tag).insertBefore(this.input.parent());
  158. this.input.val("");
  159. this.tagsArray.push(value);
  160. if (this.options.select)
  161. this._addSelect(value);
  162. return true;
  163. }
  164. ,
  165. _exists: function(value) {
  166. if (this.tagsArray.length == 0 || $.inArray(value, this.tagsArray) == -1)
  167. return false;
  168. return true;
  169. }
  170. ,
  171. _isInitKey : function(keyCode) {
  172. var keyName = "";
  173. for (var key in this._keys)
  174. if (this._keys[key] == keyCode)
  175. keyName = key
  176. if ($.inArray(keyName, this.options.triggerKeys) != -1)
  177. return true;
  178. return false;
  179. }
  180. ,
  181. _removeTag: function() {
  182. this._popTag();
  183. this.element.children(".tagit-choice:last").remove();
  184. }
  185. ,
  186. _backspace: function(li) {
  187. if (this.input.val() == "") {
  188. // When backspace is pressed, the last tag is deleted.
  189. if (this.lastKey == this._keys.backspace) {
  190. this._popTag();
  191. li.remove();
  192. this.lastKey = null;
  193. } else {
  194. li.addClass('selected');
  195. this.lastKey = this._keys.backspace;
  196. }
  197. }
  198. return true;
  199. }
  200. ,
  201. _initialTags: function() {
  202. if (this.options.initialTags.length != 0) {
  203. for (var i in this.options.initialTags)
  204. if (!this._exists(this.options.initialTags[i]))
  205. this._addTag(this.options.initialTags[i]);
  206. }
  207. }
  208. ,
  209. tags: function() {
  210. return this.tagsArray;
  211. }
  212. ,
  213. destroy: function() {
  214. $.Widget.prototype.destroy.apply(this, arguments); // default destroy
  215. this.tagsArray = [];
  216. }
  217. });
  218. })(jQuery);