Commit dad628a9875934c8d18f27efb6e4f59b94237aa0

Authored by Braulio Bhavamitra
1 parent 4ef7f762

Refactor search ordering, boost, indexing and CSS

app/controllers/public/search_controller.rb
1 1 class SearchController < PublicController
2 2  
3   - MAP_SEARCH_LIMIT = 2000
4   - LIST_SEARCH_LIMIT = 20
5   - BLOCKS_SEARCH_LIMIT = 18
6   - MULTIPLE_SEARCH_LIMIT = 8
7   -
8 3 helper TagsHelper
9 4 include SearchHelper
10 5 include ActionView::Helpers::NumberHelper
... ... @@ -33,7 +28,6 @@ class SearchController &lt; PublicController
33 28 full_text_search ['public:true']
34 29 else
35 30 @results[@asset] = @environment.articles.public.send(@filter).paginate(paginate_options)
36   - facets = {}
37 31 end
38 32 end
39 33  
... ... @@ -46,7 +40,6 @@ class SearchController &lt; PublicController
46 40 full_text_search ['public:true']
47 41 else
48 42 @results[@asset] = @environment.people.visible.send(@filter).paginate(paginate_options)
49   - @facets = {}
50 43 end
51 44 end
52 45  
... ... @@ -54,8 +47,19 @@ class SearchController &lt; PublicController
54 47 if !@empty_query
55 48 full_text_search ['public:true']
56 49 else
57   - @results[@asset] = @environment.products.send(@filter).paginate(paginate_options)
58   - @facets = {}
  50 + @one_page = true
  51 + @geosearch = logged_in? && current_user.person.lat && current_user.person.lng
  52 +
  53 + extra_limit = LIST_SEARCH_LIMIT*5
  54 + sql_options = {:limit => LIST_SEARCH_LIMIT, :order => 'random()'}
  55 + if @geosearch
  56 + full_text_search ['public:true', "{!geofilt}"], :sql_options => sql_options, :extra_limit => extra_limit,
  57 + :alternate_query => "{!boost b=recip(geodist(),#{1/DistBoost},1,1)}",
  58 + :radius => DistFilt, :latitude => current_user.person.lat, :longitude => current_user.person.lng
  59 + else
  60 + full_text_search ['public:true'], :sql_options => sql_options, :extra_limit => extra_limit,
  61 + :boost_functions => ['recip(ms(NOW/HOUR,updated_at),1.3e-10,1,1)']
  62 + end
59 63 end
60 64 end
61 65  
... ... @@ -77,40 +81,25 @@ class SearchController &lt; PublicController
77 81 end
78 82  
79 83 def events
80   - @category_id = @category ? @category.id : nil
81   -
82 84 year = (params[:year] ? params[:year].to_i : Date.today.year)
83 85 month = (params[:month] ? params[:month].to_i : Date.today.month)
84 86 day = (params[:day] ? params[:day].to_i : Date.today.day)
85   - date = Date.new(year, month, day)
  87 + date = build_date(params[:year], params[:month], params[:day])
86 88 date_range = (date - 1.month)..(date + 1.month).at_end_of_month
87 89  
88   - if @query.blank?
89   - # Ignore pagination for asset events
90   - if date_range
91   - @results[@asset] = Event.send('find', :all,
92   - :conditions => [
93   - 'start_date BETWEEN :start_day AND :end_day OR end_date BETWEEN :start_day AND :end_day',
94   - {:start_day => date_range.first, :end_day => date_range.last}
95   - ])
96   - else
97   - @results[@asset] = Event.send('find', :all)
98   - end
99   - else
100   - full_text_search
101   - end
102   -
103 90 @selected_day = nil
104 91 @events_of_the_day = []
105   - date = build_date(params[:year], params[:month], params[:day])
106   -
107 92 if params[:day] || !params[:year] && !params[:month]
108 93 @selected_day = date
109   - if @category_id and Category.exists?(@category_id)
110   - @events_of_the_day = environment.events.by_day(@selected_day).in_category(Category.find(@category_id))
111   - else
112   - @events_of_the_day = environment.events.by_day(@selected_day)
113   - end
  94 + @events_of_the_day = @category ?
  95 + environment.events.by_day(@selected_day).in_category(Category.find(@category_id)) :
  96 + environment.events.by_day(@selected_day)
  97 + end
  98 +
  99 + if !@empty_query
  100 + full_text_search
  101 + else
  102 + @results[@asset] = date_range ? environment.events.by_range(date_range) : environment.events
114 103 end
115 104  
116 105 events = @results[@asset]
... ... @@ -135,17 +124,10 @@ class SearchController &lt; PublicController
135 124 @asset = nil
136 125 @facets = {}
137 126  
138   - if @results.keys.size == 1
139   - specific_action = @results.keys.first
140   - if respond_to?(specific_action)
141   - @asset_name = getterm(@names[@results.keys.first])
142   - send(specific_action)
143   - render :action => specific_action
144   - return
145   - end
146   - end
  127 + render :action => @results.keys.first if @results.keys.size == 1
147 128 end
148 129  
  130 + # keep old URLs workings
149 131 def assets
150 132 params[:action] = params[:asset].is_a?(Array) ? :index : params.delete(:asset)
151 133 redirect_to params
... ... @@ -167,6 +149,7 @@ class SearchController &lt; PublicController
167 149 ].each do |asset, name, filter|
168 150 @order << asset
169 151 @results[asset] = @category.send(filter, limit)
  152 + raise "nao total #{asset}" unless @results[asset].respond_to?(:total_entries)
170 153 @names[asset] = name
171 154 end
172 155 end
... ... @@ -182,7 +165,8 @@ class SearchController &lt; PublicController
182 165 @tag = params[:tag]
183 166 @tag_cache_key = "tag_#{CGI.escape(@tag.to_s)}_env_#{environment.id.to_s}_page_#{params[:npage]}"
184 167 if is_cache_expired?(@tag_cache_key)
185   - @tagged = environment.articles.find_tagged_with(@tag).paginate(:per_page => 10, :page => params[:npage])
  168 + @asset = :articles
  169 + @results[@asset] = environment.articles.find_tagged_with(@tag).paginate(paginate_options)
186 170 end
187 171 end
188 172  
... ... @@ -241,7 +225,7 @@ class SearchController &lt; PublicController
241 225 'communities_more_recent' => _('More recent communities from network'),
242 226 'communities_more_active' => _('More active communities from network'),
243 227 'communities_more_popular' => _('More popular communities from network'),
244   - 'products_more_recent' => _('More recent products from network'),
  228 + 'products_more_recent' => _('Highlights'),
245 229 }[asset.to_s + '_' + filter]
246 230 end
247 231  
... ... @@ -284,21 +268,30 @@ class SearchController &lt; PublicController
284 268 { :per_page => limit, :page => page }
285 269 end
286 270  
287   - def full_text_search(filters = [])
  271 + def full_text_search(filters = [], options = {})
288 272 paginate_options = paginate_options(params[:page])
289 273 asset_class = asset_class(@asset)
290 274  
291   - solr_options = {}
292   - if !@results_only and asset_class.methods.include?('facets')
  275 + solr_options = options
  276 + if !@results_only and asset_class.respond_to? :facets
