diff --git a/admin/themes/default/template/batch_manager_global.tpl b/admin/themes/default/template/batch_manager_global.tpl index 913000a9a..0c7347026 100644 --- a/admin/themes/default/template/batch_manager_global.tpl +++ b/admin/themes/default/template/batch_manager_global.tpl @@ -55,6 +55,7 @@ jQuery(document).ready(function() { }); {/literal}{/footer_script} +{combine_css path='themes/default/js/plugins/jquery.tokeninput.css'} {combine_script id='jquery.tokeninput' load='footer' require='jquery' path='themes/default/js/plugins/jquery.tokeninput.js'} {combine_script id='jquery.progressBar' load='footer' path='themes/default/js/plugins/jquery.progressbar.min.js'} {combine_script id='jquery.ajaxmanager' load='footer' path='themes/default/js/plugins/jquery.ajaxmanager.js'} @@ -73,7 +74,7 @@ jQuery(document).ready(function() {ldelim} newText: ' ({'new'|@translate})', animateDropdown: false, preventDuplicates: true, - allowCreation: true + allowFreeTagging: true } ); @@ -85,7 +86,7 @@ jQuery(document).ready(function() {ldelim} searchingText: '{'Searching...'|@translate}', animateDropdown: false, preventDuplicates: true, - allowCreation: false + allowFreeTagging: false } ); diff --git a/admin/themes/default/template/batch_manager_unit.tpl b/admin/themes/default/template/batch_manager_unit.tpl index 7dee4fa51..859a9b6a0 100644 --- a/admin/themes/default/template/batch_manager_unit.tpl +++ b/admin/themes/default/template/batch_manager_unit.tpl @@ -2,6 +2,7 @@ {include file='include/datepicker.inc.tpl'} {include file='include/colorbox.inc.tpl'} +{combine_css path='themes/default/js/plugins/jquery.tokeninput.css'} {combine_script id='jquery.tokeninput' load='async' require='jquery' path='themes/default/js/plugins/jquery.tokeninput.js'} {footer_script require='jquery.tokeninput'} jQuery(document).ready(function() {ldelim} @@ -14,7 +15,7 @@ jQuery(document).ready(function() {ldelim} newText: ' ({'new'|@translate})', animateDropdown: false, preventDuplicates: true, - allowCreation: true + allowFreeTagging: true } ); diff --git a/admin/themes/default/template/picture_modify.tpl b/admin/themes/default/template/picture_modify.tpl index 5d2238eea..a19815f1c 100644 --- a/admin/themes/default/template/picture_modify.tpl +++ b/admin/themes/default/template/picture_modify.tpl @@ -11,6 +11,7 @@ jQuery(document).ready(function() { }); {/literal}{/footer_script} +{combine_css path='themes/default/js/plugins/jquery.tokeninput.css'} {combine_script id='jquery.tokeninput' load='async' require='jquery' path='themes/default/js/plugins/jquery.tokeninput.js'} {footer_script require='jquery.tokeninput'} jQuery(document).ready(function() {ldelim} @@ -23,7 +24,7 @@ jQuery(document).ready(function() {ldelim} newText: ' ({'new'|@translate})', animateDropdown: false, preventDuplicates: true, - allowCreation: true + allowFreeTagging: true } ); }); diff --git a/admin/themes/default/theme.css b/admin/themes/default/theme.css index ce8b78b9e..760d73398 100644 --- a/admin/themes/default/theme.css +++ b/admin/themes/default/theme.css @@ -962,24 +962,6 @@ LEGEND { #batchManagerGlobal #filter_dimension blockquote {margin:5px 0 20px 15px;} #batchManagerGlobal #filter_dimension .ui-slider-horizontal {width:650px;margin:5px 0 10px 0;} - -/* TokenInput (with Facebook style) */ -ul.token-input-list {overflow: hidden; height: auto !important; height: 1%;width: 400px;border: 1px solid #8496ba;cursor: text;font-size: 12px;font-family: Verdana;min-height: 1px;z-index: 999;margin: 0;padding: 0;background-color: #fff;list-style-type: none;clear: left;} -ul.token-input-list li input {border: 0;width: 100px;padding: 3px 8px;background-color: white;margin: 2px 0;-webkit-appearance: caret;} -li.token-input-token {overflow: hidden; height: auto !important; height: 15px;margin: 3px;padding: 1px 3px;background-color: #eff2f7;color: #000;cursor: default;border: 1px solid #ccd5e4;font-size: 11px;border-radius: 5px;-moz-border-radius: 5px;-webkit-border-radius: 5px;float: left;white-space: nowrap;} -li.token-input-token p {display: inline;padding: 0;margin: 0;} -li.token-input-token span {color: #a6b3cf;margin-left: 5px;font-weight: bold;cursor: pointer;} -li.token-input-selected-token {background-color: #5670a6;border: 1px solid #3b5998;color: #fff;} -li.token-input-input-token {float: left;margin: 0;padding: 0;list-style-type: none;width:10px;} -div.token-input-dropdown {position: absolute;width: 400px;background-color: #fff;overflow: hidden;border-left: 1px solid #ccc;border-right: 1px solid #ccc;border-bottom: 1px solid #ccc;cursor: default;font-size: 11px;font-family: Verdana;z-index: 1;} -div.token-input-dropdown p {margin: 0;padding: 5px;font-weight: bold;color: #777;} -div.token-input-dropdown ul {margin: 0;padding: 0;} -div.token-input-dropdown ul li {background-color: #fff;padding: 3px;margin: 0;list-style-type: none;} -div.token-input-dropdown ul li.token-input-dropdown-item {background-color: #fff;} -div.token-input-dropdown ul li.token-input-dropdown-item2 {background-color: #fff;} -div.token-input-dropdown ul li em {font-weight: bold;font-style: normal;} -div.token-input-dropdown ul li.token-input-selected-dropdown-item {background-color: #3b5998;color: #fff;} - #mainConf a.addFilter {font-weight:normal;margin-left:20px;} #mainConf a.removeFilter {font-weight:normal;} #mainConf span.property span.filter:first-child a.removeFilter {display:none;} /* can't delete the first field */ diff --git a/admin/themes/roma/theme.css b/admin/themes/roma/theme.css index 39167787b..c95d26c19 100644 --- a/admin/themes/roma/theme.css +++ b/admin/themes/roma/theme.css @@ -274,12 +274,12 @@ color:transparent;} #batchManagerGlobal #selectedMessage {background-color:#555; color:#ddd;} /* TokenInput (with Facebook style for ROMA) */ -ul.token-input-list {border-color:#666;background-color:#444;} -ul.token-input-list li input {background-color:#444;} -li.token-input-token span {color:#878787;} -div.token-input-dropdown {background-color:#eee;border-color:#666;} -div.token-input-dropdown ul li {background-color:#eee;} -div.token-input-dropdown ul li.token-input-selected-dropdown-item {background-color:#FF7800;} +ul.token-input-list {border-color:#666 !important;background-color:#444 !important;} +ul.token-input-list li input {background-color:#444 !important;} +li.token-input-token span {color:#878787 !important;} +div.token-input-dropdown {background-color:#eee !important;border-color:#666 !important;} +div.token-input-dropdown ul li {background-color:#eee !important;} +div.token-input-dropdown ul li.token-input-selected-dropdown-item {background-color:#FF7800 !important;} #progressbar {border:1px solid #666; background-color:#666;} diff --git a/themes/default/js/plugins/jquery.tokeninput.css b/themes/default/js/plugins/jquery.tokeninput.css new file mode 100644 index 000000000..8db9cff44 --- /dev/null +++ b/themes/default/js/plugins/jquery.tokeninput.css @@ -0,0 +1,16 @@ +/* TokenInput (with Facebook style) */ +ul.token-input-list {overflow: hidden; height: auto !important; height: 1%;width: 400px;border: 1px solid #8496ba;cursor: text;font-size: 12px;font-family: Verdana;min-height: 1px;z-index: 999;margin: 0;padding: 0;background-color: #fff;list-style-type: none;clear: left;} +ul.token-input-list li input {border: 0;width: 100px;padding: 3px 8px;background-color: white;margin: 2px 0;-webkit-appearance: caret;} +li.token-input-token {overflow: hidden; height: auto !important; height: 15px;margin: 3px;padding: 1px 3px;background-color: #eff2f7;color: #000;cursor: default;border: 1px solid #ccd5e4;font-size: 11px;border-radius: 5px;-moz-border-radius: 5px;-webkit-border-radius: 5px;float: left;white-space: nowrap;} +li.token-input-token p {display: inline;padding: 0;margin: 0;} +li.token-input-token span {color: #a6b3cf;margin-left: 5px;font-weight: bold;cursor: pointer;} +li.token-input-selected-token {background-color: #5670a6;border: 1px solid #3b5998;color: #fff;} +li.token-input-input-token {float: left;margin: 0;padding: 0;list-style-type: none;width:10px;} +div.token-input-dropdown {position: absolute;width: 400px;background-color: #fff;overflow: hidden;border-left: 1px solid #ccc;border-right: 1px solid #ccc;border-bottom: 1px solid #ccc;cursor: default;font-size: 11px;font-family: Verdana;z-index: 1;} +div.token-input-dropdown p {margin: 0;padding: 5px;font-weight: bold;color: #777;} +div.token-input-dropdown ul {margin: 0;padding: 0;} +div.token-input-dropdown ul li {background-color: #fff;padding: 3px;margin: 0;list-style-type: none;} +div.token-input-dropdown ul li.token-input-dropdown-item {background-color: #fff;} +div.token-input-dropdown ul li.token-input-dropdown-item2 {background-color: #fff;} +div.token-input-dropdown ul li em {font-weight: bold;font-style: normal;} +div.token-input-dropdown ul li.token-input-selected-dropdown-item {background-color: #3b5998;color: #fff;} \ No newline at end of file diff --git a/themes/default/js/plugins/jquery.tokeninput.js b/themes/default/js/plugins/jquery.tokeninput.js index 0bbf8336b..7348639ae 100644 --- a/themes/default/js/plugins/jquery.tokeninput.js +++ b/themes/default/js/plugins/jquery.tokeninput.js @@ -1,51 +1,85 @@ -/** - DON'T MAKE AUTOMATIC UPGRADE - This is a merged version of : - + https://github.com/gr2m/jquery-tokeninput/ - + https://github.com/mistic100/jquery-tokeninput/ -*/ - /* * jQuery Plugin: Tokenizing Autocomplete Text Entry - * Version 1.4.2 + * Version 1.6.1 * * Copyright (c) 2009 James Smith (http://loopj.com) * Licensed jointly under the GPL and MIT licenses, * choose which one suits your project best! * + * https://github.com/mistic100/jquery-tokeninput */ (function ($) { // Default settings var DEFAULT_SETTINGS = { + // Search settings + method: "GET", + queryParam: "q", + searchDelay: 300, + minChars: 1, + propertyToSearch: "name", + jsonContainer: null, + contentType: "json", + + // Prepopulation settings + prePopulate: null, + processPrePopulate: false, + + // Display settings hintText: "Type in a search term", noResultsText: "No results", searchingText: "Searching...", - newText: "(new)", deleteText: "×", - searchDelay: 300, - minChars: 1, + newText: " (new)", + animateDropdown: true, + placeholder: null, + theme: null, + zindex: 999, + resultsLimit: null, + + enableHTML: false, + + resultsFormatter: function(item) { + var string = item[this.propertyToSearch]; + return "
" + (this.enableHTML ? string : _escapeHTML(string)) + "
"+ value +"
"+settings.searchingText+"
"); + if($(input).data("settings").searchingText) { + dropdown.html("" + escapeHTML($(input).data("settings").searchingText) + "
"); show_dropdown(); } } function show_dropdown_hint () { - if(settings.hintText) { - dropdown.html(""+settings.hintText+"
"); + if($(input).data("settings").hintText) { + dropdown.html("" + escapeHTML($(input).data("settings").hintText) + "
"); show_dropdown(); } } + var regexp_special_chars = new RegExp('[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\-]', 'g'); + function regexp_escape(term) { + return term.replace(regexp_special_chars, '\\$&'); + } + // Highlight the query part of the search term function highlight_term(value, term) { - var param = "g"; - if (!settings.caseSensitive) param+= "i"; - return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + escape_regexp_chars(term) + ")(?![^<>]*>)(?![^&;]+;)", param), "$1"); + return value.replace( + new RegExp( + "(?![^&;]+;)(?!<[^<>]*)(" + regexp_escape(term) + ")(?![^<>]*>)(?![^&;]+;)", + "gi" + ), function(match, p1) { + return "" + escapeHTML(p1) + ""; + } + ); } - - function escape_regexp_chars(string) { - var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); // .*+?|()[]{}\ - return string.replace(specials, "\\$&"); + + function find_value_and_highlight_term(template, value, term) { + return template.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + regexp_escape(value) + ")(?![^<>]*>)(?![^&;]+;)", "g"), highlight_term(value, term)); } // Populate the results dropdown with some results @@ -597,38 +883,46 @@ $.TokenList = function (input, url_or_data, settings) { select_dropdown_item($(event.target).closest("li")); }) .mousedown(function (event) { - add_token($(event.target).closest("li")); + add_token($(event.target).closest("li").data("tokeninput")); + hidden_input.change(); return false; }) .hide(); + if ($(input).data("settings").resultsLimit && results.length > $(input).data("settings").resultsLimit) { + results = results.slice(0, $(input).data("settings").resultsLimit); + } + $.each(results, function(index, value) { - var this_li = $(""+settings.noResultsText+"
"); + if($(input).data("settings").noResultsText) { + dropdown.html("" + escapeHTML($(input).data("settings").noResultsText) + "
"); show_dropdown(); } } @@ -641,35 +935,34 @@ $.TokenList = function (input, url_or_data, settings) { deselect_dropdown_item($(selected_dropdown_item)); } - item.addClass(settings.classes.selectedDropdownItem); + item.addClass($(input).data("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); + item.removeClass($(input).data("settings").classes.selectedDropdownItem); selected_dropdown_item = null; } // Do a search and show the "searching" dropdown if the input is longer - // than settings.minChars + // than $(input).data("settings").minChars function do_search() { var query = input_box.val(); - if (!settings.caseSensitive) query = query.toLowerCase(); if(query && query.length) { if(selected_token) { deselect_token($(selected_token), POSITION.AFTER); } - if(query.length >= settings.minChars) { + if(query.length >= $(input).data("settings").minChars) { show_dropdown_searching(); clearTimeout(timeout); timeout = setTimeout(function(){ run_search(query); - }, settings.searchDelay); + }, $(input).data("settings").searchDelay); } else { hide_dropdown(); } @@ -678,17 +971,22 @@ $.TokenList = function (input, url_or_data, settings) { // Do the actual search function run_search(query) { - var cached_results = cache.get(query); + var cache_key = query + computeURL(); + var cached_results = cache.get(cache_key); if(cached_results) { + if ($.isFunction($(input).data("settings").onCachedResult)) { + cached_results = $(input).data("settings").onCachedResult.call(hidden_input, cached_results); + } populate_dropdown(query, cached_results); } else { // Are we doing an ajax search or local data search? - if(settings.url) { + if($(input).data("settings").url) { + var url = computeURL(); // Extract exisiting get params var ajax_params = {}; ajax_params.data = {}; - if(settings.url.indexOf("?") > -1) { - var parts = settings.url.split("?"); + if(url.indexOf("?") > -1) { + var parts = url.split("?"); ajax_params.url = parts[0]; var param_array = parts[1].split("&"); @@ -697,67 +995,73 @@ $.TokenList = function (input, url_or_data, settings) { ajax_params.data[kv[0]] = kv[1]; }); } else { - ajax_params.url = settings.url; + ajax_params.url = url; } // Prepare the request - ajax_params.data[settings.queryParam] = query; - ajax_params.type = settings.method; - ajax_params.dataType = settings.contentType; - if(settings.crossDomain) { + ajax_params.data[$(input).data("settings").queryParam] = query; + ajax_params.type = $(input).data("settings").method; + ajax_params.dataType = $(input).data("settings").contentType; + if($(input).data("settings").crossDomain) { ajax_params.dataType = "jsonp"; } // Attach the success callback ajax_params.success = function(results) { - if($.isFunction(settings.onResult)) { - results = settings.onResult.call(hidden_input, results); + cache.add(cache_key, $(input).data("settings").jsonContainer ? results[$(input).data("settings").jsonContainer] : results); + if($.isFunction($(input).data("settings").onResult)) { + results = $(input).data("settings").onResult.call(hidden_input, results); } - if(settings.allowCreation) { - results.push({name: input_box.val() + settings.newText, id: input_box.val()}); + if($(input).data("settings").allowFreeTagging && $(input).data("settings").freeTaggingHint) { + results.push({name: input_box.val() + $(input).data("settings").newText, id: input_box.val()}); } - cache.add(query, settings.jsonContainer ? results[settings.jsonContainer] : results); // only populate the dropdown if the results are associated with the active search query - var value = input_box.val(); - if (!settings.caseSensitive) value = value.toLowerCase(); - if(value === query) { - populate_dropdown(query, settings.jsonContainer ? results[settings.jsonContainer] : results); + if(input_box.val() === query) { + populate_dropdown(query, $(input).data("settings").jsonContainer ? results[$(input).data("settings").jsonContainer] : results); } }; // Make the request $.ajax(ajax_params); - } else if(settings.local_data) { + } else if($(input).data("settings").local_data) { // Do the search through local data - var results = $.grep(settings.local_data, function (row) { - if (settings.caseSensitive) { - return row.name.indexOf(query) > -1; - } - else { - return row.name.toLowerCase().indexOf(query.toLowerCase()) > -1; - } + var results = $.grep($(input).data("settings").local_data, function (row) { + return row[$(input).data("settings").propertyToSearch].toLowerCase().indexOf(query.toLowerCase()) > -1; }); + + if($(input).data("settings").allowFreeTagging && $(input).data("settings").freeTaggingHint) { + results.push({name: input_box.val() + $(input).data("settings").newText, id: input_box.val()}); + } - if($.isFunction(settings.onResult)) { - results = settings.onResult.call(hidden_input, results); + cache.add(cache_key, results); + if($.isFunction($(input).data("settings").onResult)) { + results = $(input).data("settings").onResult.call(hidden_input, results); } - - if(settings.allowCreation) { - results.push({name: input_box.val() + settings.newText, id: input_box.val()}); - } - - cache.add(query, results); - populate_dropdown(query, results); } } } - - if ($(input).get(0).tagName == 'SELECT') { - $(input).remove(); + + // compute the dynamic URL + function computeURL() { + var url = $(input).data("settings").url; + if(typeof $(input).data("settings").url == 'function') { + url = $(input).data("settings").url.call($(input).data("settings")); + } + return url; } + + // Bring browser focus to the specified object. + // Use of setTimeout is to get around an IE bug. + // (See, e.g., http://stackoverflow.com/questions/2600186/focus-doesnt-work-in-ie) + // + // obj: a jQuery object to focus() + function focus_with_timeout(obj) { + setTimeout(function() { obj.focus(); }, 50); + } + }; // Really basic cache for the results @@ -791,3 +1095,4 @@ $.TokenList.Cache = function (options) { }; }; }(jQuery)); +