Guest User

Untitled

a guest
Oct 18th, 2018
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.05 KB | None | 0 0
  1. /*
  2. * INFORMATION
  3. * ---------------------------
  4. * Owner: jquery.webspirited.com
  5. * Developer: Matthew Hailwood
  6. * ---------------------------
  7. */
  8.  
  9. (function ($) {
  10. $.widget("ui.tagit", {
  11.  
  12. // default options
  13. options:{
  14. tagSource:[],
  15. triggerKeys:['enter', 'space', 'comma', 'tab'],
  16. initialTags:[],
  17. minLength:1,
  18. select:false,
  19. allowNewTags:true,
  20. caseSensitive:false,
  21. sortable:false,
  22. highlightOnExistColor:'#0F0',
  23. emptySearch:true, // empty search on focus
  24. tagsChanged:function (tagValue, action, element) {
  25. ;
  26. }
  27. },
  28.  
  29. _splitAt:/\ |,/g,
  30. _existingAtIndex:0,
  31. _pasteMetaKeyPressed:false,
  32. _keys:{
  33. backspace:[8],
  34. enter:[13],
  35. space:[32],
  36. comma:[44, 188],
  37. tab:[9]
  38. },
  39.  
  40. _sortable:{
  41. sorting:-1
  42. },
  43.  
  44. //initialization function
  45. _create:function () {
  46.  
  47. var self = this;
  48. this.tagsArray = [];
  49. this.timer = null;
  50.  
  51. //add class "tagit" for theming
  52. this.element.addClass("tagit");
  53.  
  54. //add any initial tags added through html to the array
  55. this.element.children('li').each(function () {
  56. var tag = $(this);
  57. var tagValue = tag.attr('tagValue');
  58. self.options.initialTags.push({label:tag.text(), value:(tagValue ? tagValue : tag.text())});
  59. });
  60.  
  61. //setup split according to the trigger keys
  62. self._splitAt = null;
  63. if ($.inArray('space', self.options.triggerKeys) > 0 && $.inArray('comma', self.options.triggerKeys) > 0)
  64. self._splitAt = /\ |,/g;
  65. else if ($.inArray('space', self.options.triggerKeys) > 0)
  66. self._splitAt = /\ /g;
  67. else if ($.inArray('comma', self.options.triggerKeys) > 0)
  68. self._splitAt = /,/g;
  69.  
  70. //add the html input
  71. alert("This must be called");
  72. this.element.html('<li class="tagit-new"><input class="tagit-input" type="text" /> </li>');
  73.  
  74. this.input = this.element.find(".tagit-input");
  75.  
  76. //setup click handler
  77. $(this.element).click(function (e) {
  78. if ($(e.target).hasClass('tagit-close')) {
  79. // Removes a tag when the little 'x' is clicked.
  80. var parent = $(e.target).parent();
  81.  
  82. var tag = self.tagsArray[parent.index()];
  83.  
  84. tag.element.remove();
  85. self._popTag(tag);
  86. }
  87. else {
  88. self.input.focus();
  89. if (self.options.emptySearch && $(e.target).hasClass('tagit-input') && self.input.val() == '' && self.input.autocomplete != undefined) {
  90. self.input.autocomplete('search');
  91. }
  92. }
  93. });
  94.  
  95. //setup autocomplete 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. if (ui.item.label === undefined)
  102. self._addTag(ui.item.value);
  103. else
  104. self._addTag(ui.item.label, ui.item.value);
  105. return false;
  106. }
  107.  
  108. this.options.focus = function (event, ui) {
  109. if (ui.item.label !== undefined && /^key/.test(event.originalEvent.originalEvent.type)) {
  110. self.input.val(ui.item.label);
  111. self.input.attr('tagValue', ui.item.value);
  112. return false;
  113. }
  114. };
  115. this.options.autoFocus = !this.options.allowNewTags;
  116. this.input.autocomplete(this.options);
  117. this.options.select = os;
  118.  
  119. //setup keydown handler
  120. this.input.keydown(function (e) {
  121. var lastLi = self.element.children(".tagit-choice:last");
  122. if (e.which == self._keys.backspace)
  123. return self._backspace(lastLi);
  124.  
  125. if (self._isInitKey(e.which)) {
  126. e.preventDefault();
  127. if (!self.options.allowNewTags || (self.options.maxTags !== undefined && self.tagsArray.length == self.options.maxTags)) {
  128. self.input.val("");
  129. }
  130. else if (self.options.allowNewTags && $(this).val().length >= self.options.minLength) {
  131. self._addTag($(this).val());
  132. }
  133. }
  134.  
  135. if (self.options.maxLength !== undefined && self.input.val().length == self.options.maxLength) {
  136. e.preventDefault();
  137. }
  138.  
  139. if (lastLi.hasClass('selected'))
  140. lastLi.removeClass('selected');
  141.  
  142. _pasteMetaKeyPressed = e.metaKey;
  143. self.lastKey = e.which;
  144. });
  145.  
  146. this.input.keyup(function (e) {
  147.  
  148. if (_pasteMetaKeyPressed && (e.which == 91 || e.which == 86))
  149. $(this).blur();
  150.  
  151. // timeout for the fast copy pasters
  152. window.setTimeout(function () {
  153. _pasteMetaKeyPressed = e.metaKey;
  154. }, 250);
  155. });
  156.  
  157. //setup blur handler
  158. this.input.blur(function (e) {
  159. self.currentLabel = $(this).val();
  160. self.currentValue = $(this).attr('tagValue');
  161. if (self.options.allowNewTags) {
  162. self.timer = setTimeout(function () {
  163. self._addTag(self.currentLabel, self.currentValue);
  164. self.currentValue = '';
  165. self.currentLabel = '';
  166. }, 400);
  167. }
  168. $(this).val('').removeAttr('tagValue');
  169. return false;
  170. });
  171.  
  172. //define missing trim function for strings
  173. if (!String.prototype.trim) {
  174. String.prototype.trim = function () {
  175. return this.replace(/^\s+|\s+$/g, '');
  176. };
  177. }
  178.  
  179. if (this.options.select) {
  180. this.select = $('<select class="tagit-hiddenSelect" name="' + this.element.attr('name') + '" multiple="multiple"></select>');
  181. this.element.after(this.select);
  182. }
  183. this._initialTags();
  184.  
  185. //setup sortable handler
  186. if (self.options.sortable !== false) {
  187.  
  188. var soptions = {
  189. items:'.tagit-choice',
  190. containment:'parent',
  191. opacity: 0.6,
  192. tolerance: 'pointer',
  193. start:function (event, ui) {
  194. self._sortable.tag = $(ui.item);
  195. self._sortable.origIndex = self._sortable.tag.index();
  196. },
  197. update:function (event, ui) {
  198. self._sortable.newIndex = self._sortable.tag.index();
  199. self._moveTag(self._sortable.origIndex, self._sortable.newIndex);
  200. if(self.options.tagsChanged){
  201. var tag = self.tagsArray[self._sortable.newIndex];
  202. self.options.tagsChanged(tag.value, 'moved', tag.element);
  203. }
  204. }
  205. };
  206.  
  207. if (self.options.sortable == 'handle') {
  208. soptions.handle = 'a.ui-icon';
  209. soptions.cursor = 'move';
  210. }
  211.  
  212. self.element.sortable(soptions);
  213. }
  214.  
  215. },
  216.  
  217. _popSelect:function (tag) {
  218. $('option:eq(' + tag.index + ')', this.select).remove();
  219. this.select.change();
  220. },
  221.  
  222. _addSelect:function (tag) {
  223. this.select.append('<option selected="selected" value="' + tag.value + '">' + tag.label + '</option>');
  224. this.select.change();
  225. },
  226.  
  227. _popTag:function (tag) {
  228. for (var ind in this.tagsArray)
  229. this.tagsArray[ind].index = ind;
  230. random=this.tagsArray[ind].value;
  231. //are we removing the last tag or a specific tag?
  232. if (tag === undefined)
  233. tag = this.tagsArray.pop();
  234. else
  235. this.tagsArray.splice(tag.index, 1);
  236.  
  237. //maintain the indexes
  238. for (var ind in this.tagsArray)
  239. this.tagsArray[ind].index = ind;
  240.  
  241. if (this.options.select)
  242. this._popSelect(tag);
  243. if (this.options.tagsChanged)
  244. this.options.tagsChanged(tag.value || tag.label, 'popped', null);
  245. // alert(random);
  246. return;
  247. },
  248.  
  249. _addTag:function (label, value) {
  250. this.input.autocomplete('close').val("");
  251.  
  252. //are we trying to add a tag that should be split?
  253. if (this._splitAt && label.search(this._splitAt) > 0) {
  254. var result = label.split(this._splitAt);
  255. for (var i = 0; i < result.length; i++)
  256. this._addTag(result[i], value);
  257. return;
  258. }
  259.  
  260. label = label.replace(/,+$/, "").trim();
  261.  
  262. if (label == "")
  263. return false;
  264.  
  265. var tagExists = this._exists(label, value);
  266. if (tagExists !== false) {
  267. this._highlightExisting(tagExists);
  268. return false;
  269. }
  270.  
  271. var tag = this.tag(label, value);
  272. tag.element = $('<li class="tagit-choice"'
  273. + (value !== undefined ? ' tagValue="' + value + '"' : '') + '>'
  274. + (this.options.sortable == 'handle' ? '<a class="ui-icon ui-icon-grip-dotted-vertical" style="float:left"></a>' : '')
  275. + label + '<a class="tagit-close">x</a></li>');
  276. tag.element.insertBefore(this.input.parent());
  277. this.tagsArray.push(tag);
  278.  
  279. this.input.val("");
  280.  
  281. if (this.options.select)
  282. this._addSelect(tag);
  283. if (this.options.tagsChanged)
  284. this.options.tagsChanged(tag.label, 'added', tag.element);
  285. return true;
  286. },
  287.  
  288. _exists:function (label, value) {
  289. if (this.tagsArray.length == 0)
  290. return false;
  291.  
  292. label = this._lowerIfCaseInsensitive(label);
  293. value = this._lowerIfCaseInsensitive(value);
  294.  
  295. for (var ind in this.tagsArray) {
  296. if (this._lowerIfCaseInsensitive(this.tagsArray[ind].label) == label) {
  297. if (value !== undefined) {
  298. if (this._lowerIfCaseInsensitive(this.tagsArray[ind].value) == value)
  299. return ind;
  300. } else {
  301. return ind;
  302. }
  303. }
  304. }
  305.  
  306. return false;
  307. },
  308.  
  309. _highlightExisting:function (index) {
  310. if (this.options.highlightOnExistColor === undefined)
  311. return;
  312. var tag = this.tagsArray[index];
  313. tag.element.stop();
  314.  
  315. var initialColor = tag.element.css('color');
  316. tag.element.animate({color:this.options.highlightOnExistColor}, 100).animate({'color':initialColor}, 800);
  317. },
  318.  
  319. _isInitKey:function (keyCode) {
  320. var keyName = "";
  321. for (var key in this._keys)
  322. if ($.inArray(keyCode, this._keys[key]) != -1)
  323. keyName = key;
  324.  
  325. if ($.inArray(keyName, this.options.triggerKeys) != -1)
  326. return true;
  327. return false;
  328. },
  329.  
  330. _removeTag:function () {
  331. this._popTag();
  332. this.element.children(".tagit-choice:last").remove();
  333. },
  334.  
  335. _backspace:function (li) {
  336. if (this.input.val() == "") {
  337. // When backspace is pressed, the last tag is deleted.
  338. if (this.lastKey == this._keys.backspace) {
  339. this._popTag();
  340. li.remove();
  341. this.lastKey = null;
  342. $('input.tagit-input').attr('value',random);
  343. // $('input').attr('value',random);
  344. return false;
  345. } else {
  346. li.addClass('selected');
  347. this.lastKey = this._keys.backspace;
  348. }
  349. }
  350. return true;
  351. },
  352.  
  353. _initialTags:function () {
  354. var input = this;
  355. var _temp;
  356. if (this.options.tagsChanged)
  357. _temp = this.options.tagsChanged;
  358. this.options.tagsChanged = null;
  359.  
  360. if (this.options.initialTags.length != 0) {
  361. $(this.options.initialTags).each(function (i, element) {
  362. if (typeof (element) == "object")
  363. input._addTag(element.label, element.value);
  364. else
  365. input._addTag(element);
  366. });
  367. }
  368. this.options.tagsChanged = _temp;
  369. },
  370.  
  371. _lowerIfCaseInsensitive:function (inp) {
  372.  
  373. if (inp === undefined || typeof(inp) != typeof("a"))
  374. return inp;
  375.  
  376. if (this.options.caseSensitive)
  377. return inp;
  378.  
  379. return inp.toLowerCase();
  380.  
  381. },
  382.  
  383. _moveTag: function (old_index, new_index) {
  384. this.tagsArray.splice(new_index, 0, this.tagsArray.splice(old_index, 1)[0]);
  385. for (var ind in this.tagsArray)
  386. this.tagsArray[ind].index = ind;
  387.  
  388. if(this.options.select){
  389. $('option:eq(' + old_index + ')', this.select).insertBefore($('option:eq(' + new_index + ')', this.select));
  390. }
  391. },
  392. tags:function () {
  393. return this.tagsArray;
  394. },
  395.  
  396. destroy:function () {
  397. $.Widget.prototype.destroy.apply(this, arguments); // default destroy
  398. this.tagsArray = [];
  399. },
  400.  
  401. reset:function () {
  402. this.element.find(".tagit-choice").remove();
  403. this.tagsArray = [];
  404. if (this.options.select) {
  405. this.select.children().remove();
  406. this.select.change();
  407. }
  408. this._initialTags();
  409. if (this.options.tagsChanged)
  410. this.options.tagsChanged(null, 'reset', null);
  411. },
  412.  
  413. fill:function (tags) {
  414.  
  415. if (tags !== undefined)
  416. this.options.initialTags = tags;
  417. this.reset();
  418. },
  419.  
  420. add:function (label, value) {
  421. if(typeof(label) == "object")
  422. return this._addTag({label: label, value: value});
  423. else
  424. return this._addTag(label, value);
  425. },
  426.  
  427. tag:function (label, value, element) {
  428. var self = this;
  429. return {
  430. label:label,
  431. value:(value === undefined ? label : value),
  432. element:element,
  433. index:self.tagsArray.length
  434. }
  435. }
  436.  
  437.  
  438. });
  439. })(jQuery);
Add Comment
Please, Sign In to add comment