293 277 solr_options.merge! asset_class.facets_find_options(params[:facet])
294 278 solr_options[:all_facets] = true
295 279 solr_options[:limit] = 0 if @facets_only
296   - #solr_options[:facets][:browse] << asset_class.facet_category_query.call(@category) if @category and asset_class.facet_category_query
297 280 end
298   - solr_options[:order] = params[:order_by] if params[:order_by]
299 281 solr_options[:filter_queries] ||= []
300 282 solr_options[:filter_queries] += filters
301 283 solr_options[:filter_queries] << "environment_id:#{environment.id}"
  284 + solr_options[:filter_queries] << asset_class.facet_category_query.call(@category) if @category
  285 +
  286 + solr_options[:boost_functions] ||= []
  287 + params[:order_by] = nil if params[:order_by] == 'none'
  288 + if params[:order_by]
  289 + order = SortOptions[@asset][params[:order_by].to_sym]
  290 + raise "Unknown order by" if order.nil?
  291 + order[:solr_opts].each do |opt, value|
  292 + solr_options[opt] = value.is_a?(Proc) ? instance_eval(&value) : value
  293 + end
  294 + end
302 295  
303 296 ret = asset_class.find_by_contents(@query, paginate_options, solr_options)
304 297 @results[@asset] = ret[:results]
... ...
app/helpers/search_helper.rb
1 1 module SearchHelper
2 2  
  3 + MAP_SEARCH_LIMIT = 2000
  4 + LIST_SEARCH_LIMIT = 20
  5 + BLOCKS_SEARCH_LIMIT = 18
  6 + MULTIPLE_SEARCH_LIMIT = 8
  7 + DistFilt = 200
  8 + DistBoost = 50
  9 + SortOptions = {
  10 + :products => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
  11 + :more_recent, {:label => _('More Recent'), :solr_opts => {:sort => 'updated_at desc, score desc'}},
  12 + :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
  13 + :closest, {:label => _('Closest to me'), :if => proc{ logged_in? && (profile=current_user.person).lat && profile.lng },
  14 + :solr_opts => {:sort => "geodist() asc",
  15 + :latitude => proc{ current_user.person.lat }, :longitude => proc{ current_user.person.lng }}},
  16 + ],
  17 + :events => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
  18 + :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
  19 + ],
  20 + :articles => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
  21 + :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
  22 + :name, {:label => _('Most recent'), :solr_opts => {:sort => 'updated_at desc, score desc'}},
  23 + ],
  24 + :enterprises => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
  25 + :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
  26 + ],
  27 + :people => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
  28 + :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
  29 + ],
  30 + :communities => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')},
  31 + :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}},
  32 + ],
  33 + }
  34 +
3 35 # FIXME remove it after search_controler refactored
4 36 include EventsHelper
5 37  
... ... @@ -130,18 +162,14 @@ module SearchHelper
130 162 end
131 163  
132 164 def order_by(asset)
133   - options = {
134   - :products => [[_('Relevance'), ''], [_('More Recent'), 'updated_at desc'], [_('Name'), 'name_or_category_sort asc']],
135   - :events => [[_('Relevance'), ''], [_('Name'), 'name_sort asc']],
136   - :articles => [[_('Relevance'), ''], [_('Name'), 'name_sort asc'], [_('Most recent'), 'updated_at desc']],
137   - :enterprises => [[_('Relevance'), ''], [_('Name'), 'name_sort asc']],
138   - :people => [[_('Relevance'), ''], [_('Name'), 'name_sort asc']],
139   - :communities => [[_('Relevance'), ''], [_('Name'), 'name_sort asc']],
140   - }
  165 + options = SortOptions[asset].map do |name, options|
  166 + next if options[:if] and ! instance_eval(&options[:if])
  167 + [_(options[:label]), name.to_s]
  168 + end.compact
141 169  
142 170 content_tag('div', _('Sort results by ') +
143   - select_tag(asset.to_s + '[order]', options_for_select(options[asset], params[:order_by]),
144   - {:onchange => "window.location=jQuery.param.querystring(window.location.href, { 'order_by' : this.options[this.selectedIndex].value})"}),
  171 + select_tag(asset.to_s + '[order]', options_for_select(options, params[:order_by] || 'none'),
  172 + {:onchange => "window.location = jQuery.param.querystring(window.location.href, { 'order_by' : this.options[this.selectedIndex].value})"}),
145 173 :class => "search-ordering")
146 174 end
147 175  
... ...
app/models/article.rb
... ... @@ -618,15 +618,14 @@ class Article &lt; ActiveRecord::Base
618 618 def f_category
619 619 self.categories.collect(&:name)
620 620 end
621   - def name_sort
  621 +
  622 + delegate :region, :region_id, :environment, :environment_id, :to => :profile
  623 + def name_sortable # give a different name for solr
