app/assets/javascripts/umlaut/search_autocomplete.js in umlaut-3.0.5 vs app/assets/javascripts/umlaut/search_autocomplete.js in umlaut-3.1.0.pre1

- old
+ new

@@ -1,46 +1,105 @@ /* search_autocomplete.js. Add autocomplete to Umlaut journal title search. */ jQuery(document).ready(function($) { - - $(document).on("submit", "form.OpenURL", function() { - var form = $(this); - if ( form.find(".rft_title").val() != $(this).val()) { - form.find(".rft_object_id").val(""); - form.find(".rft_title").val(""); - } - }); - - $("input.title_search").autocomplete({ - minLength: 3, - source: function(request, response) { - var form = $(this.element).closest("form"); - $.ajax({ - url: form.attr("action").replace("journal_search", "auto_complete_for_journal_title"), - dataType: "json", - data: form.serialize(), - success: function(data) { - response($.map(data, function(item) { - return { - label: item.title, - id: item.object_id - } - })); - } - }); - }, - select: function(event, ui) { - var form = $(event.target).closest("form"); - - form.find("input.rft_object_id").val(ui.item.id); - form.find("input.rft_title").val( ui.item.label ); - form.find("select.sfx_title_search").val("exact"); - } - }); - -}); -/* select: function(event, ui) { - log(ui.item ? ("Selected: " + ui.item.value + ", geonameId: " + ui.item.id) : "Nothing selected, input was " + this.value); - } - }); -*/ + // We override typeahead's 'render' function to NOT have the first + // item selected. We simply copy and pasted it, and removed the line + // `items.first().addClass('active')`, then set the prototype to our + // own function. Yes, this changes typeahead globally, sorry we don't have + // a way to change it just for certain typeaheads. + // + // The default first-item-selected behavior has been hated by users + // in the journal search scenario, since when they hit return they + // get it even if they didn't want it. + var newRender = function(items) { + var that = this + + items = $(items).map(function (i, item) { + i = $(that.options.item).attr('data-value', item) + i.find('a').html(that.highlighter(item)) + return i[0] + }) + + this.$menu.html(items) + return this + }; + $.fn.typeahead.Constructor.prototype.render = newRender; + // have to fix 'select' to accomodate possible no selection too + $.fn.typeahead.Constructor.prototype.select = function() { + var val = this.$menu.find('.active').attr('data-value'); + if (val) { + this.$element + .val(this.updater(val)) + .change(); + } + return this.hide() + } + + $(document).on("submit", "form.OpenURL", function() { + var form = $(this); + if ( form.find(".rft_title").val() != $(this).val()) { + form.find(".rft_object_id").val(""); + form.find(".rft_title").val(""); + } + }); + + // Search for the title with the current form. Only search + // if there are more than two chars though! + // + var search_title = function(query, process) { + if (query.length > 2) { + var form = this.$element.closest("form"); + var url = form.attr("action").replace("journal_search", "auto_complete_for_journal_title"); + // Get JSON from + $.getJSON( + form.attr("action").replace("journal_search", "auto_complete_for_journal_title"), + form.serialize(), + function(data) { + process(data) + } + ) + } + } + + + var lookup_limit = 300; //ms + // Uses a timer to only do a lookup at most once every + // 300ms . Based on rejected pull request at: + // https://github.com/twitter/bootstrap/pull/6320 + var throttled_search_title = function(query, process) { + if(this.lookupTimer) { + clearTimeout(this.lookupTimer); + } + + this.lookupTimer = setTimeout($.proxy(search_title, this, query, process), lookup_limit); + return this; + } + + $("input.title_search").typeahead({ + items: 10, + minLength: 3, + source: throttled_search_title, + highlighter: function(item) { + // Bootstrap updates the item as it passes through the callback chain + // so this is a hack to ensure we get the proper values. + return "<span id=\"" + item.object_id + "\" class=\"title\">"+ item.title + "</span>"; + }, + sorter: function(items) { return items }, + matcher: function(item) { return true; }, + updater: function(item) { + // Get the selected item via our hack. + var selected_item = this.$menu.find('.active .title'); + if (selected_item.length > 0) { + // We set the id attribute as the object id + var object_id = selected_item.attr("id"); + // We set the inner text with the title + var title = selected_item.text(); + var form = this.$element.closest("form"); + form.find("input.rft_object_id").val(object_id); + form.find("input.rft_title").val(title); + form.find("select.title_search_type").val("exact"); + return title; + } + } + }); +}); \ No newline at end of file