Теперь я решил это следующим образом:
index.html.erb
<div class = "index-body">
<%= link_to 'home', root_path, id: 'home', hidden: true %>
<div class = "search-bar">
<input class = "search-input" type="text"
placeholder="Search..."
id = "search-input">
</div>
<div id = 'slots-container'>
<div class = 'slots-container' id = 'slots'>
<%= render @slots %>
<%= will_paginate @slots, hidden: true,id: "paginate" %>
</div>
</div>
</div>
index.js.erb
@identical_search
указывает, что последний результат поиска совпадает с текущим, поэтому ничего не делать
<% unless @identical_search %>
if (dirty) {
dirty = false;
$('#slots').empty();
}
$('#slots').append('<%= j render @slots %>');
<% if @slots.next_page %>
if(document.getElementById("paginate") === null)
$('#slots').append('<%= j will_paginate @slots, hidden: true, id: "paginate" %>');
$('#paginate').replaceWith('<%= j will_paginate @slots, hidden: true, id: "paginate" %>');
<% else %>
$('#paginate').remove();
<% end %>
<% end %>
main.js
var documentLoaded = false;
var dirty = false;
var pending = false;
var loadSearchTimer = null;
$( document ).on('turbolinks:load', function() {
...
documentLoaded = true;
document.getElementById("search-input").addEventListener("input", startTimerForUserInput);
})
...
function startTimerForUserInput(){
if (loadSearchTimer !==null)
clearTimeout(loadSearchTimer);
loadSearchTimer = setTimeout(loadSearch, 300);
}
function loadSearch(){
if (documentLoaded){
documentLoaded = false;
dirty=true;
var search_input = document.getElementById("search-input");
var search_for = search_input.value;
var root_page = $('#home').attr('href');
if(search_for && search_for !== '')
root_page += "?search_for=" + search_for;
$.getScript(root_page).done(function() {
$("img").lazyload();
documentLoaded = true;
if(pending){
pending = false;
loadSearch();
}
});
}
else
pending = true;
}
В main.js
Я использую таймер для поиска только через 300 мс после последнего пользовательского ввода, чтобы ограничить вызовы, чтобы он не осуществлял поиск после каждого ввода.Когда getScript
возвращает success
, я проверяю, был ли отправлен запрос на поиск, в то время как текущий запрос обрабатывался для отправки нового запроса с помощью переменной pending
.
dirty
устанавливается в значение true, когдапользовательский поиск, так что index.js.erb
знает, чтобы очистить div, содержащий элементы.
Это проходит гладко, и мне нравится, как это.
Я надеюсь, что это поможет кому-то в будущем...
Если это помогает понять всю картину целиком, вот контроллер:
class SlotsController < ApplicationController
require 'will_paginate/array'
@@last_search_content = nil
def index
@identical_search = false
@hashtags = Hashtag.all
if params[:search_for]
search_str = params[:search_for].gsub(/\s\s+/, ' ').strip
@slots = Slot.where("LOWER(slot_name) LIKE LOWER('%#{search_str}%') ")
if @@last_search_content.to_set == @slots.to_set && (params[:page] == nil || params[:page] == 1)
@identical_search = true
end
elsif params[:hashtags]
@slots = slotsWithAtLeastOneOfThose(params[:hashtags])
else
@slots = Slot.all
end
@@last_search_content = @slots
unless @identical_search
@slots = @slots.paginate(page: params[:page])
end
respond_to do |format|
format.html
format.js
end
end
def show
@slot = Slot.find(params[:id])
end
private
def slotsWithAtLeastOneOfThose(hashtags)
slots=[]
hashtags.split(' ').each do |h|
slots += Slot.joins(:hashtags).where("hashtags.value LIKE ?", "%#{h}%")
end
return slots.uniq
end
end