622 624 name
623 625 end
624 626 def public
625 627 self.public?
626 628 end
627   - def environment_id
628   - profile.environment_id
629   - end
630 629 public
631 630  
632 631 acts_as_faceted :fields => {
... ... @@ -639,16 +638,24 @@ class Article &lt; ActiveRecord::Base
639 638 :category_query => proc { |c| "f_category:\"#{c.name}\"" },
640 639 :order => [:f_type, :f_published_at, :f_profile_type, :f_category]
641 640  
642   - acts_as_searchable :additional_fields => [
643   - {:name_sort => {:type => :string}},
644   - {:public => {:type => :boolean}},
645   - {:environment_id => {:type => :integer}},
646   - ] + facets_fields_for_solr,
647   - :exclude_fields => [:setting],
648   - :include => [:profile, :comments, :categories],
649   - :facets => facets_option_for_solr,
650   - :boost => proc {|a| 10 if a.profile.enabled},
651   - :if => proc{|a| ! ['RssFeed'].include?(a.class.name)}
  641 + acts_as_searchable :fields => facets_fields_for_solr + [
  642 + # searched fields
  643 + {:name => {:type => :text, :boost => 2.0}},
  644 + {:slug => :text}, {:body => :text},
  645 + {:abstract => :text}, {:filename => :text},
  646 + # filtered fields
  647 + {:public => :boolean}, {:environment_id => :integer},
  648 + :language, :published,
  649 + # ordered/query-boosted fields
  650 + {:name_sortable => :string}, :last_changed_by_id, :published_at, :is_image,
  651 + :updated_at, :created_at,
  652 + ], :include => [
  653 + {:profile => {:fields => [:name, :identifier, :address, :nickname, :region_id, :lat, :lng]}},
  654 + {:comments => {:fields => [:title, :body, :author_name, :author_email]}},
  655 + {:categories => {:fields => [:name, :path, :slug, :lat, :lng, :acronym, :abbreviation]}},
  656 + ], :facets => facets_option_for_solr,
  657 + :boost => proc { |a| 10 if a.profile.enabled },
  658 + :if => proc{ |a| ! ['RssFeed'].include?(a.class.name) }
652 659 handle_asynchronously :solr_save
653 660  
654 661 private
... ...
app/models/category.rb
... ... @@ -15,9 +15,6 @@ class Category &lt; ActiveRecord::Base
15 15  
16 16 acts_as_filesystem
17 17  
18   - acts_as_searchable :additional_fields => [{:name => {:boost => 2.0}}]
19   - handle_asynchronously :solr_save
20   -
21 18 has_many :article_categorizations, :dependent => :destroy
22 19 has_many :articles, :through => :article_categorizations
23 20 has_many :comments, :through => :articles
... ... @@ -68,7 +65,7 @@ class Category &lt; ActiveRecord::Base
68 65 end
69 66  
70 67 def upcoming_events(limit = 10)
71   - self.events.find(:all, :conditions => [ 'start_date >= ?', Date.today ], :order => 'start_date')
  68 + self.events.paginate(:conditions => [ 'start_date >= ?', Date.today ], :order => 'start_date', :page => 1, :per_page => limit)
72 69 end
73 70  
74 71 def display_in_menu?
... ... @@ -92,4 +89,23 @@ class Category &lt; ActiveRecord::Base
92 89 self.children.find(:all, :conditions => {:display_in_menu => true}).empty?
93 90 end
94 91  
  92 + private
  93 + def name_sortable # give a different name for solr
  94 + name
  95 + end
  96 + public
  97 +
  98 + acts_as_searchable :fields => [
  99 + # searched fields
  100 + {:name => {:type => :text, :boost => 2.0}},
  101 + {:path => :text}, {:slug => :text},
  102 + {:abbreviation => :text}, {:acronym => :text},
  103 + # filtered fields
  104 + :parent_id,
  105 + # ordered/query-boosted fields
  106 + {:name_sortable => :string},
  107 + ]
  108 + after_save_reindex [:articles, :profiles], :with => :delayed_job
  109 + handle_asynchronously :solr_save
  110 +
95 111 end
... ...
app/models/certifier.rb
... ... @@ -24,4 +24,6 @@ class Certifier &lt; ActiveRecord::Base
24 24 self.name.downcase.transliterate <=> b.name.downcase.transliterate
25 25 end
26 26  
  27 + after_save_reindex [:products], :with => :delayed_job
  28 +
27 29 end
... ...
app/models/image.rb
... ... @@ -23,4 +23,9 @@ class Image &lt; ActiveRecord::Base
23 23  
24 24 postgresql_attachment_fu
25 25  
  26 + alias_method :public_filename_old, :public_filename
  27 + def public_filename(*args)
  28 + "http://cirandas.net#{public_filename_old(args)}"
  29 + end
  30 +
26 31 end
... ...
app/models/product_category.rb
1 1 class ProductCategory < Category
  2 + # FIXME: do not allow category with products or inputs to be destroyed
2 3 has_many :products
3 4 has_many :inputs
4 5  
... ... @@ -9,4 +10,7 @@ class ProductCategory &lt; Category
9 10 def self.menu_categories(top_category, env)
10 11 top_category ? top_category.children : top_level_for(env).select{|c|c.kind_of?(ProductCategory)}
11 12 end
  13 +
  14 + after_save_reindex [:products], :with => :delayed_job
  15 +
12 16 end
... ...
app/models/profile.rb
... ... @@ -87,7 +87,7 @@ class Profile &lt; ActiveRecord::Base
87 87 named_scope :more_popular
88 88 named_scope :more_active
89 89  
90   - named_scope :more_recent, :order => "updated_at DESC"
  90 + named_scope :more_recent, :order => "created_at DESC"
91 91  
92 92 acts_as_trackable :dependent => :destroy
93 93  
... ... @@ -125,8 +125,6 @@ class Profile &lt; ActiveRecord::Base
125 125  
126 126 validates_length_of :description, :maximum => 550, :allow_nil => true
127 127  
128   - acts_as_mappable :default_units => :kms
129   -
130 128 # Valid identifiers must match this format.
131 129 IDENTIFIER_FORMAT = /^#{Noosfero.identifier_format}$/
132 130  
... ... @@ -859,7 +857,8 @@ private :generate_url, :url_options
859 857 c.name
860 858 end
861 859 end
862   - def name_sort
  860 +
  861 + def name_sortable # give a different name for solr
863 862 name
864 863 end
865 864 def public
... ... @@ -875,13 +874,24 @@ private :generate_url, :url_options
875 874 :category_query => proc { |c| "f_categories:#{c.id}" },
876 875 :order => [:f_region, :f_categories]
877 876  
878   - acts_as_searchable :additional_fields => [
879   - {:name_sort => {:type => :string}},
880   - {:public => {:type => :boolean}},
881   - :extra_data_for_index ] + facets.keys.map{|i| {i => :facet}},
882   - :boost => proc {|p| 10 if p.enabled},
883   - :include => [:categories, :region],
884   - :facets => facets.keys
  877 + acts_as_searchable :fields => facets_fields_for_solr + [:extra_data_for_index,
  878 + # searched fields
  879 + {:name => {:type => :text, :boost => 2.0}},
  880 + {:identifier => :text}, {:address => :text}, {:nickname => :text},
  881 + # filtered fields
  882 + {:public => :boolean}, {:environment_id => :integer},
  883 + # ordered/query-boosted fields
  884 + {:name_sortable => :string}, {:user_id => :integer},
  885 + :enabled, :active, :validated, :public_profile,
  886 + {:lat => :float}, {:lng => :float},
  887 + :updated_at, :created_at,
  888 + ],
  889 + :include => [
  890 + {:region => {:fields => [:name, :path, :slug, :lat, :lng]}},
  891 + {:categories => {:fields => [:name, :path, :slug, :lat, :lng, :acronym, :abbreviation]}},
  892 + ], :facets => facets_option_for_solr,
  893 + :boost => proc{ |p| 10 if p.enabled }
  894 + after_save_reindex [:articles], :with => :delayed_job
885 895 handle_asynchronously :solr_save
886 896  
887 897 def control_panel_settings_button
... ...
app/models/qualifier.rb
... ... @@ -15,4 +15,6 @@ class Qualifier &lt; ActiveRecord::Base
15 15 self.name.downcase.transliterate <=> b.name.downcase.transliterate
16 16 end
17 17  
  18 + after_save_reindex [:products], :with => :delayed_job
  19 +
18 20 end
... ...
app/views/search/_article.rhtml
... ... @@ -3,9 +3,10 @@
3 3 <div class="search-content-first-column">
4 4 <%= render :partial => 'image', :object => article %>
5 5 </div>
6   - <div class="search-content-second-column">
7   -
8   - </div>
  6 + <table class="noborder search-content-second-column">
  7 + <%= render :partial => 'article_common', :object => article %>
  8 + </table>
  9 + <%= render :partial => 'article_last_change', :object => article %>
9 10  
10 11 <div style="clear:both"></div>
11 12 </li>
... ...
app/views/search/_article_author.rhtml
1 1 <% article = article_author %>
2 2  
3   -<div class="search-article-author">
4   - <div class="search-article-author-name">
5   - <span class="search-field-label"><%= _("Author") %></span>
  3 +<tr class="search-article-author search-article-author-name">
  4 + <td class="search-field-label"><%= _("Author") %></td>
  5 + <td>
6 6 <%= link_to_profile article.profile.name, article.profile.identifier %>
7   - </div>
8   -</div>
  7 + </td>
  8 +</tr>
... ...
app/views/search/_article_categories.rhtml
1   -<div class="search-article-categories">
2   - <span class="search-field-label"><%= _('Categories') %></span>
3   - <span class="search-article-categories-container">
  1 +<tr class="search-article-categories">
  2 + <td class="search-field-label"><%= _('Categories') %></td>
  3 + <td class="search-article-categories-container <%= "search-field-none" if article_categories.empty? %>">
4 4 <% article_categories.each do |category| %>
5 5 <%= link_to_category category, false, :class => "search-article-category" %>
6 6 <% end %>
7   - <span class="search-field-none"><%= _('None') if article_categories.empty? %></span>
8   - </span>
9   -</div>
  7 + <%= _('None') if article_categories.empty? %>
  8 + </td>
  9 +</tr>
... ...
app/views/search/_article_common.rhtml
... ... @@ -5,4 +5,3 @@
5 5 <%= render :partial => 'article_description', :object => article if show_description %>
6 6 <%= render :partial => 'article_tags', :object => article.tags %>
7 7 <%= render :partial => 'article_categories', :object => article.categories %>
8   -<%= render :partial => 'article_last_change', :object => article %>
... ...
app/views/search/_article_description.rhtml
1 1 <% article = article_description %>
2 2  
3   -<div class="search-article-description">
4   - <span class="search-field-label"><%= _("Description") %></span>
  3 +<tr class="search-article-description">
  4 + <td class="search-field-label"><%= _("Description") %></td>
  5 +
5 6 <% if !article.body.blank? %>
6   - <% body_stripped = strip_tags(article.body.to_s) %>
7   - <span class="search-article-body"><%= excerpt(body_stripped, body_stripped.first(3), 200) %></span>
  7 + <% description = strip_tags(article.body.to_s) %>
  8 + <% description = excerpt(description, description.first(3), 200).gsub!(/\s{2,}/, ' ') %>
  9 + <td class="search-article-body"><%= description %></td>
8 10 <% else %>
9   - <span class="search-field-none"><%= _('None') %></span>
  11 + <td class="search-field-none"><%= _('None') %></td>
10 12 <% end %>
11   -</div>
  13 +</tr>
... ...
app/views/search/_article_last_change.rhtml
1 1 <% article = article_last_change %>
2 2  
3 3 <div class="search-article-author-changes">
4   - <% if article.last_changed_by && article.last_changed_by != article.profile %>
5   - <span><%= _('by %s') % link_to(article.last_changed_by.name, article.last_changed_by.url) %>&nbsp<%= _(' at %s.') % show_date(article.updated_at) %></span>
  4 + <% if article.last_changed_by and article.last_changed_by != article.profile %>
  5 + <span><%= _('by %{name} at %{date}') % {:name => link_to(article.last_changed_by.name, article.last_changed_by.url),
  6 + :date => show_date(article.updated_at) } %></span>
6 7 <% else %>
7 8 <span><%= _('Last update: %s.') % show_date(article.updated_at) %></span>
8 9 <% end %>
... ...
app/views/search/_article_tags.rhtml
1   -<div class="search-article-tags">
2   - <span class="search-field-label"><%= _('Tags') %></span>
3   - <span class="search-article-tags-container">
  1 +<tr class="search-article-tags">
  2 + <td class="search-field-label"><%= _('Tags') %></td>
  3 + <td class="search-article-tags-container <%= "search-field-none" if article_tags.empty? %>">
4 4 <% article_tags.each do |tag| %>
5 5 <%= link_to_tag tag, :class => "search-article-tag" %>
6 6 <% end %>
7   - <span class="search-field-none"><%= _('None') if article_tags.empty? %></span>
8   - </span>
9   -</div>
  7 + <%= _('None') if article_tags.empty? %></td>
  8 + </td>
  9 +</tr>
... ...
app/views/search/_blog.rhtml
... ... @@ -3,21 +3,22 @@
3 3 <div class="search-content-first-column">
4 4 <%= render :partial => 'image', :object => blog %>
5 5 </div>
6   - <div class="search-content-second-column">
7   - <div class="search-blog-items">
8   - <span class="search-field-label"><%= _("Last posts") %></span>
  6 + <table class="noborder search-content-second-column">
  7 + <tr class="search-blog-items">
  8 + <td class="search-field-label"><%= _("Last posts") %></td>
  9 +
9 10 <% r = blog.children.find(:all, :order => :updated_at, :conditions => ['type != ?', 'RssFeed']).last(3) %>
10   - <% r.each do |a| %>
11   - <%= link_to a.title, a.view_url, :class => 'search-blog-sample-item '+icon_for_article(a) %>
12   - <% end %>
13   - <span class="search-field-none"><%= _('None') if r.empty? %></span>
14   - </div>
  11 + <td class="<%= "search-field-none" if r.empty? %>">
  12 + <% r.each do |a| %>
  13 + <%= link_to a.title, a.view_url, :class => 'search-blog-sample-item '+icon_for_article(a) %>
  14 + <% end %>
  15 + <%= _('None') if r.empty? %>
  16 + </td>
  17 + </tr>
15 18  
16   - <%= render :partial => 'article_author', :object => blog %>
17   - <%= render :partial => 'article_tags', :object => blog.tags %>
18   - <%= render :partial => 'article_categories', :object => blog.categories %>
19   - <%= render :partial => 'article_last_change', :object => blog %>
20   - </div>
  19 + <%= render :partial => 'article_common', :object => blog %>
  20 + </table>
  21 + <%= render :partial => 'article_last_change', :object => blog %>
21 22  
22 23 <div style="clear: both;"/></div>
23 24 </li>
... ...
app/views/search/_display_results.rhtml
1 1 <div id="search-results" class="<%= 'only-one-result-box' if @results.size == 1 %>">
2   -
3 2 <% @order.each do |name| %>
4 3 <% results = @results[name] %>
5   - <% if !results.nil? and !results.empty? %>
6   - <div class="search-results-<%= name %> search-results-box">
7   -
  4 + <% empty = results.nil? || results.empty? %>
  5 +
  6 + <div class="search-results-<%= name %> search-results-box <%= "search-results-empty" if empty %>">
  7 + <% if not empty %>
  8 + <% partial = partial_for_class(results.first.class.class_name.constantize) %>
  9 +
8 10 <% if @results.size > 1 %>
9 11 <h3><%= @names[name] %></h3>
10   - <%= link_to(results.respond_to?(:total_entries) ? _('see all (%d)') % results.total_entries : _('see all...'),
11   - params.merge(:action => name), :class => 'see-more' ) %>
  12 + <% if results.total_entries > SearchController::MULTIPLE_SEARCH_LIMIT %>
  13 + <%= link_to(_('see all (%d)') % results.total_entries, params.merge(:action => name), :class => 'see-more' ) %>
  14 + <% end %>
12 15 <% end %>
13   -
14   - <% partial = partial_for_class(results.first.class.class_name.constantize) %>
  16 +
15 17 <div class="search-results-innerbox search-results-type-<%= partial %> <%= 'common-profile-list-block' if partial == 'profile' %>">
16   - <div class="search-results-innerbox2"><!-- the innerbox2 is a workarround for MSIE -->
17   - <ul>
18   - <% results.each do |hit| %>
19   - <%= render :partial => partial_for_class(hit.class), :object => hit %>
20   - <% end %>
21   - </ul>
22   - <hr />
23   - </div><!-- end class="search-results-innerbox2" -->
24   - </div><!-- end class="search-results-innerbox" -->
25   -
26   - </div><!-- end class="search-results-<%= name %>" -->
27   - <% else %>
28   - <div class="search-results-<%= name %> search-results-empty search-results-box">
  18 + <ul>
  19 + <% results.each do |hit| %>
  20 + <%= render :partial => partial_for_class(hit.class), :object => hit %>
  21 + <% end %>
  22 + </ul>
  23 + </div>
  24 + <% else %>
29 25 <% if @results.size > 1 %>
30 26 <h3><%= @names[name] %></h3>
31 27 <% end %>
32 28 <div class="search-results-innerbox search-results-type-empty">
33 29 <div> <%= _('None') %> </div>
34   - <hr />
35   - </div><!-- end class="search-results-innerbox" -->
36   - </div><!-- end class="search-results-<%= name %>" -->
37   - <% end %>
  30 + </div>
  31 + <% end %>
  32 + </div>
38 33 <% end %>
39 34  
40 35 <div style="clear:both"></div>
41 36  
42 37 <%= add_zoom_to_images %>
43   -</div><!-- end id="search-results" -->
  38 +</div>
44 39  
... ...
app/views/search/_event.rhtml
... ... @@ -3,22 +3,23 @@
3 3 <div class="search-content-first-column">
4 4 <%= render :partial => 'image', :object => event %>
5 5 </div>
6   - <div class="search-content-second-column">
  6 + <table class="noborder search-content-second-column">
7 7 <% if event.start_date %>
8   - <div class="searc-article-event-date">
9   - <span class="search-field-label"><%= _('Start date') %></span>
10   - <span class="article-item-date"><%= event.start_date %></span>
11   - </div>
  8 + <tr class="searc-article-event-date">
  9 + <td class="search-field-label"><%= _('Start date') %></td>
  10 + <td class="article-item-date"><%= event.start_date %></td>
  11 + </tr>
12 12 <% end %>
13 13 <% if event.end_date %>
14   - <div class="searc-article-event-date">
15   - <span class="search-field-label"><%= _('End date') %></span>
16   - <span class="article-item-date"><%= event.end_date %></span>
17   - </div>
  14 + <tr class="searc-article-event-date">
  15 + <td class="search-field-label"><%= _('End date') %></td>
  16 + <td class="article-item-date"><%= event.end_date %></td>
  17 + </tr>
18 18 <% end %>
19 19  
20 20 <%= render :partial => 'article_common', :object => event %>
21   - </div>
  21 + </table>
  22 + <%= render :partial => 'article_last_change', :object => event %>
22 23  
23 24 <div style="clear: both"></div>
24 25 </li>
... ...
app/views/search/_folder.rhtml
... ... @@ -3,18 +3,22 @@
3 3 <div class="search-content-first-column">
4 4 <%= render :partial => 'image', :object => folder %>
5 5 </div>
6   - <div class="search-content-second-column">
7   - <div class="search-folder-items">
8   - <span class="search-field-label"><%= _("Last items") %></span>
  6 + <table class="noborder search-content-second-column">
  7 + <tr class="search-folder-items">
  8 + <td class="search-field-label"><%= _("Last items") %></td>
  9 +
9 10 <% r = folder.children.last(3) %>
10   - <% r.each do |a| %>
11   - <%= link_to a.title, a.view_url, :class => 'search-folder-sample-item '+icon_for_article(a) %>
12   - <% end %>
13   - <span class="search-field-none"><%= _('None') if r.empty? %></span>
14   - </div>
  11 + <td class="<%= "search-field-none" if r.empty? %>">
  12 + <% r.each do |a| %>
  13 + <%= link_to a.title, a.view_url, :class => 'search-folder-sample-item '+icon_for_article(a) %>
  14 + <% end %>
  15 + <%= _('None') if r.empty? %>
  16 + </td>
  17 + </tr>
15 18  
16 19 <%= render :partial => 'article_common', :object => folder %>
17   - </div>
  20 + </table>
  21 + <%= render :partial => 'article_last_change', :object => folder %>
18 22  
19 23 <div style="clear:both"></div>
20 24 </li>
... ...
app/views/search/_forum.rhtml
... ... @@ -3,18 +3,22 @@
3 3 <div class="search-content-first-column">
4 4 <%= render :partial => 'image', :object => forum %>
5 5 </div>
6   - <div class="search-content-second-column">
7   - <div class="search-forum-items">
8   - <span class="search-field-label"><%= _("Last topics") %></span>
  6 + <table class="noborder search-content-second-column">
  7 + <tr class="search-forum-items">
  8 + <td class="search-field-label"><%= _("Last topics") %></td>
  9 +
9 10 <% r = forum.children.find(:all, :order => :updated_at, :conditions => ['type != ?', 'RssFeed']).last(3) %>
10   - <% r.each do |a| %>
11   - <%= link_to a.title, a.view_url, :class => 'search-forum-sample-item '+icon_for_article(a) %>
12   - <% end %>
13   - <span class="search-field-none"><%= _('None') if r.empty? %></span>
14   - </div>
  11 + <td class="<%= "search-field-none" if r.empty? %>">
  12 + <% r.each do |a| %>
  13 + <%= link_to a.title, a.view_url, :class => 'search-forum-sample-item '+icon_for_article(a) %>
  14 + <% end %>
  15 + <%= _('None') if r.empty? %>
  16 + </td>
  17 + </tr>
15 18  
16 19 <%= render :partial => 'article_common', :object => forum %>
17   - </div>
  20 + </table>
  21 + <%= render :partial => 'article_last_change', :object => forum %>
18 22  
19 23 <div style="clear:both"></div>
20 24 </li>
... ...
app/views/search/_gallery.rhtml
... ... @@ -3,9 +3,10 @@
3 3 <div class="search-content-first-column">
4 4 <%= render :partial => 'image', :object => gallery %>
5 5 </div>
6   - <div class="search-content-second-column">
  6 + <table class="noborder search-content-second-column">
7 7 <%= render :partial => 'article_common', :object => gallery %>
8   - </div>
  8 + </table>
  9 + <%= render :partial => 'article_last_change', :object => gallery %>
9 10  
10 11 <div style="clear: both"></div>
11 12 </li>
... ...
app/views/search/_image.rhtml
1 1 <div class="search-image-container">
2 2  
3   - <% if image.is_a? UploadedFile %>
  3 + <% if image.is_a? UploadedFile and image.filename %>
4 4 <% extension = image.filename[(image.filename.rindex('.')+1)..-1].downcase %>
5 5 <% if ['jpg', 'jpeg', 'gif', 'png', 'tiff', 'svg'].include? extension %>
6 6 <%= link_to '', image.view_url, :class => "search-image-pic", :style => 'background-image: url(%s)'% image.public_filename(:thumb) %>
... ...
app/views/search/_product.rhtml
... ... @@ -2,6 +2,7 @@
2 2 <% extra_properties = @plugins.dispatch(:asset_product_properties, product)%>
3 3  
4 4 <li class="search-product-item">
  5 +
5 6 <div class="search-product-item-first-column">
6 7 <%= render :partial => 'search/image', :object => product %>
7 8  
... ... @@ -18,17 +19,9 @@
18 19 <% end %>
19 20 <% end %>
20 21 <div class="search-product-inputs-info">
21   - <% if product.inputs.count > product.inputs.collect(&:is_from_solidarity_economy).count(nil) %>
22   - <% se_i = t_i = 0 %>
23   - <% product.inputs.each{ |i| t_i += 1; se_i += 1 if i.is_from_solidarity_economy } %>
24   - <% p = case (se_i.to_f/t_i)*100
25   - when 0..24.999 then ["0", _("")];
26   - when 25..49.999 then ["25", _("25%")];
27   - when 50..74.999 then ["50", _("50%")];
28   - when 75..99.999 then ["75", _("75%")];
29   - when 100 then ["100", _("100%")];
30   - end %>
31   - <div class="search-product-percentage-from-solidarity-economy search-product-ecosol-percentage-icon-<%=p[0]%>" title="<%=_('Percentage of inputs from solidarity economy')%>">
  22 + <% if p = product.percentage_from_solidarity_economy %>
  23 + <div class="search-product-percentage-from-solidarity-economy search-product-ecosol-percentage-icon-<%= p[0].to_s %>"
  24 + title="<%=_('Percentage of inputs from solidarity economy')%>">
32 25 <%= p[1] %>
33 26 </div>
34 27 <% end %>
... ...
app/views/search/_profile.rhtml
... ... @@ -39,6 +39,7 @@
39 39 <% end %>
40 40 </div>
41 41 </div>
  42 +
42 43 <hr class="clearfix" />
43 44 </div>
44 45 <% end %>
... ...
app/views/search/_search_form.rhtml
... ... @@ -5,10 +5,13 @@
5 5  
6 6 <%= hidden_field_tag :display, params[:display] %>
7 7  
8   - <% CGI::unescape(request.request_uri).split("&").each do |part| %>
9   - <% if part.start_with? "facet" %>
10   - <% name_value = part.split("=") %>
11   - <%= hidden_field_tag name_value[0], name_value[1] %>
  8 + <% params_uri = CGI::unescape(request.request_uri) %>
  9 + <% if params_uri.index('?') %>
  10 + <% params_uri[(params_uri.index('?')+1)..-1].to_s.split("&").each do |part| %>
  11 + <% if part.start_with? "facet" %>
  12 + <% name_value = part.split("=") %>
  13 + <%= hidden_field_tag name_value[0], name_value[1] %>
  14 + <% end %>
12 15 <% end %>
13 16 <% end %>
14 17  
... ... @@ -16,19 +19,9 @@
16 19 <span class="formfield">
17 20 <%= text_field_tag 'query', @query, :id => 'search-input', :size => 50 %>
18 21 <%= javascript_tag "jQuery('#search-input').attr('title', \"#{hint}\").hint()" if defined?(hint) %>
19   - <%= javascript_tag "jQuery('.search_form').submit(function() {
20   - if (jQuery('#search-input').val().length < 3) {
21   - jQuery('#search-empty-query-error').slideDown(200).delay(2500).slideUp(200);
22   - return false;
23   - }
24   - });" %>
25 22 </span>
26 23  
27 24 <%= submit_button(:search, _('Search')) %>
28   -
29   - <div id="search-empty-query-error">
30   - <%= _("Type more than 2 characters to start a search") %>
31   - </div>
32 25 </div>
33 26  
34 27 <% end %>
... ...
app/views/search/_text_article.rhtml
1 1 <li class="search-text-article-item article-item">
2 2 <%= link_to(text_article.title, text_article.url, :class => "search-result-title") %>
  3 +
