diff --git a/app/assets/stylesheets/basic/orbit_bar.css.erb b/app/assets/stylesheets/basic/orbit_bar.css.erb index c381c4d..290f61f 100644 --- a/app/assets/stylesheets/basic/orbit_bar.css.erb +++ b/app/assets/stylesheets/basic/orbit_bar.css.erb @@ -125,8 +125,8 @@ top: 14px; } #orbit-bar #search .icon-search { - left: 13px; - top: 15px; + left: 20px; + top: 12px; font-size: 1.2em; } #orbit-bar #search .search-clear { @@ -138,11 +138,114 @@ 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{ + min-height: 10px; + padding: 5px 25px 5px 10px; + border-top: 1px solid #DDD; + border-bottom: 1px solid #CCC; + color: #666; + background: #EEE; +} + +#search_footer .pagination{ + margin: 0; +} + +#search_footer .pagination ul li a{ + padding: 4px 10px; + color: #0053CF; +} + +#search_results{ + max-height: 500px; + overflow-y: auto; + overflow-x: hidden; +} +#search_results img{ + margin: 20px auto; + display: block; +} +#search_results::-webkit-scrollbar { + width: 8px; + background: #CCC; +} + +#search_results::-webkit-scrollbar-track { +} + +#search_results::-webkit-scrollbar-thumb { + background: #888; +} + +#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 a{ + width: 100%; +} + +.search_result b{ + font-weight: normal; + color: #B90000; +} + /*User info*/ #orbit-bar #orbit-user .user-pic { width: 40px; height: 40px; - margin: -12px 10px -10px -15px; + margin: -13px 10px -10px -15px; } /*Language & flag*/ diff --git a/app/controllers/site_search_controller.rb b/app/controllers/site_search_controller.rb new file mode 100644 index 0000000..7d21359 --- /dev/null +++ b/app/controllers/site_search_controller.rb @@ -0,0 +1,89 @@ +class SiteSearchController < ApplicationController + include ActionView::Helpers::TextHelper + 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] + key_string = key_string.strip.nil? ? key_string : key_string.strip + 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 rescue nil + next if title.nil? and context.nil? + + context = context.gsub(/<\/?[^>]*>/, "").gsub(/ /i,"") rescue "" + title_matches = title.match(regex) + context_matches = context.match(regex) + if title_matches or context_matches + tmp = {} + tmp[:id] = page.id + tmp[:module] = "page" + tmp[:url] = "/"+page.path + tmp[:title] = title + tmp[:content] = context + 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.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 = ActionView::Base.full_sanitizer.sanitize(eval("r.#{f}")) rescue "" + value = value.nil? ? "" : value + + if f=="title" or f=="name" + tmp[:title] = value + else + tmp[:content] << value + end + end + + result.push(tmp) + end + end + end + + result.each do |res| + res[:matches] = 0 + + res[:matches] += res[:title].match(/(#{key_string})/i) ? 500 : 0 rescue 0 + res[:matches] += res[:content].match(/(#{key_string})/i) ? 300 : 0 rescue 0 + + keywords.each do |k| + res[:matches] += (res[:title].scan(/(#{k})/i).size)*100 + res[:content].scan(/(#{k})/i).size + res[:title].gsub!(/(#{k})/i, '\1') rescue "" + res[:content].gsub!(/(#{k})/i, '\1') rescue "" + end + + if res[:matches]==0 + result = result - [res] + next + end + + res[:content] = truncate(res[:content], length: 120) + end + + result = result.sort_by { |k| k[:matches] }.reverse rescue [] + + render :json => { "results" => result, "time"=> ((Time.now-startTime)*1000).to_i , "keywords"=>keywords} + end + +end \ No newline at end of file diff --git a/app/views/layouts/_search.erb b/app/views/layouts/_search.erb new file mode 100644 index 0000000..c6381fc --- /dev/null +++ b/app/views/layouts/_search.erb @@ -0,0 +1,120 @@ +