diff --git a/src/definitions/modules/search.js b/src/definitions/modules/search.js index 07963b1ea..d27b2bd73 100644 --- a/src/definitions/modules/search.js +++ b/src/definitions/modules/search.js @@ -46,6 +46,8 @@ $.fn.search = function(parameters) { $module = $(this), $prompt = $module.find(selector.prompt), + $input = $module.find(selector.input), + $remove = $module.find(selector.remove), $searchButton = $module.find(selector.searchButton), $results = $module.find(selector.results), $result = $module.find(selector.result), @@ -105,6 +107,11 @@ $.fn.search = function(parameters) { .on('mouseup' + eventNamespace, selector.results, module.event.result.mouseup) .on('click' + eventNamespace, selector.result, module.event.result.click) ; + if(module.is.searchSelection()) { + $module + .on('click' + eventNamespace, selector.remove, module.event.remove.click) + ; + } } }, @@ -137,11 +144,19 @@ $.fn.search = function(parameters) { pageLostFocus = (document.activeElement === this) ; if(!pageLostFocus && !module.resultsClicked) { + if( settings.forceSelection && module.is.searchSelection() ) { + module.set.value( module.get.selectedValue() ); + } module.cancel.query(); module.remove.focus(); module.timer = setTimeout(module.hideResults, settings.hideDelay); } }, + remove: { + click: function() { + module.clear.selectedValue(); + } + }, result: { mousedown: function() { module.resultsClicked = true; @@ -174,7 +189,7 @@ $.fn.search = function(parameters) { } module.hideResults(); if(value) { - module.set.value(value); + module.set.selectedValue(value); } if(href) { module.verbose('Opening search link found in result', $link); @@ -209,7 +224,9 @@ $.fn.search = function(parameters) { // search shortcuts if(keyCode == keys.escape) { module.verbose('Escape key pressed, blurring search field'); - module.trigger.blur(); + $prompt + .trigger('blur') + ; } if( module.is.visible() ) { if(keyCode == keys.enter) { @@ -298,9 +315,15 @@ $.fn.search = function(parameters) { }, is: { + input : function() { + $module.is('input'); + }, empty: function() { return ($results.html() === ''); }, + searchSelection: function() { + return $module.hasClass(className.selection); + }, visible: function() { return ($results.filter(':visible').length > 0); }, @@ -309,20 +332,6 @@ $.fn.search = function(parameters) { } }, - trigger: { - blur: function() { - var - events = document.createEvent('HTMLEvents'), - promptElement = $prompt[0] - ; - if(promptElement) { - module.verbose('Triggering native blur event'); - events.initEvent('blur', false, false); - promptElement.dispatchEvent(events); - } - } - }, - get: { inputEvent: function() { var @@ -335,6 +344,12 @@ $.fn.search = function(parameters) { ; return inputEvent; }, + selectedValue: function() { + return ($input.length > 0) + ? $input.val() || '' + : $module.data(metadata.value) || '' + ; + }, value: function() { return $prompt.val(); }, @@ -362,7 +377,7 @@ $.fn.search = function(parameters) { $.each(results, function(index, category) { if($.isArray(category.results)) { result = module.search.object(value, category.results, lookupFields)[0]; - // don't continue searching if a result is found + // dont continue searching if a result is found if(result) { return false; } @@ -378,6 +393,9 @@ $.fn.search = function(parameters) { }, set: { + clearable: function() { + $remove.addClass(className.active); + }, focus: function() { $module.addClass(className.focus); }, @@ -390,6 +408,21 @@ $.fn.search = function(parameters) { .val(value) ; }, + selectedValue: function(value) { + if($input.length > 0) { + $input.val(value); + } + else { + $module.data(metadata.value, value); + } + if(value === '') { + module.remove.clearable(); + } + else { + module.set.clearable(); + } + module.set.value(value); + }, type: function(type) { type = type || settings.type; if(settings.type == 'category') { @@ -402,6 +435,9 @@ $.fn.search = function(parameters) { }, remove: { + clearable: function() { + $remove.removeClass(className.active); + }, loading: function() { $module.removeClass(className.loading); }, @@ -436,8 +472,8 @@ $.fn.search = function(parameters) { else { module.error(error.source); } + settings.onSearchQuery.call(element, searchTerm); } - settings.onSearchQuery.call(element, searchTerm); } else { module.hideResults(); @@ -612,10 +648,19 @@ $.fn.search = function(parameters) { numCharacters = searchTerm.length ; return (numCharacters >= settings.minCharacters); + }, + selectedValue: function() { + return module.get.selectedValue() + ? true + : false + ; } }, clear: { + selectedValue: function() { + module.set.selectedValue(''); + }, cache: function(value) { var cache = $module.data(metadata.cache) @@ -1075,6 +1120,9 @@ $.fn.search.settings = { searchFullText : true, // whether to include fuzzy results in local search + forceSelection : true, + // whether to remove unmatched input values from a selection search + automatic : true, // whether to add events to prompt automatically @@ -1111,6 +1159,7 @@ $.fn.search.settings = { focus : 'focus', loading : 'loading', results : 'results', + selection: 'selection', pressed : 'down' }, @@ -1128,7 +1177,8 @@ $.fn.search.settings = { metadata: { cache : 'cache', results : 'results', - result : 'result' + result : 'result', + value : 'value' }, regExp: { @@ -1146,18 +1196,19 @@ $.fn.search.settings = { price : 'price', // result price results : 'results', // array of results (standard) title : 'title', // result title - url : 'url', // result url action : 'action', // "view more" object name actionText : 'text', // "view more" text actionURL : 'url' // "view more" url }, selector : { - prompt : '.prompt', - searchButton : '.search.button', - results : '.results', category : '.category', + input : '> input[type="hidden"]', + prompt : '.prompt', + remove : '> .icon.input > .remove.icon', result : '.result', + results : '.results', + searchButton : '.search.button', title : '.title, .name' }, @@ -1224,8 +1275,8 @@ $.fn.search.settings = { // each item inside category $.each(category.results, function(index, result) { - if(result[fields.url]) { - html += ''; + if(response[fields.url]) { + html += ''; } else { html += ''; @@ -1275,8 +1326,8 @@ $.fn.search.settings = { // each result $.each(response[fields.results], function(index, result) { - if(result[fields.url]) { - html += ''; + if(response[fields.url]) { + html += ''; } else { html += ''; @@ -1317,4 +1368,4 @@ $.fn.search.settings = { } }; -})( jQuery, window, document ); +})( jQuery, window , document ); diff --git a/src/definitions/modules/search.less b/src/definitions/modules/search.less index 83928f49e..a416de9f8 100755 --- a/src/definitions/modules/search.less +++ b/src/definitions/modules/search.less @@ -275,7 +275,40 @@ *******************************/ /*-------------- - Categories + Selection +---------------*/ + +.ui.search.selection .prompt { + border-radius: @selectionPromptBorderRadius; +} + +/* Remove input */ +.ui.search.selection > .icon.input > .remove.icon { + pointer-events: none; + position: absolute; + left: auto; + opacity: 0; + color: @selectionCloseIconColor; + top: @selectionCloseTop; + right: @selectionCloseRight; + transition: @selectionCloseTransition; +} +.ui.search.selection > .icon.input > .active.remove.icon { + cursor: pointer; + opacity: @selectionCloseIconOpacity; + pointer-events: auto; +} +.ui.search.selection > .icon.input:not([class*="left icon"]) > .icon ~ .remove.icon { + right: @selectionCloseIconInputRight; +} +.ui.search.selection > .icon.input > .remove.icon:hover { + opacity: @selectionCloseIconHoverOpacity; + color: @selectionCloseIconHoverColor; +} + + +/*-------------- + Category ---------------*/ .ui.category.search .results { diff --git a/src/themes/default/modules/search.variables b/src/themes/default/modules/search.variables index ee27e8444..c84249fb3 100644 --- a/src/themes/default/modules/search.variables +++ b/src/themes/default/modules/search.variables @@ -114,6 +114,22 @@ Types *******************************/ +/* Selection */ +@selectionPromptBorderRadius: @defaultBorderRadius; + +@selectionCloseTop: 0em; +@selectionCloseTransition: + color @defaultDuration @defaultEasing, + opacity @defaultDuration @defaultEasing +; +@selectionCloseRight: 0em; +@selectionCloseIconOpacity: 0.8; +@selectionCloseIconColor: ''; +@selectionCloseIconHoverOpacity: 1; +@selectionCloseIconHoverColor: @red; + +@selectionCloseIconInputRight: 1.85714em; + /* Category */ @categoryBackground: @darkWhite; @categoryBoxShadow: none;