3 4 <div class="search-content-first-column">
4 5 <%= render :partial => 'image', :object => text_article %>
5 6 </div>
6   - <div class="search-content-second-column">
  7 + <table class="noborder search-content-second-column">
7 8 <%= render :partial => 'article_common', :object => text_article %>
8   - </div>
  9 + </table>
  10 + <%= render :partial => 'article_last_change', :object => text_article %>
9 11  
10 12 <div style="clear: both"></div>
11 13 </li>
... ...
app/views/search/_uploaded_file.rhtml
1 1 <li class="search-uploaded-file-item article-item">
2 2 <%= link_to uploaded_file.filename, uploaded_file.view_url, :class => 'search-result-title' %>
3   - <hr class="clear" />
4 3  
5 4 <div class="search-content-first-column">
6 5 <%= render :partial => 'image', :object => uploaded_file %>
7 6 </div>
8 7  
9   - <div class="search-uploaded-file-second-column">
  8 + <table class="noborder search-content-second-column">
10 9 <%= render :partial => 'article_author', :object => uploaded_file %>
  10 + <%= render :partial => 'article_description', :object => uploaded_file %>
11 11  
12   - <div class="search-uploaded-file-description">
13   - <% if !uploaded_file.body.blank? %>
14   - <span class="search-field-label"><%= _("Description") %></span>
15   - <% body = strip_tags(uploaded_file.body.to_s) %>
16   - <%= excerpt(body, body.first(3), 200) %>
17   - <% end %>
18   - </div>
19   -
20   - <div class="search-uploaded-file-parent">
21   - <% if uploaded_file.parent && uploaded_file.parent.published? %>
22   - <% if uploaded_file.parent.gallery? %>
23   - <span class="search-field-label"><%= _("Gallery") %></span>
24   - <% else %>
25   - <span class="search-field-label"><%= _("Folder") %></span>
26   - <% end %>
27   - <%= link_to uploaded_file.parent.name, {:controller => 'content_viewer', :profile => uploaded_file.profile.identifier, :action => 'view_page', :page => [uploaded_file.parent.slug]} %>
28   - <% end %>
29   - </div>
  12 + <% if uploaded_file.parent and uploaded_file.parent.published? %>
  13 + <tr class="search-uploaded-file-parent">
  14 + <td class="search-field-label"><%= uploaded_file.parent.gallery? ? _("Gallery") : _("Folder") %></td>
  15 + <td><%= link_to uploaded_file.parent.name, uploaded_file.parent.url %></td>
  16 + </tr>
  17 + <% end %>
