Skip to content
Browse files

setup skeleton

  • Loading branch information...
0 parents commit 43426e93c8131cdda92f7099edfa4694c12787da @taweili committed Jun 10, 2011
9 .gitignore
@@ -0,0 +1,9 @@
+\#*
+*~
+.#*
+.DS_Store
+.idea
+.project
+tmp
+nbproject
+*.swp
23 LICENSE
@@ -0,0 +1,23 @@
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the Rails Dog LLC nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15 README.md
@@ -0,0 +1,15 @@
+SpreeFbtabViews
+================
+
+Adds support of mobile devices to Spree stores through jQuery Mobile.
+
+
+Installation
+============
+
+1. Add following line to Gemfile: `gem 'spree_fbtab_views'`
+1. Run `bundle install`
+1. Run `rake spree_fbtab_views:install:assets`
+
+
+Copyright (c) 2011 Roman Smirnov, released under the New BSD License
75 Rakefile
@@ -0,0 +1,75 @@
+require 'rubygems'
+require 'rake'
+require 'rake/testtask'
+require 'rake/packagetask'
+require 'rake/gempackagetask'
+
+gemfile = File.expand_path('../spec/test_app/Gemfile', __FILE__)
+if File.exists?(gemfile) && (%w(spec cucumber).include?(ARGV.first.to_s) || ARGV.size == 0)
+ require 'bundler'
+ ENV['BUNDLE_GEMFILE'] = gemfile
+ Bundler.setup
+
+ require 'rspec'
+ require 'rspec/core/rake_task'
+ RSpec::Core::RakeTask.new
+
+ require 'cucumber/rake/task'
+ Cucumber::Rake::Task.new do |t|
+ t.cucumber_opts = %w{--format progress}
+ end
+end
+
+desc "Default Task"
+task :default => [:spec, :cucumber ]
+
+spec = eval(File.read('spree_fbtab_views.gemspec'))
+
+Rake::GemPackageTask.new(spec) do |p|
+ p.gem_spec = spec
+end
+
+desc "Release to gemcutter"
+task :release => :package do
+ require 'rake/gemcutter'
+ Rake::Gemcutter::Tasks.new(spec).define
+ Rake::Task['gem:push'].invoke
+end
+
+desc "Default Task"
+task :default => [ :spec ]
+
+desc "Regenerates a rails 3 app for testing"
+task :test_app do
+ require '../spree/lib/generators/spree/test_app_generator'
+ class SpreeMobileViewTestAppGenerator < Spree::Generators::TestAppGenerator
+
+ def install_gems
+ inside "test_app" do
+ run 'rake spree_core:install'
+ run 'rake spree_fbtab_views:install'
+ end
+ end
+
+ def migrate_db
+ run_migrations
+ end
+
+ protected
+ def full_path_for_local_gems
+ <<-gems
+gem 'spree_core', :path => \'#{File.join(File.dirname(__FILE__), "../spree/", "core")}\'
+gem 'spree_fbtab_views', :path => \'#{File.dirname(__FILE__)}\'
+ gems
+ end
+
+ end
+ SpreeMobileViewTestAppGenerator.start
+end
+
+namespace :test_app do
+ desc 'Rebuild test and cucumber databases'
+ task :rebuild_dbs do
+ system("cd spec/test_app && rake db:drop db:migrate RAILS_ENV=test && rake db:drop db:migrate RAILS_ENV=cucumber")
+ end
+end
1 Versionfile
@@ -0,0 +1 @@
+"0.50.x" => { :branch => "master" }
4 app/controllers/products_controller_decorator.rb
@@ -0,0 +1,4 @@
+ProductsController.class_eval do
+ def search
+ end
+end
116 app/fbtab_views/checkout/_address.html.erb
@@ -0,0 +1,116 @@
+<fieldset id='billing' data-role="fieldcontain">
+ <%= form.fields_for :bill_address do |bill_form| %>
+ <legend><%= t("billing_address")%></legend>
+ <div class="inner">
+ <p id="bfname" class="field">
+ <%= bill_form.label :firstname, [t(:first_name), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= bill_form.text_field :firstname, :class => 'required' %>
+ </p>
+ <p id="blname" class="field">
+ <%= bill_form.label :lastname, [t(:last_name), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= bill_form.text_field :lastname, :class => 'required' %>
+ </p>
+ <p id="baddress" class="field">
+ <%= bill_form.label :address1, [t(:street_address), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= bill_form.text_field :address1, :class => 'required' %>
+ </p>
+ <p id="baddress2" class="field">
+ <%= bill_form.label :address2, t(:street_address_2) %>
+ <%= bill_form.text_field :address2 %>
+ </p>
+ <p id="bcity" class="field">
+ <%= bill_form.label :city, [t(:city), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= bill_form.text_field :city, :class => 'required' %>
+ </p>
+ <% if Spree::Config[:address_requires_state] %>
+ <p class="field">
+ <span id="bstate">
+ <% have_states = !@order.bill_address.country.states.empty? %>
+ <%= bill_form.label :state_name, [t(:state), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= bill_form.text_field :state_name, :class => 'required' %>
+ </span>
+ </p>
+ <% end %>
+ <p id="bzip" class="field">
+ <%= bill_form.label :zipcode, [t(:zip), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= bill_form.text_field :zipcode, :class => 'required' %>
+ </p>
+ <p id="bcountry" class="field">
+ <%= bill_form.label :country_id, [t(:country), '<span class="req">*</span>'].join(' ').html_safe %><br />
+ <%= bill_form.collection_select :country_id, available_countries, :id, :name, {}, {:class => 'required'} %>
+ </p>
+ <p id="bphone" class="field">
+ <%= bill_form.label :phone, [t(:phone), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= bill_form.text_field :phone, :class => 'required' %>
+ </p>
+ <% if Spree::Config[:alternative_billing_phone] %>
+ <p id="baltphone">
+ <%= bill_form.label :alternative_phone, t(:alternative_phone) %>
+ <%= bill_form.text_field :alternative_phone %>
+ </p>
+ <% end %>
+ </div>
+ <% end %>
+</fieldset>
+<fieldset id='shipping' data-role="fieldcontain">
+ <%= form.fields_for :ship_address do |ship_form| %>
+ <legend><%= t("shipping_address")%></legend>
+ <p class="field checkbox">
+ <label for="order_use_billing" id="use_billing">
+ <%= check_box_tag 'order[use_billing]', '1', (!(@order.bill_address.empty? && @order.ship_address.empty?) && @order.bill_address.eql?(@order.ship_address)) %> <%= t("use_billing_address") %>
+ </label>
+ </p>
+ <div class="inner">
+ <p id="sfname" class="field">
+ <%= ship_form.label :firstname, [t(:first_name), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= ship_form.text_field :firstname, :class => 'required' %>
+ </p>
+ <p id="slname" class="field">
+ <%= ship_form.label :lastname, [t(:last_name), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= ship_form.text_field :lastname, :class => 'required' %>
+ </p>
+ <p id="saddress" class="field">
+ <%= ship_form.label :address1, [t(:street_address), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= ship_form.text_field :address1, :class => 'required' %>
+ </p>
+ <p id="saddress2" class="field">
+ <%= ship_form.label :address2, t(:street_address_2) %>
+ <%= ship_form.text_field :address2 %>
+ </p>
+ <p id="scity" class="field">
+ <%= ship_form.label :city, [t(:city), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= ship_form.text_field :city, :class => 'required' %>
+ </p>
+ <% if Spree::Config[:address_requires_state] %>
+ <p class="field">
+ <span id="sstate">
+ <% have_states = !@order.ship_address.country.states.empty? %>
+ <%= ship_form.label :state_name, [t(:state), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= ship_form.text_field :state_name, :class => 'required' %>
+ </span>
+ </p>
+ <% end %>
+ <p id="szip" class="field">
+ <%= ship_form.label :zipcode, [t(:zip), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= ship_form.text_field :zipcode, :class => 'required' %>
+ </p>
+ <p id="scountry" class="field">
+ <%= ship_form.label :country_id, [t(:country), '<span class="req">*</span>'].join(' ').html_safe %><br />
+ <%= ship_form.collection_select :country_id, available_countries, :id, :name, {}, {:class => 'required'} %>
+ </p>
+ <p id="sphone" class="field">
+ <%= ship_form.label :phone, [t(:phone), '<span class="req">*</span>'].join(' ').html_safe %>
+ <%= ship_form.text_field :phone, :class => 'required' %>
+ </p>
+ <% if Spree::Config[:alternative_shipping_phone] %>
+ <p id="saltphone">
+ <%= ship_form.label :alternative_phone, t(:alternative_phone) %>
+ <%= ship_form.text_field :alternative_phone %>
+ </p>
+ <% end %>
+ </div>
+ <% end %>
+</fieldset>
+
+<input type="submit" value="<%=t("save_and_continue") %>" />
+
24 app/fbtab_views/checkout/_delivery.html.erb
@@ -0,0 +1,24 @@
+<fieldset id='shipping_method'>
+ <legend><%= t("shipping_method") %></legend>
+ <div data-role="fieldcontain">
+ <fieldset data-role="controlgroup">
+ <% @order.rate_hash.each do |shipping_method| %>
+ <%= form.label(['shipping_method_id', shipping_method[:id].to_s].join('_'),
+ "#{shipping_method[:name]} #{number_to_currency(shipping_method[:cost])}") %>
+ <%= radio_button(:order, :shipping_method_id, shipping_method[:id]) %>
+ <% end %>
+ </p>
+ </fieldset>
+ </div>
+ <% if Spree::Config[:shipping_instructions] && @order.rate_hash.present? %>
+ <div data-role="fieldcontain">
+ <%= form.label :special_instructions, t("shipping_instructions") %><br />
+ <%= form.text_area :special_instructions, :cols => 40, :rows => 7 %>
+ </div>
+ <% end %>
+</fieldset>
+
+<div class="form-buttons">
+ <input type="submit" value="<%=t("save_and_continue") %>"/>
+</div>
+
27 app/fbtab_views/checkout/_payment.html.erb
@@ -0,0 +1,27 @@
+<fieldset id="payment">
+ <legend><%= t("payment_information") %></legend>
+ <%= hook :checkout_payment_step, {:form => form} do %>
+ <div data-role="fieldcontain">
+ <fieldset data-role="controlgroup">
+ <% @order.available_payment_methods.each do |method| %>
+ <%= form.label "payments_attributes__payment_method_id_#{method.id}", t(method.name, :scope => :payment_methods, :default => method.name) %>
+ <%= radio_button_tag "order[payments_attributes][][payment_method_id]", method.id, method == @order.payment_method %>
+ <% end %>
+ </fieldset>
+ </div>
+ <div id="payment-methods">
+ <% @order.available_payment_methods.each do |method| %>
+ <fieldset>
+ <%= render "checkout/payment/#{method.method_type}", :payment_method => method %>
+ </fieldset>
+ </li>
+ <% end %>
+ </div>
+ <br style='clear:both;' />
+ <%= hook :coupon_code_field, {:form => form} %>
+ <% end %>
+</fieldset>
+
+<div class="form-buttons">
+ <input type="submit" class="continue button primary" value="<%=t("save_and_continue") %>" />
+</div>
14 app/fbtab_views/checkout/edit.html.erb
@@ -0,0 +1,14 @@
+<div id="checkout">
+ <h1><%= t("checkout")%></h1>
+ <%= checkout_progress %>
+ <br clear="left" />
+ <%= render "shared/error_messages", :target => @order %>
+ <%= hook :checkout_summary_box do %>
+ <div id="checkout-summary">
+ <%= render 'summary', :order => @order %>
+ </div>
+ <% end %>
+ <%= form_for @order, :url => update_checkout_path(@order.state), :html => { :id => "checkout_form_#{@order.state}" } do |form| %>
+ <%= render @order.state, :form => form %>
+ <% end %>
+</div>
32 app/fbtab_views/checkout/payment/_gateway.html.erb
@@ -0,0 +1,32 @@
+<legend><%= payment_method.name %><legend>
+<%= image_tag "creditcard.gif", :id => 'creditcard-image' %>
+<% param_prefix = "payment_source[#{payment_method.id}]" %>
+
+<div data-role="fieldcontain">
+ <%= label_tag "#{param_prefix}_number", t("card_number") %>
+ <% options_hash = Rails.env.production? ? {:autocomplete => "off"} : {} %>
+ <%= text_field_tag "#{param_prefix}[number]", '', options_hash.merge(:id => 'card_number', :class => 'required', :size => 19, :maxlength => 19) %>
+ <span class="req">*</span>
+ &nbsp;
+ <span id="card_type" style="display:none;">
+ ( <span id="looks_like" ><%= t('card_type_is') %> <span id="type"></span></span>
+ <span id="unrecognized"><%= t('unrecognized_card_type') %></span>
+ )
+ </span>
+</div>
+<div data-role="fieldcontain">
+ <label for=""><%= t("expiration") %></label><br />
+ <%= select_month(Date.today, :prefix => param_prefix, :field_name => 'month', :use_month_numbers => true, :class => 'required') %>
+ <%= select_year(Date.today, :prefix => param_prefix, :field_name => 'year', :start_year => Date.today.year, :end_year => Date.today.year + 15, :class => 'required') %>
+ <span class="req">*</span>
+</div>
+<div data-role="fieldcontain">
+ <label for=""><%= t("card_code") %></label><br />
+ <%= text_field_tag "#{param_prefix}[verification_value]", '', options_hash.merge(:id => 'card_code', :class => 'required', :size => 5) %>
+ <span class="req">*</span>
+ <a href="/content/cvv" target="_blank" onclick="window.open(this.href,'cvv_info','left=20,top=20,width=500,height=500,toolbar=0,resizable=0,scrollbars=1');return false">
+ (<%= t("whats_this") %>)
+ </a>
+</div>
+<%= hidden_field param_prefix, 'first_name', :value => @order.billing_firstname %>
+<%= hidden_field param_prefix, 'last_name', :value => @order.billing_lastname %>
68 app/fbtab_views/layouts/spree_application.html.erb
@@ -0,0 +1,68 @@
+<html>
+ <head>
+ <title><%= title %></title>
+ <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.css" />
+ <script src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
+ <script type="text/javascript">
+ //<![CDATA[
+ $(document).bind("mobileinit", function(){
+ $.mobile.ajaxEnabled = false;
+ });
+ //]]>
+ </script>
+ <script src="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.js"></script>
+ <%= javascript_include_tag 'rails' %>
+ <%= stylesheet_link_tag 'mobile' %>
+ <%= csrf_meta_tag %>
+ </head>
+ <body>
+ <div data-role="page">
+ <div data-role="header">
+ <a href="/" id='home_link' data-icon="home" data-ajax="false" class="ui-btn-left">&nbsp;</a>
+ <h1><%= title %></h1>
+ <a href="?mobile=0" data-icon="gear" data-ajax="false" class="ui-btn-right"><%= t(:full_site)%></a>
+ <div data-role="navbar">
+ <ul>
+ <% if current_user %>
+ <li><%= link_to t('my_account'), account_path, :class => css_class(account_path) %></li>
+ <li><%= link_to t('logout'), destroy_user_session_path %></li>
+ <% else %>
+ <li><%= link_to t('log_in'), login_path, :class => css_class(login_path) %></li>
+ <% end %>
+ <li><%= link_to t(:search), search_path, :class => css_class(search_path) %></li>
+ <li><%= link_to_cart %></li>
+ </ul>
+ </div>
+
+ <% [:notice, :error].each do |message_type| %>
+ <% if flash[message_type] %>
+ <script>
+ $("<div class='ui-loader ui-overlay-shadow <%= (message_type == :error) ? 'ui-body-a' : 'ui-body-e' %> ui-corner-all'><h1><%= flash[message_type] %></h1></div>")
+ .css({ "display": "block", "opacity": 0.96, "top": $(window).scrollTop() + 100 })
+ .appendTo( $.mobile.pageContainer )
+ .delay( 2500 )
+ .fadeOut( 400, function(){
+ $(this).remove();
+ });
+ </script>
+ <noscript>
+ <div data-role="navbar">
+ <%= flash[message_type] %>
+ </div>
+ </noscript>
+ <% end %>
+ <% end %>
+
+ </div>
+ <div data-role="content">
+ <%= yield %>
+ </div>
+ <div data-role="footer">
+ <div id="footer-left" data-hook="footer_left">
+ <p><%= t("powered_by") %> <a href="http://spreecommerce.com/">Spree</a></p>
+ </div>
+ <div id="footer-right" data-hook="footer_right"></div>
+ </div>
+ <%= render 'shared/google_analytics' %>
+ </body>
+</html>
18 app/fbtab_views/orders/_form.html.erb
@@ -0,0 +1,18 @@
+<%= render "shared/error_messages", :target => @order %>
+<table id="cart-detail" data-role="listview">
+ <thead>
+ <tr class="ui-bar-b">
+ <%= hook :cart_items_headers do %>
+ <th><%= t("item") %></th>
+ <th><%= t("price") %></th>
+ <th><%= t("qty") %></th>
+ <th><%= t("total") %></th>
+ <% end %>
+ </tr>
+ </thead>
+ <tbody id="line_items">
+ <%= order_form.fields_for :line_items do |item_form| %>
+ <%= render 'line_item', :variant => item_form.object.variant, :line_item => item_form.object, :item_form => item_form %>
+ <% end %>
+ </tbody>
+</table>
32 app/fbtab_views/orders/_line_item.html.erb
@@ -0,0 +1,32 @@
+<tr class="<%= cycle('', 'alt') %>">
+ <%- locals = {:item_form => item_form, :variant => variant, :line_item => line_item} %>
+ <td>
+ <%= hook :cart_item_description, locals do %>
+ <p><%= link_to variant.product.name, product_path(variant.product) %></p>
+ <p><%= variant_options variant %></p>
+ <p><%= truncate(variant.product.description, :length => 70, :omission => "...") %></p>
+ <% end %>
+ </td>
+ <td>
+ <%= hook :cart_item_price, locals do %>
+ <%= product_price(line_item) %>
+ <% end %>
+ </td>
+ <td>
+ <%= hook :cart_item_quantity, locals do %>
+ <%= item_form.text_field :quantity, :size => 3, :class => "line_item_quantity" %>
+ <% end %>
+ </td>
+
+ <td>
+ <%= hook :cart_item_total, locals do %>
+ <%= format_price(product_price(line_item, :format_as_currency => false) * line_item.quantity) unless line_item.quantity.nil? %>
+ <% end %>
+ </td>
+ <td style='display:none'>
+ <%= hook :cart_item_delete, locals do %>
+ <%= link_to(image_tag('/images/admin/icons/delete.png'), '#', :class => 'delete') %>
+ <% end %>
+ </td>
+
+</tr>
43 app/fbtab_views/orders/edit.html.erb
@@ -0,0 +1,43 @@
+<% if @order.line_items.empty? %>
+
+ <%= hook :empty_cart do %>
+ <p><%= t("your_cart_is_empty.") %></p>
+ <p><%= link_to t("continue_shopping"), products_path, :class => 'button continue' %></p>
+ <% end %>
+
+<% else %>
+ <%= hook :outside_cart_form do %>
+ <%= form_for(@order, :url => update_cart_path, :html=>{:id=>'updatecart'}) do |order_form| %>
+ <%= hook :inside_cart_form do %>
+
+ <%= hook :cart_items do %>
+ <%= render :partial => 'form', :locals => {:order_form => order_form} %>
+ <% end %>
+
+ <div id="subtotal">
+ <h3><%= "#{t("subtotal")}: #{order_price(@order)}" %></h3>
+ </div>
+ <fieldset class="ui-grid-a">
+ <div class="ui-block-a">
+ <input type="submit" value="<%= t('update') %>" data-icon="refresh" />
+ </div>
+ <div class="ui-block-b">
+ <%= link_to t("checkout"), checkout_path, "data-role" => "button", "data-icon" => "gear" %>
+ </div>
+ <div class="ui-block-a">
+ <%= link_to t("continue_shopping"), root_path, "data-role" => "button", "data-icon" => "back" %>
+ </div>
+ </fieldset>
+ <% end %>
+ <% end %>
+ <% end %>
+
+ <%= form_tag empty_cart_path, :method => :put do %>
+ <fieldset class="ui-grid-a">
+ <div class="ui-block-a">
+ <input type="submit" value="<%= t('empty_cart') %>" data-icon="delete" />
+ </div>
+ </fieldset>
+ <% end %>
+
+<% end %>
50 app/fbtab_views/products/_cart_form.html.erb
@@ -0,0 +1,50 @@
+<%= form_for :order, :url => populate_orders_path do |f| %>
+<%= hook :inside_product_cart_form do %>
+
+ <% if product_price(@product) %>
+ <%= hook :product_price do %>
+ <p class="prices">
+ <%= t("price") %>:
+ <span class="price selling"><strong><%= product_price(@product) %></strong></span>
+ </p>
+ <% end %>
+ <% end %>
+
+ <% if @product.has_variants? %>
+ <div data-role="fieldcontain" id="product-variants">
+ <h4><%= t('variants') %></h4>
+ <fieldset data-role="controlgroup">
+ <% has_checked = false
+ @product.variants.active.each_with_index do |v,index|
+ next if v.option_values.empty? || (!v.in_stock && !Spree::Config[:show_zero_stock_products])
+ checked = !has_checked && (v.in_stock || Spree::Config[:allow_backorders])
+ has_checked = true if checked %>
+
+ <%= radio_button_tag "products[#{@product.id}]", v.id, checked, :disabled => !v.in_stock && !Spree::Config[:allow_backorders] %>
+ <label for="products_<%= [@product.id, v.id].join('_') %>">
+ <%= variant_options v %>
+
+ <% if variant_price_diff v %>
+ <span class="price diff"><%= variant_price_diff v %></span>
+ <% end %>
+ </label>
+ <% end%>
+ </fieldset>
+ </div>
+ <% end%>
+
+ <% if @product.has_stock? || Spree::Config[:allow_backorders] %>
+ <fieldset class="ui-grid-a">
+ <div>
+ <%= text_field_tag((@product.has_variants? ? :quantity : "variants[#{@product.master.id}]"), 1, :maxlength => 5, :style => "width:5em", 'data-inline' => "true") %>
+ <button type='submit' data-inline="true" data-icon="plus">
+ <%= t('add_to_cart') %>
+ </button>
+ </div>
+ </fieldset>
+ <% else %>
+ <%= content_tag('strong', t('out_of_stock')) %>
+ <% end %>
+
+<% end %>
+<% end %>
5 app/fbtab_views/products/index.html.erb
@@ -0,0 +1,5 @@
+<% if current_page?('/') && params[:keywords].nil? %>
+ <%= render :template => "taxons/index" %>
+<% else %>
+ <%= render :partial => "shared/products" %>
+<% end %>
11 app/fbtab_views/products/search.html.erb
@@ -0,0 +1,11 @@
+<%= form_tag products_url, :method => :get do %>
+<div class="ui-grid-b">
+ <div data-role="fieldcontain">
+ <%= text_field_tag :keywords, params[:keywords], 'type' => 'search' %>
+ </div>
+ <div class="ui-block-a">&nbsp;</div>
+ <div class="ui-block-b">
+ <%= submit_tag t(:search), :name => nil %>
+ </div>
+</div>
+<% end %>
31 app/fbtab_views/products/show.html.erb
@@ -0,0 +1,31 @@
+<div data-role="content">
+ <h1><%= @product.name %></h1>
+ <table>
+ <tr>
+ <td id="main-image">
+ <%= render 'image' %>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <%= hook :cart_form do %>
+ <div id="cart-form">
+ <%= render 'cart_form' %>
+ </div>
+ <% end %>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+ <div id="product-description">
+ <%= hook :product_description do %>
+ <%= product_description(@product) rescue t("product_has_no_description") %>
+ <% end %>
+ <%= hook :product_properties do %>
+ <%= render 'properties' %>
+ <% end %>
+ </div>
+ </td>
+ </tr>
+ </table>
+</div>
50 app/fbtab_views/shared/_order_details.html.erb
@@ -0,0 +1,50 @@
+<table class="index" data-role="listview">
+ <tbody id='line-items'>
+ <tr class="ui-bar-b">
+ <%= hook :order_details_line_items_headers do %>
+ <th><%= t('item_description') %></th>
+ <th class="price"><%= t('price') %></th>
+ <th class="qty"><%= t('qty') %></th>
+ <th class="total"><span><%= t('total') %></span></th>
+ <% end %>
+ </tr>
+
+ <% @order.line_items.each do |item| %>
+ <tr>
+ <%- locals = {:item => item} %>
+ <%= hook :order_details_line_item_row, locals do %>
+ <td width="300"><%=item.variant.product.name%> <%= "(" + variant_options(item.variant) + ")" unless item.variant .option_values.empty? %></td>
+ <td class="price"><%= number_to_currency item.price %></td>
+ <td class="qty"><%=item.quantity%></td>
+ <td class="total"><span><%= number_to_currency (item.price * item.quantity)%></span></td>
+ <% end %>
+ </tr>
+ <% end %>
+ </tbody>
+ <%= hook :order_details_subtotal do %>
+ <tbody id='subtotal'>
+ <tr class="total" id="subtotal-row">
+ <td colspan="3"><b><%= t('subtotal') %>:</b></td>
+ <td class="total"><span><%= number_to_currency @order.item_total %></span></td>
+ </tr>
+ </tbody>
+ <% end %>
+ <%= hook :order_details_adjustments do %>
+ <tbody id="order-charges">
+ <% @order.adjustments.each do |adjustment| %>
+ <tr class="total">
+ <td colspan="3"><strong><%= adjustment.label %></strong></td>
+ <td class="total"><span><%= number_to_currency adjustment.amount %></span></td>
+ </tr>
+ <% end %>
+ </tbody>
+ <% end %>
+ <%= hook :order_details_total do %>
+ <tbody id='order-total'>
+ <tr class="total">
+ <td colspan="3"><b><%= t('order_total') %>:</b></td>
+ <td class="total"><span id="order_total"><%= number_to_currency @order.total %></span></td>
+ </tr>
+ </tbody>
+ <% end %>
+</table>
30 app/fbtab_views/shared/_products.html.erb
@@ -0,0 +1,30 @@
+<%
+ paginated_products = @searcher.products if params.key?(:keywords)
+ paginated_products ||= @products
+%>
+<% if params.key?(:keywords) %>
+ <h3><%= t(:search_results, :keywords => h(params[:keywords])) %></h3>
+<% end %>
+<% if @products.present? %>
+ <ul data-role="listview">
+ <% @products.each do |product| %>
+ <li>
+ <a href="<%= product_path(product) %>">
+ <%= product_image(product) %>
+ <h3><%= product.name %></h3>
+ <p><%= product.description ? truncate(strip_tags(product.description).mb_chars, :length => 70) : t("product_has_no_description") %></p>
+ </a>
+ </li>
+ <% end %>
+ </ul>
+ <% if paginated_products.respond_to?(:total_pages)
+ params.delete(:search)
+ params.delete(:taxon)
+
+ %><%= will_paginate(paginated_products,
+ :previous_label => "&#171; #{t('previous')}",
+ :next_label => "#{t('next')} &#187;") %>
+ <% end %>
+<% else %>
+ <%= t(:no_products_found) %>
+<% end %>
8 app/fbtab_views/taxons/index.html.erb
@@ -0,0 +1,8 @@
+<% get_taxonomies.each do |taxonomy| %>
+ <ul data-role="listview" data-inset="true">
+ <li data-role="list-divider"><%= taxonomy.name %></li>
+ <% taxonomy.root.children.each do |taxon| %>
+ <li><%= link_to taxon.name, seo_url(taxon) %></li>
+ <% end %>
+ </ul>
+<% end %>
9 app/fbtab_views/taxons/show.html.erb
@@ -0,0 +1,9 @@
+<% if @taxon.children.present? %>
+ <ul data-role="listview">
+ <% @taxon.children.each do |taxon| %>
+ <li><%= link_to taxon.name, seo_url(taxon) %></li>
+ <% end %>
+ </ul>
+<% else %>
+ <%= render :partial => "shared/products" %>
+<% end %>
16 app/helpers/base_helper_decorator.rb
@@ -0,0 +1,16 @@
+Spree::BaseHelper.module_eval do
+
+ def link_to_cart(text = t('cart'))
+ if current_order.nil? or current_order.line_items.empty?
+ text = "#{text}: (#{t('empty')})"
+ else
+ text = "#{text}: (#{current_order.item_count}) #{order_price(current_order)}"
+ end
+ link_to text, cart_path, :class => css_class(cart_path)
+ end
+
+ def css_class(path)
+ current_page?(path) ? "ui-btn-active" : ""
+ end
+
+end
2 config/locales/en.yml
@@ -0,0 +1,2 @@
+en:
+ full_site: "Full site"
4 config/locales/ru.yml
@@ -0,0 +1,4 @@
+ru:
+ full_site: "Полная версия"
+ log_in: "Вход"
+ my_account: "Профиль"
3 config/routes.rb
@@ -0,0 +1,3 @@
+Rails.application.routes.draw do
+ match "/search" => "products#search", :as => :search
+end
62 lib/spree_fbtab_views.rb
@@ -0,0 +1,62 @@
+require 'spree_core'
+require 'spree_fbtab_views_hooks'
+
+module SpreeFbtabViews
+ class Engine < Rails::Engine
+
+ config.autoload_paths += %W(#{config.root}/lib)
+
+ def self.activate
+ Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
+ Rails.env.production? ? require(c) : load(c)
+ end
+ end
+
+ config.to_prepare &method(:activate).to_proc
+ end
+end
+
+
+module SpreeBase
+ module InstanceMethods
+ protected
+ MOBILE_USER_AGENTS = 'palm|blackberry|nokia|phone|midp|mobi|symbian|chtml|ericsson|minimo|' +
+ 'audiovox|motorola|samsung|telit|upg1|windows ce|ucweb|astel|plucker|' +
+ 'x320|x240|j2me|sgh|portable|sprint|docomo|kddi|softbank|android|mmp|' +
+ 'pdxgw|netfront|xiino|vodafone|portalmmm|sagem|mot-|sie-|ipod|up\\.b|' +
+ 'webos|amoi|novarra|cdm|alcatel|pocket|ipad|iphone|mobileexplorer|mobile'
+
+ def mobile_device?
+ if cookies[:mobile_param]
+ cookies[:mobile_param] == "1"
+ else
+ request.user_agent.to_s.downcase =~ Regexp.new(MOBILE_USER_AGENTS)
+ end
+ end
+
+ def prepare_for_mobile
+ cookies[:mobile_param] = params[:mobile] if params[:mobile]
+ end
+
+ def prepend_view_path_if_mobile
+ if mobile_device?
+ prepend_view_path File.join(File.dirname(__FILE__), '..', 'app', 'fbtab_views')
+ prepend_view_path File.join(Rails.root, 'app', 'fbtab_views')
+ end
+ end
+ end
+
+ class << self
+
+ def included_with_fbtab_views(receiver)
+ included_without_fbtab_views(receiver)
+
+ receiver.send :helper_method, 'mobile_device?'
+ receiver.send :before_filter, 'prepare_for_mobile'
+ receiver.send :before_filter, 'prepend_view_path_if_mobile'
+ end
+
+ alias_method_chain :included, :fbtab_views
+
+ end
+end
3 lib/spree_fbtab_views_hooks.rb
@@ -0,0 +1,3 @@
+class SpreeFbtabViewsHooks < Spree::ThemeSupport::HookListener
+ # custom hooks go here
+end
25 lib/tasks/install.rake
@@ -0,0 +1,25 @@
+namespace :spree_fbtab_views do
+ desc "Copies all migrations and assets (NOTE: This will be obsolete with Rails 3.1)"
+ task :install do
+ Rake::Task['spree_fbtab_views:install:migrations'].invoke
+ Rake::Task['spree_fbtab_views:install:assets'].invoke
+ end
+
+ namespace :install do
+ desc "Copies all migrations (NOTE: This will be obsolete with Rails 3.1)"
+ task :migrations do
+ source = File.join(File.dirname(__FILE__), '..', '..', 'db')
+ destination = File.join(Rails.root, 'db')
+ Spree::FileUtilz.mirror_files(source, destination)
+ end
+
+ desc "Copies all assets (NOTE: This will be obsolete with Rails 3.1)"
+ task :assets do
+ source = File.join(File.dirname(__FILE__), '..', '..', 'public')
+ destination = File.join(Rails.root, 'public')
+ puts "INFO: Mirroring assets from #{source} to #{destination}"
+ Spree::FileUtilz.mirror_files(source, destination)
+ end
+ end
+
+end
1 lib/tasks/spree_fbtab_views.rake
@@ -0,0 +1 @@
+# add custom rake tasks here
55 public/stylesheets/mobile.css
@@ -0,0 +1,55 @@
+#cart-form input { max-width: 250px; }
+#cart-detail .ui-li-desc { white-space: normal; }
+dt { font-weight: bold; }
+#line_items input { width: 3em; }
+#line_items td { padding: 3px; background: #EEE; }
+#updatecart #subtotal { text-align: right; margin: 2em 0.5em 0 0; }
+.min-width-480px label.ui-input-text { width: 60%; }
+.min-width-480px .ui-input-search { width: 90%; }
+#checkout fieldset { margin-top: 2em; }
+#checkout fieldset legend { font-weight: bold; }
+#billing input, #shipping input { width: 100%; }
+span.req { color: #D11; }
+legend { font-size: 12pt; }
+
+ol.progress-steps {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ line-height: 1em;
+ font-size: 12px;
+}
+
+ol.progress-steps li {
+ float: left;
+ padding: 6px;
+}
+
+ol.progress-steps li.current-first, ol.progress-steps li.current {
+ color: white;
+ background-image: url(../images/step-progress/current-first.gif);
+}
+
+div#checkout-summary {
+ border: #EEF 2px solid;
+ background: #FFE;
+ padding: 1em;
+ margin-top: 1em;
+}
+
+.ui-header .ui-title .ui-link { color: white; text-decoration: none; }
+.ui-header #home_link .ui-btn-inner { padding-left: 15px; }
+
+.odd { background: #FFE; }
+.even { background: #EEF; }
+
+dl#product-properties dd { padding-bottom: 0.5em; }
+
+/* Margins */
+form { margin: 0; }
+#line_items p { margin: 0; }
+#footer { margin: 0em 0.5em; }
+.ui-listview-inset { margin: 1em 0.5em; }
+.ui-content h3 { margin: 0 0 1.5em 0; }
+.ui-content div.pagination { margin-top: 2em; }
+.ui-header .ui-title { margin-left: 3em; margin-right: 8em; text-align: left; }
30 spec/spec_helper.rb
@@ -0,0 +1,30 @@
+# This file is copied to ~/spec when you run 'ruby script/generate rspec'
+# from the project root directory.
+ENV["RAILS_ENV"] ||= 'test'
+require File.expand_path("../test_app/config/environment", __FILE__)
+require 'rspec/rails'
+
+# Requires supporting files with custom matchers and macros, etc,
+# in ./support/ and its subdirectories.
+Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
+
+RSpec.configure do |config|
+ # == Mock Framework
+ #
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
+ #
+ # config.mock_with :mocha
+ # config.mock_with :flexmock
+ # config.mock_with :rr
+ config.mock_with :rspec
+
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
+
+ #config.include Devise::TestHelpers, :type => :controller
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
+ # examples within a transaction, comment the following line or assign false
+ # instead of true.
+ config.use_transactional_fixtures = true
+end
+
+@configuration ||= AppConfiguration.find_or_create_by_name("Default configuration")
20 spree_fbtab_views.gemspec
@@ -0,0 +1,20 @@
+Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = 'spree_fbtab_views'
+ s.version = '0.0.1'
+ s.summary = 'Adds support of Facebook Tab to Spree stores'
+ s.description = 'Works through jQuery Mobile'
+ s.required_ruby_version = '>= 1.8.7'
+
+ s.author = 'David Li'
+ s.email = 'taweili@yahoo.com'
+ s.homepage = 'https://github.com/taweili/spree_fbtab_views'
+ # s.rubyforge_project = 'actionmailer'
+
+ s.files = `git ls-files`.split("\n")
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ s.require_path = 'lib'
+ s.requirements << 'none'
+
+ s.add_dependency('spree_core', '>= 0.50.0')
+end

0 comments on commit 43426e9

Please sign in to comment.
Something went wrong with that request. Please try again.