Search Engine
This commit is contained in:
parent
c0105e7cb8
commit
4482fa50eb
|
@ -125,8 +125,8 @@
|
||||||
top: 14px;
|
top: 14px;
|
||||||
}
|
}
|
||||||
#orbit-bar #search .icon-search {
|
#orbit-bar #search .icon-search {
|
||||||
left: 13px;
|
left: 20px;
|
||||||
top: 15px;
|
top: 12px;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
#orbit-bar #search .search-clear {
|
#orbit-bar #search .search-clear {
|
||||||
|
@ -138,11 +138,103 @@
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*Search Container*/
|
||||||
|
#search_container{
|
||||||
|
display: none;
|
||||||
|
top: 40px;
|
||||||
|
right: 20px;
|
||||||
|
width: 40%;
|
||||||
|
background: #FAFAFA;
|
||||||
|
position: absolute;
|
||||||
|
box-shadow: 0px 5px 20px #666;
|
||||||
|
color: #666;
|
||||||
|
font-family: "微軟正黑體", "Raleway";
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_head{
|
||||||
|
text-align: right;
|
||||||
|
padding: 5px 25px 5px 10px;
|
||||||
|
/*border-bottom: 1px solid #CCC;*/
|
||||||
|
color: #666;
|
||||||
|
/*background: #EEE;*/
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_loading{
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_footer{
|
||||||
|
height: 10px;
|
||||||
|
padding: 5px 25px 5px 10px;
|
||||||
|
border-bottom: 1px solid #CCC;
|
||||||
|
color: #666;
|
||||||
|
/*background: #DDD;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_results{
|
||||||
|
max-height: 500px;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_results::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
background: #CCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_results::-webkit-scrollbar-track {
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_results::-webkit-scrollbar-thumb {
|
||||||
|
background: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_results a{
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_results a:hover{
|
||||||
|
text-decoration: none;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.seach_title{
|
||||||
|
padding: 5px 0;
|
||||||
|
color: #0053CF;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search_result{
|
||||||
|
padding: 15px 15px;
|
||||||
|
/*border-bottom: 1px solid #DDD;
|
||||||
|
border-top: 1px solid #FFF;*/
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search_result:hover{
|
||||||
|
background: #FFF;
|
||||||
|
box-shadow: 0px 0px 20px #DDD;
|
||||||
|
/*border-bottom: 1px solid #FFF;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.search_result h5{
|
||||||
|
}
|
||||||
|
|
||||||
|
.search_result strong{
|
||||||
|
/*font-weight: bold;*/
|
||||||
|
color: #B90000;
|
||||||
|
}
|
||||||
|
|
||||||
/*User info*/
|
/*User info*/
|
||||||
#orbit-bar #orbit-user .user-pic {
|
#orbit-bar #orbit-user .user-pic {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
margin: -12px 10px -10px -15px;
|
margin: -13px 10px -10px -15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Language & flag*/
|
/*Language & flag*/
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
class SiteSearchController < ApplicationController
|
||||||
|
|
||||||
|
def search
|
||||||
|
startTime = Time.now
|
||||||
|
if params[:keywords].present?
|
||||||
|
modules = [
|
||||||
|
{:key=>"announcement", :model=>"Bulletin", :fields=>["title","subtitle","text"], :url=>"/panel/announcement/front_end/bulletin/"}
|
||||||
|
]
|
||||||
|
|
||||||
|
key_string = params[:keywords]
|
||||||
|
keywords = key_string.split(/\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/)
|
||||||
|
regex = Regexp.union(keywords.map{|word| Regexp.new(".*"+word+".*", "i")})
|
||||||
|
|
||||||
|
result = []
|
||||||
|
|
||||||
|
# Search Pages
|
||||||
|
Item.where(:app_frontend_url=>"page_contexts", :is_published=>true).each do |page|
|
||||||
|
title = page.title
|
||||||
|
context = PageContext.where(:page_id=>page.id).first.context
|
||||||
|
context = ActionController::Base.helpers.strip_tags(context).gsub(/ /i," ") rescue ""
|
||||||
|
title_matches = title.scan(regex).size
|
||||||
|
context_matches = context.scan(regex).size rescue 0
|
||||||
|
if title_matches > 0 or context_matches > 0
|
||||||
|
tmp = {}
|
||||||
|
tmp[:id] = page.id
|
||||||
|
tmp[:module] = "page"
|
||||||
|
tmp[:url] = "/"+page.path
|
||||||
|
tmp[:title] = hight_light(keywords, title)
|
||||||
|
tmp[:content] = hight_light(keywords, context, true)
|
||||||
|
tmp[:matches] = title_matches+context_matches
|
||||||
|
tmp[:matches] += title.scan(Regexp.new(".*"+key_string+".*", "i")).size > 0 ? 20 : 0 rescue 0
|
||||||
|
tmp[:matches] += context.scan(Regexp.new(".*"+key_string+".*", "i")).size > 0 ? 20 : 0 rescue 0
|
||||||
|
result.push(tmp)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Search Modules
|
||||||
|
modules.each do |mod|
|
||||||
|
query = mod[:fields].map{|f| {f.to_sym => regex} }
|
||||||
|
res = Kernel.const_get(mod[:model]).any_of(query)
|
||||||
|
res.all.each do |r|
|
||||||
|
tmp = {}
|
||||||
|
tmp[:id] = r.id
|
||||||
|
tmp[:module] = mod[:key]
|
||||||
|
tmp[:url] = mod[:url]+r.id.to_s
|
||||||
|
tmp[:content] = ""
|
||||||
|
tmp[:matches] = 0
|
||||||
|
mod[:fields].each do |f|
|
||||||
|
value = ActionController::Base.helpers.strip_tags(eval("r.#{f}")).gsub(/ /i,"")
|
||||||
|
|
||||||
|
if f=="title" or f=="name"
|
||||||
|
tmp[:title] = value
|
||||||
|
else
|
||||||
|
tmp[:content] << value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
tmp[:matches] = tmp[:content].scan(regex).size + tmp[:title].scan(regex).size
|
||||||
|
tmp[:matches] += tmp[:title].scan(Regexp.new(".*"+key_string+".*", "i")).size > 0 ? 20 : 0 rescue 0
|
||||||
|
tmp[:matches] += tmp[:content].scan(Regexp.new(".*"+key_string+".*", "i")).size > 0 ? 20 : 0 rescue 0
|
||||||
|
|
||||||
|
tmp[:title] = hight_light(keywords, tmp[:title])
|
||||||
|
tmp[:content] = hight_light(keywords, tmp[:content], true)
|
||||||
|
|
||||||
|
result.push(tmp) unless tmp[:matches]==0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
result = result.sort_by { |k| k[:matches] }.reverse rescue []
|
||||||
|
render :json => { "results" => result, "time"=> ((Time.now-startTime)*1000).to_i , "keywords"=>keywords}
|
||||||
|
end
|
||||||
|
|
||||||
|
def hight_light(keywords, content, filter=false)
|
||||||
|
matches = 0
|
||||||
|
keywords.each do |k|
|
||||||
|
matches += content.scan(/(#{k})/i).size
|
||||||
|
content.gsub!(/(#{k})/i, '<strong>\1</strong>') rescue ""
|
||||||
|
end
|
||||||
|
|
||||||
|
if filter
|
||||||
|
index = content.index '<strong>'
|
||||||
|
unless index.nil?
|
||||||
|
index = index>50 ? index-50 : 0
|
||||||
|
deadline = 150
|
||||||
|
content = content[index, deadline]
|
||||||
|
else
|
||||||
|
content = content[0, 100]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return content
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -1,7 +1,7 @@
|
||||||
<header id="orbit-bar" class="orbit-bar navbar">
|
<header id="orbit-bar" class="orbit-bar navbar">
|
||||||
|
<%= render "layouts/search" %>
|
||||||
<div class="navbar-inner">
|
<div class="navbar-inner">
|
||||||
<%= render "layouts/left_menu" %>
|
<%= render "layouts/left_menu" %>
|
||||||
<%= render "layouts/right_menu" %>
|
<%= render "layouts/right_menu" %>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
@ -2,14 +2,8 @@
|
||||||
|
|
||||||
<!-- search -->
|
<!-- search -->
|
||||||
<li id="search" class="searchClear">
|
<li id="search" class="searchClear">
|
||||||
<form method="get" action="http://www.google.com/custom">
|
<form id="search_form" method="get" action="/site_search">
|
||||||
<input type="hidden" name="client" value="pub-&" />
|
<%= text_field_tag 'q','', {:class => "search-query input-medium", :placeholder => "Search", 'x-webkit-speech' => ''} %>
|
||||||
<input type="hidden" name="ie" id="ie" value="utf-8" />
|
|
||||||
<input type="hidden" name="oe" id="oe" value="utf-8" />
|
|
||||||
<input type="hidden" name="cof" id="cof" value="AH:center;AWFID:03de271f1940eea3;" />
|
|
||||||
<input type='hidden' name='domains' value='<%= @site.search["domains"] rescue ''%>'>
|
|
||||||
<input type='hidden' name='sitesearch' value='<%= @site.search["sitesearch"] rescue '' %>'>
|
|
||||||
<%= text_field_tag 'q','', {:class => "search-query input-medium", :placeholder => t(:search_google), 'x-webkit-speech' => ''} %>
|
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
<div id="search_container">
|
||||||
|
<div id='search_head'>
|
||||||
|
<button type="button" id="search_close" class="close pull-left">×</button>
|
||||||
|
<div id='search_time'></div>
|
||||||
|
</div>
|
||||||
|
<div id='search_results'></div>
|
||||||
|
<div id='search_footer'></div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
var interval = 0;
|
||||||
|
var keyword;
|
||||||
|
var processLock=false;
|
||||||
|
|
||||||
|
$("#q").keyup(function(){queueSearch();});
|
||||||
|
$("#search_form").submit(function(){queueSearch(); return false; });
|
||||||
|
|
||||||
|
function queueSearch(){
|
||||||
|
if($("#q").val() != keyword && $("#q").val()!=""){
|
||||||
|
keyword = $("#q").val();
|
||||||
|
interval=500;
|
||||||
|
if(!processLock) processSearch();
|
||||||
|
}else if($("#q").val()==""){
|
||||||
|
keyword = ""
|
||||||
|
$("#search_container").fadeOut(300);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#search_close").click(function(){$("#search_container").fadeOut(300);});
|
||||||
|
|
||||||
|
function processSearch(){
|
||||||
|
processLock = true;
|
||||||
|
if(interval==0 && keyword!=""){
|
||||||
|
$.getJSON("/site_search?keywords="+keyword, function(data){
|
||||||
|
$("#search_results").scrollTop(0);
|
||||||
|
$("#search_results").html("");
|
||||||
|
$("#search_time").html("Found "+data.results.length+" Results, Search Time: "+data.time+"ms");
|
||||||
|
$.each(data.results,function(key,res){
|
||||||
|
search_result =
|
||||||
|
"<div class='search_result'>"+
|
||||||
|
"<a href='"+res.url+"' target='_blank'>"+
|
||||||
|
"<div class='seach_title'>"+res.title+"</div>"+
|
||||||
|
"</a><br/>"+
|
||||||
|
"<span>"+res.content+"</span>"+
|
||||||
|
"</div>";
|
||||||
|
$("#search_results").append(search_result);
|
||||||
|
});
|
||||||
|
$("#search_container").fadeIn(300);
|
||||||
|
processLock = false;
|
||||||
|
});
|
||||||
|
}else if(interval>0){
|
||||||
|
interval -= 100;
|
||||||
|
setTimeout(processSearch,100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -25,6 +25,9 @@ Orbit::Application.routes.draw do
|
||||||
get 'basic_infos/confirmation' => "basic_infos#confirmation"
|
get 'basic_infos/confirmation' => "basic_infos#confirmation"
|
||||||
post 'basic_infos/role_update' => "basic_infos#role_update"
|
post 'basic_infos/role_update' => "basic_infos#role_update"
|
||||||
match 'basic_infos/basic_info_update' => "basic_infos#basic_info_update"
|
match 'basic_infos/basic_info_update' => "basic_infos#basic_info_update"
|
||||||
|
|
||||||
|
get "site_search" => "site_search#search"
|
||||||
|
|
||||||
# routes for admin
|
# routes for admin
|
||||||
namespace :admin do
|
namespace :admin do
|
||||||
match 'user_actions' => 'user_actions#index'
|
match 'user_actions' => 'user_actions#index'
|
||||||
|
|
Loading…
Reference in New Issue