30 18  
31 19 <%= render :partial => 'article_tags', :object => uploaded_file.tags %>
32 20 <%= render :partial => 'article_categories', :object => uploaded_file.categories %>
33   - <%= render :partial => 'article_last_change', :object => uploaded_file %>
34   - </div>
  21 + </table>
  22 + <%= render :partial => 'article_last_change', :object => uploaded_file %>
35 23  
36 24 <div style="clear:both"></div>
37 25 </li>
... ...
app/views/search/products.rhtml
... ... @@ -14,7 +14,7 @@
14 14 <%= render :partial => 'results_header' %>
15 15  
16 16 <%= display_results(true) %>
17   - <% if params[:display] != 'map' %>
  17 + <% if !@one_page and params[:display] != 'map' %>
18 18 <%= pagination_links @results[:products] %>
19 19 <% end %>
20 20 </div>
... ...
app/views/search/tag.rhtml
... ... @@ -7,16 +7,7 @@
7 7 <% end %>
8 8  
9 9 <% cache_timeout(@tag_cache_key, 4.hour) do %>
10   - <div class='search-tagged-items'>
11   - <% @tagged.each do |hit| %>
12   - <ul class="clean-list">
13   - <%= render :partial => partial_for_class(hit.class), :object => hit %>
14   - </ul>
15   - <br style='clear: left;'/>
16   - <% end %>
17   -
18   - </div>
19   - <%= pagination_links @tagged, :param_name => 'npage' %>
  10 + <%= display_results %>
