{"version":3,"sources":["suggestion-box.js"],"names":["$","SuggestionBox","options","context","setup","setSuggestionBoxPosition","height","$suggestionBox","css","scrollable","noConflict","self","this","mousemoveEvents","e","isSuggestion","autoScrolled","unselect","selectedLi","getSelectionMouseIsOver","select","mouseHover","mouseoutEvents","resetSelection","attr","focus","clickEvents","preventDefault","doClick","blurEvent","active","hideSuggestionBox","keyupEvents","which","UP_ARROW_KEY","DOWN_ARROW_KEY","ESCAPE_KEY","ENTER_KEY","input","val","url","timer","clearTimeout","request","paramName","setTimeout","getSuggestions","delay","filter","showSuggestions","hybrid","length","matches","clearSuggestions","urlClone","focusEvents","jsonData","keydownEvents","moveDown","moveUp","find","click","pasteEvents","keyup","onClick","target","parents","nodeName","position","scroll","selectedHref","addClass","doScroll","removeClass","to","pos","top","scrollTo","scrollTop","listSize","size","goToSelection","window","location","ajaxCalledVal","ajax","data","dataType","success","selectionHasChanged","currentLi","suggestions","JSON","stringify","setJsonData","ajaxSuccess","error","ajaxError","$parentLi","parent","children","index","borders","getCssValue","padding","left","offset","leftOffset","topOffset","element","name","parseInt","replace","fadeOut","adjustBorderRadius","searchBoxBorderRadius","bottomLeft","bottomRight","onHide","showSuggestionBox","fadeIn","onShow","setSuggestionBoxWidth","searchBoxWidth","getSearchBoxWidth","widthAdjustment","menuWidth","min-width","width","createAttributes","value","each","key","keys","Object","i","createCustomValues","$suggestions","customData","custom","createSuggestionsList","filterPattern","heading","suggestion","image","RegExp","results","getNoSuggestionMarkup","html","noSuggestionsMessage","forceShow","filterResults","showNoSuggestionsMessage","json","parseJSON","sort","loadJson","console","log","regex","grep","test","extend","highlightMatch","randId","Math","floor","random","appendTo","on","resize","addSuggestions","loadSuggestions","getJson","selectedUrl","selectedSuggestion","text","selectedImage","show","force","hide","getId","withHash","reservedKey","el","destroy","unbind","remove","off","set","option","fn","suggestionBox","domElement","get","args","makeArray","arguments","jQuery"],"mappings":"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","file":"suggestion-box.min.js","sourcesContent":["(function ($) {\r\n\r\n $.fn.suggestionBox = function (options) {\r\n\r\n // Get the bound dom element\r\n var domElement = $(this).get()[0];\r\n\r\n var args = $.makeArray(arguments);\r\n var suggestionBox = $.data(domElement, 'suggestionBox');\r\n\r\n if (suggestionBox) {\r\n suggestionBox.set(args[0], args[1]);\r\n } else {\r\n suggestionBox = new SuggestionBox(options, this);\r\n $.data(domElement, 'suggestionBox', suggestionBox);\r\n }\r\n\r\n return suggestionBox;\r\n };\r\n\r\n function SuggestionBox(options, context) {\r\n\r\n options = $.extend({\r\n topOffset: 0,\r\n leftOffset: 0,\r\n widthAdjustment: 0,\r\n delay: 400, // in ms\r\n heading: 'Suggestions',\r\n results: 10,\r\n fadeIn: true,\r\n fadeOut: false,\r\n menuWidth: 'auto',\r\n showNoSuggestionsMessage: false,\r\n noSuggestionsMessage: 'No Suggestions Found',\r\n filter: true,\r\n filterPattern: \"({INPUT})\",\r\n highlightMatch: false,\r\n adjustBorderRadius: true,\r\n ajaxError: function (e) {\r\n console.log(e);\r\n },\r\n ajaxSuccess: function (data) {\r\n },\r\n onClick: function () {\r\n goToSelection();\r\n hideSuggestionBox();\r\n context.val('');\r\n },\r\n onShow: function () {\r\n },\r\n onHide: function () {\r\n },\r\n paramName: 'search',\r\n customData: [],\r\n scrollable: false,\r\n hybrid: false,\r\n noConflict: false\r\n }, options);\r\n\r\n // Initially set the return context to context\r\n var self = context;\r\n\r\n // Constants for key values\r\n var ENTER_KEY = 13;\r\n var UP_ARROW_KEY = 38;\r\n var DOWN_ARROW_KEY = 40;\r\n var ESCAPE_KEY = 27;\r\n\r\n // Default values for selected list item\r\n var selectedLi = -1;\r\n var selectedHref = '#';\r\n\r\n // Is the mouse hovering over the suggestion box?\r\n var mouseHover = false;\r\n // Timer for only making ajax calls when the user stops typing\r\n var timer = null;\r\n // Did we get any suggestions?\r\n var matches = false;\r\n // Is the search box active (does it have focus)\r\n var active = false;\r\n // Whether or not the scroll action was done pragmatically\r\n var autoScrolled = false;\r\n // create a blank object for our request\r\n var request = {};\r\n var jsonData = {};\r\n // The value of the input when ajax was called\r\n var ajaxCalledVal;\r\n var urlClone;\r\n\r\n var searchBoxBorderRadius,\r\n $suggestionBox = null,\r\n randId;\r\n\r\n /**\r\n * Initialise the plugin\r\n */\r\n (function _init() {\r\n // Inject the suggestion box into the body of the web page\r\n randId = 'suggestion-box-' + Math.floor(Math.random() * 10000000);\r\n // Inject the suggestion box into the body of the web page\r\n $suggestionBox = $('
').appendTo('body');\r\n\r\n searchBoxBorderRadius = {\r\n bottomLeft: context.css('border-bottom-left-radius'),\r\n bottomRight: context.css('border-bottom-right-radius')\r\n };\r\n\r\n urlClone = options.url;\r\n\r\n // Turn off autocomplete\r\n context.attr('autocomplete', 'off');\r\n\r\n // Bind event handlers\r\n context.on('blur', blurEvent);\r\n context.on('keyup', keyupEvents);\r\n context.on('focus', focusEvents);\r\n context.on('keydown', keydownEvents);\r\n context.on('paste', pasteEvents);\r\n\r\n $suggestionBox.on('mousemove', mousemoveEvents);\r\n $suggestionBox.on('mouseout', mouseoutEvents);\r\n $suggestionBox.on('click', clickEvents);\r\n\r\n // Reset the position of the suggestion box if the window is re-sized\r\n $(window).resize(function () {\r\n setSuggestionBoxPosition();\r\n });\r\n\r\n setup();\r\n })();\r\n\r\n function setup() {\r\n setSuggestionBoxPosition();\r\n\r\n if (options.height) {\r\n $suggestionBox.css('max-height', options.height);\r\n }\r\n if (options.scrollable) {\r\n $suggestionBox.css('overflow', 'auto');\r\n }\r\n\r\n // If noConflict set the return context to this\r\n if (options.noConflict) {\r\n self = this;\r\n }\r\n }\r\n\r\n /**\r\n * Events for the mouse moving inside the suggestion box\r\n * @param e\r\n */\r\n function mousemoveEvents(e) {\r\n if (isSuggestion(e) && !autoScrolled) {\r\n unselect(selectedLi);\r\n selectedLi = getSelectionMouseIsOver(e);\r\n select(selectedLi);\r\n }\r\n\r\n mouseHover = true;\r\n autoScrolled = false;\r\n }\r\n\r\n /**\r\n * Events for when the mouse leaves the suggestion box\r\n * @param e\r\n */\r\n function mouseoutEvents(e) {\r\n if (isSuggestion(e) && !autoScrolled) {\r\n unselect(selectedLi);\r\n resetSelection();\r\n } else if ($(':focus').attr('id') !== context.attr('id')) {\r\n // We're out of the suggestion box so re-focus on search\r\n context.focus();\r\n }\r\n mouseHover = false;\r\n }\r\n\r\n /**\r\n * Events for clicks inside the suggestion box\r\n * @param e\r\n */\r\n function clickEvents(e) {\r\n if (isSuggestion(e)) {\r\n e.preventDefault();\r\n doClick(e);\r\n }\r\n }\r\n\r\n /**\r\n * Events for when the search box loses focus\r\n */\r\n function blurEvent() {\r\n active = false;\r\n if (!mouseHover) {\r\n hideSuggestionBox();\r\n }\r\n }\r\n\r\n /**\r\n * Keyup events for the search box\r\n * @param e\r\n */\r\n function keyupEvents(e) {\r\n // Ignore the navigation keys. We don't want to fire ajax calls when navigating\r\n if (e.which !== UP_ARROW_KEY && e.which !== DOWN_ARROW_KEY && e.which !== ESCAPE_KEY && e.which !== ENTER_KEY) {\r\n var input = context.val();\r\n if (options.url) {\r\n resetSelection();\r\n if (timer) {\r\n clearTimeout(timer);\r\n }\r\n\r\n // set the request to be sent sent as the data parameter\r\n request[options.paramName] = input;\r\n timer = setTimeout(function () {\r\n getSuggestions(options.url)\r\n }, options.delay);\r\n }\r\n\r\n // If filter set to true, call showSuggestions() - it will filter the results for us\r\n if (options.filter) {\r\n showSuggestions();\r\n }\r\n\r\n if (options.hybrid && (input.length <= 0 || !matches)) {\r\n self.clearSuggestions();\r\n getSuggestions(urlClone);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Events for when the search box is focused\r\n */\r\n function focusEvents() {\r\n active = true;\r\n if ($(this).val()) {\r\n showSuggestions(jsonData);\r\n }\r\n }\r\n\r\n function keydownEvents(e) {\r\n if (e.which == DOWN_ARROW_KEY) {\r\n e.preventDefault();\r\n moveDown(true);\r\n }\r\n if ($suggestionBox.css('display') !== 'none') {\r\n if (e.which == UP_ARROW_KEY) {\r\n e.preventDefault();\r\n moveUp(true);\r\n }\r\n if (e.which === ENTER_KEY && selectedLi > -1) {\r\n e.preventDefault();\r\n $suggestionBox.find('.selected a').click();\r\n }\r\n if (e.which == ESCAPE_KEY) {\r\n e.preventDefault();\r\n hideSuggestionBox();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Events for when text is pasted in to the search box\r\n */\r\n function pasteEvents() {\r\n // Simulate keyup after 200ms otherwise the value of the search box will not be available\r\n setTimeout(function () {\r\n context.keyup();\r\n }, 200);\r\n }\r\n\r\n\r\n /**\r\n * Performs the click action, this can be called for any event you want to recreate a click action for.\r\n * @param e\r\n */\r\n function doClick(e) {\r\n options.onClick(e);\r\n }\r\n\r\n /**\r\n * Is the given event made on a suggestion?\r\n * @param e\r\n * @returns {boolean}\r\n */\r\n function isSuggestion(e) {\r\n return $(e.target).parents('a').length > 0 || e.target.nodeName === 'A';\r\n }\r\n\r\n /**\r\n * Selects the suggestion at the given position\r\n * @param position\r\n * @param scroll\r\n */\r\n function select(position, scroll) {\r\n selectedHref = $suggestionBox.find(\"li:eq(\" + position + \") a\").attr('href');\r\n $suggestionBox.find(\"li:eq(\" + position + \")\").addClass('selected');\r\n\r\n if (scroll) {\r\n doScroll(position);\r\n }\r\n }\r\n\r\n /**\r\n * Unselects the suggestion at the given position\r\n * @param position\r\n */\r\n function unselect(position) {\r\n $suggestionBox.find(\"li:eq(\" + position + \")\").removeClass('selected');\r\n }\r\n\r\n /**\r\n * Resets any selected suggestions\r\n */\r\n function resetSelection() {\r\n selectedHref = '#';\r\n selectedLi = -1;\r\n // remove all selected on reset\r\n $suggestionBox.find('li').removeClass('selected');\r\n }\r\n\r\n\r\n /**\r\n * Scrolls the suggestion box to the given position\r\n * @param to\r\n */\r\n function doScroll(to) {\r\n autoScrolled = true;\r\n\r\n if (to > -1) {\r\n var pos = $suggestionBox.find('li:eq(' + to + ')').position().top -\r\n $suggestionBox.find('li:eq(0)').position().top;\r\n }\r\n\r\n // find scroll position at to and set scroll bars to it\r\n var scrollTo = (to > -1) ? pos : 0;\r\n $suggestionBox.scrollTop(scrollTo);\r\n }\r\n\r\n /**\r\n * Moves the selection down to the next suggestion\r\n */\r\n function moveDown(scroll) {\r\n var listSize = $suggestionBox.find('li').size();\r\n\r\n if ($suggestionBox.css('display') === 'none') {\r\n showSuggestions();\r\n } else if (selectedLi === (listSize - 1)) {\r\n unselect(selectedLi);\r\n resetSelection();\r\n } else {\r\n unselect(selectedLi);\r\n selectedLi++;\r\n select(selectedLi);\r\n }\r\n\r\n if (scroll) {\r\n doScroll(selectedLi);\r\n }\r\n }\r\n\r\n /**\r\n * Moves the selection up to the previous suggestions\r\n */\r\n function moveUp(scroll) {\r\n if (selectedLi > 0) {\r\n unselect(selectedLi);\r\n selectedLi--;\r\n select(selectedLi);\r\n } else if (selectedLi == -1) {\r\n unselect(selectedLi);\r\n selectedLi = $suggestionBox.find('li').size() - 1;\r\n select(selectedLi);\r\n } else {\r\n unselect(0);\r\n resetSelection();\r\n }\r\n\r\n if (scroll) {\r\n doScroll(selectedLi);\r\n }\r\n }\r\n\r\n /**\r\n * Redirects the user to the selected suggestion location\r\n */\r\n function goToSelection() {\r\n window.location = selectedHref;\r\n }\r\n\r\n /**\r\n * Makes an ajax call to the given url\r\n * @param url\r\n */\r\n function getSuggestions(url) {\r\n ajaxCalledVal = context.val();\r\n $.ajax({\r\n url: url,\r\n data: request,\r\n dataType: 'json',\r\n success: function (data) {\r\n\r\n var selectionHasChanged = true;\r\n var currentLi = selectedLi;\r\n\r\n if (jsonData.suggestions && data.suggestions) {\r\n selectionHasChanged = (JSON.stringify(jsonData.suggestions[selectedLi]) !== JSON.stringify(data.suggestions[selectedLi]))\r\n }\r\n\r\n setJsonData(data);\r\n showSuggestions();\r\n\r\n // Keep selection if no new information has been entered since ajax was called and the selection is the same.\r\n // This prevents the flick back effect when menu has the same data but the ajax hasn't finished.\r\n if (currentLi > -1 && (context.val() === ajaxCalledVal) && !selectionHasChanged) {\r\n selectedLi = currentLi;\r\n select(selectedLi);\r\n }\r\n\r\n if (options.hybrid) {\r\n urlClone = options.url;\r\n }\r\n\r\n options.ajaxSuccess(data);\r\n },\r\n error: function (e) {\r\n options.ajaxError(e);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Returns the index of the list item the mouse is currently hovering over\r\n * @param e\r\n * @returns {Number}\r\n */\r\n function getSelectionMouseIsOver(e) {\r\n var $parentLi = $(e.target).parents('li');\r\n return $parentLi.parent().children().index($parentLi);\r\n }\r\n\r\n /**\r\n * Sets the position of the suggestion box\r\n */\r\n function setSuggestionBoxPosition() {\r\n var borders = getCssValue(context, 'border-bottom-width') + getCssValue(context, 'border-top-width');\r\n var padding = getCssValue(context, 'padding-bottom') + getCssValue(context, 'padding-top');\r\n\r\n $suggestionBox.css({\r\n 'position': 'absolute',\r\n 'left': (context.offset().left) + options.leftOffset,\r\n 'top': (context.offset().top) + (context.height() + borders + padding + options.topOffset)\r\n });\r\n\r\n }\r\n\r\n /**\r\n * Gets the css integer value for the given element.\r\n * @param element\r\n * @param name\r\n * @returns {Number}\r\n */\r\n function getCssValue(element, name) {\r\n return parseInt(element.css(name).replace('px', ''));\r\n }\r\n\r\n /**\r\n * Hides the suggestion box\r\n */\r\n function hideSuggestionBox() {\r\n $suggestionBox.scrollTop(0);\r\n\r\n if (options.fadeOut) {\r\n $suggestionBox.fadeOut();\r\n } else {\r\n $suggestionBox.css('display', 'none');\r\n }\r\n resetSelection();\r\n\r\n if (options.adjustBorderRadius) {\r\n context.css('border-bottom-left-radius', searchBoxBorderRadius.bottomLeft);\r\n context.css('border-bottom-right-radius', searchBoxBorderRadius.bottomRight);\r\n }\r\n\r\n options.onHide()\r\n }\r\n\r\n /**\r\n * Displays the suggestion-box\r\n */\r\n function showSuggestionBox() {\r\n if (options.fadeIn) {\r\n $suggestionBox.fadeIn();\r\n } else {\r\n $suggestionBox.css('display', 'block');\r\n }\r\n\r\n if (options.adjustBorderRadius) {\r\n context.css('border-bottom-left-radius', 0);\r\n context.css('border-bottom-right-radius', 0);\r\n }\r\n\r\n options.onShow();\r\n\r\n }\r\n\r\n /**\r\n * Sets the width of the suggestion box\r\n */\r\n function setSuggestionBoxWidth() {\r\n var searchBoxWidth = getSearchBoxWidth() + options.widthAdjustment;\r\n if (options.menuWidth == 'auto') {\r\n $suggestionBox.css({\r\n 'min-width': searchBoxWidth\r\n });\r\n } else if (options.menuWidth == 'constrain') {\r\n $suggestionBox.css({\r\n 'width': searchBoxWidth\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Returns the width of the search box\r\n * @returns {number}\r\n */\r\n function getSearchBoxWidth() {\r\n return (\r\n context.width() +\r\n getCssValue(context, 'border-left-width') +\r\n getCssValue(context, 'border-right-width') +\r\n getCssValue(context, 'padding-left') +\r\n getCssValue(context, 'padding-right')\r\n );\r\n }\r\n\r\n /**\r\n * Builds the attributes from the JSON\r\n * @param value\r\n * @param attr\r\n * @returns {*}\r\n */\r\n function createAttributes(value, attr) {\r\n $.each(value.attr, function (key, value) {\r\n var keys = Object.keys(value);\r\n for (var i = 0; i < keys.length; i++) {\r\n attr += keys[i] + '=\"' + value[keys[i]] + '\" '\r\n }\r\n });\r\n return attr;\r\n }\r\n\r\n /**\r\n * Adds any given custom values from the JSON file\r\n * @param value\r\n * @param $suggestions\r\n * @returns {*}\r\n */\r\n function createCustomValues(value, $suggestions) {\r\n for (var i = 0; i < options.customData.length; i++) {\r\n var custom = value[options.customData[i]];\r\n if (custom) {\r\n $suggestions += value[options.customData[i]];\r\n }\r\n }\r\n\r\n return $suggestions;\r\n }\r\n\r\n /**\r\n * Builds the suggestions list from the JSON\r\n * @param data\r\n * @returns {string}\r\n */\r\n function createSuggestionsList(data) {\r\n\r\n var filterPattern = options.filterPattern.replace(\"{INPUT}\", context.val());\r\n\r\n var $suggestions = '