Skip to content
Browse files

The ability to create new tokens is now working, as it should.

  • Loading branch information...
1 parent 3821fec commit ce4e5182e7ee97f563ae8f60c62f8c38fe13fa93 @chadisfaction committed Jan 14, 2010
Showing with 721 additions and 577 deletions.
  1. +721 −577 src/jquery.tokeninput.js
View
1,298 src/jquery.tokeninput.js
@@ -1,6 +1,6 @@
/*
* jQuery Plugin: Tokenizing Autocomplete Text Entry
- * Version 1.1
+ * Version 1.1.1
*
* Copyright (c) 2009 James Smith (http://loopj.com)
* Licensed jointly under the GPL and MIT licenses,
@@ -10,585 +10,729 @@
(function($) {
-$.fn.tokenInput = function (url, options) {
- var settings = $.extend({
- url: url,
- hintText: "Type in a search term",
- noResultsText: "No results",
- searchingText: "Searching...",
- searchDelay: 300,
- minChars: 1,
- tokenLimit: null,
- jsonContainer: null,
- method: "GET",
- contentType: "json",
- queryParam: "q",
- onResult: null
- }, options);
-
- settings.classes = $.extend({
- tokenList: "token-input-list",
- token: "token-input-token",
- tokenDelete: "token-input-delete-token",
- selectedToken: "token-input-selected-token",
- highlightedToken: "token-input-highlighted-token",
- dropdown: "token-input-dropdown",
- dropdownItem: "token-input-dropdown-item",
- dropdownItem2: "token-input-dropdown-item2",
- selectedDropdownItem: "token-input-selected-dropdown-item",
- inputToken: "token-input-input-token"
- }, options.classes);
-
- return this.each(function () {
- var list = new $.TokenList(this, settings);
- });
-};
-
-$.TokenList = function (input, settings) {
- //
- // Variables
- //
-
- // Input box position "enum"
- var POSITION = {
- BEFORE: 0,
- AFTER: 1,
- END: 2
- };
-
- // Keys "enum"
- var KEY = {
- BACKSPACE: 8,
- TAB: 9,
- RETURN: 13,
- ESC: 27,
- LEFT: 37,
- UP: 38,
- RIGHT: 39,
- DOWN: 40,
- COMMA: 188
- };
-
- // Save the tokens
- var saved_tokens = [];
+ $.fn.tokenInput = function (url, options) {
+ var settings = $.extend({
+ url: url,
+ hintText: "Type in a search term",
+ noResultsText: "No results",
+ searchingText: "Searching...",
+ createText: "Create",
+ searchDelay: 300,
+ allowNewValues: false,
+ prePopulate: null,
+ minChars: 1,
+ tokenLimit: null,
+ jsonContainer: null,
+ method: "GET",
+ contentType: "json",
+ queryParam: "q",
+ onResult: null,
+ canCreate: false,
+ additionalParams: null,
+ isCreateOnly: false
+ }, options);
+
+ settings.classes = $.extend({
+ tokenList: "token-input-list",
+ token: "token-input-token",
+ tokenDelete: "token-input-delete-token",
+ selectedToken: "token-input-selected-token",
+ highlightedToken: "token-input-highlighted-token",
+ dropdown: "token-input-dropdown",
+ dropdownItem: "token-input-dropdown-item",
+ dropdownItem2: "token-input-dropdown-item2",
+ selectedDropdownItem: "token-input-selected-dropdown-item",
+ inputToken: "token-input-input-token"
+ }, options.classes);
- // Keep track of the number of tokens in the list
- var token_count = 0;
-
- // Basic cache to save on db hits
- var cache = new $.TokenList.Cache();
-
- // Keep track of the timeout
- var timeout;
-
- // Create a new text input an attach keyup events
- var input_box = $("<input type=\"text\">")
- .css({
- outline: "none"
- })
- .focus(function () {
- if (settings.tokenLimit == null || settings.tokenLimit != token_count) {
- show_dropdown_hint();
- }
- })
- .blur(function () {
- hide_dropdown();
- })
- .keydown(function (event) {
- var previous_token;
- var next_token;
-
- switch(event.keyCode) {
- case KEY.LEFT:
- case KEY.RIGHT:
- case KEY.UP:
- case KEY.DOWN:
- if(!$(this).val()) {
- previous_token = input_token.prev();
- next_token = input_token.next();
-
- if((previous_token.length && previous_token.get(0) === selected_token) || (next_token.length && next_token.get(0) === selected_token)) {
- // Check if there is a previous/next token and it is selected
- if(event.keyCode == KEY.LEFT || event.keyCode == KEY.UP) {
- deselect_token($(selected_token), POSITION.BEFORE);
- } else {
- deselect_token($(selected_token), POSITION.AFTER);
- }
- } else if((event.keyCode == KEY.LEFT || event.keyCode == KEY.UP) && previous_token.length) {
- // We are moving left, select the previous token if it exists
- select_token($(previous_token.get(0)));
- } else if((event.keyCode == KEY.RIGHT || event.keyCode == KEY.DOWN) && next_token.length) {
- // We are moving right, select the next token if it exists
- select_token($(next_token.get(0)));
- }
- } else {
- var dropdown_item = null;
-
- if(event.keyCode == KEY.DOWN || event.keyCode == KEY.RIGHT) {
- dropdown_item = $(selected_dropdown_item).next();
- } else {
- dropdown_item = $(selected_dropdown_item).prev();
- }
-
- if(dropdown_item.length) {
- select_dropdown_item(dropdown_item);
- }
- return false;
- }
- break;
-
- case KEY.BACKSPACE:
- previous_token = input_token.prev();
-
- if(!$(this).val().length) {
- if(selected_token) {
- delete_token($(selected_token));
- } else if(previous_token.length) {
- select_token($(previous_token.get(0)));
- }
-
- return false;
- } else if($(this).val().length == 1) {
- hide_dropdown();
- } else {
- // set a timeout just long enough to let this function finish.
- setTimeout(function(){do_search(false);}, 5);
- }
- break;
-
- case KEY.TAB:
- case KEY.RETURN:
- case KEY.COMMA:
- if(selected_dropdown_item) {
- add_token($(selected_dropdown_item));
- return false;
- }
- break;
-
- case KEY.ESC:
- hide_dropdown();
- return true;
-
- default:
- if(is_printable_character(event.keyCode)) {
- // set a timeout just long enough to let this function finish.
- setTimeout(function(){do_search(false);}, 5);
- }
- break;
- }
- });
-
- // Keep a reference to the original input box
- var hidden_input = $(input)
- .hide()
- .focus(function () {
- input_box.focus();
- })
- .blur(function () {
- input_box.blur();
- });
-
- // Keep a reference to the selected token and dropdown item
- var selected_token = null;
- var selected_dropdown_item = null;
-
- // The list to store the token items in
- var token_list = $("<ul />")
- .addClass(settings.classes.tokenList)
- .insertAfter(hidden_input)
- .click(function (event) {
- var li = get_element_from_event(event, "li");
- if(li && li.get(0) != input_token.get(0)) {
- toggle_select_token(li);
- return false;
- } else {
- input_box.focus();
-
- if(selected_token) {
- deselect_token($(selected_token), POSITION.END);
- }
- }
- })
- .mouseover(function (event) {
- var li = get_element_from_event(event, "li");
- if(li && selected_token !== this) {
- li.addClass(settings.classes.highlightedToken);
- }
- })
- .mouseout(function (event) {
- var li = get_element_from_event(event, "li");
- if(li && selected_token !== this) {
- li.removeClass(settings.classes.highlightedToken);
- }
- })
- .mousedown(function (event) {
- // Stop user selecting text on tokens
- var li = get_element_from_event(event, "li");
- if(li){
- return false;
- }
- });
-
-
- // The list to store the dropdown items in
- var dropdown = $("<div>")
- .addClass(settings.classes.dropdown)
- .insertAfter(token_list)
- .hide();
-
- // The token holding the input box
- var input_token = $("<li />")
- .addClass(settings.classes.inputToken)
- .appendTo(token_list)
- .append(input_box);
-
- init_list();
-
- //
- // Functions
- //
-
-
- // Pre-populate list if items exist
- function init_list () {
- li_data = settings.prePopulate;
- if(li_data && li_data.length) {
- for(var i in li_data) {
- var this_token = $("<li><p>"+li_data[i].name+"</p> </li>")
- .addClass(settings.classes.token)
- .insertBefore(input_token);
-
- $("<span>x</span>")
- .addClass(settings.classes.tokenDelete)
- .appendTo(this_token)
- .click(function () {
- delete_token($(this).parent());
- return false;
- });
-
- $.data(this_token.get(0), "tokeninput", {"id": li_data[i].id, "name": li_data[i].name});
-
- // Clear input box and make sure it keeps focus
- input_box
- .val("")
- .focus();
-
- // Don't show the help dropdown, they've got the idea
- hide_dropdown();
-
- // Save this token id
- var id_string = li_data[i].id + ","
- hidden_input.val(hidden_input.val() + id_string);
- }
- }
- }
-
- function is_printable_character(keycode) {
- if((keycode >= 48 && keycode <= 90) || // 0-1a-z
- (keycode >= 96 && keycode <= 111) || // numpad 0-9 + - / * .
- (keycode >= 186 && keycode <= 192) || // ; = , - . / ^
- (keycode >= 219 && keycode <= 222) // ( \ ) '
- ) {
- return true;
- } else {
- return false;
- }
- }
-
- // Get an element of a particular type from an event (click/mouseover etc)
- function get_element_from_event (event, element_type) {
- var target = $(event.target);
- var element = null;
-
- if(target.is(element_type)) {
- element = target;
- } else if(target.parent(element_type).length) {
- element = target.parent(element_type+":first");
- }
-
- return element;
- }
-
- // Inner function to a token to the list
- function insert_token(id, value) {
- var this_token = $("<li><p>"+ value +"</p> </li>")
- .addClass(settings.classes.token)
- .insertBefore(input_token);
-
- // The 'delete token' button
- $("<span>x</span>")
- .addClass(settings.classes.tokenDelete)
- .appendTo(this_token)
- .click(function () {
- delete_token($(this).parent());
- return false;
- });
-
- $.data(this_token.get(0), "tokeninput", {"id": id, "name": value});
-
- return this_token;
- }
-
- // Add a token to the token list based on user input
- function add_token (item) {
- var li_data = $.data(item.get(0), "tokeninput");
- var this_token = insert_token(li_data.id, li_data.name);
-
- // Clear input box and make sure it keeps focus
- input_box
- .val("")
- .focus();
-
- // Don't show the help dropdown, they've got the idea
- hide_dropdown();
-
- // Save this token id
- var id_string = li_data.id + ","
- hidden_input.val(hidden_input.val() + id_string);
+ return this.each(function () {
+ var list = new $.TokenList(this, settings);
+ });
+ };
+
+ $.TokenList = function (input, settings) {
+ //
+ // Variables
+ //
+
+ // Input box position "enum"
+ var POSITION = {
+ BEFORE: 0,
+ AFTER: 1,
+ END: 2
+ };
+
+ // Keys "enum"
+ var KEY = {
+ BACKSPACE: 8,
+ TAB: 9,
+ RETURN: 13,
+ ESC: 27,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ COMMA: 188
+ };
+
+ // Save the tokens
+ var saved_tokens = [];
+
+ // Keep track of the number of tokens in the list
+ var token_count = 0;
+
+ // Basic cache to save on db hits
+ var cache = new $.TokenList.Cache();
+
+ // Keep track of the timeout
+ var timeout;
+
+ // Create a new text input an attach keyup events
+ var input_box = $("<input type=\"text\">")
+ .css({
+ outline: "none"
+ })
+ .focus(function () {
+ if (settings.tokenLimit == null || settings.tokenLimit != token_count) {
+ show_dropdown_hint();
+ }
+ })
+ .blur(function () {
+ // If the user has been typing, create what they typed as a new value
+ if(settings.allowNewValues) create_new_token();
+
+ hide_dropdown();
+ })
+ .keydown(function (event) {
+ var previous_token;
+ var next_token;
+ //alert(event.keyCode);
+
+ switch(event.keyCode) {
+ case KEY.LEFT:
+ case KEY.RIGHT:
+ case KEY.UP:
+ case KEY.DOWN:
+ if(!$(this).val()) {
+ previous_token = input_token.prev();
+ next_token = input_token.next();
+
+ if((previous_token.length && previous_token.get(0) === selected_token) || (next_token.length && next_token.get(0) === selected_token)) {
+ // Check if there is a previous/next token and it is selected
+ if(event.keyCode == KEY.LEFT || event.keyCode == KEY.UP) {
+ deselect_token($(selected_token), POSITION.BEFORE);
+ } else {
+ deselect_token($(selected_token), POSITION.AFTER);
+ }
+ } else if((event.keyCode == KEY.LEFT || event.keyCode == KEY.UP) && previous_token.length) {
+ // We are moving left, select the previous token if it exists
+ select_token($(previous_token.get(0)));
+ } else if((event.keyCode == KEY.RIGHT || event.keyCode == KEY.DOWN) && next_token.length) {
+ // We are moving right, select the next token if it exists
+ select_token($(next_token.get(0)));
+ }
+ } else {
+ var dropdown_item = null;
+
+ if(event.keyCode == KEY.DOWN || event.keyCode == KEY.RIGHT) {
+ dropdown_item = $(selected_dropdown_item).next();
+ } else {
+ dropdown_item = $(selected_dropdown_item).prev();
+ }
+
+ if(dropdown_item.length) {
+ select_dropdown_item(dropdown_item);
+ }
+ return false;
+ }
+ break;
+
+ case KEY.BACKSPACE:
+ previous_token = input_token.prev();
+
+ if(!$(this).val().length) {
+ if(selected_token) {
+ delete_token($(selected_token));
+ } else if(previous_token.length) {
+ select_token($(previous_token.get(0)));
+ }
+
+ return false;
+ } else if($(this).val().length == 1) {
+ hide_dropdown();
+ } else {
+ // set a timeout just long enough to let this function finish.
+ setTimeout(function(){
+ do_search(false);
+ }, 5);
+ }
+ break;
+
+ case KEY.TAB:
+ case KEY.RETURN:
+ case KEY.COMMA:
+ if(selected_dropdown_item) {
+ //var li_data = $.data($(selected_dropdown_item).get(0), "tokeninput");
+ //add_token(li_data.id, li_data.name);
+ add_token($(selected_dropdown_item));
+ return false;
+ } else if(settings.allowNewValues) {
+ create_new_token();
+ return false;
+ }
+ break;
+
+ case KEY.ESC:
+ hide_dropdown();
+ return true;
+
+ default:
+ if(is_printable_character(event.keyCode)) {
+ // set a timeout just long enough to let this function finish.
+ setTimeout(function(){
+ do_search(false);
+ }, 5);
+ }
+ break;
+ }
+
+ return true;
+ });
+
+ // Keep a reference to the original input box
+ var hidden_input = $(input)
+ .hide()
+ .focus(function () {
+ input_box.focus();
+ })
+ .blur(function () {
+ input_box.blur();
+ });
+
+ // Keep a reference to the selected token and dropdown item
+ var selected_token = null;
+ var selected_dropdown_item = null;
+
+ // The list to store the token items in
+ var token_list = $("<ul />")
+ .addClass(settings.classes.tokenList)
+ .insertAfter(hidden_input)
+ .click(function (event) {
+ var li = get_element_from_event(event, "li");
+ if(li && li.get(0) != input_token.get(0)) {
+ toggle_select_token(li);
+ return false;
+ } else {
+ input_box.focus();
+
+ if(selected_token) {
+ deselect_token($(selected_token), POSITION.END);
+ }
+ }
+ return true;
+ })
+ .mouseover(function (event) {
+ var li = get_element_from_event(event, "li");
+ if(li && selected_token !== this) {
+ li.addClass(settings.classes.highlightedToken);
+ }
+ })
+ .mouseout(function (event) {
+ var li = get_element_from_event(event, "li");
+ if(li && selected_token !== this) {
+ li.removeClass(settings.classes.highlightedToken);
+ }
+ })
+ .mousedown(function (event) {
+ // Stop user selecting text on tokens
+ var li = get_element_from_event(event, "li");
+ if(li){
+ return false;
+ }
+ return true;
+ });
+
+
+ // The list to store the dropdown items in
+ var dropdown = $("<div>")
+ .addClass(settings.classes.dropdown)
+ .insertAfter(token_list)
+ .hide();
+
+ // The token holding the input box
+ var input_token = $("<li />")
+ .addClass(settings.classes.inputToken)
+ .appendTo(token_list)
+ .append(input_box);
+
+ init_list();
+
+ //
+ // Functions
+ //
+
+
+ // Pre-populate list if items exist
+ function init_list () {
+ hidden_input.val("");
+ li_data = settings.prePopulate;
+ if(li_data && li_data.length) {
+ jQuery.each(li_data, function(i, val) {
+ var this_token = $("<li><p>"+li_data[i].name+"</p> </li>")
+ .addClass(settings.classes.token)
+ .insertBefore(input_token);
+
+ $("<span>x</span>")
+ .addClass(settings.classes.tokenDelete)
+ .appendTo(this_token)
+ .click(function () {
+ delete_token($(this).parent());
+ return false;
+ });
+ $.data(this_token.get(0), "tokeninput", {
+ "id": li_data[i].id,
+ "name": li_data[i].name
+ });
+
+ // Clear input box and make sure it keeps focus
+ input_box
+ .val('');
+ //.focus();
+
+ // Don't show the help dropdown, they've got the idea
+ hide_dropdown();
+
+ // Save this token id
+ var id_string = li_data[i].name + ","
+ hidden_input.val(hidden_input.val() + id_string);
+
+ });
+ }
+ }
+
+ function is_printable_character(keycode) {
+ if((keycode >= 48 && keycode <= 90) || // 0-1a-z
+ (keycode >= 96 && keycode <= 111) || // numpad 0-9 + - / * .
+ (keycode >= 186 && keycode <= 192) || // ; = , - . / ^
+ (keycode >= 219 && keycode <= 222) // ( \ ) '
+ ) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ // Get an element of a particular type from an event (click/mouseover etc)
+ function get_element_from_event (event, element_type) {
+ var target = $(event.target);
+ var element = null;
+
+ if(target.is(element_type)) {
+ element = target;
+ } else if(target.parent(element_type).length) {
+ element = target.parent(element_type+":first");
+ }
+
+ return element;
+ }
+
+ // Inner function to a token to the list
+ function insert_token(id, value) {
+ var this_token = $("<li><p>"+ value +"</p> </li>")
+ .addClass(settings.classes.token)
+ .insertBefore(input_token);
+
+ // The 'delete token' button
+ $("<span>x</span>")
+ .addClass(settings.classes.tokenDelete)
+ .appendTo(this_token)
+ .click(function () {
+ delete_token($(this).parent());
+ return false;
+ });
+
+ $.data(this_token.get(0), "tokeninput", {
+ "id": id,
+ "name": value
+ });
+
+ return this_token;
+ }
+
+ // Add a token to the token list based on user input
+ function add_token (item) {
+ var li_data = $.data(item.get(0), "tokeninput");
+ create_token(li_data);
+ }
+
+ function create_token (li_data) {
+ //input_box.val("");
+ if(!li_data){return;}
+ var this_token = insert_token(li_data.id, li_data.name);
+
+ // Clear input box and make sure it keeps focus
+ input_box
+ .val("")
+ .focus();
+
+ // Don't show the help dropdown, they've got the idea
+ hide_dropdown();
+
+ // Save this token id
+ var id_string = li_data.name + ","
+ hidden_input.val(hidden_input.val() + id_string);
+
+ token_count++;
+
+ if(settings.tokenLimit != null && settings.tokenLimit >= token_count) {
+ input_box.hide();
+ hide_dropdown();
+ }
+
+ $(hidden_input).trigger('tokenadd', {
+ update: update_token,
+ remove: delete_token,
+ data: li_data,
+ token: this_token.get(0)
+ });
+ }
+
+ function update_token (item, data) {
+ var old_data = $.data(item, "tokeninput");
+ var new_data = {
+ id: data.id == undefined ? old_data.id : data.id,
+ name: data.name == undefined ? old_data.name : data.name
+ };
- token_count++;
+ $.data(item, "tokeninput", data);
- if(settings.tokenLimit != null && settings.tokenLimit >= token_count) {
- input_box.hide();
- hide_dropdown();
- }
- }
-
- // Select a token in the token list
- function select_token (token) {
- token.addClass(settings.classes.selectedToken);
- selected_token = token.get(0);
-
- // Hide input box
- input_box.val("");
-
- // Hide dropdown if it is visible (eg if we clicked to select token)
- hide_dropdown();
- }
-
- // Deselect a token in the token list
- function deselect_token (token, position) {
- token.removeClass(settings.classes.selectedToken);
- selected_token = null;
-
- if(position == POSITION.BEFORE) {
- input_token.insertBefore(token);
- } else if(position == POSITION.AFTER) {
- input_token.insertAfter(token);
- } else {
- input_token.appendTo(token_list);
- }
-
- // Show the input box and give it focus again
- input_box.focus();
- }
-
- // Toggle selection of a token in the token list
- function toggle_select_token (token) {
- if(selected_token == token.get(0)) {
- deselect_token(token, POSITION.END);
- } else {
- if(selected_token) {
- deselect_token($(selected_token), POSITION.END);
- }
- select_token(token);
- }
- }
-
- // Delete a token from the token list
- function delete_token (token) {
- // Remove the id from the saved list
- var token_data = $.data(token.get(0), "tokeninput");
-
- // Delete the token
- token.remove();
- selected_token = null;
-
- // Show the input box and give it focus again
- input_box.focus();
-
- // Delete this token's id from hidden input
- var str = hidden_input.val()
- var start = str.indexOf(token_data.id+",");
- var end = str.indexOf(",", start) + 1;
-
- if(end >= str.length) {
- hidden_input.val(str.slice(0, start));
- } else {
- hidden_input.val(str.slice(0, start) + str.slice(end, str.length));
- }
+ var old_id_string = old_data.id + ",";
+ var new_id_string = new_data.id + ",";
- token_count--;
+ hidden_input.val(
+ hidden_input.val().replace(old_id_string, new_id_string)
+ );
+ }
+
+ function create_new_token () {
+ //return;
+ var string = input_box.val().toLowerCase();
+ //alert(string);
+ if(string.length > 0) {
+ //add_token(string, string);
+ var this_token = $("<li><p>"+string+"</p> </li>");
+ // .addClass(settings.classes.token)
+ // .insertBefore(input_token);
+ //
+ // $("<span>x</span>")
+ // .addClass(settings.classes.tokenDelete)
+ // .appendTo(this_token)
+ // .click(function () {
+ // delete_token($(this).parent());
+ // return false;
+ // });
+ $.data(this_token.get(0), "tokeninput", {
+ "id": 0,
+ "name": string
+ });
+ add_token(this_token);
+ }
+ }
+
+ // Select a token in the token list
+ function select_token (token) {
+ token.addClass(settings.classes.selectedToken);
+ selected_token = token.get(0);
+
+ // Hide input box
+ input_box.val("");
+
+ // Hide dropdown if it is visible (eg if we clicked to select token)
+ hide_dropdown();
+ }
+
+ // Deselect a token in the token list
+ function deselect_token (token, position) {
+ token.removeClass(settings.classes.selectedToken);
+ selected_token = null;
+
+ if(position == POSITION.BEFORE) {
+ input_token.insertBefore(token);
+ } else if(position == POSITION.AFTER) {
+ input_token.insertAfter(token);
+ } else {
+ input_token.appendTo(token_list);
+ }
+
+ // Show the input box and give it focus again
+ input_box.focus();
+ }
+
+ // Toggle selection of a token in the token list
+ function toggle_select_token (token) {
+ if(selected_token == token.get(0)) {
+ deselect_token(token, POSITION.END);
+ } else {
+ if(selected_token) {
+ deselect_token($(selected_token), POSITION.END);
+ }
+ select_token(token);
+ }
+ }
+
+ // Delete a token from the token list
+ function delete_token (token) {
+ // Remove the id from the saved list
+ var token_data = $.data(token.get(0), "tokeninput");
+
+ // Delete the token
+ token.remove();
+ selected_token = null;
+
+ // Show the input box and give it focus again
+ input_box.focus();
+
+ // Delete this token's id from hidden input
+ var str = hidden_input.val()
+ var start = str.indexOf(token_data.name+",");
+ var end = str.indexOf(",", start) + 1;
+ if(end >= str.length) {
+ hidden_input.val(str.slice(0, start));
+ } else {
+ hidden_input.val(str.slice(0, start) + str.slice(end, str.length));
+ }
+ token_count--;
- if (settings.tokenLimit != null) {
- input_box
- .show()
- .val("")
- .focus();
- }
- }
-
- // Hide and clear the results dropdown
- function hide_dropdown () {
- dropdown.hide().empty();
- selected_dropdown_item = null;
- }
-
- function show_dropdown_searching () {
- dropdown
- .html("<p>"+settings.searchingText+"</p>")
- .show();
- }
-
- function show_dropdown_hint () {
- dropdown
- .html("<p>"+settings.hintText+"</p>")
- .show();
- }
-
- // Highlight the query part of the search term
- function highlight_term(value, term) {
- return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<b>$1</b>");
- }
-
- // Populate the results dropdown with some results
- function populate_dropdown (query, results) {
- if(results.length) {
- dropdown.empty();
- var dropdown_ul = $("<ul>")
- .appendTo(dropdown)
- .mouseover(function (event) {
- select_dropdown_item(get_element_from_event(event, "li"));
- })
- .mousedown(function (event) {
- add_token(get_element_from_event(event, "li"));
- return false;
- })
- .hide();
-
- for(var i in results) {
- if (results.hasOwnProperty(i)) {
- var this_li = $("<li>"+highlight_term(results[i].name, query)+"</li>")
- .appendTo(dropdown_ul);
-
- if(i%2) {
- this_li.addClass(settings.classes.dropdownItem);
- } else {
- this_li.addClass(settings.classes.dropdownItem2);
- }
-
- if(i == 0) {
- select_dropdown_item(this_li);
- }
-
- $.data(this_li.get(0), "tokeninput", {"id": results[i].id, "name": results[i].name});
- }
- }
-
- dropdown.show();
- dropdown_ul.slideDown("fast");
-
- } else {
- dropdown
- .html("<p>"+settings.noResultsText+"</p>")
- .show();
- }
- }
-
- // Highlight an item in the results dropdown
- function select_dropdown_item (item) {
- if(item) {
- if(selected_dropdown_item) {
- deselect_dropdown_item($(selected_dropdown_item));
- }
-
- item.addClass(settings.classes.selectedDropdownItem);
- selected_dropdown_item = item.get(0);
- }
- }
-
- // Remove highlighting from an item in the results dropdown
- function deselect_dropdown_item (item) {
- item.removeClass(settings.classes.selectedDropdownItem);
- selected_dropdown_item = null;
- }
-
- // Do a search and show the "searching" dropdown if the input is longer
- // than settings.minChars
- function do_search(immediate) {
- var query = input_box.val().toLowerCase();
-
- if (query && query.length) {
- if(selected_token) {
- deselect_token($(selected_token), POSITION.AFTER);
- }
- if (query.length >= settings.minChars) {
- show_dropdown_searching();
- if (immediate) {
- run_search(query);
- } else {
- clearTimeout(timeout);
- timeout = setTimeout(function(){run_search(query);}, settings.searchDelay);
- }
- } else {
- hide_dropdown();
- }
- }
- }
-
- // Do the actual search
- function run_search(query) {
- var cached_results = cache.get(query);
- if(cached_results) {
- populate_dropdown(query, cached_results);
- } else {
- var queryStringDelimiter = settings.url.indexOf("?") < 0 ? "?" : "&";
- var callback = function(results) {
- if($.isFunction(settings.onResult)) {
- results = settings.onResult.call(this, results);
- }
- cache.add(query, settings.jsonContainer ? results[settings.jsonContainer] : results);
- populate_dropdown(query, settings.jsonContainer ? results[settings.jsonContainer] : results);
- };
+ if (settings.tokenLimit != null) {
+ input_box
+ .show()
+ .val("")
+ .focus();
+ }
+
+ $(hidden_input).trigger('tokendelete', {
+ add: create_token,
+ data: token_data
+ });
+ }
+
+ // Hide and clear the results dropdown
+ function hide_dropdown () {
+ dropdown.hide().empty();
+ selected_dropdown_item = null;
+ }
+
+ function show_dropdown_searching () {
+ if(settings.searchingText.length > 0) {
+ dropdown
+ .html("<p>"+settings.searchingText+"</p>")
+ .show();
+ }
+ }
+
+ function show_dropdown_hint () {
+ dropdown
+ .html("<p>"+settings.hintText+"</p>")
+ .show();
+ }
+
+ // Highlight the query part of the search term
+ function highlight_term(value, term) {
+ return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<b>$1</b>");
+ }
+
+ // Populate the results dropdown with some results
+ function populate_dropdown (query, results) {
+ if(results.length || settings.canCreate) {
+ dropdown.empty();
+ var dropdown_ul = $("<ul>")
+ .appendTo(dropdown)
+ .mouseover(function (event) {
+ select_dropdown_item(get_element_from_event(event, "li"));
+ })
+ .click(function (event) {
+ //var item = get_element_from_event(event, "li");
+ //var the_data = $.data(item.get(0), "tokeninput");
+ //add_token(the_data.id, the_data.name);
+ add_token(get_element_from_event(event, "li"));
+ })
+ .mousedown(function (event) {
+ // Stop user selecting text on tokens
+ return false;
+ })
+ .hide();
+
+ // Check for duplicates
+ var resultAdded = new Array();
+ $("." + settings.classes.token, token_list)
+ .each(function(i, val) {
+ var data = $.data(val, "tokeninput");
+ resultAdded[data.name] = 1;
+ }
+ );
+
+ // Save the first li for selecting
+ var firstLi;
+ jQuery.each(results, function(i, val) {
+ if (results.hasOwnProperty(i) && !resultAdded[results[i].name]) {
+ var this_li = $("<li>"+highlight_term(results[i].name, query)+"</li>")
+ .appendTo(dropdown_ul);
+
+ if(i%2) {
+ this_li.addClass(settings.classes.dropdownItem);
+ } else {
+ this_li.addClass(settings.classes.dropdownItem2);
+ }
+
+ if(i == 0) {
+ firstLi = this_li;
+ }
+
+ resultAdded[results[i].name] = 1;
+ $.data(this_li.get(0), "tokeninput", {
+ "id": results[i].id,
+ "name": results[i].name
+ });
+ }else{
+ settings.isCreateOnly = true;
+ }
+ });
+
+ // If canCreate option enabled, show "Create 'token-name'"
+ if(settings.canCreate && !resultAdded[query]) {
+ var li = $("<li>" + settings.createText + " '" + query + "'</li>")
+ .appendTo(dropdown_ul);
+ // li.addClass(results.length%2 ? settings.classes.dropdownItem : settings.classes.dropdownItem2);
+ if(results.length % 2) {
+ li.addClass(settings.classes.dropdownItem);
+ } else {
+ li.addClass(settings.classes.dropdownItem2);
+ }
+ //if(results.length == 0) {
+ if (settings.isCreateOnly){
+ firstLi = li;
+ }
+
+ $.data(li.get(0), "tokeninput", {
+ "id": "+" + query,
+ "name": query
+ });
+ }
+
+ if(firstLi) {
+ select_dropdown_item(firstLi);
+ }
+
+ dropdown.show();
+ dropdown_ul.show();
+
+ } else {
+ if(settings.noResultsText.length > 0) {
+ dropdown
+ .html("<p>"+settings.noResultsText+"</p>")
+ .show();
+ } else {
+ hide_dropdown();
+ }
+ }
+ }
+
+ // Highlight an item in the results dropdown
+ function select_dropdown_item (item) {
+ if(item) {
+ if(selected_dropdown_item) {
+ deselect_dropdown_item($(selected_dropdown_item));
+ }
+
+ item.addClass(settings.classes.selectedDropdownItem);
+ selected_dropdown_item = item.get(0);
+ }
+ }
+
+ // Remove highlighting from an item in the results dropdown
+ function deselect_dropdown_item (item) {
+ item.removeClass(settings.classes.selectedDropdownItem);
+ selected_dropdown_item = null;
+ }
+
+ // Do a search and show the "searching" dropdown if the input is longer
+ // than settings.minChars
+ function do_search(immediate) {
+ var query = input_box.val().toLowerCase();
+
+ if (query && query.length) {
+ if(selected_token) {
+ deselect_token($(selected_token), POSITION.AFTER);
+ }
+ if (query.length >= settings.minChars) {
+ show_dropdown_searching();
+ if (immediate) {
+ run_search(query);
+ } else {
+ clearTimeout(timeout);
+ timeout = setTimeout(function(){
+ run_search(query);
+ }, settings.searchDelay);
+ }
+ } else {
+ hide_dropdown();
+ }
+ }
+ }
+
+ // Do the actual search
+ function run_search(query) {
+ var cached_results = cache.get(query);
+ if(cached_results) {
+ populate_dropdown(query, cached_results);
+ } else {
+ var queryStringDelimiter = settings.url.indexOf("?") < 0 ? "?" : "&";
+ var callback = function(results) {
+ if($.isFunction(settings.onResult)) {
+ results = settings.onResult.call(this, results);
+ }
+ cache.add(query, settings.jsonContainer ? results[settings.jsonContainer] : results);
+ populate_dropdown(query, settings.jsonContainer ? results[settings.jsonContainer] : results);
+ };
- if(settings.method == "POST") {
- $.post(settings.url + queryStringDelimiter + settings.queryParam + "=" + query, {}, callback, settings.contentType);
- } else {
- $.get(settings.url + queryStringDelimiter + settings.queryParam + "=" + query, {}, callback, settings.contentType);
- }
- }
- }
-};
-
-// Really basic cache for the results
-$.TokenList.Cache = function (options) {
- var settings = $.extend({
- max_size: 50
- }, options);
-
- var data = {};
- var size = 0;
-
- var flush = function () {
- data = {};
- size = 0;
- };
-
- this.add = function (query, results) {
- if(size > settings.max_size) {
- flush();
- }
-
- if(!data[query]) {
- size++;
- }
-
- data[query] = results;
- };
-
- this.get = function (query) {
- return data[query];
- };
-};
-
-})(jQuery);
+ if(settings.method == "POST") {
+ $.post(settings.url + queryStringDelimiter + settings.queryParam + "=" + query, settings.additionalParams, callback, settings.contentType);
+ } else {
+ $.get(settings.url + queryStringDelimiter + settings.queryParam + "=" + query, settings.additionalParams, callback, settings.contentType);
+ }
+ }
+ }
+ };
+
+ // Really basic cache for the results
+ $.TokenList.Cache = function (options) {
+ var settings = $.extend({
+ max_size: 50
+ }, options);
+
+ var data = {};
+ var size = 0;
+
+ var flush = function () {
+ data = {};
+ size = 0;
+ };
+
+ this.add = function (query, results) {
+ if(size > settings.max_size) {
+ flush();
+ }
+
+ if(!data[query]) {
+ size++;
+ }
+
+ data[query] = results;
+ };
+
+ this.get = function (query) {
+ return data[query];
+ };
+ };
+
+})(jQuery);

0 comments on commit ce4e518

Please sign in to comment.
Something went wrong with that request. Please try again.