20 11  
21 12 <div style="clear: both"></div>
22 13 <% end %>
... ...
public/designs/themes/base/style.css
... ... @@ -872,30 +872,6 @@ X.sep {
872 872 border-top: 1px solid #CCC;
873 873 }
874 874  
875   -#content .search-results-box a.see-more {
876   - z-index: 10;
877   - position: absolute;
878   - bottom: 20px;
879   - right: 20px;
880   - background: transparent url(imgs/arrow-right-p.png) 100% 55% no-repeat;
881   - border: none;
882   - padding-right: 15px;
883   - color: #000;
884   - text-decoration: none;
885   - font-weight: bold;
886   -}
887   -#content .search-results-box a.see-more:hover {
888   - background: transparent url(imgs/arrow-right-p.png) 100% 55% no-repeat;
889   - color: #888;
890   -}
891   -
892   -
893   -.search-results-type-article.search-results-innerbox {
894   - padding: 5px 0px 5px 10px;
895   - max-height: 215px;
896   - height: 225px;
897   -}
898   -
899 875 #content .search-results-type-article li,
900 876 #content .search-results-type-event li {
901 877 padding: 5px 0px;
... ... @@ -1207,12 +1183,6 @@ table.profile th {
1207 1183  
1208 1184 /**************************** Browse *******************************/
1209 1185  
1210   -.search-results-type-article.search-results-innerbox {
1211   - padding: 5px 0px 5px 10px;
1212   - max-height: 215px;
1213   - height: 225px;
1214   -}
1215   -
1216 1186 #content .search-results-type-article li {
1217 1187 padding: 5px 0px;
1218 1188 }
... ...
public/stylesheets/application.css
... ... @@ -3216,7 +3216,7 @@ div#article-parent {
3216 3216 #agenda .calendar-day-out.selected {
3217 3217 background: none;
3218 3218 }
3219   -#agenda td {
  3219 +#agenda .agenda-calendar td {
