Permalink
Browse files

Initial commit.

  • Loading branch information...
0 parents commit 15119fb07e295404a1712ca35f073d50421b83c5 Steph Skardal committed Feb 23, 2011
@@ -0,0 +1,3 @@
+= Search Tag Cloud
+
+Description goes here
@@ -0,0 +1,41 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the search_tag_cloud extension.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+namespace :test do
+ desc 'Functional test the search_tag_cloud extension.'
+ Rake::TestTask.new(:functionals) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/functional/*_test.rb'
+ t.verbose = true
+ end
+
+ desc 'Unit test the search_tag_cloud extension.'
+ Rake::TestTask.new(:units) do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/unit/*_test.rb'
+ t.verbose = true
+ end
+end
+
+desc 'Generate documentation for the search_tag_cloud extension.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'SearchTagCloudExtension'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README.markdown')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
+
+# Load any custom rakefiles for extension
+Dir[File.dirname(__FILE__) + '/lib/tasks/*.rake'].sort.each { |f| require f }
@@ -0,0 +1,15 @@
+class Admin::SearchTagCloudsController < Admin::BaseController
+ def index
+ @search_records = SearchRecord.all.collect { |r| [r.count, r.term] }.sort.reverse[0..Spree::SearchTagCloud::Config[:count]]
+ max = @search_records.empty? ? 1 : @search_records.first.first
+
+ #solution is: a*x_factor - y_shift = font size
+ x_factor = (Spree::SearchTagCloud::Config[:max] - Spree::SearchTagCloud::Config[:min]) / max.to_f
+ y_shift = max.to_f*x_factor - Spree::SearchTagCloud::Config[:max]
+
+ @search_records_cloud = @search_records.shuffle.inject([]) do |a, b|
+ a.push([b[0].to_f*x_factor - y_shift, b[1]])
+ a
+ end
+ end
+end
@@ -0,0 +1,2 @@
+module SearchTagCloudHelper
+end
@@ -0,0 +1,5 @@
+class SearchRecord < ActiveRecord::Base
+ def self.filter(term)
+ term.gsub(/\+/, ' ').gsub(/^\s+/, '').gsub(/\s+$/, '').downcase.gsub(/[^a-z\s-]/, '')
+ end
+end
@@ -0,0 +1,33 @@
+<% content_for :head do -%>
+<%= stylesheet_link_tag 'search_tag_cloud.css' %>
+<% end -%>
+
+<div id="tag_cloud">
+<% @search_records_cloud.each do |b| %>
+<span style="font-size:<%= b[0] %>px;"><%= b[1] %></span>
+<% end -%>
+</div>
+
+<table id="search_results" class="tablesorter">
+ <thead>
+ <tr>
+ <th>Search Term</th>
+ <th>Count</th>
+ </tr>
+ </thead>
+ <tbody>
+ <% @search_records.each do |b| %>
+ <tr>
+ <td><%= b[1] %></td>
+ <td><%= b[0] %></td>
+ </tr>
+ <% end -%>
+ </tbody>
+</table>
+
+<script type="text/javascript">
+$(function() {
+ $('#search_results').tablesorter();
+});
+</script>
+<script src="/javascripts/jquery.tablesorter.min.js"></script>
@@ -0,0 +1,3 @@
+map.namespace :admin do |admin|
+ admin.resources :search_tag_clouds, :only => [:index]
+end
@@ -0,0 +1,12 @@
+class CreateSearchRecords < ActiveRecord::Migration
+ def self.up
+ create_table :search_records do |t|
+ t.string :term
+ t.integer :count, :null => false, :default => 0
+ end
+ end
+
+ def self.down
+ drop_table :search_records
+ end
+end
@@ -0,0 +1,5 @@
+class SearchTagCloudConfiguration < Configuration
+ preference :count, :integer, :default => 100
+ preference :max, :float, :default => 25
+ preference :min, :float, :default => 8
+end
@@ -0,0 +1,22 @@
+module Spree
+ module SearchTagCloud
+ # Singleton class to access the google base configuration object (SearchTagCloudConfiguration.first by default) and it's preferences.
+ #
+ # Usage:
+ # Spree::SearchTagCloud::Config[:foo] # Returns the foo preference
+ # Spree::SearchTagCloud::Config[] # Returns a Hash with all the google base preferences
+ # Spree::SearchTagCloud::Config.instance # Returns the configuration object (SearchTagCloudConfiguration.first)
+ # Spree::SearchTagCloud::Config.set(preferences_hash) # Set the google base preferences as especified in +preference_hash+
+ class Config
+ include Singleton
+ include PreferenceAccess
+
+ class << self
+ def instance
+ return nil unless ActiveRecord::Base.connection.tables.include?('configurations')
+ SearchTagCloudConfiguration.find_or_create_by_name("Default product reviews and ratings configuration")
+ end
+ end
+ end
+ end
+end
@@ -0,0 +1,16 @@
+module Spree::SearchTagCloud::ProductsController
+ def self.included(controller)
+ controller.class_eval do
+ controller.append_after_filter :record_search, :only => :index
+ end
+ end
+
+ def record_search
+ if params[:keywords]
+ term = SearchRecord.filter(params[:keywords])
+ return if term == ''
+ record = SearchRecord.find_or_initialize_by_term(term)
+ record.update_attribute(:count, record.count+1)
+ end
+ end
+end
@@ -0,0 +1,17 @@
+namespace :spree do
+ namespace :extensions do
+ namespace :search_tag_cloud do
+ desc "Copies public assets of the Search Tag Cloud to the instance public/ directory."
+ task :update => :environment do
+ is_svn_git_or_dir = proc {|path| path =~ /\.svn/ || path =~ /\.git/ || File.directory?(path) }
+ Dir[SearchTagCloudExtension.root + "/public/**/*"].reject(&is_svn_git_or_dir).each do |file|
+ path = file.sub(SearchTagCloudExtension.root, '')
+ directory = File.dirname(path)
+ puts "Copying #{path}..."
+ mkdir_p Rails.root + directory
+ cp file, Rails.root + path
+ end
+ end
+ end
+ end
+end
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,9 @@
+/* tables */
+table.tablesorter { font-family:arial; background-color: #CDCDCD; margin:10px 0pt 15px; font-size: 8pt; width: 100%; text-align: left; }
+table.tablesorter thead tr th, table.tablesorter tfoot tr th { background-color: #e6EEEE; border: 1px solid #FFF; font-size: 8pt; padding: 4px; }
+table.tablesorter thead tr .header { background-image: url(/images/search_tag_cloud/bg.gif); background-repeat: no-repeat; background-position: center right; cursor: pointer; }
+table.tablesorter tbody td { color: #3D3D3D; padding: 4px; background-color: #FFF; vertical-align: top; }
+table.tablesorter tbody tr.odd td { background-color:#F0F0F6; }
+table.tablesorter thead tr .headerSortUp { background-image: url(/images/search_tag_cloud/asc.gif); }
+table.tablesorter thead tr .headerSortDown { background-image: url(/images/search_tag_cloud/desc.gif); }
+table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp { background-color: #8dbdd8; }
@@ -0,0 +1,12 @@
+# Uncomment this if you reference any of your controllers in activate
+# require_dependency 'application'
+
+class SearchTagCloudExtension < Spree::Extension
+ version "1.0"
+ description "Search Tag Cloud to report search statistics and generate tag cloud"
+ url "http://www.endpoint.com/"
+
+ def activate
+ Spree::ProductsController.send(:include, Spree::SearchTagCloud::ProductsController)
+ end
+end
@@ -0,0 +1,43 @@
+class SearchTagCloudHooks < Spree::ThemeSupport::HookListener
+
+ #
+ # In this file you can modify the content of the hooks available in the default templates
+ # and avoid overriding a template in many situations. Multiple extensions can modify the
+ # same hook, the changes being applied cumulatively based on extension load order
+ #
+ # Most hooks are defined with blocks so they span a region of the template, allowing content
+ # to be replaced or removed as well as added to.
+ #
+ # Usage
+ #
+ # The following methods are available
+ #
+ # * insert_before
+ # * insert_after
+ # * replace
+ # * remove
+ #
+ # All accept a block name symbol followed either by arguments that would be valid for 'render'
+ # or a block which returns the string to be inserted. The block will have access to any methods
+ # or instance variables accessible in your views
+ #
+ # Examples
+ #
+ # insert_before :homepage_products, :text => "<h1>Welcome!</h1>"
+ # insert_after :homepage_products, 'shared/offers' # renders a partial
+ # replace :taxon_sidebar_navigation, 'shared/my_sidebar
+ #
+ # adding a link below product details:
+ #
+ # insert_after :product_description do
+ # '<p>' + link_to('Back to products', products_path) + '</p>'
+ # end
+ #
+ # adding a new tab to the admin navigation
+ #
+ # insert_after :admin_tabs do
+ # tab(:taxonomies)
+ # end
+ #
+
+end

0 comments on commit 15119fb

Please sign in to comment.