diff --git a/invenio/modules/search/static/js/.jshintrc b/invenio/modules/search/static/js/.jshintrc new file mode 100644 index 000000000..79148f1f6 --- /dev/null +++ b/invenio/modules/search/static/js/.jshintrc @@ -0,0 +1,4 @@ +{ + "asi": true, + "indent": 4 +} diff --git a/invenio/modules/search/static/js/search/form.js b/invenio/modules/search/static/js/search/form.js index d0b28cce5..736cd15c8 100644 --- a/invenio/modules/search/static/js/search/form.js +++ b/invenio/modules/search/static/js/search/form.js @@ -1,314 +1,315 @@ /* * This file is part of Invenio. * Copyright (C) 2014 CERN. * * Invenio is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Invenio is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Invenio; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ define(['jquery'], function($) { + "use strict"; $("form[name=search]").submit(function() { $('.add_to_search-form').remove() return true; // ensure form still submits }) var spanWidth = "100px" // side buttons for results number field $('form[name=settings] select[name="of"]').buttonSelect({ button: '
', span: '', next: '', prev: '' }) // side buttons for output format field $('form[name=settings] select[name="rg"]').buttonSelect({ button: '
', span: '', next: '', prev: '' }) // if (!("autofocus" in $("form[name=search] input[name=q]"))) { // // ensure we get the focus always in search input // $("form[name=search] input[name=q]").focus(); // } /** * Allows to deactivate a radio buttons (like check-buttons) * and make them behave as radio ones when the another one is clicked */ $(".invenio-collapsable-tabs a").each(function(elem) { $(elem).click(function (){ var buttons = $(this).siblings(); if (buttons.hasClass("active")) { buttons.click() } }) }) // ------------ typeahead for "Add to search" form ---------------- $('[data-provide="typeahead-url"]').each(function(index, elem) { var field = $(elem), source = field.data('source') var engine = new Bloodhound({ datumTokenizer: function(d) { return Bloodhound.tokenizers.whitespace(d.value) }, queryTokenizer: Bloodhound.tokenizers.whitespace, limit: 10, remote: { url: source, replace: function(url, query) { return url + '?q=' + query }, filter: function(response) { return response.results } } }) engine.initialize() field.typeahead( { minLength: 3 }, { source: engine.ttAdapter(), displayKey: 'value' } ) }) //--------------------- return function(form) { var operators = {'a': 'AND ', 'o': 'OR ', 'n': 'AND NOT '}, // the visible search field searchQueryField = $('form[name=search] input[name=p]'), // all fields containg search query, there are some hidden ones too allSearchQueryFields = $('[name=p]') /** * Sets value of the main search field. Should be used * instead of jQuery's val() to update typeahead's * internal query. * * @method setSearchFieldValue * @param {String} val value to be set */ function setSearchFieldValue(val) { searchQueryField.data('search_typeahead').setFieldValue(val) allSearchQueryFields.val(val) } /** * Merges value from 'advanced' tab in 'Add to search' form * with the current search query * * @method addAdvancedQuery * @returns {String} search query after adding the form content */ function getAdvancedQuery() { var m1 = $('[name=m1]').val(), p1 = $('[name=p1]').val(), f = $('[name=f]').val(), p = $('[name=p]') if (p1 === "") { return '' } if (f !== "") { f += ':' } return form.matchingTypes[m1](p1, f) } /** * Removes query value from 'what?' field in 'advanced' tab * * @method cleanAdvancedQuery */ function cleanAdvancedQueryForm() { $('[name=p1]').val('') } /** * Creates search query from 'simple' tab in 'Add to search' form * * @method getSimpleQuery * @returns {String} query from the form content * */ function getSimpleQuery() { var query_str = ''; // get values var p = $('[name=p]'), query = [], op1 = $('#add_type-btn-group .active').children(':first').val(), author = $('#author').val(), title = $('#title').val(), rn = $('#rn').val(), - aff = $('#aff').val() + aff = $('#aff').val(), cn = $('#cn').val(), k = $('#k').val(), //eprinttype = $('#eprint-type').val(), //eprintnumber = $('#eprint-number').val(), j = $('#journal-name').val(), jvol = $('#journal-vol').val(), - jpage = $('#journal-page').val(); + jpage = $('#journal-page').val() if (author !== '') { query.push('author:' + author) } if (title !== '') { query.push('title:' + title) } if (rn !== '') { query.push('reportnumber:' + rn) } if (aff !== '') { query.push('affiliation:' + aff) } if (cn !== '') { query.push('collaboration:' + cn) } if (k !== '') { query.push('keyword:' + k) } if (j !== '') { query.push('journal:' + j) } if (jvol !== '') { query.push('909C4v:' + jvol) } if (jpage !== '') { query.push('909C4c:' + jpage) } if (query.length > 0) { query_str = query.join(' ' + operators[op1]) } return query_str } /** * Adds query from 'advanced' tab to the search field * * @method addAdvancedQueryToSearch */ function addAdvancedQueryToSearch() { var current_query = $.trim(searchQueryField.val()); var new_part = getAdvancedQuery(); cleanAdvancedQueryForm(); setSearchFieldValue(mergeQuery(current_query, new_part)); } /** * Merges new part to old query using currently * chosen logic function * * @method mergeQuery * @param {String} old_query old query * @param {String} new_part a string which user is going to merge */ function mergeQuery(current_query, new_part) { var op1 = $('#add_type-btn-group .active').children(':first').val(), op = ''; if (op1 !== 'a' || current_query !== "") { op = operators[op1] } if (current_query + new_part !== "") { current_query += ' ' + op; } return current_query + new_part; } /** * Updates query value in the search field * * @method makeSearchQuery */ function makeSearchQuery() { var active_tab = $('.add_to_search-form .tab-buttons li.active a').attr('href'); if (active_tab === '#simple-search') { var current_query = $.trim(searchQueryField.val()) var new_part = getSimpleQuery() setSearchFieldValue(mergeQuery(current_query, new_part)) } else { addAdvancedQueryToSearch() $('.add_to_search-form .appender').trigger('click') } } // search buttons $('.add_to_search-form button[name=action_search]').on('click', function(e) { makeSearchQuery() e.stopPropagation() }) // browse buttons $('.add_to_search-form button[name=action_browse]').on('click', function(e) { makeSearchQuery() var $main_search_button = $('#searchform-input-group button[name=action_search]') $main_search_button.attr('name', 'action_browse') $main_search_button.trigger('click') }) $('#add_to_search-button').on('click', function(e) { addAdvancedQueryToSearch() return false }) $('.add_to_search-form #advanced-search [name=p1]').keypress(function(event) { // on 'return' key if ( event.which == 13 ) { addAdvancedQueryToSearch() return false } }) $('.add_to_search-form #advanced-search .appender').on('click', function(e) { var op1 = $('#add_type-btn-group .active').children(':first').val(), btn = $(this), source = $('[name=' + btn.data('source') + ']'), target = $('[name=' + btn.data('target') + ']'), val = $.trim(target.val()), - op = (op1=='a' && val=="") ? '' : operators[op1] + op = (op1 == 'a' && val === '') ? '' : operators[op1] - if (val !== "") { + if (val !== '') { val += ' ' + op } if (source.val().length > 0) { target.val(val + source.attr('name') + ':"' + source.val() + '"') source.val('') } e.stopPropagation() return false }) // -------------- SEARCH FIELD TYPEAHEAD ---------------- var areaKeywords = $.map(form.keywords, function(val, i) { return val[0] }) $('form[name=search] input[name=p]').searchTypeahead({ value_hints_url: form.hintsUrl, options_sets: { invenio: getDefaultParserConf(areaKeywords) }, default_set: form.defaultSet }) } }) diff --git a/invenio/modules/search/static/js/search/search.js b/invenio/modules/search/static/js/search/search.js index 246b176c3..c24ca9b51 100644 --- a/invenio/modules/search/static/js/search/search.js +++ b/invenio/modules/search/static/js/search/search.js @@ -1,308 +1,310 @@ /* * This file is part of Invenio. * Copyright (C) 2014 CERN. * * Invenio is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Invenio is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Invenio; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ define(function(require, exports, module) { + "use strict"; var $ = require('jquery') module.exports = function(facets) { // side facet list var facet_list = $(facets.elem) $('#overlay').modal({ keyboard: false, backdrop: 'static' }).modal('hide'); if (facet_list.length && typeof facets !== undefined) { var parent = facet_list.closest('.container, .row'), popupTimer facet_list.affix({ offset: { top: function () { - return parent.offset()['top'] + return parent.offset().top }, bottom: 170 } }) facet_list.facet({ button_builder: function(title) { return require('hgn!./templates/button')({ title: title }) }, row_builder: function(data, name) { var title = data[(data.length==3) ? 2 : 0], counter = data[1] return require('hgn!./templates/row')({ target: facets.elem, key: name, value: data[0], title: title, counter: counter }) }, box_builder: function(name, title) { return require('hgn!./templates/box')({ target: facets.elem, key: name, title: title }) }, facets: facets.data }).on('updated', function(event) { var p = $('#facet_filter input[name=p]').val(), facet = facet_list.data('facet') $('#search-box-main input[name=p]').val(p+' '+facet.queryString()); var filter = JSON.stringify(facet.filter), hash = decodeURIComponent(document.location.hash) if (filter != hash.substr(1)) { if (filter != '[]') { document.location.hash = encodeURIComponent(filter); } else { document.location.hash = ''; } } var showModal = true; var modalShow= function() { if (showModal) { $("#overlay").modal('show'); } }; setTimeout(modalShow, 100); $.ajax(facets.searchResultsUrl, { type: 'POST', data: $.extend({}, facets.args, {filter: filter}) }).done(function(data) { $('#search_results').html(data); showModal = false; $("#overlay").modal('hide'); }); }).on('loaded', function(event) { var typeahead = $('form[name=search] input[name=p]').data('typeahead'), facet = facet_list.data('facet') // Move out from library var expand = jQuery.grep(facet.filter, function (a) { return a[0] == '!' }) $.each(expand, function(i,v) { facet.$element.trigger($.Event('added', {op: v[0], key: v[1], value: v[2]})); }); $('[data-facet="toggle"]') .filter('[data-facet-key="'+event.name+'"]') .addClass('muted').each(function(i) { var toggle = $(this), filterContent = $.proxy(function() { return facets.labels.action + require('hgn!./templates/action')({ targe: facets.elem, key: this.data('facet-key'), value: this.data('facet-value'), title: facets.labels.exclude }) }, toggle) toggle.popover({ html: true, placement: 'right', trigger: 'manual', content: filterContent, title: facets.labels.didyouknow }).on('mouseenter', function() { if (popupTimer) { clearTimeout(popupTimer) } popupTimer = setTimeout(function() { toggle.popover('show') }, 2000) }).on('click', function() { if (popupTimer) { clearTimeout(popupTimer) } toggle.popover('hide') }).parent().on('mouseleave', function() { if (popupTimer) { clearTimeout(popupTimer) } toggle.popover('hide') }) }).on('click', function(event) { var $el_clicked = $(this), options = facet_list.data('facet').options if (!$el_clicked.hasClass('expandable') && $el_clicked.attr('data-facet-key') === 'collection') { if ($el_clicked.parent().has('ul')) { var $ul = $el_clicked.parent().find('ul') $ul.each(function(i, ul) { $(this).find('[data-facet="toggle"]').each(function() { facet_list.data('facet').delete('+', $(this).attr('data-facet-key'), $(this).attr('data-facet-value')) facet_list.data('facet').delete('-', $(this).attr('data-facet-key'), $(this).attr('data-facet-value')) }) }) if ($el_clicked.hasClass('text-info') || $el_clicked.hasClass('text-danger')) { $ul.remove() $el_clicked.addClass('expandable') facet_list.data('facet').filter = facet_list.data('facet').exclude('!', $(this).attr('data-facet-key'), $(this).attr('data-facet-value')) } } } }) // on hover add button in popover //$('[data-facet="reset-key"]').addClass('text-info') $('[data-facet="reset-key"]').each(function(e) { $(this).on('click', function() { $('[data-facet-key="'+ $(this).attr('data-facet-key') +'"]') .attr('data-facet-action', '+') .removeClass('text-danger') .removeClass('text-info') .css('font-weight', 'normal') $(this).removeClass('muted').addClass('text-info') }) }) $('#search_results').css('min-height', facet_list.height()) facet_list.affix('checkPosition'); // When we load data we should select facets from filter. if (facet.findByKey(event.name).length > 0) { facet.rebuildFilter(facet.filter) } }).on('deleted', function(event) { $('[data-facet-key="'+event.key+'"]') .filter('[data-facet-value="'+event.value+'"]') .each(function(e) { $(this) .removeClass('text-danger') .removeClass('text-info') .css('font-weight', 'normal') .attr('data-facet-action', '+') }) var resetKey = false try { - if ($(this).data('facet').findByKey(event.key).length == 0) { + if ($(this).data('facet').findByKey(event.key).length === 0) { resetKey = true } } catch(err) { resetKey = true } if (resetKey) { $('[data-facet="reset-key"]') .filter('[data-facet-key="'+event.key+'"]') .addClass('text-info') } }).on('added', function(event) { - var type = (event.op == '+')?'info':'error' - , other_type = (event.op == '-')?'info':'error' + var type = (event.op == '+')?'info':'error', + other_type = (event.op == '-')?'info':'error' + $('[data-facet-key="'+event.key+'"]') .filter('[data-facet-value="'+event.value+'"]') .each(function(e) { if (event.op != '!') { $(this) .removeClass('text-'+other_type) .addClass('text-'+type) .css('font-weight', 'bold') } }) .filter('.expandable') .each(function() { var $el_clicked = $(this), - options = facet_list.data('facet').options + options = facet_list.data('facet').options $el_clicked.removeClass('expandable') if (event.key === 'collection') { $(this).parent().find('ul').remove() - var facet = {url: options.url_map[event.key] - , facet: event.key} - , data = {parent: event.value} - , $ul = $('
      ').clone().appendTo($el_clicked.parent()) + var facet = {url: options.url_map[event.key], + facet: event.key}, + data = {parent: event.value}, + $ul = $('
          ').clone().appendTo($el_clicked.parent()) var data_facet = facet_list.data('facet') - if (data_facet.find('!', event.key, event.value).length == 0) { + if (data_facet.find('!', event.key, event.value).length === 0) { data_facet.filter.push(['!', event.key, event.value]) } data_facet.createFacetBox(facet, $ul, data) } }) $('[data-facet="reset-key"]') .filter('[data-facet-key="'+event.key+'"]') .removeClass('text-info') .addClass('muted') }).on('exists', function(event) { alert(facets.labels.alreadyin); }); // Rebuild facet filter on hash change. $(window).bind('hashchange', function() { var hash = decodeURIComponent(document.location.hash), hash_filter = hash.substr(1), filter; try { filter = $.parseJSON(hash_filter) } catch (exc) { console.exception(exc) } if (typeof JSON === undefined || JSON.stringify(facet_list.data('facet').filter) != hash_filter) { facet_list.data('facet').rebuildFilter(filter || []) } }) // Parse hash URI component. if (document.location.hash.length > 2) { var hash = decodeURIComponent(document.location.hash), hash_filter = hash.substr(1), filter try { filter = $.parseJSON(hash_filter) } catch (exc) { console.exception(exc) } facet_list.data('facet').filter = filter || [] } } } })