3220 3220 vertical-align: middle;
3221 3221 }
3222 3222 #agenda .agenda-calendar .current-month caption {
... ...
public/stylesheets/search.css
... ... @@ -91,7 +91,8 @@
91 91 margin: 0px;
92 92 padding: 0px;
93 93 }
94   -.controller-search #product-categories-menu .sub-opening, .controller-search #product-categories-menu .sub-closeing {
  94 +.controller-search #product-categories-menu .sub-opening,
  95 +.controller-search #product-categories-menu .sub-closeing {
95 96 background-color: #FF8;
96 97 }
97 98 .controller-search #product-categories-menu .sub-opened {
... ... @@ -101,9 +102,13 @@
101 102 float: right;
102 103 }
103 104 .controller-search #content .search-results-box a.see-more {
  105 + z-index: 10;
104 106 position: absolute;
105 107 bottom: 0px;
106 108 right: 25px;
  109 + color: black;
  110 + text-decoration: none;
  111 + font-weight: bold;
107 112 font-size: 11px;
108 113 line-height: 11px;
109 114 background: #B8CFE7;
... ... @@ -116,10 +121,14 @@
116 121 color: #FFF;
117 122 text-decoration: none;
118 123 }
  124 +.controller-search .search-results-innerbox.common-profile-list-block {
  125 + overflow: hidden;
  126 +}
119 127 .controller-search .search-results-innerbox {
120   - padding: 8px 0px 10px 10px;
  128 + padding: 8px 10px 10px 10px;
  129 + overflow: auto;
  130 + overflow-x: hidden;
121 131 height: 230px;
122   - overflow: visible;
123 132 position: relative; /* work-arround-bug fo MSIE */
124 133 }
125 134 .controller-search .search-results-innerbox hr {
... ... @@ -138,7 +147,10 @@
138 147 height: 0px;
139 148 visibility: hidden;
140 149 }
141   -.controller-search #content .search-results-type-article ul, .controller-search #content .search-results-type-article li, .controller-search #content .search-results-type-event ul, .controller-search #content .search-results-type-event li {
  150 +.search-results-type-article ul,
  151 +.controller-search #content .search-results-type-article li,
  152 +.controller-search #content .search-results-type-event ul,
  153 +.controller-search #content .search-results-type-event li {
142 154 margin: 0px;
143 155 padding: 0px;
144 156 list-style: none;
... ... @@ -146,21 +158,19 @@
146 158 .controller-search #content .search-results-type-event li {
147 159 padding: 2px 0px 4px 0px;
148 160 }
149   -.controller-search #content .search-results-type-article li, .controller-search #content .search-results-type-event li {
150   - padding: 0px 0px 4px 20px;
  161 +.controller-search #content .search-results-type-article li {
  162 + padding: 10px 0;
151 163 background-repeat: no-repeat;
152   - border-color: transparent;
153 164 }
154   -.controller-search #content .search-results-type-article li:hover, .controller-search #content .search-results-type-event li:hover {
  165 +.controller-search #content .search-results-type-article li:hover,
  166 +.controller-search #content .search-results-type-event li:hover {
