/** Copyright 2014 Red Hat, Inc. This software is licensed to you under the GNU General Public License as published by the Free Software Foundation; either version 2 of the License (GPLv2) or (at your option) any later version. There is NO WARRANTY for this software, express or implied, including the implied warranties of MERCHANTABILITY, NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 along with this software; if not, see http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. */ KT.favorite = function(form, input) { var success = function(data) { form.find(".qdropdown").html(data); // process the elements of the list and truncate any that are too long with ellipsis (...) (e.g. jquery.text-overflow.js) $(".one-line-ellipsis").trunk8({lines: 1}); }, error = function(data) { }, save = function(event) { // we want to submit the request using Ajax (prevent page refresh) event.preventDefault(); var newFavorite = form.find('input').attr('value'); var url = $(this).attr('data-url'); // send a request to the server to save/create this favorite $.ajax({ type: "POST", url: url, data: {"favorite": newFavorite}, cache: false, success: success, error: error }); }, destroy = function (data) { var id = $(this).attr('data-id'); var url = $(this).attr('data-url'); // send a request to the server to save/create this favorite client_common.destroy(url, success, error); }, clear = function(data){ var search_input = form.find('input'); search_input.val(''); search_input.change(); form.find('.qdropdown').hide(); }; return { save: save, destroy: destroy, clear: clear }; }; /** * * @param input_id id of the search input * @param list_id id of the list * @param list_module module that provides the following api: * replace_list(html, args) //insert a new list * append(html) //append new data to the list * update_counts(current, total, results, clear) //update counts * full_spinner() //clear list and show full list spinner (for full list reload/search) * current_count() //returns # of items in list (used for offset) * * @param params list of options: * disable_fancy - disable fancy queries * * @param extra_params list of extra parameters to pass along with search */ KT.search = function(form_id, list_id, list_module, params, extra_params){ var form = $('#' + form_id), input = form.find('input'), list_elem = $('#' + list_id), url = params.url, search_key = "_search", search_hash = list_id + search_key, event_name = list_id + ".search", extend_event_name = list_id + ".search.extend", url_param = "search", favorite = KT.favorite(form, input), current_search = {}, retrievingNewContent = false, trigger_name = params.trigger || "hashchange", //custom event to trigger search init = function(){ $(window).scroll(extend); $(window).bind(trigger_name, hash_change); if (!params.disable_fancy) { form.fancyQueries(); } setupSearch(); //TODO make these classes form.delegate('#search_favorite_save', "click", favorite.save); form.delegate('#search_favorite_destroy', "click", favorite.destroy); form.delegate('#search_clear', "click", favorite.clear); form.delegate('.search_query', 'click', function(){ input.val($(this).html()); form.find('button').click(); form.find('.qdropdown').hide(); }); reset_current_search(); }, search_bbq = function(){ return search_hash; }, search_event = function(){ return event_name; }, extend_event = function(){ return extend_event_name; }, hash_change = function(event, args){ if (url){ start_search(args); } }, set_url = function(url_in){ if (url !== url_in){ reset_current_search(); url = url_in; } }, reset_current_search = function(){ current_search = {}; current_search[search_hash] = null; }, refresh_search = function() { reset_current_search(); start_search({}); }, setupSearch = function() { var button = form.find('button'); button.click(function(){ var value = input.val(); if( button.attr('disabled') !== "disabled" ){ if( value === "" ){ $.bbq.removeState(search_hash); } else { var obj = {}; obj[search_hash] = value; $.bbq.pushState(obj); } } }); input.live('change', function(){ if( $(this).val() === "" ){ $.bbq.removeState(search_hash); } }).live('keypress', function(event){ if( event.keyCode === 13 ){ event.preventDefault(); button.click(); return false; } }); form.live('submit', function(e){ e.preventDefault(); start_search(); }); }, start_search = function(args){ var button = form.find('button'), data = get_params(), search_val = $.bbq.getState(search_hash), event = $.Deferred(), pre_state, params_changed = function(){ var changed = KT.utils.all(current_search, function(item, index){ return item === $.bbq.getState(index); }); return !changed; }; if (params.pre_search_state){ pre_state = params.pre_search_state(); } //search already in process, or already searched for if ( !params_changed() ){ $(document).trigger(event_name); return; } current_search[search_hash] = search_val; input.val(search_val); $(document).trigger(event_name, [event.promise()]); list_module.full_spinner(); button.attr("disabled", "disabled"); if(search_val) { data[url_param] = search_val; } if (extra_params) { $.each(extra_params, function(index, item){ var item_id = item['hash_id']; data[item_id] = $.bbq.getState(item_id); current_search[item_id] = $.bbq.getState(item_id); }); } $.ajax({ url: url, data: data, cache: false, success: function (data) { var to_append = data.html ? data.html : data; list_module.replace_list(to_append, pre_state); button.removeAttr('disabled'); list_module.update_counts(data['current_items'], data['total_items'], data['results_count'], true, pre_state); $('.ui-autocomplete').hide(); list_elem.addClass("ajaxScroll"); event.resolve(); }, error: function (e) { button.removeAttr('disabled'); event.fail(); } }); }, get_params = function(){ return KT.panel.queryParameters(); }, extend = function(){ var offset = list_module.current_count(), page_size = list_elem.attr("data-page_size"), search, pre_state = params.pre_search_state ? params.pre_search_state() : undefined, ajax_params = { "offset": offset }, expand_list = list_elem.hasClass("expand_list") ? list_elem : list_elem.find(".expand_list"); if ($.bbq) { search = $.bbq.getState(search_hash); } if (!url) { return; } if (list_elem.hasClass("ajaxScroll") && !retrievingNewContent && KT.common.scrollTop() >= ($(document).height() - $(window).height()) - 700) { retrievingNewContent = true; if (parseInt(page_size, 10) > parseInt(offset, 10)) { return; //If we have fewer items than the pagesize, don't try to fetch anything else } $.extend(ajax_params, get_params()); if (search) { $.extend(ajax_params, {search:search}); } expand_list.append('<div class="list-spinner"> <img src="' + KT.common.spinner_path() + '" class="ajax_scroll"> </div>'); $.ajax({ type: "GET", url: url, data: ajax_params, cache: false, success: function (data) { retrievingNewContent = false; expand_list.find('.list-spinner').remove(); list_module.append(data['html'], pre_state); if (data['current_items'] + offset >= data["total_items"]) { list_elem.removeClass("ajaxScroll"); } list_module.update_counts(data['current_items'], 0, 0); $(window).trigger(extend_event_name); }, error: function () { expand_list.find('.list-spinner').remove(); retrievingNewContent = false; } }); } }, enableAutoComplete = function(params){ var url = params['url'], data = params['data'], request_issued = false, getAutoCompleteData; if(url) { getAutoCompleteData = function(request, response){ if( !request_issued ){ request_issued = true; $.getJSON(url, { search : request.term }, function(json){ request_issued = false; response(json); }) .error(function(){ request_issued = false; }); } }; } else { getAutoCompleteData = data; } autocomplete_override(); input.catcomplete({ source : getAutoCompleteData, minLength: 0, delay : 200, search : function(event, ui) { $(".auto_complete_clear").hide(); }, open : function(event, ui) { $(".auto_complete_clear").show(); } }); input.focus(function( event ) { if( $( this )[0].value === "" ) { $( this ).catcomplete( "search" ); } }); }, autocomplete_override = function(){ $.widget( "custom.catcomplete", $.ui.autocomplete, { _renderMenu: function( ul, items ) { var self = this, currentCategory = ""; $.each( items, function( index, item ) { if ( item.category !== undefined && item.category !== currentCategory ) { ul.append( "<li class='ui-autocomplete-category'>" + item.category + "</li>" ); currentCategory = item.category; } if ( item.error !== undefined ) { ul.append( "<li class='ui-autocomplete-error'>" + item.error + "</li>" ); } if( item.completed !== undefined ) { $( "<li></li>" ).data( "item.autocomplete", item ) .append( "<a>" + "<strong class='ui-autocomplete-completed'>" + item.completed + "</strong>" + item.part + "</a>" ) .appendTo( ul ); } else { self._renderItem( ul, item ); } }); } }); }; init(); return { enableAutoComplete : enableAutoComplete, search_event : search_event, extend_event : extend_event, search_bbq : search_bbq, set_url : set_url, refresh_search : refresh_search }; };