155 167 background-color: transparent;
156 168 }
157   -.controller-search .search-results-type-article .item_meta, .controller-search .search-results-type-event .item_meta {
  169 +.controller-search .search-results-type-article .item_meta,
  170 +.controller-search .search-results-type-event .item_meta {
158 171 font-size: 10px;
159 172 color: #888;
160 173 }
161   -.search-results-type-article.search-results-innerbox {
162   - overflow: auto;
163   -}
164 174 #content .only-one-result-box .search-results-enterprises li.vcard {
165 175 margin: 4.5px;
166 176 }
... ... @@ -171,19 +181,14 @@
171 181 min-height: 16px;
172 182 overflow: hidden;
173 183 }
174   -.controller-search #content .search-results-type-article ul {
  184 +.search-results-type-article ul {
175 185 margin: 0;
176   - padding:0;
177   -}
178   -.controller-search #content .search-results-type-article li.article-item,
179   -.controller-search .search-tagged-items li.article-item,
180   -.controller-search #content .only-one-result-box li.search-product-item {
181   - padding:0;
182   - border-bottom:1px solid #000;
183   - margin: 0 0 10px 0;
184   - padding: 0 0 10px 0;
185   - font-size: 11px;
186   - height: auto;
  186 + padding: 0;
  187 +}
  188 +.search-results-type-article li.article-item,
  189 +.search-tagged-items li.article-item,
  190 +.only-one-result-box li.search-product-item {
  191 + border-bottom: 1px solid #000;
187 192 }
188 193 .search-result-title {
189 194 display:inline-block;
... ... @@ -199,8 +204,6 @@
199 204 }
200 205 li.article-item .search-result-title {
201 206 color: #007788;
202   - clear:both;
203   - float:left;
204 207 }
205 208 .search-article-tags,
206 209 .search-uploaded-file-description,
... ... @@ -216,37 +219,24 @@ li.article-item .search-result-title {
216 219 clear: both;
217 220 }
218 221 .search-article-body {
219   - float: right;
220 222 width: 80%;
221 223 margin-bottom: 7px;
222 224 }
223 225 .search-field-none {
224 226 color: #ccc;
225 227 }
226   -.search-forum-items .search-field-label {
227   - height: 36px;
228   -}
229 228 .search-field-label {
230   - display: block;
231   - float: left;
232 229 font-size: 10px;
233 230 font-weight: bold;
234   - height: 18px;
235   - line-height: 18px;
236   - margin: 0 5px 0 0;
237 231 text-transform: uppercase;
238 232 width: 110px;
  233 + display: block;
239 234 }
240 235 .search-product-item-third-column .search-field-label {
241 236 width: 150px;
242 237 }
243   -li.article-item .search-article-tags-container,
244   -li.article-item .search-article-categories-container {
245   - display: block;
246   - min-height: 18px;
247   - line-height: 18px;
248   -}
249   -.search-article-tags .search-article-tag, .search-article-categories .search-article-category {
  238 +.search-article-tags .search-article-tag,
  239 +.search-article-categories .search-article-category {
250 240 background: #BBB;
251 241 padding:0 2px;
252 242 -moz-border-radius: 3px;
... ... @@ -260,10 +250,12 @@ li.article-item .search-article-categories-container {
260 250 color: #FFF;
261 251 font-size: 10px;
262 252 }
263   -.search-article-tags a.search-article-tag, .search-article-categories a.search-article-category {
  253 +.search-article-tags a.search-article-tag,
  254 +.search-article-categories a.search-article-category {
264 255 text-decoration:none;
265 256 }
266   -.search-article-tags a:hover.search-article-tag, .search-article-categories a:hover.search-article-category {
  257 +.search-article-tags a:hover.search-article-tag,
  258 +.search-article-categories a:hover.search-article-category {
267 259 background: #555753;
268 260 text-decoration:none;
269 261 }
... ... @@ -292,7 +284,8 @@ li.article-item .search-article-categories-container {
292 284 .search-results-innerbox .menu-submenu {
293 285 bottom: 107px;
294 286 }
295   -.controller-search .search-results-type-product, .controller-search .search-results-type-event {
  287 +.controller-search .search-results-type-product,
  288 +.controller-search .search-results-type-event {
296 289 overflow: auto;
297 290 }
298 291 li.search-product-item {
... ... @@ -364,8 +357,8 @@ li.search-product-item {
364 357 float: left;
365 358 font-size: 70%;
366 359 background-repeat: no-repeat;
367   - height: 18px;
368   - line-height: 18px;
  360 + height: 21px;
  361 + line-height: 21px;
369 362 }
370 363 .search-product-ecosol-percentage-icon-0 {
371 364 background-image: none;
... ... @@ -376,7 +369,8 @@ li.search-product-item {
376 369 .search-product-ecosol-percentage-icon-50 {
377 370 background-position: 0px -42px;
378 371 }
379   -.search-product-ecosol-percentage-icon-75 {
  372 +.search-product-ecosol-percentage-icon-75,
  373 +.search-product-ecosol-percentage-icon-100 {
380 374 background-position: 0px -63px;
381 375 }
382 376 .search-product-price-details {
... ... @@ -388,18 +382,23 @@ li.search-product-item {
388 382 .controller-search #category-comments {
389 383 margin-left: 55%;
390 384 }
391   -.controller-search #content .search-results-comments ul, .controller-search #content .search-results-comments li, .controller-search #content #category-comments ul, .controller-search #content #category-comments li {
  385 +.controller-search #content .search-results-comments ul,
  386 +.controller-search #content .search-results-comments li,
  387 +.controller-search #content #category-comments ul,
  388 +.controller-search #content #category-comments li {
392 389 margin: 0px;
393 390 padding: 0px;
394 391 list-style: none;
395 392 color: #888;
396 393 }
397   -.controller-search .search-results-comments .comment-picture, .controller-search #category-comments .comment-picture {
  394 +.controller-search .search-results-comments .comment-picture,
  395 +.controller-search #category-comments .comment-picture {
398 396 width: 20px;
399 397 height: 20px;
400 398 margin: -2px 5px 0px 0px;
401 399 }
402   -.controller-search #content .search-results-type-product ul, .controller-search #content .search-results-type-product li {
  400 +.controller-search #content .search-results-type-product ul,
  401 +.controller-search #content .search-results-type-product li {
403 402 margin: 0px;
404 403 padding: 0px;
405 404 list-style: none;
... ... @@ -572,7 +571,9 @@ li.search-product-item hr {
572 571 border: none;
573 572 background: none;
574 573 }
575   -.search-product-item-first-column, .search-product-item-second-column, .search-product-item-third-column {
  574 +.search-product-item-first-column,
  575 +.search-product-item-second-column,
  576 +.search-product-item-third-column {
576 577 float: left;
577 578 margin:0 !important;
578 579 }
... ... @@ -600,7 +601,6 @@ li.search-product-item hr {
600 601 }
601 602 .only-one-result-box .common-profile-list-block {
602 603 float: left;
603   - margin: 10px;
604 604 }
605 605 .search-enterprise-item {
606 606 border-bottom: 1px solid #ccc;
... ... @@ -760,30 +760,41 @@ form .search-field input:hover.button.submit {
760 760 background-repeat: no-repeat;
761 761 padding: 0 0 0 20px;
762 762 }
763   -.facet-menu a.facet-options-toggle.facet-more-options, .facet-menu a.facet-options-toggle {
  763 +.facet-menu a.facet-options-toggle.facet-more-options,
  764 +.facet-menu a.facet-options-toggle {
764 765 background-position: 0 0;
765 766 }
766 767 .facet-menu a.facet-options-toggle.facet-less-options {
767 768 background-position: 0 -32px;
768 769 }
769 770  
770   -.search-uploaded-file-first-column,
771   -.search-text-article-first-column,
772 771 .search-content-first-column {
773   - clear: both;
774   - float: left;
775   - margin: 0 10px 0 0;
776 772 width: 130px;
777   - min-height:98px;
  773 + min-height: 98px;
  774 + position: absolute;
778 775 }
779   -.search-uploaded-file-second-column,
780   -.search-text-article-second-column,
781 776 .search-content-second-column {
782   - float: left;
783   - width: 570px;
  777 + margin-left: 140px;
  778 + width: auto;
  779 +}
  780 +.search-content-second-column tr:hover {
  781 + background-color: none;
  782 +}
  783 +.search-content-second-column td {
  784 + height: auto;
  785 +}
  786 +.search-results-articles li {
  787 + position: relative;
  788 +}
  789 +
  790 +a.search-blog-sample-item.icon,
  791 +.search-folder-items a,
  792 +.search-forum-items a,
  793 +.search-blog-items a {
  794 + border: none;
  795 + margin-bottom: 3px;
  796 + display: block;
784 797 }
785   -ul.clean-list .search-uploaded-file-second-column,
786   -ul.clean-list .search-text-article-second-column,
787 798 ul.clean-list .search-content-second-column {
788 799 width:795px;
789 800 }
... ... @@ -864,10 +875,7 @@ a.search-image-pic {
864 875 }
865 876 .search-content-first-column .icon-application-vnd-oasis-opendocument-text,
866 877 .search-content-first-column .icon-application-vnd-oasis-opendocument-spreadsheet,
867   -.search-content-first-column .icon-text-content,
868   -.search-uploaded-file-first-column .icon-application-vnd-oasis-opendocument-text,
869   -.search-uploaded-file-first-column .icon-application-vnd-oasis-opendocument-spreadsheet,
870   -.search-text-article-first-column .icon-text-content {
  878 +.search-content-first-column .icon-text-content {
871 879 display:block;
872 880 width: 16px;
873 881 height: 16px;
... ... @@ -879,18 +887,6 @@ a.search-image-pic {
879 887 margin: auto;
880 888  
881 889 }
882   -.search-content-first-column .icon-application-vnd-oasis-opendocument-spreadsheet,
883   -.search-content-first-column .icon-application-vnd-oasis-opendocument-spreadsheet {
884   -
885   -}
886   -.search-content-first-column .icon-application-opendocument-spreadsheet,
887   -.search-uploaded-file-first-column .icon-application-opendocument-spreadsheet {
888   -
889   -}
890   -.search-content-first-column .icon-text-content,
891   -.search-text-article-first-column .icon-text-content {
892   -
893   -}
894 890 .search-uploaded-file-line {
895 891 clear: both;
896 892 float: left;
... ... @@ -904,7 +900,6 @@ a.search-image-pic {
904 900 width: 130px;
905 901 height: 130px;
906 902 display: block;
907   -
908 903 }
909 904 #search-input {
910 905 font-size: 140%;
... ... @@ -933,7 +928,8 @@ a.search-image-pic {
933 928 font-style: italic;
934 929 color: gray;
935 930 }
936   -.search-relevance, .search-result-text {
  931 +.search-relevance,
  932 +.search-result-text {
937 933 margin-left: 40px;
938 934 }
939 935  
... ...