From 1c84a4bef9854db3771d42f60b360978390d8320 Mon Sep 17 00:00:00 2001 From: Matchu Date: Tue, 12 Jul 2011 19:37:16 -0400 Subject: [PATCH 01/69] closet page, closet hanger --- Gemfile | 2 + Gemfile.lock | 2 + app/models/closet_hanger.rb | 7 ++ app/models/closet_page.rb | 110 ++++++++++++++++++ app/models/item.rb | 1 + app/models/user.rb | 14 ++- .../20110712232259_create_closet_hangers.rb | 15 +++ db/schema.rb | 10 +- spec/models/closet_hanger_spec.rb | 5 + vendor/cache/nokogiri-1.5.0.gem | Bin 0 -> 187904 bytes 10 files changed, 159 insertions(+), 7 deletions(-) create mode 100644 app/models/closet_hanger.rb create mode 100644 app/models/closet_page.rb create mode 100644 db/migrate/20110712232259_create_closet_hangers.rb create mode 100644 spec/models/closet_hanger_spec.rb create mode 100644 vendor/cache/nokogiri-1.5.0.gem diff --git a/Gemfile b/Gemfile index d2f2e627..ab837d3b 100644 --- a/Gemfile +++ b/Gemfile @@ -33,6 +33,8 @@ gem 'right_aws', '~> 2.1.0' gem "character-encodings", "~> 0.4.1", :platforms => :ruby_18 +gem "nokogiri", "~> 1.5.0" + group :development_async do # async wrappers gem 'eventmachine', :git => 'git://github.com/eventmachine/eventmachine.git' diff --git a/Gemfile.lock b/Gemfile.lock index 4fd0dbbf..1554d6b9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -107,6 +107,7 @@ GEM mime-types (1.16) msgpack (0.4.4) mysql2 (0.2.6) + nokogiri (1.5.0) openneo-auth-signatory (0.1.0) ruby-hmac polyglot (0.3.1) @@ -204,6 +205,7 @@ DEPENDENCIES msgpack (~> 0.4.3) mysql2 mysqlplus! + nokogiri (~> 1.5.0) openneo-auth-signatory (~> 0.1.0) rack-fiber_pool rails (= 3.0.4) diff --git a/app/models/closet_hanger.rb b/app/models/closet_hanger.rb new file mode 100644 index 00000000..1129cf63 --- /dev/null +++ b/app/models/closet_hanger.rb @@ -0,0 +1,7 @@ +class ClosetHanger < ActiveRecord::Base + belongs_to :item + belongs_to :user + + scope :alphabetical_by_item_name, joins(:item).order(Item.arel_table[:name]) +end + diff --git a/app/models/closet_page.rb b/app/models/closet_page.rb new file mode 100644 index 00000000..d9de7430 --- /dev/null +++ b/app/models/closet_page.rb @@ -0,0 +1,110 @@ +require 'yaml' + +class ClosetPage + SELECTORS = { + :items => "form[action=\"process_closet.phtml\"] tr[bgcolor!=silver][bgcolor!=\"#E4E4E4\"]", + :item_thumbnail => "img", + :item_name => "td:nth-child(2)", + :item_quantity => "td:nth-child(5)", + :item_remove => "input", + :page_select => "select[name=page]", + :selected => "option[selected]" + } + + attr_reader :hangers, :index, :total_pages, :unknown_item_names + + def initialize(user) + raise ArgumentError, "Expected #{user.inspect} to be a User", caller unless user.is_a?(User) + @user = user + end + + def save_hangers! + @hangers.each(&:save!) + end + + def source=(source) + parse_source!(source) + end + + protected + + def element(selector_name, parent) + parent.at_css(SELECTORS[selector_name]) || + raise(ParseError, "Closet #{selector_name} element not found in #{parent.inspect}") + end + + def elements(selector_name, parent) + parent.css(SELECTORS[selector_name]) + end + + def parse_source!(source) + doc = Nokogiri::HTML(source) + + page_selector = element(:page_select, doc) + @total_pages = page_selector.children.size + @index = element(:selected, page_selector)['value'] + + items_data = { + :id => {}, + :thumbnail_url => {} + } + + # Go through the items, and find the ID/thumbnail for each and data with it + elements(:items, doc).each do |row| + # For normal items, the td contains essentially: + # NAME
OPTIONAL ADJECTIVE
+ # For PB items, the td contains: + # NAME
OPTIONAL ADJECTIVE + # So, we want the first text node. If it's a PB item, that's the first + # child. If it's a normal item, it's the first child 's child. + name_el = element(:item_name, row).children[0] + name_el = name_el.children[0] if name_el.name == 'b' + + data = { + :name => name_el.text, + :quantity => element(:item_quantity, row).text.to_i + } + + if id = element(:item_remove, row)['name'] + id = id.to_i + items_data[:id][id] = data + else # if this is a pb item, which does not give ID, go by thumbnail + thumbnail_url = element(:item_thumbnail, row)['src'] + items_data[:thumbnail_url][thumbnail_url] = data + end + end + + # Find items with either a matching ID or matching thumbnail URL + # Check out that single-query beauty :) + i = Item.arel_table + items = Item.where( + i[:id].in(items_data[:id].keys). + or( + i[:thumbnail_url].in(items_data[:thumbnail_url].keys) + ) + ) + + # Create closet hanger from each item, and remove them from the reference + # lists + @hangers = items.map do |item| + data = items_data[:id].delete(item.id) || + items_data[:thumbnail_url].delete(item.thumbnail_url) + hanger = @user.closet_hangers.build + hanger.item = item + hanger.quantity = data[:quantity] + hanger + end + + # Take the names of the items remaining in the reference lists, meaning + # that they weren't found + @unknown_item_names = [] + items_data.each do |type, data_by_key| + data_by_key.each do |key, data| + @unknown_item_names << data[:name] + end + end + end + + class ParseError < RuntimeError;end +end + diff --git a/app/models/item.rb b/app/models/item.rb index 2d4e4f37..91386315 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -3,6 +3,7 @@ class Item < ActiveRecord::Base SwfAssetType = 'object' + has_many :closet_hangers has_one :contribution, :as => :contributed has_many :parent_swf_asset_relationships, :foreign_key => 'parent_id', :conditions => {:swf_asset_type => SwfAssetType} diff --git a/app/models/user.rb b/app/models/user.rb index a13ade3a..fe8f6820 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,14 +1,15 @@ class User < ActiveRecord::Base DefaultAuthServerId = 1 PreviewTopContributorsCount = 3 - + + has_many :closet_hangers has_many :contributions has_many :outfits - + scope :top_contributors, order('points DESC').where(arel_table[:points].gt(0)) - + devise :rememberable - + def contribute!(pet) new_contributions = [] new_points = 0 @@ -38,7 +39,7 @@ class User < ActiveRecord::Base end new_points end - + def self.find_or_create_from_remote_auth_data(user_data) user = find_or_initialize_by_remote_id_and_auth_server_id( user_data['id'], @@ -50,9 +51,10 @@ class User < ActiveRecord::Base end user end - + def self.points_required_to_pass_top_contributor(offset) user = User.top_contributors.select(:points).limit(1).offset(offset).first user ? user.points : 0 end end + diff --git a/db/migrate/20110712232259_create_closet_hangers.rb b/db/migrate/20110712232259_create_closet_hangers.rb new file mode 100644 index 00000000..80fc9f07 --- /dev/null +++ b/db/migrate/20110712232259_create_closet_hangers.rb @@ -0,0 +1,15 @@ +class CreateClosetHangers < ActiveRecord::Migration + def self.up + create_table :closet_hangers do |t| + t.integer :item_id + t.integer :user_id + t.integer :quantity + + t.timestamps + end + end + + def self.down + drop_table :closet_hangers + end +end diff --git a/db/schema.rb b/db/schema.rb index 69c5dca6..931e3818 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20110626202605) do +ActiveRecord::Schema.define(:version => 20110712232259) do create_table "auth_servers", :force => true do |t| t.string "short_name", :limit => 10, :null => false @@ -20,6 +20,14 @@ ActiveRecord::Schema.define(:version => 20110626202605) do t.string "secret", :limit => 64, :null => false end + create_table "closet_hangers", :force => true do |t| + t.integer "item_id" + t.integer "user_id" + t.integer "quantity" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "contributions", :force => true do |t| t.string "contributed_type", :limit => 8, :null => false t.integer "contributed_id", :null => false diff --git a/spec/models/closet_hanger_spec.rb b/spec/models/closet_hanger_spec.rb new file mode 100644 index 00000000..d8d2f0bb --- /dev/null +++ b/spec/models/closet_hanger_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe ClosetHanger do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/vendor/cache/nokogiri-1.5.0.gem b/vendor/cache/nokogiri-1.5.0.gem new file mode 100644 index 0000000000000000000000000000000000000000..47c37a67abacd0343943d214a02786a00608b120 GIT binary patch literal 187904 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
sFzRJd-*TK$=Sz?Gr4utS$@>RZ|PyY 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
', {'class': 'nc-icon', text: 'NC', title: 'NC'}).appendTo(li); } + if(item.closeted) { + $('', {'class': 'closeted-icon', alt: 'Closet', title: 'You own this', src: '/images/closeted.png'}).appendTo(li); + } li.append(img).append(controls).append(info_link).append(item.name).appendTo(ul); } setClosetItems(wardrobe.outfit.getClosetItems()); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 47b6d943..18d6cbe9 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -271,49 +271,76 @@ ul.buttons li, ul.buttons li form { vertical-align: middle; *display: inline; *vertical-align: auto; - padding: 0.5em; + margin: 0.5em 0; + padding: 0 0.5em; position: relative; text-align: center; vertical-align: top; width: 100px; } -/* line 165, ../../../app/stylesheets/_layout.sass */ +/* line 166, ../../../app/stylesheets/_layout.sass */ .object a { text-decoration: none; } -/* line 167, ../../../app/stylesheets/_layout.sass */ +/* line 168, ../../../app/stylesheets/_layout.sass */ .object a img { -moz-opacity: 0.75; -webkit-opacity: 0.75; -o-opacity: 0.75; -khtml-opacity: 0.75; } -/* line 169, ../../../app/stylesheets/_layout.sass */ +/* line 170, ../../../app/stylesheets/_layout.sass */ .object a:hover img { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 171, ../../../app/stylesheets/_layout.sass */ +/* line 172, ../../../app/stylesheets/_layout.sass */ .object img { display: block; height: 80px; margin: 0 auto; width: 80px; } +/* line 178, ../../../app/stylesheets/_layout.sass */ +.object .nc-icon, .object .closeted-icon { + -moz-opacity: 1; + -webkit-opacity: 1; + -o-opacity: 1; + -khtml-opacity: 1; + height: 16px; + position: absolute; + top: 64px; + width: 16px; +} +/* line 184, ../../../app/stylesheets/_layout.sass */ +.object .nc-icon:hover, .object .closeted-icon:hover { + -moz-opacity: 0.5; + -webkit-opacity: 0.5; + -o-opacity: 0.5; + -khtml-opacity: 0.5; +} +/* line 187, ../../../app/stylesheets/_layout.sass */ +.object .nc-icon { + right: 16px; +} +/* line 190, ../../../app/stylesheets/_layout.sass */ +.object .closeted-icon { + left: 16px; +} -/* line 177, ../../../app/stylesheets/_layout.sass */ +/* line 193, ../../../app/stylesheets/_layout.sass */ dt { font-weight: bold; } -/* line 180, ../../../app/stylesheets/_layout.sass */ +/* line 196, ../../../app/stylesheets/_layout.sass */ dd { margin: 0 0 1.5em 1em; } -/* line 183, ../../../app/stylesheets/_layout.sass */ +/* line 199, ../../../app/stylesheets/_layout.sass */ #home-link { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 175%; @@ -324,41 +351,25 @@ dd { position: absolute; top: 0; } -/* line 193, ../../../app/stylesheets/_layout.sass */ +/* line 209, ../../../app/stylesheets/_layout.sass */ #home-link:hover { background: #eeffee; text-decoration: none; } -/* line 196, ../../../app/stylesheets/_layout.sass */ +/* line 212, ../../../app/stylesheets/_layout.sass */ #home-link span:before { content: "<< "; } -/* line 200, ../../../app/stylesheets/_layout.sass */ +/* line 216, ../../../app/stylesheets/_layout.sass */ .pagination a, .pagination span { margin: 0 0.5em; } -/* line 202, ../../../app/stylesheets/_layout.sass */ +/* line 218, ../../../app/stylesheets/_layout.sass */ .pagination .current { font-weight: bold; } -/* line 205, ../../../app/stylesheets/_layout.sass */ -.object .nc-icon { - height: 16px; - position: absolute; - right: 16px; - top: 64px; - width: 16px; -} -/* line 211, ../../../app/stylesheets/_layout.sass */ -.object .nc-icon:hover { - -moz-opacity: 0.5; - -webkit-opacity: 0.5; - -o-opacity: 0.5; - -khtml-opacity: 0.5; -} - /* Fonts */ /* A font by Jos Buivenga (exljbris) -> www.exljbris.nl */ @font-face { @@ -1511,7 +1522,11 @@ body.outfits-edit .object:hover ul, body.outfits-edit .object:hover .object-info } /* line 415, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .nc-icon { +<<<<<<< HEAD background: url('/images/nc.png?1310662236') no-repeat; +======= + background: url('/images/nc.png?1310533288') no-repeat; +>>>>>>> closeted icon, all over the place height: 16px; position: absolute; right: 16px; From 46698d42976ac8841ac1f6561e2fe3a9beb8fbbc Mon Sep 17 00:00:00 2001 From: Matchu Date: Wed, 13 Jul 2011 12:10:47 -0400 Subject: [PATCH 06/69] rebrand Your Closet as Your Items to avoid ambiguity will all these other closet things --- app/views/closet_hangers/index.html.haml | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 25d9b459..56e81d09 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -1,21 +1,23 @@ - if user_is?(@user) - - title 'Your Closet' + - title 'Your Items' = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' - else - - title "#{@user.name}'s Closet" + - title "#{@user.name}'s Items" #closet-hangers - if !@closet_hangers.empty? = render @closet_hangers - else - if user_is?(@user) - %p You don't have any items in your Dress to Impress closet. + %p You haven't tracked any items on Dress to Impress. %p - Your Dress to Impress closet is a way to keep track of what items you - have in your Neopets closet. Once you load your Neopets closet into - Dress to Impress, as you play with various outfit ideas you can keep - track of what items you already own. And, who knows? Maybe some day - you can use it as a up-for-trade list or wishlist. We'll see what - happens. + Here you can keep track of what items you already own, so that as you + design fancy outfits you can know what you have and what you still + need. And, who knows? Maybe some day this page will include wishlists + and up-for-trade items. We'll see what happens. + %p + It's easy to get started! + = link_to "Just import your Neopets closet in a few quick steps.", new_closet_page_path + Have fun! - else - %p #{@user.name} doesn't have any items in their Dress to Impress closet. + %p #{@user.name} hasn't tracked any items on Dress to Impress. From fab612950a3974632f166508dfee186ef54f5058 Mon Sep 17 00:00:00 2001 From: Matchu Date: Thu, 14 Jul 2011 12:50:24 -0400 Subject: [PATCH 07/69] basic hanger interface from item --- app/controllers/closet_hangers_controller.rb | 43 +++++++++++++++++++ app/controllers/items_controller.rb | 4 ++ app/models/closet_hanger.rb | 6 +++ app/stylesheets/_layout.sass | 2 +- app/stylesheets/items/_show.sass | 20 +++++++++ app/views/items/show.html.haml | 8 +++- config/routes.rb | 2 + ...closet_hangers_quantity_default_to_zero.rb | 7 +++ public/stylesheets/compiled/screen.css | 27 +++++++++++- 9 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20110713162012_set_closet_hangers_quantity_default_to_zero.rb diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index def5dfbe..cc9e1a76 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -1,7 +1,50 @@ class ClosetHangersController < ApplicationController + before_filter :find_item, :only => [:create, :update] + + def create + @closet_hanger = new_hanger + save_hanger! + end + + def update + begin + @closet_hanger = @item.closet_hangers.find(params[:id]) + @closet_hanger.attributes = params[:closet_hanger] + rescue ActiveRecord::RecordNotFound + # Since updating a hanger is really just changing an item quantity, if + # for some reason this hanger doesn't exist (like if user left a tab + # open), we can still create a new hanger and do the job the user wants + @closet_hanger = new_hanger + end + save_hanger! + end + def index @user = User.find params[:user_id] @closet_hangers = @user.closet_hangers.alphabetical_by_item_name.includes(:item) end + + protected + + def find_item + @item = Item.find params[:item_id] + end + + def new_hanger + current_user.closet_hangers.find_or_initialize_by_item_id(@item.id, params[:closet_hanger]) + end + + def save_hanger! + if @closet_hanger.quantity == 0 + @closet_hanger.destroy + flash[:success] = "Success! You do not own #{@item.name}." + elsif @closet_hanger.save + flash[:success] = "Success! You own #{@closet_hanger.quantity} #{@item.name.pluralize}." + else + flash[:alert] = "We couldn't save how many of this item you own: #{@closet_hanger.errors.full_messages.to_sentence}" + end + + redirect_to @item + end end diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index db12323e..a5f6a142 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -39,6 +39,10 @@ class ItemsController < ApplicationController def show @item = Item.find params[:id] + if user_signed_in? + @hanger = current_user.closet_hangers.find_or_initialize_by_item_id(@item.id) + @hanger.quantity ||= 0 + end end def needed diff --git a/app/models/closet_hanger.rb b/app/models/closet_hanger.rb index 1129cf63..4556c605 100644 --- a/app/models/closet_hanger.rb +++ b/app/models/closet_hanger.rb @@ -2,6 +2,12 @@ class ClosetHanger < ActiveRecord::Base belongs_to :item belongs_to :user + attr_accessible :quantity + + validates :item_id, :uniqueness => {:scope => :user_id} + validates :quantity, :numericality => {:greater_than => 0} + validates_presence_of :item, :user + scope :alphabetical_by_item_name, joins(:item).order(Item.arel_table[:name]) end diff --git a/app/stylesheets/_layout.sass b/app/stylesheets/_layout.sass index 58bfc903..0918b315 100644 --- a/app/stylesheets/_layout.sass +++ b/app/stylesheets/_layout.sass @@ -76,7 +76,7 @@ $container_width: 800px input, button, select, label cursor: pointer -input[type=text], input[type=password], input[type=search], select +input[type=text], input[type=password], input[type=search], input[type=number], select +border-radius(3px) background: #fff border: 1px solid $input-border-color diff --git a/app/stylesheets/items/_show.sass b/app/stylesheets/items/_show.sass index 24b3b239..6443f295 100644 --- a/app/stylesheets/items/_show.sass +++ b/app/stylesheets/items/_show.sass @@ -62,3 +62,23 @@ body.items-show .nc-icon height: 16px width: 16px + + #closet-hanger-form + border: 1px solid $module-border-color + float: right + font-size: 85% + padding: 1em .5em .5em + width: 18em + + label + display: block + font-weight: bold + + input[type=number] + width: 4em + + a + display: block + margin-top: .5em + text-align: right + diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index 83c04220..a9589995 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -10,8 +10,14 @@ = nc_icon_for(@item) - unless @item.rarity.blank? == Rarity: #{@item.rarity_index} (#{@item.rarity}) - %a.button{:href => neoitems_url_for(@item)} NeoItems + = link_to 'NeoItems', neoitems_url_for(@item), :class => 'button' + - if @hanger + = form_for([@item, @hanger], :html => {:id => 'closet-hanger-form'}) do |f| + = f.label :quantity, "How many of these do you own?" + = f.number_field :quantity, :min => 0, :required => true + = f.submit "Save" + = link_to 'Your Items →'.html_safe, user_closet_hangers_path(current_user) %p= @item.description #item-zones diff --git a/config/routes.rb b/config/routes.rb index 6ad714b7..9189fe2a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -19,6 +19,8 @@ OpenneoImpressItems::Application.routes.draw do |map| collection do get :needed end + + resources :closet_hangers, :only => [:create, :update] end resources :outfits, :only => [:show, :create, :update, :destroy] resources :pet_attributes, :only => [:index] diff --git a/db/migrate/20110713162012_set_closet_hangers_quantity_default_to_zero.rb b/db/migrate/20110713162012_set_closet_hangers_quantity_default_to_zero.rb new file mode 100644 index 00000000..4a32f700 --- /dev/null +++ b/db/migrate/20110713162012_set_closet_hangers_quantity_default_to_zero.rb @@ -0,0 +1,7 @@ +class SetClosetHangersQuantityDefaultToZero < ActiveRecord::Migration + def self.up + end + + def self.down + end +end diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 18d6cbe9..7d7a0fc8 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -97,7 +97,7 @@ input, button, select, label { } /* line 79, ../../../app/stylesheets/_layout.sass */ -input[type=text], body.pets-bulk #bulk-pets-form textarea, input[type=password], input[type=search], select { +input[type=text], body.pets-bulk #bulk-pets-form textarea, input[type=password], input[type=search], input[type=number], select { -moz-border-radius: 3px; -webkit-border-radius: 3px; background: white; @@ -106,7 +106,7 @@ input[type=text], body.pets-bulk #bulk-pets-form textarea, input[type=password], padding: 0.25em; } /* line 85, ../../../app/stylesheets/_layout.sass */ -input[type=text]:focus, body.pets-bulk #bulk-pets-form textarea:focus, input[type=text]:active, body.pets-bulk #bulk-pets-form textarea:active, input[type=password]:focus, input[type=password]:active, input[type=search]:focus, input[type=search]:active, select:focus, select:active { +input[type=text]:focus, body.pets-bulk #bulk-pets-form textarea:focus, input[type=text]:active, body.pets-bulk #bulk-pets-form textarea:active, input[type=password]:focus, input[type=password]:active, input[type=search]:focus, input[type=search]:active, input[type=number]:focus, input[type=number]:active, select:focus, select:active { color: inherit; } @@ -952,6 +952,29 @@ body.items-show .nc-icon { height: 16px; width: 16px; } +/* line 66, ../../../app/stylesheets/items/_show.sass */ +body.items-show #closet-hanger-form { + border: 1px solid #006600; + float: right; + font-size: 85%; + padding: 1em 0.5em 0.5em; + width: 18em; +} +/* line 73, ../../../app/stylesheets/items/_show.sass */ +body.items-show #closet-hanger-form label { + display: block; + font-weight: bold; +} +/* line 77, ../../../app/stylesheets/items/_show.sass */ +body.items-show #closet-hanger-form input[type=number] { + width: 4em; +} +/* line 80, ../../../app/stylesheets/items/_show.sass */ +body.items-show #closet-hanger-form a { + display: block; + margin-top: 0.5em; + text-align: right; +} @import url(../shared/jquery.jgrowl.css); /* line 112, ../../../app/stylesheets/outfits/_edit.sass */ From 47e3b72937b43b7e53ccb4e74bab45832fb84883 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 15 Jul 2011 16:15:57 -0400 Subject: [PATCH 08/69] restructure backend of closet hanger quantity updates --- app/controllers/application_controller.rb | 8 +++ app/controllers/closet_hangers_controller.rb | 61 +++++++++----------- app/views/items/show.html.haml | 2 +- config/routes.rb | 6 +- public/403.html | 28 +++++++++ 5 files changed, 69 insertions(+), 36 deletions(-) create mode 100644 public/403.html diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4543f7c7..6c9a3e5e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -10,5 +10,13 @@ class ApplicationController < ActionController::Base def can_use_image_mode? user_signed_in? && current_user.image_mode_tester? end + + class AccessDenied < StandardError;end + + rescue_from AccessDenied, :with => :on_access_denied + + def on_access_denied + render :file => 'public/403.html', :layout => false, :status => :forbidden + end end diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index cc9e1a76..eb059dda 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -1,50 +1,45 @@ class ClosetHangersController < ApplicationController - before_filter :find_item, :only => [:create, :update] - - def create - @closet_hanger = new_hanger - save_hanger! - end - - def update - begin - @closet_hanger = @item.closet_hangers.find(params[:id]) - @closet_hanger.attributes = params[:closet_hanger] - rescue ActiveRecord::RecordNotFound - # Since updating a hanger is really just changing an item quantity, if - # for some reason this hanger doesn't exist (like if user left a tab - # open), we can still create a new hanger and do the job the user wants - @closet_hanger = new_hanger - end - save_hanger! - end + before_filter :authorize_user!, :only => [:set_quantity] def index @user = User.find params[:user_id] @closet_hangers = @user.closet_hangers.alphabetical_by_item_name.includes(:item) end - protected - - def find_item + # Since the user does not care about the idea of a hanger, but rather the + # quantity of an item they own, the user would expect a create form to work + # even after the record already exists, and an update form to work even after + # the record is deleted. So, create and update are aliased, and both find + # the record if it exists or create a new one if it does not. + # + # This is kinda a violation of REST. It's not worth breaking user + # expectations, though, and I can't really think of a genuinely RESTful way + # to pull this off. + def update @item = Item.find params[:item_id] - end + @closet_hanger = current_user.closet_hangers.find_or_initialize_by_item_id(@item.id) + @closet_hanger.attributes = params[:closet_hanger] - def new_hanger - current_user.closet_hangers.find_or_initialize_by_item_id(@item.id, params[:closet_hanger]) - end - - def save_hanger! - if @closet_hanger.quantity == 0 + unless @closet_hanger.quantity == 0 # save the hanger, new record or not + if @closet_hanger.save + flash[:success] = "Success! You own #{@closet_hanger.quantity} #{@item.name.pluralize}." + else + flash[:alert] = "We couldn't save how many of this item you own: #{@closet_hanger.errors.full_messages.to_sentence}" + end + else # delete the hanger since the user doesn't want it @closet_hanger.destroy flash[:success] = "Success! You do not own #{@item.name}." - elsif @closet_hanger.save - flash[:success] = "Success! You own #{@closet_hanger.quantity} #{@item.name.pluralize}." - else - flash[:alert] = "We couldn't save how many of this item you own: #{@closet_hanger.errors.full_messages.to_sentence}" end redirect_to @item end + + alias_method :create, :update + + protected + + def authorize_user! + raise AccessDenied unless user_signed_in? && current_user.id == params[:user_id].to_i + end end diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index a9589995..81c99120 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -13,7 +13,7 @@ = link_to 'NeoItems', neoitems_url_for(@item), :class => 'button' - if @hanger - = form_for([@item, @hanger], :html => {:id => 'closet-hanger-form'}) do |f| + = form_for(@hanger, :url => user_item_closet_hanger_path(current_user, @item), :html => {:id => 'closet-hanger-form'}) do |f| = f.label :quantity, "How many of these do you own?" = f.number_field :quantity, :min => 0, :required => true = f.submit "Save" diff --git a/config/routes.rb b/config/routes.rb index 9189fe2a..6dbb1921 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -19,8 +19,6 @@ OpenneoImpressItems::Application.routes.draw do |map| collection do get :needed end - - resources :closet_hangers, :only => [:create, :update] end resources :outfits, :only => [:show, :create, :update, :destroy] resources :pet_attributes, :only => [:index] @@ -40,6 +38,10 @@ OpenneoImpressItems::Application.routes.draw do |map| resources :user, :only => [] do resources :contributions, :only => [:index] resources :closet_hangers, :only => [:index], :path => 'closet' + + resources :items, :only => [] do + resource :closet_hanger, :only => [:create, :update] + end end match 'users/top-contributors' => 'users#top_contributors', :as => :top_contributors diff --git a/public/403.html b/public/403.html new file mode 100644 index 00000000..0ccf5383 --- /dev/null +++ b/public/403.html @@ -0,0 +1,28 @@ + + + + You do not have permission to access this page (403) + + + + + + + + + From e6020a5cfe338161473f59f848a5df0959ad1fa1 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 15 Jul 2011 16:32:05 -0400 Subject: [PATCH 09/69] simplify closeting item --- app/controllers/items_controller.rb | 2 +- app/stylesheets/items/_show.sass | 9 ++++++--- app/views/items/show.html.haml | 17 ++++++++++++----- public/stylesheets/compiled/screen.css | 22 +++++++++++----------- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index a5f6a142..b5e12c80 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -41,7 +41,7 @@ class ItemsController < ApplicationController @item = Item.find params[:id] if user_signed_in? @hanger = current_user.closet_hangers.find_or_initialize_by_item_id(@item.id) - @hanger.quantity ||= 0 + @hanger.quantity ||= 1 end end diff --git a/app/stylesheets/items/_show.sass b/app/stylesheets/items/_show.sass index 6443f295..7bc4d7d6 100644 --- a/app/stylesheets/items/_show.sass +++ b/app/stylesheets/items/_show.sass @@ -1,5 +1,5 @@ body.items-show - header + #item-header border-bottom: 1px solid $module-border-color display: block margin-bottom: 1em @@ -70,15 +70,18 @@ body.items-show padding: 1em .5em .5em width: 18em - label + label, header display: block font-weight: bold input[type=number] width: 4em - a + #closet-hanger-form-your-items display: block margin-top: .5em text-align: right + p + font-family: $main-font + diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index 81c99120..201982d5 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -3,7 +3,7 @@ %link{:rel => 'canonical', :href => url_for(@item)} - cache "items_show_#{@item.id}_main_content" do - %header + %header#item-header = image_tag @item.thumbnail_url, :id => 'item-thumbnail' %div %h2#item-name= @item.name @@ -14,10 +14,17 @@ - if @hanger = form_for(@hanger, :url => user_item_closet_hanger_path(current_user, @item), :html => {:id => 'closet-hanger-form'}) do |f| - = f.label :quantity, "How many of these do you own?" - = f.number_field :quantity, :min => 0, :required => true - = f.submit "Save" - = link_to 'Your Items →'.html_safe, user_closet_hangers_path(current_user) + - if @hanger.new_record? + %header Do you own this item? + %p + We can help you track your closet. + = f.hidden_field :quantity + = f.submit "I own this item!" + - else + = f.label :quantity, "How many of these do you own?" + = f.number_field :quantity, :min => 0, :required => true + = f.submit "Save" + = link_to 'Your Items →'.html_safe, user_closet_hangers_path(current_user), :id => 'closet-hanger-form-your-items' %p= @item.description #item-zones diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 7d7a0fc8..d6d5953a 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -834,14 +834,14 @@ body.items-index #species-search-links img { } /* line 2, ../../../app/stylesheets/items/_show.sass */ -body.items-show header { +body.items-show #item-header { border-bottom: 1px solid #006600; display: block; margin-bottom: 1em; padding: 1em 0; } /* line 7, ../../../app/stylesheets/items/_show.sass */ -body.items-show header div, body.items-show header img { +body.items-show #item-header div, body.items-show #item-header img { display: -moz-inline-box; -moz-box-orient: vertical; display: inline-block; @@ -850,11 +850,11 @@ body.items-show header div, body.items-show header img { *vertical-align: auto; } /* line 9, ../../../app/stylesheets/items/_show.sass */ -body.items-show header div { +body.items-show #item-header div { text-align: left; } /* line 11, ../../../app/stylesheets/items/_show.sass */ -body.items-show header a { +body.items-show #item-header a { font-size: 75%; margin-left: 1em; } @@ -961,7 +961,7 @@ body.items-show #closet-hanger-form { width: 18em; } /* line 73, ../../../app/stylesheets/items/_show.sass */ -body.items-show #closet-hanger-form label { +body.items-show #closet-hanger-form label, body.items-show #closet-hanger-form header { display: block; font-weight: bold; } @@ -970,11 +970,15 @@ body.items-show #closet-hanger-form input[type=number] { width: 4em; } /* line 80, ../../../app/stylesheets/items/_show.sass */ -body.items-show #closet-hanger-form a { +body.items-show #closet-hanger-form #closet-hanger-form-your-items { display: block; margin-top: 0.5em; text-align: right; } +/* line 85, ../../../app/stylesheets/items/_show.sass */ +body.items-show #closet-hanger-form p { + font-family: "Droid Sans", Helvetica, Arial, Verdana, sans-serif; +} @import url(../shared/jquery.jgrowl.css); /* line 112, ../../../app/stylesheets/outfits/_edit.sass */ @@ -1545,11 +1549,7 @@ body.outfits-edit .object:hover ul, body.outfits-edit .object:hover .object-info } /* line 415, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .nc-icon { -<<<<<<< HEAD - background: url('/images/nc.png?1310662236') no-repeat; -======= - background: url('/images/nc.png?1310533288') no-repeat; ->>>>>>> closeted icon, all over the place + background: url('/images/nc.png?1310666180') no-repeat; height: 16px; position: absolute; right: 16px; From 1fa9a48ad2b9b5f7d21b5d3d6ba12008c91a3ec6 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 15 Jul 2011 16:59:15 -0400 Subject: [PATCH 10/69] pretty quantities on hangers index --- app/stylesheets/closet_hangers/_index.sass | 10 ++++++++++ app/views/closet_hangers/_closet_hanger.html.haml | 4 +--- public/stylesheets/compiled/screen.css | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index c9b0d0f6..c2826e54 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -13,3 +13,13 @@ body.closet_hangers-index clear: both text-align: center + .object .quantity + +opacity(.75) + background: white + font-size: 16px + font-weight: bold + padding: 2px 4px + position: absolute + left: ($object-width - $object-img-size) / 2 + $object-padding + top: $object-img-size - 24px + diff --git a/app/views/closet_hangers/_closet_hanger.html.haml b/app/views/closet_hangers/_closet_hanger.html.haml index fce078bb..67fe5234 100644 --- a/app/views/closet_hangers/_closet_hanger.html.haml +++ b/app/views/closet_hangers/_closet_hanger.html.haml @@ -1,6 +1,4 @@ .object = render :partial => 'items/item_link', :locals => {:item => closet_hanger.item} - %span.quantity - = surround '(', ')' do - = closet_hanger.quantity + %span.quantity{:title => "You own #{pluralize closet_hanger.quantity, closet_hanger.item.name}"}= closet_hanger.quantity diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index d6d5953a..f5af8b29 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -596,6 +596,20 @@ body.closet_hangers-index #closet-hangers { clear: both; text-align: center; } +/* line 16, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers .object .quantity { + -moz-opacity: 0.75; + -webkit-opacity: 0.75; + -o-opacity: 0.75; + -khtml-opacity: 0.75; + background: white; + font-size: 16px; + font-weight: bold; + padding: 2px 4px; + position: absolute; + left: 16px; + top: 56px; +} /* line 3, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new #closet-page-form, body.closet_pages-create #closet-page-form { From d782108e00ff8de20ae35d04ce85782b2037a4b4 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 15 Jul 2011 16:59:22 -0400 Subject: [PATCH 11/69] items link in userbar --- app/views/layouts/application.html.haml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 40300d78..fbf7fc6f 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -45,6 +45,7 @@ = succeed '!' do = link_to current_user.name, user_contributions_path(current_user) == You have #{current_user.points} points. + = link_to 'Items', user_closet_hangers_path(current_user) = link_to 'Outfits', current_user_outfits_path = link_to 'Settings', Openneo::Auth.remote_settings_url = link_to 'Log out', logout_path_with_return_to From 437b1c052d065ce2d2c8adc8f1c0ca3504242083 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 15 Jul 2011 17:21:18 -0400 Subject: [PATCH 12/69] quantity form on your items page --- app/controllers/closet_hangers_controller.rb | 2 +- app/helpers/application_helper.rb | 2 +- app/stylesheets/closet_hangers/_index.sass | 47 ++++++++++++++---- .../closet_hangers/_closet_hanger.html.haml | 7 ++- app/views/closet_hangers/index.html.haml | 3 +- public/stylesheets/compiled/screen.css | 48 +++++++++++++++++-- 6 files changed, 91 insertions(+), 18 deletions(-) diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index eb059dda..98f606b9 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -31,7 +31,7 @@ class ClosetHangersController < ApplicationController flash[:success] = "Success! You do not own #{@item.name}." end - redirect_to @item + redirect_to params[:return_to] || @item end alias_method :create, :update diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 6c338888..7496defa 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -32,7 +32,7 @@ module ApplicationHelper def flashes raw(flash.inject('') do |html, pair| key, value = pair - html + content_tag('p', value, :class => key) + html + content_tag('p', value, :class => "flash #{key}") end) end diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index c2826e54..2d8aafbc 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -1,6 +1,10 @@ body.closet_hangers-index #title float: left + margin-bottom: .5em + + .flash + clear: both #import-link +awesome-button @@ -13,13 +17,38 @@ body.closet_hangers-index clear: both text-align: center - .object .quantity - +opacity(.75) - background: white - font-size: 16px - font-weight: bold - padding: 2px 4px - position: absolute - left: ($object-width - $object-img-size) / 2 + $object-padding - top: $object-img-size - 24px + .object + .quantity + +opacity(.75) + background: white + padding: 2px 4px + position: absolute + left: ($object-width - $object-img-size) / 2 + $object-padding + text-align: left + top: $object-img-size - 24px + + form + display: none + + span, input[type=number] + font-size: 16px + font-weight: bold + + &:hover + .quantity + +opacity(1) + top: $object-img-size - 30px + + span + display: none + + form + display: inline + + input[type=number] + padding: 2px + width: 2em + + input[type=submit] + font-size: 85% diff --git a/app/views/closet_hangers/_closet_hanger.html.haml b/app/views/closet_hangers/_closet_hanger.html.haml index 67fe5234..5c767cbd 100644 --- a/app/views/closet_hangers/_closet_hanger.html.haml +++ b/app/views/closet_hangers/_closet_hanger.html.haml @@ -1,4 +1,9 @@ .object = render :partial => 'items/item_link', :locals => {:item => closet_hanger.item} - %span.quantity{:title => "You own #{pluralize closet_hanger.quantity, closet_hanger.item.name}"}= closet_hanger.quantity + .quantity + %span{:title => "You own #{pluralize closet_hanger.quantity, closet_hanger.item.name}"}= closet_hanger.quantity + = form_for closet_hanger, :url => user_item_closet_hanger_path(current_user, closet_hanger.item) do |f| + = hidden_field_tag :return_to, request.fullpath + = f.number_field :quantity, :min => 0, :required => true, :title => "You own #{pluralize closet_hanger.quantity, closet_hanger.item.name}" + = f.submit "Save" diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 56e81d09..7a9bf0b8 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -1,6 +1,7 @@ - if user_is?(@user) - title 'Your Items' - = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' + - content_for :before_flashes do + = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' - else - title "#{@user.name}'s Items" #closet-hangers diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index f5af8b29..dd0f88db 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -552,8 +552,13 @@ div.jGrowl div.jGrowl-closer { /* line 2, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #title { float: left; + margin-bottom: 0.5em; } -/* line 5, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 6, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .flash { + clear: both; +} +/* line 9, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #import-link { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -591,25 +596,58 @@ body.closet_hangers-index #import-link:active { body.closet_hangers-index #import-link:hover { background-color: #ee4b00; } -/* line 12, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 16, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers { clear: both; text-align: center; } -/* line 16, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 21, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity { -moz-opacity: 0.75; -webkit-opacity: 0.75; -o-opacity: 0.75; -khtml-opacity: 0.75; background: white; - font-size: 16px; - font-weight: bold; padding: 2px 4px; position: absolute; left: 16px; + text-align: left; top: 56px; } +/* line 30, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers .object .quantity form { + display: none; +} +/* line 33, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { + font-size: 16px; + font-weight: bold; +} +/* line 38, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers .object:hover .quantity { + -moz-opacity: 1; + -webkit-opacity: 1; + -o-opacity: 1; + -khtml-opacity: 1; + top: 50px; +} +/* line 42, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers .object:hover .quantity span { + display: none; +} +/* line 45, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers .object:hover .quantity form { + display: inline; +} +/* line 48, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers .object:hover .quantity form input[type=number] { + padding: 2px; + width: 2em; +} +/* line 52, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers .object:hover .quantity input[type=submit] { + font-size: 85%; +} /* line 3, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new #closet-page-form, body.closet_pages-create #closet-page-form { From 99e59a2f9b346610a187780a677e5edb9e326f4f Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 15 Jul 2011 19:29:43 -0400 Subject: [PATCH 13/69] oops. quantity form only shows on current user closet --- app/stylesheets/closet_hangers/_index.sass | 3 ++- .../closet_hangers/_closet_hanger.html.haml | 11 +++++----- app/views/closet_hangers/index.html.haml | 2 +- public/stylesheets/compiled/screen.css | 20 +++++++++---------- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 2d8aafbc..6737d1f4 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -34,7 +34,8 @@ body.closet_hangers-index font-size: 16px font-weight: bold - &:hover + &.current-user + .object:hover .quantity +opacity(1) top: $object-img-size - 30px diff --git a/app/views/closet_hangers/_closet_hanger.html.haml b/app/views/closet_hangers/_closet_hanger.html.haml index 5c767cbd..31c48471 100644 --- a/app/views/closet_hangers/_closet_hanger.html.haml +++ b/app/views/closet_hangers/_closet_hanger.html.haml @@ -1,9 +1,10 @@ .object = render :partial => 'items/item_link', :locals => {:item => closet_hanger.item} .quantity - %span{:title => "You own #{pluralize closet_hanger.quantity, closet_hanger.item.name}"}= closet_hanger.quantity - = form_for closet_hanger, :url => user_item_closet_hanger_path(current_user, closet_hanger.item) do |f| - = hidden_field_tag :return_to, request.fullpath - = f.number_field :quantity, :min => 0, :required => true, :title => "You own #{pluralize closet_hanger.quantity, closet_hanger.item.name}" - = f.submit "Save" + %span= closet_hanger.quantity + - if user_is?(closet_hanger.user) + = form_for closet_hanger, :url => user_item_closet_hanger_path(current_user, closet_hanger.item) do |f| + = hidden_field_tag :return_to, request.fullpath + = f.number_field :quantity, :min => 0, :required => true, :title => "You own #{pluralize closet_hanger.quantity, closet_hanger.item.name}" + = f.submit "Save" diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 7a9bf0b8..df705da8 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -4,7 +4,7 @@ = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' - else - title "#{@user.name}'s Items" -#closet-hangers +#closet-hangers{:class => user_is?(@user) ? 'current-user' : nil} - if !@closet_hangers.empty? = render @closet_hangers - else diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index dd0f88db..42aca470 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -623,29 +623,29 @@ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_ha font-size: 16px; font-weight: bold; } -/* line 38, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers .object:hover .quantity { +/* line 39, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; top: 50px; } -/* line 42, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers .object:hover .quantity span { +/* line 43, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity span { display: none; } -/* line 45, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers .object:hover .quantity form { +/* line 46, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity form { display: inline; } -/* line 48, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers .object:hover .quantity form input[type=number] { +/* line 49, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity form input[type=number] { padding: 2px; width: 2em; } -/* line 52, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers .object:hover .quantity input[type=submit] { +/* line 53, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity input[type=submit] { font-size: 85%; } From 3ac30bb6b1a771a4190d7e15fb90506409229521 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 15 Jul 2011 19:39:20 -0400 Subject: [PATCH 14/69] cleaner hover state for closet quantity --- app/stylesheets/_layout.sass | 7 +++- app/stylesheets/closet_hangers/_index.sass | 4 +- public/stylesheets/compiled/screen.css | 48 +++++++++++----------- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/app/stylesheets/_layout.sass b/app/stylesheets/_layout.sass index 0918b315..62e30d25 100644 --- a/app/stylesheets/_layout.sass +++ b/app/stylesheets/_layout.sass @@ -167,13 +167,16 @@ ul.buttons text-decoration: none img +opacity(0.75) - &:hover img - +opacity(1) img display: block height: $object-img-size margin: 0 auto width: $object-img-size + &:hover img, a:hover img + // behave in browsers that only respond to a:hover, but also be in the + // hover state more often for browsers who support div:hover + // (quantity form in user items) + +opacity(1) .nc-icon, .closeted-icon +opacity(1) diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 6737d1f4..8f489f88 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -38,7 +38,9 @@ body.closet_hangers-index .object:hover .quantity +opacity(1) - top: $object-img-size - 30px + background: transparent + top: $object-img-size - 25px + padding: 0 span display: none diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 42aca470..d075cabd 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -290,20 +290,20 @@ ul.buttons li, ul.buttons li form { -khtml-opacity: 0.75; } /* line 170, ../../../app/stylesheets/_layout.sass */ -.object a:hover img { - -moz-opacity: 1; - -webkit-opacity: 1; - -o-opacity: 1; - -khtml-opacity: 1; -} -/* line 172, ../../../app/stylesheets/_layout.sass */ .object img { display: block; height: 80px; margin: 0 auto; width: 80px; } -/* line 178, ../../../app/stylesheets/_layout.sass */ +/* line 175, ../../../app/stylesheets/_layout.sass */ +.object:hover img, .object a:hover img { + -moz-opacity: 1; + -webkit-opacity: 1; + -o-opacity: 1; + -khtml-opacity: 1; +} +/* line 181, ../../../app/stylesheets/_layout.sass */ .object .nc-icon, .object .closeted-icon { -moz-opacity: 1; -webkit-opacity: 1; @@ -314,33 +314,33 @@ ul.buttons li, ul.buttons li form { top: 64px; width: 16px; } -/* line 184, ../../../app/stylesheets/_layout.sass */ +/* line 187, ../../../app/stylesheets/_layout.sass */ .object .nc-icon:hover, .object .closeted-icon:hover { -moz-opacity: 0.5; -webkit-opacity: 0.5; -o-opacity: 0.5; -khtml-opacity: 0.5; } -/* line 187, ../../../app/stylesheets/_layout.sass */ +/* line 190, ../../../app/stylesheets/_layout.sass */ .object .nc-icon { right: 16px; } -/* line 190, ../../../app/stylesheets/_layout.sass */ +/* line 193, ../../../app/stylesheets/_layout.sass */ .object .closeted-icon { left: 16px; } -/* line 193, ../../../app/stylesheets/_layout.sass */ +/* line 196, ../../../app/stylesheets/_layout.sass */ dt { font-weight: bold; } -/* line 196, ../../../app/stylesheets/_layout.sass */ +/* line 199, ../../../app/stylesheets/_layout.sass */ dd { margin: 0 0 1.5em 1em; } -/* line 199, ../../../app/stylesheets/_layout.sass */ +/* line 202, ../../../app/stylesheets/_layout.sass */ #home-link { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 175%; @@ -351,21 +351,21 @@ dd { position: absolute; top: 0; } -/* line 209, ../../../app/stylesheets/_layout.sass */ +/* line 212, ../../../app/stylesheets/_layout.sass */ #home-link:hover { background: #eeffee; text-decoration: none; } -/* line 212, ../../../app/stylesheets/_layout.sass */ +/* line 215, ../../../app/stylesheets/_layout.sass */ #home-link span:before { content: "<< "; } -/* line 216, ../../../app/stylesheets/_layout.sass */ +/* line 219, ../../../app/stylesheets/_layout.sass */ .pagination a, .pagination span { margin: 0 0.5em; } -/* line 218, ../../../app/stylesheets/_layout.sass */ +/* line 221, ../../../app/stylesheets/_layout.sass */ .pagination .current { font-weight: bold; } @@ -629,22 +629,24 @@ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity { -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; - top: 50px; + background: transparent; + top: 55px; + padding: 0; } -/* line 43, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 45, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity span { display: none; } -/* line 46, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 48, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity form { display: inline; } -/* line 49, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 51, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity form input[type=number] { padding: 2px; width: 2em; } -/* line 53, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 55, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity input[type=submit] { font-size: 85%; } From eeb3fc3af9e02ce689620e1b6e29c711c1eefaa7 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 15 Jul 2011 22:52:53 -0400 Subject: [PATCH 15/69] closet hangers page gets serious ajax action --- app/controllers/closet_hangers_controller.rb | 33 +++++++-- app/stylesheets/_layout.sass | 4 +- app/stylesheets/closet_hangers/_index.sass | 45 ++++++++---- .../partials/clean/_constants.sass | 3 +- app/views/closet_hangers/index.html.haml | 9 +++ public/javascripts/closet_hangers/index.js | 70 +++++++++++++++++++ public/stylesheets/compiled/screen.css | 38 +++++++--- 7 files changed, 169 insertions(+), 33 deletions(-) create mode 100644 public/javascripts/closet_hangers/index.js diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 98f606b9..6b60f4ac 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -22,16 +22,35 @@ class ClosetHangersController < ApplicationController unless @closet_hanger.quantity == 0 # save the hanger, new record or not if @closet_hanger.save - flash[:success] = "Success! You own #{@closet_hanger.quantity} #{@item.name.pluralize}." + respond_to do |format| + format.html { + flash[:success] = "Success! You own #{@closet_hanger.quantity} #{@item.name.pluralize}." + redirect_back! + } + + format.json { render :json => true } + end else - flash[:alert] = "We couldn't save how many of this item you own: #{@closet_hanger.errors.full_messages.to_sentence}" + respond_to do |format| + format.html { + flash[:alert] = "We couldn't save how many of this item you own: #{@closet_hanger.errors.full_messages.to_sentence}" + redirect_back! + } + + format.json { render :json => {:errors => @closet_hanger.errors.full_messages}, :status => :unprocessable_entity } + end end else # delete the hanger since the user doesn't want it @closet_hanger.destroy - flash[:success] = "Success! You do not own #{@item.name}." - end + respond_to do |format| + format.html { + flash[:success] = "Success! You do not own #{@item.name}." + redirect_back! + } - redirect_to params[:return_to] || @item + format.json { render :json => true } + end + end end alias_method :create, :update @@ -41,5 +60,9 @@ class ClosetHangersController < ApplicationController def authorize_user! raise AccessDenied unless user_signed_in? && current_user.id == params[:user_id].to_i end + + def redirect_back! + redirect_to params[:return_to] || @item + end end diff --git a/app/stylesheets/_layout.sass b/app/stylesheets/_layout.sass index 62e30d25..9a3eaaf7 100644 --- a/app/stylesheets/_layout.sass +++ b/app/stylesheets/_layout.sass @@ -157,8 +157,8 @@ ul.buttons .object +inline-block - margin: .5em 0 - padding: 0 .5em + margin: $object-padding 0 + padding: 0 $object-padding position: relative text-align: center vertical-align: top diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 8f489f88..6470149a 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -24,8 +24,9 @@ body.closet_hangers-index padding: 2px 4px position: absolute left: ($object-width - $object-img-size) / 2 + $object-padding + line-height: 1 text-align: left - top: $object-img-size - 24px + top: $object-img-size - 20px form display: none @@ -35,23 +36,37 @@ body.closet_hangers-index font-weight: bold &.current-user - .object:hover - .quantity - +opacity(1) - background: transparent - top: $object-img-size - 25px - padding: 0 + .object:hover .quantity + +opacity(1) + background: transparent + top: $object-img-size - 24px + padding: 0 - span - display: none + span + display: none - form - display: inline + form + display: inline - input[type=number] - padding: 2px - width: 2em + input[type=number] + padding: 2px + width: 2em + + input[type=submit] + font-size: 85% + + &.js + .object:hover .quantity + input[type=number] + width: 2.5em input[type=submit] - font-size: 85% + display: none + + .object.loading + background: $module-bg-color + outline: 1px solid $module-border-color + + .quantity span:after + content: "…" diff --git a/app/stylesheets/partials/clean/_constants.sass b/app/stylesheets/partials/clean/_constants.sass index 877b5b2f..f0595da9 100644 --- a/app/stylesheets/partials/clean/_constants.sass +++ b/app/stylesheets/partials/clean/_constants.sass @@ -24,7 +24,8 @@ $text-font: "Droid Serif", Georgia, "Times New Roman", Times, serif $object-img-size: 80px $object-width: 100px -$object-padding: 6px +$object-padding: 8px $nc-icon-size: 16px $container-top-padding: 3em + diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index df705da8..c5d600d9 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -4,8 +4,13 @@ = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' - else - title "#{@user.name}'s Items" + #closet-hangers{:class => user_is?(@user) ? 'current-user' : nil} - if !@closet_hangers.empty? + - if user_is?(@user) + %p + These are the items you own. Hover over an item to remove it from the + list or to change the quantity. = render @closet_hangers - else - if user_is?(@user) @@ -22,3 +27,7 @@ - else %p #{@user.name} hasn't tracked any items on Dress to Impress. +- content_for :javascripts do + = include_javascript_libraries :jquery + = javascript_include_tag 'jquery.jgrowl.js', 'closet_hangers/index' + diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js new file mode 100644 index 00000000..a4574dc3 --- /dev/null +++ b/public/javascripts/closet_hangers/index.js @@ -0,0 +1,70 @@ +(function () { + var hangersEl = $('#closet-hangers.current-user'); + hangersEl.addClass('js'); + + $.fn.hasChanged = function () { + return this.data('previousValue') != this.val(); + } + + $.fn.revertValue = function () { + this.each(function () { + var el = $(this); + el.val(el.data('previousValue')); + }); + } + + $.fn.storeValue = function () { + this.each(function () { + var el = $(this); + el.data('previousValue', el.val()); + }); + } + + function submitForm(form) { + if(form.data('loading')) return false; + var input = form.children("input[type=number]"); + if(input.hasChanged()) { + var objectWrapper = form.closest(".object").addClass("loading"); + var span = objectWrapper.find("span").text(input.val()); + form.data('loading', true); + + $.ajax({ + url: form.attr("action") + ".json", + type: "post", + data: form.serialize(), + dataType: "json", + complete: function (data) { + objectWrapper.removeClass("loading"); + form.data('loading', false); + }, + success: function () { + input.storeValue(); + }, + error: function (xhr) { + var data = $.parseJSON(xhr.responseText); + input.revertValue(); + span.text(input.val()); + if(typeof data.errors != 'undefined') { + $.jGrowl("Error updating quantity: " + data.errors.join(", ")); + } else { + $.jGrowl("We had trouble updating the quantity just now. Try again?"); + } + } + }); + } + } + + hangersEl.find('form').submit(function (e) { + e.preventDefault(); + submitForm($(this)); + }); + + hangersEl.find('input[type=number]').change(function () { + submitForm($(this).parent()); + }).storeValue(); + + hangersEl.find('div.object').mouseleave(function () { + submitForm($(this).find('form')); + }); +})(); + diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index d075cabd..5609ad53 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -271,8 +271,8 @@ ul.buttons li, ul.buttons li form { vertical-align: middle; *display: inline; *vertical-align: auto; - margin: 0.5em 0; - padding: 0 0.5em; + margin: 8px 0; + padding: 0 8px; position: relative; text-align: center; vertical-align: top; @@ -323,11 +323,11 @@ ul.buttons li, ul.buttons li form { } /* line 190, ../../../app/stylesheets/_layout.sass */ .object .nc-icon { - right: 16px; + right: 18px; } /* line 193, ../../../app/stylesheets/_layout.sass */ .object .closeted-icon { - left: 16px; + left: 18px; } /* line 196, ../../../app/stylesheets/_layout.sass */ @@ -610,15 +610,16 @@ body.closet_hangers-index #closet-hangers .object .quantity { background: white; padding: 2px 4px; position: absolute; - left: 16px; + left: 18px; + line-height: 1; text-align: left; - top: 56px; + top: 60px; } -/* line 30, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 31, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity form { display: none; } -/* line 33, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 34, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { font-size: 16px; font-weight: bold; @@ -630,7 +631,7 @@ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity { -o-opacity: 1; -khtml-opacity: 1; background: transparent; - top: 55px; + top: 56px; padding: 0; } /* line 45, ../../../app/stylesheets/closet_hangers/_index.sass */ @@ -642,7 +643,7 @@ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity f display: inline; } /* line 51, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity form input[type=number] { +body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } @@ -650,6 +651,23 @@ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity f body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity input[type=submit] { font-size: 85%; } +/* line 60, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers.current-user.js .object:hover .quantity input[type=number] { + width: 2.5em; +} +/* line 63, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers.current-user.js .object:hover .quantity input[type=submit] { + display: none; +} +/* line 66, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers.current-user.js .object.loading { + background: #eeffee; + outline: 1px solid #006600; +} +/* line 70, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers.current-user.js .object.loading .quantity span:after { + content: "…"; +} /* line 3, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new #closet-page-form, body.closet_pages-create #closet-page-form { From 77818471c55459577e975c07de3b651f3b23da2a Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 15 Jul 2011 23:14:26 -0400 Subject: [PATCH 16/69] closet hangers page has nice remove button --- app/controllers/closet_hangers_controller.rb | 30 +- app/helpers/application_helper.rb | 4 + app/stylesheets/closet_hangers/_index.sass | 45 +- app/stylesheets/outfits/_edit.sass | 6 +- app/stylesheets/partials/_context_button.sass | 6 + .../closet_hangers/_closet_hanger.html.haml | 11 +- app/views/closet_hangers/index.html.haml | 2 +- config/routes.rb | 2 +- public/javascripts/closet_hangers/index.js | 4 +- public/stylesheets/compiled/screen.css | 467 ++++++++++-------- 10 files changed, 332 insertions(+), 245 deletions(-) create mode 100644 app/stylesheets/partials/_context_button.sass diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 6b60f4ac..a25a6527 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -1,5 +1,15 @@ class ClosetHangersController < ApplicationController - before_filter :authorize_user!, :only => [:set_quantity] + before_filter :authorize_user!, :only => [:destroy, :update] + before_filter :find_item, :only => [:destroy, :update] + + def destroy + @closet_hanger = current_user.closet_hangers.find_by_item_id!(@item.id) + @closet_hanger.destroy + respond_to do |format| + format.html { redirect_after_destroy! } + format.js { render :json => true } + end + end def index @user = User.find params[:user_id] @@ -10,13 +20,13 @@ class ClosetHangersController < ApplicationController # quantity of an item they own, the user would expect a create form to work # even after the record already exists, and an update form to work even after # the record is deleted. So, create and update are aliased, and both find - # the record if it exists or create a new one if it does not. + # the record if it exists or create a new one if it does not. They will even + # delete the record if quantity is zero. # # This is kinda a violation of REST. It's not worth breaking user # expectations, though, and I can't really think of a genuinely RESTful way # to pull this off. def update - @item = Item.find params[:item_id] @closet_hanger = current_user.closet_hangers.find_or_initialize_by_item_id(@item.id) @closet_hanger.attributes = params[:closet_hanger] @@ -43,10 +53,7 @@ class ClosetHangersController < ApplicationController else # delete the hanger since the user doesn't want it @closet_hanger.destroy respond_to do |format| - format.html { - flash[:success] = "Success! You do not own #{@item.name}." - redirect_back! - } + format.html { redirect_after_destroy! } format.json { render :json => true } end @@ -61,6 +68,15 @@ class ClosetHangersController < ApplicationController raise AccessDenied unless user_signed_in? && current_user.id == params[:user_id].to_i end + def find_item + @item = Item.find params[:item_id] + end + + def redirect_after_destroy! + flash[:success] = "Success! You do not own #{@item.name}." + redirect_back! + end + def redirect_back! redirect_to params[:return_to] || @item end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7496defa..1bc47e4a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -86,6 +86,10 @@ module ApplicationHelper hidden_field_tag 'origin', value, :id => nil end + def return_to_field_tag + hidden_field_tag :return_to, request.fullpath + end + def show_title_header? params[:controller] != 'items' end diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 6470149a..067edcbc 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -1,3 +1,5 @@ +@import "partials/context_button" + body.closet_hangers-index #title float: left @@ -28,32 +30,41 @@ body.closet_hangers-index text-align: left top: $object-img-size - 20px - form - display: none - span, input[type=number] font-size: 16px font-weight: bold + form + display: none + &.current-user - .object:hover .quantity - +opacity(1) - background: transparent - top: $object-img-size - 24px - padding: 0 - - span - display: none - + .object:hover form display: inline - input[type=number] - padding: 2px - width: 2em + .closet-hanger-destroy + position: absolute + right: ($object-width - $object-img-size) / 2 + $object-padding + top: 0 - input[type=submit] - font-size: 85% + input + +context-button + + .quantity + +opacity(1) + background: transparent + top: $object-img-size - 24px + padding: 0 + + span + display: none + + input[type=number] + padding: 2px + width: 2em + + input[type=submit] + font-size: 85% &.js .object:hover .quantity diff --git a/app/stylesheets/outfits/_edit.sass b/app/stylesheets/outfits/_edit.sass index 4c2b1e3b..bcefb3a6 100644 --- a/app/stylesheets/outfits/_edit.sass +++ b/app/stylesheets/outfits/_edit.sass @@ -1,6 +1,7 @@ @import ../shared/jquery.jgrowl @import partials/wardrobe +@import "partials/context_button" @import "partials/icon" @import star @@ -400,10 +401,7 @@ body.outfits-edit li margin-bottom: .25em a - +awesome-button - +awesome-button-color(#aaaaaa) - +opacity(0.9) - font-size: 80% + +context-button &:hover ul, .object-info display: block diff --git a/app/stylesheets/partials/_context_button.sass b/app/stylesheets/partials/_context_button.sass new file mode 100644 index 00000000..a49f6cc3 --- /dev/null +++ b/app/stylesheets/partials/_context_button.sass @@ -0,0 +1,6 @@ +=context-button + +awesome-button + +awesome-button-color(#aaaaaa) + +opacity(0.9) + font-size: 80% + diff --git a/app/views/closet_hangers/_closet_hanger.html.haml b/app/views/closet_hangers/_closet_hanger.html.haml index 31c48471..17015c5b 100644 --- a/app/views/closet_hangers/_closet_hanger.html.haml +++ b/app/views/closet_hangers/_closet_hanger.html.haml @@ -1,10 +1,15 @@ +- show_controls ||= false # we could do user check here, but may as well do it once .object = render :partial => 'items/item_link', :locals => {:item => closet_hanger.item} .quantity %span= closet_hanger.quantity - - if user_is?(closet_hanger.user) - = form_for closet_hanger, :url => user_item_closet_hanger_path(current_user, closet_hanger.item) do |f| - = hidden_field_tag :return_to, request.fullpath + - if show_controls + = form_for closet_hanger, :url => user_item_closet_hanger_path(current_user, closet_hanger.item), :html => {:class => 'closet-hanger-update'} do |f| + = return_to_field_tag = f.number_field :quantity, :min => 0, :required => true, :title => "You own #{pluralize closet_hanger.quantity, closet_hanger.item.name}" = f.submit "Save" + - if show_controls + = form_tag user_item_closet_hanger_path(current_user, closet_hanger.item), :method => :delete, :class => 'closet-hanger-destroy' do + = return_to_field_tag + = submit_tag "Remove" diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index c5d600d9..d9b27d6c 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -11,7 +11,7 @@ %p These are the items you own. Hover over an item to remove it from the list or to change the quantity. - = render @closet_hangers + = render :partial => 'closet_hanger', :collection => @closet_hangers, :locals => {:show_controls => user_is?(@user)} - else - if user_is?(@user) %p You haven't tracked any items on Dress to Impress. diff --git a/config/routes.rb b/config/routes.rb index 6dbb1921..f3fe0d21 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -40,7 +40,7 @@ OpenneoImpressItems::Application.routes.draw do |map| resources :closet_hangers, :only => [:index], :path => 'closet' resources :items, :only => [] do - resource :closet_hanger, :only => [:create, :update] + resource :closet_hanger, :only => [:create, :update, :destroy] end end diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index a4574dc3..f189499b 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -54,7 +54,7 @@ } } - hangersEl.find('form').submit(function (e) { + hangersEl.find('form.closet-hanger-update').submit(function (e) { e.preventDefault(); submitForm($(this)); }); @@ -64,7 +64,7 @@ }).storeValue(); hangersEl.find('div.object').mouseleave(function () { - submitForm($(this).find('form')); + submitForm($(this).find('form.closet-hanger-update')); }); })(); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 5609ad53..1c6065fe 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -549,16 +549,16 @@ div.jGrowl div.jGrowl-closer { } } -/* line 2, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 4, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #title { float: left; margin-bottom: 0.5em; } -/* line 6, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 8, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .flash { clear: both; } -/* line 9, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 11, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #import-link { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -596,12 +596,12 @@ body.closet_hangers-index #import-link:active { body.closet_hangers-index #import-link:hover { background-color: #ee4b00; } -/* line 16, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 18, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers { clear: both; text-align: center; } -/* line 21, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 23, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -615,16 +615,67 @@ body.closet_hangers-index #closet-hangers .object .quantity { text-align: left; top: 60px; } -/* line 31, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers .object .quantity form { - display: none; -} -/* line 34, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 33, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { font-size: 16px; font-weight: bold; } -/* line 39, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 37, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers .object form { + display: none; +} +/* line 42, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers.current-user .object:hover form { + display: inline; +} +/* line 45, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy { + position: absolute; + right: 18px; + top: 0; +} +/* line 50, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input { + /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + background: #006400 url('/images/alert-overlay.png?1296599919') repeat-x; + border: 0; + display: inline-block; + padding: 0.5em 0.75em 0.45em; + color: white; + text-decoration: none; + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); + border-bottom: 1px solid rgba(0, 0, 0, 0.25); + position: relative; + font-weight: bold; + line-height: 1; + background: #aaaaaa url('/images/alert-overlay.png?1296599919') repeat-x; + -moz-opacity: 0.9; + -webkit-opacity: 0.9; + -o-opacity: 0.9; + -khtml-opacity: 0.9; + font-size: 80%; +} +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input:hover { + background-color: #005300; +} +/* line 53, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input:hover { + color: white; +} +/* line 55, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input:active { + top: 1px; +} +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input:hover { + background-color: #999999; +} +/* line 53, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -634,37 +685,33 @@ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity { top: 56px; padding: 0; } -/* line 45, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 59, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity span { display: none; } -/* line 48, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity form { - display: inline; -} -/* line 51, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 62, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 55, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 66, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 60, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 71, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user.js .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 63, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 74, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user.js .object:hover .quantity input[type=submit] { display: none; } -/* line 66, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 77, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user.js .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 70, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 81, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user.js .object.loading .quantity span:after { content: "…"; } @@ -1053,12 +1100,12 @@ body.items-show #closet-hanger-form p { } @import url(../shared/jquery.jgrowl.css); -/* line 112, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 113, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-toolbar { margin-bottom: 0.5em; text-align: left; } -/* line 115, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 116, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-toolbar form { display: -moz-inline-box; -moz-box-orient: vertical; @@ -1068,23 +1115,23 @@ body.outfits-edit #preview-toolbar form { *vertical-align: auto; margin-right: 2em; } -/* line 118, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 119, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-info form { display: inline; } -/* line 121, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 122, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-state-form ul { list-style: none; } -/* line 123, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 124, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-state-form ul, body.outfits-edit #pet-state-form ul li { display: inline; } -/* line 125, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 126, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-state-form input { display: none; } -/* line 127, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 128, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-state-form label { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1116,7 +1163,7 @@ body.outfits-edit #pet-state-form label:hover { body.outfits-edit #pet-state-form label:active { top: 1px; } -/* line 130, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 131, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-state-form li.selected button { background: #0b61a4 url('/images/alert-overlay.png?1296599919') repeat-x; } @@ -1124,30 +1171,30 @@ body.outfits-edit #pet-state-form li.selected button { body.outfits-edit #pet-state-form li.selected button:hover { background-color: #005093; } -/* line 132, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 133, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-state-form.hidden { visibility: hidden; } -/* line 134, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 135, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper { float: right; } -/* line 136, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 137, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper button { display: none; } -/* line 138, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 139, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper #share-outfit { display: inline-block; } -/* line 140, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 141, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper.loading { background-image: url('/images/loading.gif?1296599919'); background-position: left center; background-repeat: no-repeat; padding-left: 20px; } -/* line 146, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 147, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit, body.outfits-edit #save-outfit-not-signed-in, body.outfits-edit #save-current-outfit, body.outfits-edit #save-outfit-copy, body.outfits-edit #save-outfit-finish { background: #ff5c00 url('/images/alert-overlay.png?1296599919') repeat-x; } @@ -1155,28 +1202,28 @@ body.outfits-edit #save-outfit, body.outfits-edit #save-outfit-not-signed-in, bo body.outfits-edit #save-outfit:hover, body.outfits-edit #save-outfit-not-signed-in:hover, body.outfits-edit #save-current-outfit:hover, body.outfits-edit #save-outfit-copy:hover, body.outfits-edit #save-outfit-finish:hover { background-color: #ee4b00; } -/* line 148, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 149, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #current-outfit-permalink, body.outfits-edit #shared-outfit-permalink { display: none; margin-right: 0.25em; } -/* line 151, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 152, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #current-outfit-permalink img, body.outfits-edit #shared-outfit-permalink img { bottom: -2px; height: 16px; position: relative; width: 16px; } -/* line 153, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 154, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #shared-outfit-url { display: none; width: 15em; } -/* line 156, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 157, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview { clear: both; } -/* line 158, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 159, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-swf { float: left; height: 400px; @@ -1184,15 +1231,15 @@ body.outfits-edit #preview-swf { position: relative; width: 400px; } -/* line 165, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 166, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-swf.swf-adapter #preview-image-container { display: none; } -/* line 168, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 169, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-swf.image-adapter #preview-swf-container { display: none; } -/* line 170, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 171, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-image-container { position: relative; } @@ -1202,12 +1249,12 @@ body.outfits-edit #preview-image-container img { position: absolute; top: 0; } -/* line 173, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 174, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-image-container, body.outfits-edit #preview-image-container img { height: 100%; width: 100%; } -/* line 176, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 177, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-swf-overlay { -moz-opacity: 0; -webkit-opacity: 0; @@ -1220,7 +1267,7 @@ body.outfits-edit #preview-swf-overlay { top: 0; width: 100%; } -/* line 184, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 185, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-images-pending { background: black; background: rgba(0, 0, 0, 0.75); @@ -1232,11 +1279,11 @@ body.outfits-edit #preview-images-pending { right: 0; z-index: 1000; } -/* line 194, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 195, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-images-pending.waiting-on-0 { display: none; } -/* line 196, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 197, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode { margin-right: 1em; position: absolute; @@ -1245,21 +1292,21 @@ body.outfits-edit #preview-mode { top: 0; width: 7em; } -/* line 204, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 205, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode.flash-active #preview-mode-flash { color: #004400; font-weight: bold; } -/* line 207, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 208, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode.image-active #preview-mode-image { color: #004400; font-weight: bold; } -/* line 210, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 211, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode.image-active.can-download #preview-download-image { display: inline-block; } -/* line 212, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 213, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode-toggle { -moz-border-radius: 0.5em; -webkit-border-radius: 0.5em; @@ -1271,24 +1318,24 @@ body.outfits-edit #preview-mode-toggle { text-align: center; width: 5em; } -/* line 221, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 222, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode-toggle li { border-top: 1px solid #aaddaa; cursor: pointer; padding: 0.125em 0; width: 100%; } -/* line 226, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 227, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode-toggle li:first-child { border-top: 0; } -/* line 228, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 229, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-download-image { display: none; font-size: 85%; margin: 0 auto; } -/* line 232, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 233, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode-image-access-denied { display: block; font-size: 75%; @@ -1296,12 +1343,12 @@ body.outfits-edit #preview-mode-image-access-denied { text-decoration: none; width: 100%; } -/* line 238, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 239, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode-image-access-denied em { font-style: normal; text-decoration: underline; } -/* line 241, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 242, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar { -moz-border-radius: 10px; -webkit-border-radius: 10px; @@ -1313,73 +1360,73 @@ body.outfits-edit #preview-sidebar { overflow: auto; width: 378px; } -/* line 251, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 252, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar.viewing-outfits #preview-closet { display: none; } -/* line 253, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 254, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar.viewing-outfits #preview-outfits { display: block; } -/* line 255, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 256, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar.viewing-saving-outfit { height: auto; max-height: 100%; } -/* line 258, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 259, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar.viewing-saving-outfit #preview-closet { display: none; } -/* line 260, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 261, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar.viewing-saving-outfit #preview-saving-outfit { display: block; } -/* line 263, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 264, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar .sidebar-view h2 { margin-bottom: 0.25em; margin-left: 24px; } -/* line 268, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 269, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet h2 { margin-bottom: 0; } -/* line 270, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 271, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet ul { text-align: center; } -/* line 272, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 273, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object { background: #eeffee; } -/* line 274, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 275, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object img { -moz-opacity: 0.5; -webkit-opacity: 0.5; -o-opacity: 0.5; -khtml-opacity: 0.5; } -/* line 276, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 277, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object.worn { background: transparent; } -/* line 278, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 279, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object.worn img { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 280, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 281, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object.no-assets { background: #fbe3e4; color: #8a1f11; padding-bottom: 1.25em; } -/* line 284, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 285, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object.no-assets .no-assets-message { display: block; } -/* line 286, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 287, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .no-assets-message { background: #f3dbdc; bottom: 0; @@ -1391,7 +1438,7 @@ body.outfits-edit .no-assets-message { position: absolute; width: 100%; } -/* line 296, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 297, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #no-assets-full-message { -moz-border-radius: 5px; -webkit-border-radius: 5px; @@ -1405,12 +1452,12 @@ body.outfits-edit #no-assets-full-message { top: -9999px; width: 30em; } -/* line 307, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 308, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form { clear: both; text-align: left; } -/* line 310, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 311, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form h2 { display: -moz-inline-box; -moz-box-orient: vertical; @@ -1420,7 +1467,7 @@ body.outfits-edit #preview-search-form h2 { *vertical-align: auto; margin: 0 1em 0 0; } -/* line 313, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 314, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form input { display: -moz-inline-box; -moz-box-orient: vertical; @@ -1429,7 +1476,7 @@ body.outfits-edit #preview-search-form input { *display: inline; *vertical-align: auto; } -/* line 315, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 316, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-pagination { display: -moz-inline-box; -moz-box-orient: vertical; @@ -1439,53 +1486,53 @@ body.outfits-edit #preview-search-form-pagination { *vertical-align: auto; margin-left: 2em; } -/* line 318, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 319, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-pagination a, body.outfits-edit #preview-search-form-pagination span { margin: 0 0.25em; } -/* line 320, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 321, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-pagination .current { font-weight: bold; } -/* line 322, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 323, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-clear { display: none; font-size: 87.5%; margin-left: 2em; } -/* line 326, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 327, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-loading { display: none; font-size: 75%; font-style: italic; margin-left: 2em; } -/* line 332, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 333, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-no-results { display: none; } -/* line 334, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 335, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-help { font-size: 87.5%; margin-left: 2em; } -/* line 337, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 338, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .search-helper { font-family: inherit; } -/* line 339, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 340, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .possible-error { display: none; } -/* line 342, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 343, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #fullscreen-copyright { display: none; } -/* line 344, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 345, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen { height: 100%; } -/* line 347, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 348, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #container { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; @@ -1498,19 +1545,19 @@ body.outfits-edit.fullscreen #container { position: relative; width: 80%; } -/* line 355, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 356, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen h1 { display: none; } -/* line 357, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 358, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #short-url-response { position: static; } -/* line 359, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 360, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview { width: 100%; } -/* line 361, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 362, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-sidebar { float: right; height: 100%; @@ -1518,12 +1565,12 @@ body.outfits-edit.fullscreen #preview-sidebar { position: relative; width: 400px; } -/* line 367, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 368, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-sidebar.viewing-saving-outfit { height: auto; max-height: 100%; } -/* line 370, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 371, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-search-form { bottom: 1.5em; left: 0; @@ -1532,7 +1579,7 @@ body.outfits-edit.fullscreen #preview-search-form { position: absolute; width: 100%; } -/* line 378, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 379, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-search-form-help div { display: -moz-inline-box; -moz-box-orient: vertical; @@ -1542,27 +1589,27 @@ body.outfits-edit.fullscreen #preview-search-form-help div { *vertical-align: auto; width: 48%; } -/* line 381, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 382, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #footer { bottom: 0; left: 0; position: absolute; width: 100%; } -/* line 386, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 387, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #footer ul, body.outfits-edit.fullscreen #footer p, body.outfits-edit.fullscreen #footer li { display: inline; } -/* line 388, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 389, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #footer ul { margin-right: 2em; } -/* line 391, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 392, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object { padding: 6px; position: relative; } -/* line 394, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 395, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object ul { display: none; left: 0; @@ -1570,11 +1617,11 @@ body.outfits-edit .object ul { position: absolute; top: 0; } -/* line 400, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 401, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object ul li { margin-bottom: 0.25em; } -/* line 402, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 403, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object ul li a { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1615,11 +1662,11 @@ body.outfits-edit .object ul li a:active { body.outfits-edit .object ul li a:hover { background-color: #999999; } -/* line 408, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 406, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object:hover ul, body.outfits-edit .object:hover .object-info { display: block; } -/* line 415, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 413, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .nc-icon { background: url('/images/nc.png?1310666180') no-repeat; height: 16px; @@ -1629,14 +1676,14 @@ body.outfits-edit .nc-icon { top: 64px; width: 16px; } -/* line 423, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 421, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .nc-icon:hover { -moz-opacity: 0.5; -webkit-opacity: 0.5; -o-opacity: 0.5; -khtml-opacity: 0.5; } -/* line 426, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 424, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object-info { -moz-border-radius: 12px; -webkit-border-radius: 12px; @@ -1653,26 +1700,26 @@ body.outfits-edit .object-info { top: 0; width: 16px; } -/* line 437, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 435, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object-info span { font-family: "Droid Serif", Georgia, "Times New Roman", Times, serif; font-weight: bold; position: relative; top: -2px; } -/* line 443, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 441, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object-info:hover { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 446, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 444, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits { display: none; text-align: left; } -/* line 449, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 447, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul { margin-left: 24px; margin-right: 24px; @@ -1683,7 +1730,7 @@ body.outfits-edit #preview-outfits > ul { margin-bottom: 1em; min-height: 16px; } -/* line 458, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 456, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li { padding: 0.25em 0; } @@ -1718,7 +1765,7 @@ body.outfits-edit #preview-outfits > ul > li .outfit-star { margin-left: -24px; margin-right: 0; } -/* line 37, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 38, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li img { height: 100px; left: -25px; @@ -1726,7 +1773,7 @@ body.outfits-edit #preview-outfits > ul > li img { top: -25px; width: 100px; } -/* line 43, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 44, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li .outfit-delete { -moz-border-radius: 0; -webkit-border-radius: 0; @@ -1760,7 +1807,7 @@ body.outfits-edit #preview-outfits > ul > li .outfit-delete:hover { body.outfits-edit #preview-outfits > ul > li .outfit-delete:active { top: auto; } -/* line 51, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 52, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li .outfit-delete:hover { -moz-opacity: 1; -webkit-opacity: 1; @@ -1768,29 +1815,29 @@ body.outfits-edit #preview-outfits > ul > li .outfit-delete:hover { -khtml-opacity: 1; background: #eeffee; } -/* line 54, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 55, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li header { display: block; padding-left: 24px; } -/* line 57, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 58, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li h4 { cursor: pointer; display: inline; } -/* line 60, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 61, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li h4:hover { text-decoration: underline; } -/* line 62, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 63, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li h4, body.outfits-edit #preview-outfits > ul > li .outfit-rename-field { font-size: 115%; } -/* line 64, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 65, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li .outfit-rename-button, body.outfits-edit #preview-outfits > ul > li .outfit-rename-form { display: none; } -/* line 66, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 67, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li .outfit-rename-button { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -1799,7 +1846,7 @@ body.outfits-edit #preview-outfits > ul > li .outfit-rename-button { font-size: 75%; margin-left: 1em; } -/* line 70, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 71, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li .outfit-url { -moz-opacity: 0.5; -webkit-opacity: 0.5; @@ -1809,7 +1856,7 @@ body.outfits-edit #preview-outfits > ul > li .outfit-url { border-width: 0; width: 284px; } -/* line 75, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 76, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li .outfit-url:hover { -moz-opacity: 1; -webkit-opacity: 1; @@ -1817,63 +1864,63 @@ body.outfits-edit #preview-outfits > ul > li .outfit-url:hover { -khtml-opacity: 1; border-width: 1px; } -/* line 78, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 79, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li .outfit-delete-confirmation { display: none; font-size: 75%; } -/* line 81, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 82, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li .outfit-delete-confirmation span { color: red; } -/* line 83, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 84, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li .outfit-delete-confirmation a { margin: 0 0.25em; } -/* line 85, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 86, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li.active { background: #eeffee; } -/* line 88, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 89, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li.confirming-deletion .outfit-delete { visibility: hidden; } -/* line 90, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 91, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li.confirming-deletion .outfit-url { display: none; } -/* line 92, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 93, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li.confirming-deletion .outfit-delete-confirmation { display: block; } -/* line 95, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 96, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li.renaming h4 { display: none; } -/* line 97, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 98, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li.renaming .outfit-rename-form { display: inline; } -/* line 100, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 101, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li.renaming:hover .outfit-rename-button { display: none; } -/* line 103, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 104, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li:hover .outfit-rename-button { display: inline; } -/* line 460, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 458, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul.loaded { background: transparent; } -/* line 463, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 461, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .preview-sidebar-nav { float: right; font-size: 85%; margin-right: 24px; margin-top: 1em; } -/* line 470, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 468, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-success, body.outfits-edit #save-error, body.outfits-edit #outfit-not-found, body.outfits-edit #preview-sidebar-donation-request { margin-left: 24px; margin-right: 24px; @@ -1881,7 +1928,7 @@ body.outfits-edit #save-success, body.outfits-edit #save-error, body.outfits-edi margin-top: 1em; text-align: center; } -/* line 477, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 475, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar-donation-request { background: #e6efc2; border: 1px solid #c6d880; @@ -1889,23 +1936,23 @@ body.outfits-edit #preview-sidebar-donation-request { font-size: 85%; padding: 1em; } -/* line 482, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 480, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar-donation-request-no-thanks { margin-left: 1em; } -/* line 485, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 483, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-success { background: #e6efc2; border: 1px solid #c6d880; color: #264409; } -/* line 488, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 486, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-error, body.outfits-edit #outfit-not-found { background: #fbe3e4; border: 1px solid #fbc2c4; color: #8a1f11; } -/* line 491, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 489, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #userbar-message { -moz-opacity: 0.5; -webkit-opacity: 0.5; @@ -1913,7 +1960,7 @@ body.outfits-edit #userbar-message { -khtml-opacity: 0.5; display: none; } -/* line 495, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 493, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit { padding: 0.25em 0; margin-left: 24px; @@ -1951,7 +1998,7 @@ body.outfits-edit #new-outfit .outfit-star { margin-left: -24px; margin-right: 0; } -/* line 37, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 38, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit img { height: 100px; left: -25px; @@ -1959,7 +2006,7 @@ body.outfits-edit #new-outfit img { top: -25px; width: 100px; } -/* line 43, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 44, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit .outfit-delete { -moz-border-radius: 0; -webkit-border-radius: 0; @@ -1993,7 +2040,7 @@ body.outfits-edit #new-outfit .outfit-delete:hover { body.outfits-edit #new-outfit .outfit-delete:active { top: auto; } -/* line 51, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 52, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit .outfit-delete:hover { -moz-opacity: 1; -webkit-opacity: 1; @@ -2001,29 +2048,29 @@ body.outfits-edit #new-outfit .outfit-delete:hover { -khtml-opacity: 1; background: #eeffee; } -/* line 54, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 55, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit header { display: block; padding-left: 24px; } -/* line 57, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 58, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit h4 { cursor: pointer; display: inline; } -/* line 60, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 61, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit h4:hover { text-decoration: underline; } -/* line 62, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 63, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit h4, body.outfits-edit #new-outfit .outfit-rename-field { font-size: 115%; } -/* line 64, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 65, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit .outfit-rename-button, body.outfits-edit #new-outfit .outfit-rename-form { display: none; } -/* line 66, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 67, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit .outfit-rename-button { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -2032,7 +2079,7 @@ body.outfits-edit #new-outfit .outfit-rename-button { font-size: 75%; margin-left: 1em; } -/* line 70, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 71, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit .outfit-url { -moz-opacity: 0.5; -webkit-opacity: 0.5; @@ -2042,7 +2089,7 @@ body.outfits-edit #new-outfit .outfit-url { border-width: 0; width: 284px; } -/* line 75, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 76, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit .outfit-url:hover { -moz-opacity: 1; -webkit-opacity: 1; @@ -2050,78 +2097,78 @@ body.outfits-edit #new-outfit .outfit-url:hover { -khtml-opacity: 1; border-width: 1px; } -/* line 78, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 79, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit .outfit-delete-confirmation { display: none; font-size: 75%; } -/* line 81, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 82, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit .outfit-delete-confirmation span { color: red; } -/* line 83, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 84, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit .outfit-delete-confirmation a { margin: 0 0.25em; } -/* line 85, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 86, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit.active { background: #eeffee; } -/* line 88, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 89, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit.confirming-deletion .outfit-delete { visibility: hidden; } -/* line 90, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 91, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit.confirming-deletion .outfit-url { display: none; } -/* line 92, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 93, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit.confirming-deletion .outfit-delete-confirmation { display: block; } -/* line 95, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 96, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit.renaming h4 { display: none; } -/* line 97, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 98, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit.renaming .outfit-rename-form { display: inline; } -/* line 100, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 101, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit.renaming:hover .outfit-rename-button { display: none; } -/* line 103, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 104, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit:hover .outfit-rename-button { display: inline; } -/* line 499, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 497, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit h4 { display: inline; } -/* line 501, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 499, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit h4:hover { text-decoration: none; } -/* line 503, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 501, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit .outfit-star { margin-top: 0.5em; } -/* line 506, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 504, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit-name { font: inherit; line-height: 1; } -/* line 510, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 508, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-saving-outfit { display: none; padding-bottom: 1em; } -/* line 514, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 512, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-type-form, body.outfits-edit #pet-state-form, body.outfits-edit #preview-swf, body.outfits-edit #preview-search-form { position: relative; } -/* line 517, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 515, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .control-overlay { height: 100%; left: 0; @@ -2130,11 +2177,11 @@ body.outfits-edit .control-overlay { width: 100%; z-index: 5; } -/* line 525, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 523, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar-nav-outfits, body.outfits-edit #save-outfit-signed-in { display: none; } -/* line 528, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 526, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form { padding: 0.25em 0; display: none; @@ -2172,7 +2219,7 @@ body.outfits-edit form#save-outfit-form .outfit-star { margin-left: -24px; margin-right: 0; } -/* line 37, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 38, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form img { height: 100px; left: -25px; @@ -2180,7 +2227,7 @@ body.outfits-edit form#save-outfit-form img { top: -25px; width: 100px; } -/* line 43, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 44, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-delete { -moz-border-radius: 0; -webkit-border-radius: 0; @@ -2214,7 +2261,7 @@ body.outfits-edit form#save-outfit-form .outfit-delete:hover { body.outfits-edit form#save-outfit-form .outfit-delete:active { top: auto; } -/* line 51, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 52, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-delete:hover { -moz-opacity: 1; -webkit-opacity: 1; @@ -2222,29 +2269,29 @@ body.outfits-edit form#save-outfit-form .outfit-delete:hover { -khtml-opacity: 1; background: #eeffee; } -/* line 54, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 55, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form header { display: block; padding-left: 24px; } -/* line 57, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 58, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form h4 { cursor: pointer; display: inline; } -/* line 60, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 61, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form h4:hover { text-decoration: underline; } -/* line 62, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 63, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form h4, body.outfits-edit form#save-outfit-form .outfit-rename-field { font-size: 115%; } -/* line 64, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 65, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-rename-button, body.outfits-edit form#save-outfit-form .outfit-rename-form { display: none; } -/* line 66, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 67, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-rename-button { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -2253,7 +2300,7 @@ body.outfits-edit form#save-outfit-form .outfit-rename-button { font-size: 75%; margin-left: 1em; } -/* line 70, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 71, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-url { -moz-opacity: 0.5; -webkit-opacity: 0.5; @@ -2263,7 +2310,7 @@ body.outfits-edit form#save-outfit-form .outfit-url { border-width: 0; width: 284px; } -/* line 75, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 76, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-url:hover { -moz-opacity: 1; -webkit-opacity: 1; @@ -2271,52 +2318,52 @@ body.outfits-edit form#save-outfit-form .outfit-url:hover { -khtml-opacity: 1; border-width: 1px; } -/* line 78, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 79, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-delete-confirmation { display: none; font-size: 75%; } -/* line 81, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 82, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-delete-confirmation span { color: red; } -/* line 83, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 84, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-delete-confirmation a { margin: 0 0.25em; } -/* line 85, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 86, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form.active { background: #eeffee; } -/* line 88, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 89, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form.confirming-deletion .outfit-delete { visibility: hidden; } -/* line 90, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 91, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form.confirming-deletion .outfit-url { display: none; } -/* line 92, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 93, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form.confirming-deletion .outfit-delete-confirmation { display: block; } -/* line 95, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 96, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form.renaming h4 { display: none; } -/* line 97, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 98, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form.renaming .outfit-rename-form { display: inline; } -/* line 100, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 101, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form.renaming:hover .outfit-rename-button { display: none; } -/* line 103, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 104, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form:hover .outfit-rename-button { display: inline; } -/* line 534, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 532, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-star, body.outfits-edit form#save-outfit-form input, body.outfits-edit form#save-outfit-form button { display: -moz-inline-box; -moz-box-orient: vertical; @@ -2327,51 +2374,51 @@ body.outfits-edit form#save-outfit-form .outfit-star, body.outfits-edit form#sav float: none; vertical-align: top; } -/* line 539, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 537, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-star { margin-top: 0.25em; } -/* line 542, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 540, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .outfit-url { font-size: 75%; } -/* line 546, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 544, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #preview-sidebar-nav-outfits { display: block; } -/* line 548, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 546, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit { display: inline-block; } -/* line 552, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 550, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-outfit { display: none; } -/* line 554, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 552, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-current-outfit, body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-outfit-copy { display: inline-block; } -/* line 556, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 554, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #current-outfit-permalink { display: inline-block; } -/* line 559, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 557, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit-form { display: block; } -/* line 561, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 559, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-current-outfit, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit-copy, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #current-outfit-permalink, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #shared-outfit-permalink, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #share-outfit, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #shared-outfit-url { display: none; } -/* line 565, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 563, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-not-signed-in #save-outfit-not-signed-in { display: inline-block; } -/* line 569, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 567, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper.shared-outfit #shared-outfit-permalink, body.outfits-edit #save-outfit-wrapper.shared-outfit #shared-outfit-url { display: inline-block; } -/* line 571, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 569, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper.shared-outfit #current-outfit-permalink { display: none !important; } From e72c9a0092b7b41d4aa9887e1e9de153ecda5ffc Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 15 Jul 2011 23:39:19 -0400 Subject: [PATCH 17/69] closet hangers delete gets nifty ajax, too --- app/controllers/closet_hangers_controller.rb | 6 +-- public/javascripts/closet_hangers/index.js | 54 +++++++++++++++++--- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index a25a6527..e57c75db 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -1,13 +1,13 @@ class ClosetHangersController < ApplicationController - before_filter :authorize_user!, :only => [:destroy, :update] - before_filter :find_item, :only => [:destroy, :update] + before_filter :authorize_user!, :only => [:destroy, :create, :update] + before_filter :find_item, :only => [:destroy, :create, :update] def destroy @closet_hanger = current_user.closet_hangers.find_by_item_id!(@item.id) @closet_hanger.destroy respond_to do |format| format.html { redirect_after_destroy! } - format.js { render :json => true } + format.json { render :json => true } end end diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index f189499b..1257225c 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -2,6 +2,14 @@ var hangersEl = $('#closet-hangers.current-user'); hangersEl.addClass('js'); + $.fn.disableForms = function () { + return this.data("formsDisabled", true).find("input").attr("disabled", "disabled").end(); + } + + $.fn.enableForms = function () { + return this.data("formsDisabled", false).find("input").removeAttr("disabled").end(); + } + $.fn.hasChanged = function () { return this.data('previousValue') != this.val(); } @@ -20,28 +28,33 @@ }); } - function submitForm(form) { + function submitUpdateForm(form) { if(form.data('loading')) return false; var input = form.children("input[type=number]"); if(input.hasChanged()) { var objectWrapper = form.closest(".object").addClass("loading"); var span = objectWrapper.find("span").text(input.val()); + var data = form.serialize(); // get data before disabling inputs + objectWrapper.disableForms(); form.data('loading', true); - $.ajax({ url: form.attr("action") + ".json", type: "post", - data: form.serialize(), + data: data, dataType: "json", complete: function (data) { - objectWrapper.removeClass("loading"); + objectWrapper.removeClass("loading").enableForms(); form.data('loading', false); }, success: function () { input.storeValue(); }, error: function (xhr) { - var data = $.parseJSON(xhr.responseText); + try { + var data = $.parseJSON(xhr.responseText); + } catch(e) { + var data = {}; + } input.revertValue(); span.text(input.val()); if(typeof data.errors != 'undefined') { @@ -56,15 +69,40 @@ hangersEl.find('form.closet-hanger-update').submit(function (e) { e.preventDefault(); - submitForm($(this)); + submitUpdateForm($(this)); }); hangersEl.find('input[type=number]').change(function () { - submitForm($(this).parent()); + submitUpdateForm($(this).parent()); }).storeValue(); hangersEl.find('div.object').mouseleave(function () { - submitForm($(this).find('form.closet-hanger-update')); + submitUpdateForm($(this).find('form.closet-hanger-update')); + }); + + hangersEl.find("form.closet-hanger-destroy").submit(function (e) { + e.preventDefault(); + var form = $(this); + var button = form.children("input").val("Removing…"); + var objectWrapper = form.closest(".object").addClass("loading"); + var data = form.serialize(); // get data before disabling inputs + objectWrapper.addClass("loading").disableForms(); + $.ajax({ + url: form.attr("action") + ".json", + type: "post", + data: data, + dataType: "json", + complete: function () { + button.val("Remove"); + }, + success: function () { + objectWrapper.hide(500); + }, + error: function () { + objectWrapper.removeClass("loading").enableForms(); + $.jGrowl("Error removing item. Try again?"); + } + }); }); })(); From eac0d327f9a7092c850fd9ccadb28c24865fc28a Mon Sep 17 00:00:00 2001 From: Matchu Date: Sat, 16 Jul 2011 01:09:04 -0400 Subject: [PATCH 18/69] add items to closet via magic autocomplete --- app/stylesheets/closet_hangers/_index.sass | 19 +- app/views/closet_hangers/index.html.haml | 8 +- app/views/layouts/application.html.haml | 1 + public/javascripts/closet_hangers/index.js | 102 +++++- public/javascripts/jquery.ui.js | 81 +++++ public/javascripts/placeholder.js | 3 + public/stylesheets/compiled/screen.css | 52 ++- .../images/ui-bg_glass_55_fcf0ba_1x400.png | Bin 0 -> 127 bytes .../ui-bg_gloss-wave_100_ece8da_500x100.png | Bin 0 -> 2130 bytes .../ui-bg_highlight-hard_100_f5f3e5_1x100.png | Bin 0 -> 139 bytes .../ui-bg_highlight-hard_100_fafaf4_1x100.png | Bin 0 -> 96 bytes .../ui-bg_highlight-hard_15_459e00_1x100.png | Bin 0 -> 153 bytes .../ui-bg_highlight-hard_95_cccccc_1x100.png | Bin 0 -> 105 bytes .../ui-bg_highlight-soft_25_67b021_1x100.png | Bin 0 -> 124 bytes .../ui-bg_highlight-soft_95_ffedad_1x100.png | Bin 0 -> 165 bytes .../ui-bg_inset-soft_15_2b2922_1x100.png | Bin 0 -> 119 bytes .../images/ui-icons_808080_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_847e71_256x240.png | Bin 0 -> 5355 bytes .../images/ui-icons_8dc262_256x240.png | Bin 0 -> 5355 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_eeeeee_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 4369 bytes public/stylesheets/south-street/jquery-ui.css | 342 ++++++++++++++++++ 23 files changed, 566 insertions(+), 42 deletions(-) create mode 100644 public/javascripts/jquery.ui.js create mode 100644 public/javascripts/placeholder.js create mode 100644 public/stylesheets/south-street/images/ui-bg_glass_55_fcf0ba_1x400.png create mode 100644 public/stylesheets/south-street/images/ui-bg_gloss-wave_100_ece8da_500x100.png create mode 100644 public/stylesheets/south-street/images/ui-bg_highlight-hard_100_f5f3e5_1x100.png create mode 100644 public/stylesheets/south-street/images/ui-bg_highlight-hard_100_fafaf4_1x100.png create mode 100644 public/stylesheets/south-street/images/ui-bg_highlight-hard_15_459e00_1x100.png create mode 100644 public/stylesheets/south-street/images/ui-bg_highlight-hard_95_cccccc_1x100.png create mode 100644 public/stylesheets/south-street/images/ui-bg_highlight-soft_25_67b021_1x100.png create mode 100644 public/stylesheets/south-street/images/ui-bg_highlight-soft_95_ffedad_1x100.png create mode 100644 public/stylesheets/south-street/images/ui-bg_inset-soft_15_2b2922_1x100.png create mode 100644 public/stylesheets/south-street/images/ui-icons_808080_256x240.png create mode 100644 public/stylesheets/south-street/images/ui-icons_847e71_256x240.png create mode 100644 public/stylesheets/south-street/images/ui-icons_8dc262_256x240.png create mode 100644 public/stylesheets/south-street/images/ui-icons_cd0a0a_256x240.png create mode 100644 public/stylesheets/south-street/images/ui-icons_eeeeee_256x240.png create mode 100644 public/stylesheets/south-street/images/ui-icons_ffffff_256x240.png create mode 100644 public/stylesheets/south-street/jquery-ui.css diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 067edcbc..2b61baf3 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -1,4 +1,5 @@ @import "partials/context_button" +@import "partials/icon" body.closet_hangers-index #title @@ -8,12 +9,24 @@ body.closet_hangers-index .flash clear: both + #import-link, #closet-hangers-items-search + margin-top: .75em + #import-link +awesome-button +loud-awesome-button-color - margin: - left: 2em - top: .75em + margin-left: 2em + + #closet-hangers-items-search + float: right + + input[type=search] + &.loading + background: + image: url(/images/loading.gif) + position: 2px center + repeat: no-repeat + padding-left: $icon-width + 4px #closet-hangers clear: both diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index d9b27d6c..c8d4beab 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -2,6 +2,9 @@ - title 'Your Items' - content_for :before_flashes do = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' + = form_tag items_path, :method => :get, :id => 'closet-hangers-items-search', 'data-current-user-id' => current_user.id do + = search_field_tag :q, nil, :placeholder => "Search items" + = submit_tag 'Search', :name => nil - else - title "#{@user.name}'s Items" @@ -27,7 +30,10 @@ - else %p #{@user.name} hasn't tracked any items on Dress to Impress. +- content_for :stylesheets do + = stylesheet_link_tag 'south-street/jquery-ui' + - content_for :javascripts do = include_javascript_libraries :jquery - = javascript_include_tag 'jquery.jgrowl.js', 'closet_hangers/index' + = javascript_include_tag 'jquery.ui', 'jquery.jgrowl', 'placeholder', 'closet_hangers/index' diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index fbf7fc6f..b3e99087 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -11,6 +11,7 @@ Dress to Impress: Preview customized Neopets' clothing and wearables /[if IE] = include_javascript_libraries :html5 + = yield :stylesheets = stylesheet_link_tag "compiled/screen" = yield :meta = csrf_meta_tag diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index 1257225c..b26eb31e 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -1,5 +1,6 @@ (function () { - var hangersEl = $('#closet-hangers.current-user'); + var hangersElQuery = '#closet-hangers.current-user'; + var hangersEl = $(hangersElQuery); hangersEl.addClass('js'); $.fn.disableForms = function () { @@ -15,19 +16,37 @@ } $.fn.revertValue = function () { - this.each(function () { + return this.each(function () { var el = $(this); el.val(el.data('previousValue')); }); } $.fn.storeValue = function () { - this.each(function () { + return this.each(function () { var el = $(this); el.data('previousValue', el.val()); }); } + function handleHangerError(xhr, action) { + try { + var data = $.parseJSON(xhr.responseText); + } catch(e) { + var data = {}; + } + + if(typeof data.errors != 'undefined') { + $.jGrowl("Error " + action + ": " + data.errors.join(", ")); + } else { + $.jGrowl("We had trouble " + action + " just now. Try again?"); + } + } + + function objectRemoved(objectWrapper) { + objectWrapper.hide(250); + } + function submitUpdateForm(form) { if(form.data('loading')) return false; var input = form.children("input[type=number]"); @@ -43,44 +62,42 @@ data: data, dataType: "json", complete: function (data) { - objectWrapper.removeClass("loading").enableForms(); + if(input.val() == 0) { + objectRemoved(objectWrapper); + } else { + objectWrapper.removeClass("loading").enableForms(); + } form.data('loading', false); }, success: function () { input.storeValue(); }, error: function (xhr) { - try { - var data = $.parseJSON(xhr.responseText); - } catch(e) { - var data = {}; - } input.revertValue(); span.text(input.val()); - if(typeof data.errors != 'undefined') { - $.jGrowl("Error updating quantity: " + data.errors.join(", ")); - } else { - $.jGrowl("We had trouble updating the quantity just now. Try again?"); - } + + handleHangerError(xhr, "updating the quantity"); } }); } } - hangersEl.find('form.closet-hanger-update').submit(function (e) { + $(hangersElQuery + ' form.closet-hanger-update').live('submit', function (e) { e.preventDefault(); submitUpdateForm($(this)); }); - hangersEl.find('input[type=number]').change(function () { + function quantityInputs() { return $(hangersElQuery + ' input[type=number]') } + + quantityInputs().live('change', function () { submitUpdateForm($(this).parent()); }).storeValue(); - hangersEl.find('div.object').mouseleave(function () { + $(hangersElQuery + ' div.object').live('mouseleave', function () { submitUpdateForm($(this).find('form.closet-hanger-update')); }); - hangersEl.find("form.closet-hanger-destroy").submit(function (e) { + $(hangersElQuery + " form.closet-hanger-destroy").live("submit", function (e) { e.preventDefault(); var form = $(this); var button = form.children("input").val("Removing…"); @@ -96,7 +113,7 @@ button.val("Remove"); }, success: function () { - objectWrapper.hide(500); + objectRemoved(objectWrapper); }, error: function () { objectWrapper.removeClass("loading").enableForms(); @@ -104,5 +121,52 @@ } }); }); + + $('input, textarea').placeholder(); + + var itemsSearchForm = $("#closet-hangers-items-search[data-current-user-id]"); + var itemsSearchField = itemsSearchForm.children("input[type=search]"); + + itemsSearchField.autocomplete({ + select: function (e, ui) { + var item = ui.item; + itemsSearchField.addClass("loading"); + + $.ajax({ + url: "/user/" + itemsSearchForm.data("current-user-id") + "/items/" + item.id + "/closet_hanger", + type: "post", + data: {closet_hanger: {quantity: 1}, return_to: window.location.pathname + window.location.search}, + complete: function () { + itemsSearchField.removeClass("loading"); + }, + success: function (html) { + var doc = $(html); + hangersEl.html( doc.find('#closet-hangers').html() ); + quantityInputs().storeValue(); // since all the quantity inputs are new, gotta store initial value again + doc.find('.flash').hide().insertBefore(hangersEl).show(500).delay(5000).hide(250); + itemsSearchField.val(""); + }, + error: function (xhr) { + handleHangerError(xhr, "adding the item"); + } + }); + }, + source: function (input, callback) { + $.getJSON("/items.json?q=" + input.term, function (data) { + var output = []; + var items = data.items; + for(var i in items) { + items[i].label = items[i].name; + output[output.length] = items[i]; + } + callback(output); + }) + } + }).data( "autocomplete" )._renderItem = function( ul, item ) { + return $( "
  • " ) + .data( "item.autocomplete", item ) + .append( "Add " + item.label + "" ) + .appendTo( ul ); + } })(); diff --git a/public/javascripts/jquery.ui.js b/public/javascripts/jquery.ui.js new file mode 100644 index 00000000..dad0f2e5 --- /dev/null +++ b/public/javascripts/jquery.ui.js @@ -0,0 +1,81 @@ +/*! + * jQuery UI 1.8.14 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */ +(function(c,j){function k(a,b){var d=a.nodeName.toLowerCase();if("area"===d){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&l(a)}return(/input|select|textarea|button|object/.test(d)?!a.disabled:"a"==d?a.href||b:b)&&l(a)}function l(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.14", +keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus(); +b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this, +"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection", +function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,m,n){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(m)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(n)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth, +outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){return k(a,!isNaN(c.attr(a,"tabindex")))},tabbable:function(a){var b=c.attr(a,"tabindex"),d=isNaN(b); +return(d||b>=0)&&k(a,!d)}});c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e= +0;e0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a0?b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();b.top=d>0?b.top-d:Math.max(b.top-a.collisionPosition.top,b.top)}},flip:{left:function(b,a){if(a.at[0]!=="center"){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();var g=a.my[0]==="left"?-a.elemWidth:a.my[0]==="right"?a.elemWidth:0,e=a.at[0]==="left"?a.targetWidth:-a.targetWidth,h=-2*a.offset[0];b.left+= +a.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!=="center"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]==="top"?-a.elemHeight:a.my[1]==="bottom"?a.elemHeight:0,e=a.at[1]==="top"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,"position")))b.style.position="relative";var d=c(b), +g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"left",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};"using"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery); +;/* + * jQuery UI Autocomplete 1.8.14 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function(d){var e=0;d.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:false,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var a=this,b=this.element[0].ownerDocument,g;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!(a.options.disabled||a.element.attr("readonly"))){g= +false;var f=d.ui.keyCode;switch(c.keyCode){case f.PAGE_UP:a._move("previousPage",c);break;case f.PAGE_DOWN:a._move("nextPage",c);break;case f.UP:a._move("previous",c);c.preventDefault();break;case f.DOWN:a._move("next",c);c.preventDefault();break;case f.ENTER:case f.NUMPAD_ENTER:if(a.menu.active){g=true;c.preventDefault()}case f.TAB:if(!a.menu.active)return;a.menu.select(c);break;case f.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!= +a.element.val()){a.selectedItem=null;a.search(null,c)}},a.options.delay);break}}}).bind("keypress.autocomplete",function(c){if(g){g=false;c.preventDefault()}}).bind("focus.autocomplete",function(){if(!a.options.disabled){a.selectedItem=null;a.previous=a.element.val()}}).bind("blur.autocomplete",function(c){if(!a.options.disabled){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)}});this._initSource();this.response=function(){return a._response.apply(a,arguments)}; +this.menu=d("
      ").addClass("ui-autocomplete").appendTo(d(this.options.appendTo||"body",b)[0]).mousedown(function(c){var f=a.menu.element[0];d(c.target).closest(".ui-menu-item").length||setTimeout(function(){d(document).one("mousedown",function(h){h.target!==a.element[0]&&h.target!==f&&!d.ui.contains(f,h.target)&&a.close()})},1);setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(c,f){f=f.item.data("item.autocomplete");false!==a._trigger("focus",c,{item:f})&&/^key/.test(c.originalEvent.type)&& +a.element.val(f.value)},selected:function(c,f){var h=f.item.data("item.autocomplete"),i=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();a.previous=i;setTimeout(function(){a.previous=i;a.selectedItem=h},1)}false!==a._trigger("select",c,{item:h})&&a.element.val(h.value);a.term=a.element.val();a.close(c);a.selectedItem=h},blur:function(){a.menu.element.is(":visible")&&a.element.val()!==a.term&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu"); +d.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();d.Widget.prototype.destroy.call(this)},_setOption:function(a,b){d.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource();if(a==="appendTo")this.menu.element.appendTo(d(b||"body",this.element[0].ownerDocument)[0]);a==="disabled"&& +b&&this.xhr&&this.xhr.abort()},_initSource:function(){var a=this,b,g;if(d.isArray(this.options.source)){b=this.options.source;this.source=function(c,f){f(d.ui.autocomplete.filter(b,c.term))}}else if(typeof this.options.source==="string"){g=this.options.source;this.source=function(c,f){a.xhr&&a.xhr.abort();a.xhr=d.ajax({url:g,data:c,dataType:"json",autocompleteRequest:++e,success:function(h){this.autocompleteRequest===e&&f(h)},error:function(){this.autocompleteRequest===e&&f([])}})}}else this.source= +this.options.source},search:function(a,b){a=a!=null?a:this.element.val();this.term=this.element.val();if(a.length").data("item.autocomplete",b).append(d("
      ").text(b.label)).appendTo(a)},_move:function(a,b){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});d.extend(d.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, +"\\$&")},filter:function(a,b){var g=new RegExp(d.ui.autocomplete.escapeRegex(b),"i");return d.grep(a,function(c){return g.test(c.label||c.value||c)})}})})(jQuery); +(function(d){d.widget("ui.menu",{_create:function(){var e=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(a){if(d(a.target).closest(".ui-menu-item a").length){a.preventDefault();e.select(a)}});this.refresh()},refresh:function(){var e=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex", +-1).mouseenter(function(a){e.activate(a,d(this).parent())}).mouseleave(function(){e.deactivate()})},activate:function(e,a){this.deactivate();if(this.hasScroll()){var b=a.offset().top-this.element.offset().top,g=this.element.scrollTop(),c=this.element.height();if(b<0)this.element.scrollTop(g+b);else b>=c&&this.element.scrollTop(g+b-c+a.height())}this.active=a.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",e,{item:a})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id"); +this._trigger("blur");this.active=null}},next:function(e){this.move("next",".ui-menu-item:first",e)},previous:function(e){this.move("prev",".ui-menu-item:last",e)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(e,a,b){if(this.active){e=this.active[e+"All"](".ui-menu-item").eq(0);e.length?this.activate(b,e):this.activate(b,this.element.children(a))}else this.activate(b, +this.element.children(a))},nextPage:function(e){if(this.hasScroll())if(!this.active||this.last())this.activate(e,this.element.children(".ui-menu-item:first"));else{var a=this.active.offset().top,b=this.element.height(),g=this.element.children(".ui-menu-item").filter(function(){var c=d(this).offset().top-a-b+d(this).height();return c<10&&c>-10});g.length||(g=this.element.children(".ui-menu-item:last"));this.activate(e,g)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active|| +this.last()?":first":":last"))},previousPage:function(e){if(this.hasScroll())if(!this.active||this.first())this.activate(e,this.element.children(".ui-menu-item:last"));else{var a=this.active.offset().top,b=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var g=d(this).offset().top-a+b-d(this).height();return g<10&&g>-10});result.length||(result=this.element.children(".ui-menu-item:first"));this.activate(e,result)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active|| +this.first()?":last":":first"))},hasScroll:function(){return this.element.height()').attr($.extend(c(this),{type:'text'}))}j.removeAttr('name').data('placeholder-password',true).data('placeholder-id',h).bind('focus.placeholder',b);i.data('placeholder-textinput',j).data('placeholder-id',h).before(j)}i=i.removeAttr('id').hide().prev().attr('id',h).show()}i.addClass('placeholder').val(i.attr('placeholder'))}else{i.removeClass('placeholder')}}}(jQuery)); + diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 1c6065fe..abf1b935 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -549,16 +549,20 @@ div.jGrowl div.jGrowl-closer { } } -/* line 4, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 5, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #title { float: left; margin-bottom: 0.5em; } -/* line 8, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 9, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .flash { clear: both; } -/* line 11, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 12, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #import-link, body.closet_hangers-index #closet-hangers-items-search { + margin-top: 0.75em; +} +/* line 15, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #import-link { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -578,7 +582,6 @@ body.closet_hangers-index #import-link { line-height: 1; background: #ff5c00 url('/images/alert-overlay.png?1296599919') repeat-x; margin-left: 2em; - margin-top: 0.75em; } /* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ body.closet_hangers-index #import-link:hover { @@ -596,12 +599,23 @@ body.closet_hangers-index #import-link:active { body.closet_hangers-index #import-link:hover { background-color: #ee4b00; } -/* line 18, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 20, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-items-search { + float: right; +} +/* line 24, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-items-search input[type=search].loading { + background-image: url(/images/loading.gif); + background-position: 2px center; + background-repeat: no-repeat; + padding-left: 20px; +} +/* line 31, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers { clear: both; text-align: center; } -/* line 23, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 36, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -615,26 +629,26 @@ body.closet_hangers-index #closet-hangers .object .quantity { text-align: left; top: 60px; } -/* line 33, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 46, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { font-size: 16px; font-weight: bold; } -/* line 37, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 50, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object form { display: none; } -/* line 42, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 55, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover form { display: inline; } -/* line 45, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 58, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 50, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 63, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -675,7 +689,7 @@ body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-han body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 53, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 66, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -685,33 +699,33 @@ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity { top: 56px; padding: 0; } -/* line 59, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 72, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity span { display: none; } -/* line 62, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 75, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 66, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 79, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 71, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 84, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user.js .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 74, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 87, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user.js .object:hover .quantity input[type=submit] { display: none; } -/* line 77, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 90, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user.js .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 81, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 94, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user.js .object.loading .quantity span:after { content: "…"; } diff --git a/public/stylesheets/south-street/images/ui-bg_glass_55_fcf0ba_1x400.png b/public/stylesheets/south-street/images/ui-bg_glass_55_fcf0ba_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..a95fa334ed460cfae0f7be46c622558969a120a9 GIT binary patch literal 127 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq})7R978O6-<~(*I$*%#d{O`D zKlamwPS-`s3%9*%UG!A3*P=#+E1{@pF!m*t^JZyLz>j b4~LkYGkNYge|6CZn#kbk>gTe~DWM4fRyitb literal 0 HcmV?d00001 diff --git a/public/stylesheets/south-street/images/ui-bg_gloss-wave_100_ece8da_500x100.png b/public/stylesheets/south-street/images/ui-bg_gloss-wave_100_ece8da_500x100.png new file mode 100644 index 0000000000000000000000000000000000000000..709b5ab1dc97b439bad3ab7413187aa9378a938f GIT binary patch literal 2130 zcmb7`dr;Ep8pnU-?%Hm+(bH6-9|yhMqJWTt{hbvm^L|kRPi(hn_d|tv6P%Kw-<9A}5K&gKO|)NpqT9T%s^$QIr$)@O z0syURjaAPVdoBTYu3WbPwwC^}E@Aza03hP<5$h{oADaRGx$bL6z-9N}aVp)j?D1Zp z&*XudSlKUUrkQCwRj|BxLQs)wA+KTBy`?ON&g3VJ*$bJ&&C2Eo3?yWsU4Ne(yI+tt zSIcB~q$ZU+R?~Au?iM9NPh9?!6JOrzLY}Np6Maw08S#$>1C)9e!8p zKQ}JzN+$rQIJaPWycxtfm0wx{@ z9sPd_dDRn3GU|+;7fsPHj{7qsB3*r-?vCU*jcgaam_=jxaAMRr{3Sva?a%;oVj9u4 zg5_Om=D5@hM~<3DyKiuG=DjMKDk>dYWgP`(S3{>G8AC89d?K3dbo)Y;0~^osM{6k5 zt|!8S!_9dxsPr;}@7_-%qSeRM9r|5ABZRd^geJwyutF6*dsdAoW-rl4TG!$i!%6sI zRdWo%+$toQA|-df0;qS8+K(NY@dkfkBjC>#`&74zO%-xkb-WmZT*x_7uP7gJiVaVe zJF^2==9rPm-$bQkaTZc)f$`zvPx4cEh)TX!h@3D+?hke-SxXd=;`l`7_8Jl2TKj&N z=+2NqPDE$cb1821Od$iq_D#(^6d*(r$&&?hASsyAXi#Qye166!FXi^plB9)o3hXOW z*d##Y%(N0-=vX<% zGG#g+XzkMud55uABjTRz`qsE(!3b8#`v3!E-Kyrai*) zY&+?scA&FcSej7=So|x5X2Ucq34r8~;PZdBJom*L=-r3komz>B0Te+3f$fg-8+UMQ z4TVLn+otU27YY_RG2bs=^vu{dmH5C?SISkG&FP2VC-#~)UiazVol(;hzIUru-ap@x zwam=8b){rjsN81#Z7%XUC)E7AnR8*ESn`cE0F<_;6vlorM z!XJB&zWdY;pMZ6E>Nsu`FA_aI6%Wc07A zuu+=CX|~GRkXQelrV7MIP^kO4SqH@LVievaXfQXeo#s~0uSQ;e9$ir_&ss)t$B~dR zOOu|LWN4Q!ffD!w4{VRBz5AH{sY^cuL>efBw_{us7}TWM>@;w0RU;$iRt5sy9Yrq@ zR%`U}Sz~UGXzL{)he-Q`SK)^@Jpb)y$PIS4TC>&ruOa$#eJdW>Yc|yXAUz?I0txH? z8*8QRgZHPCdGDGE!#KAR!yqhz4Rb6b-Is|$qIegp5hlhC)*Zs^@T6qY(PO*jtQ^)~ z>ByyBj4FojVsP+Db33Oauy@B+_6o5&pL@>ENjF7N+O0!kcRga9u-qOccQxXXFKO%s zUsSCTiP1Gjjdouc@$0nFwOl1g`x*sf_A-Zuk8%-3bqYJt3nWJx`aXw4!e~(@9o53n z&*EC*EvsTM>JX5zKArb*7WJgSwFFyDlyr)U(`1E^&NI}7G#WfaE?)H~Xr{0b8zDPB!eUH(;ytU{PH z#FZPql+W&TeBx$Bin?QOTTA#^UL06Q=Hy-~rfV-)yc0d;(K2qUp&eP&HPYZlBMc;9 z9rSuNR&A8t@~XhD9#@?$~HOWGT{iAQbr48vuzcFs_@zm&cy zKaxntKnT~A&&;U4I1VnPk{y81kuC>8`xYOmmK%MYY?o#hz&D}I!O$5{HD1*@tyoEO zUMPOtzme|(tR9cl6s)Bpe|-e5Nn=X=Bl&mq_T3P9LTCqi0| HBwYIs4ueI^ literal 0 HcmV?d00001 diff --git a/public/stylesheets/south-street/images/ui-bg_highlight-hard_100_f5f3e5_1x100.png b/public/stylesheets/south-street/images/ui-bg_highlight-hard_100_f5f3e5_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..f0d2e151ead75b7e48419ccd102462f1af6f0649 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3Ja)XlH!`a)LZv9780g?wxRutHFTBS^n?; z^P;VJxqCwP*5?&t;ucLK6UJ Ck~V?> literal 0 HcmV?d00001 diff --git a/public/stylesheets/south-street/images/ui-bg_highlight-hard_95_cccccc_1x100.png b/public/stylesheets/south-street/images/ui-bg_highlight-hard_95_cccccc_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ca80bffc64e4aed87a021b53260373ae22f0f175 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0l!2#w literal 0 HcmV?d00001 diff --git a/public/stylesheets/south-street/images/ui-bg_highlight-soft_25_67b021_1x100.png b/public/stylesheets/south-street/images/ui-bg_highlight-soft_25_67b021_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..51773351978c84da7955422db14ae3c90b4f9b61 GIT binary patch literal 124 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0l(VOcV~E7mtNj~!8yo}<`?w_= zs3mWk!DRcQnrq+2NgBI?EzaF#&}oTk5^Buoob7yf!W2JA|JF%Xkp(ez^$+B~)%9>+ Xi!%M!VJE@@G>*a3)z4*}Q$iB}AxI}% literal 0 HcmV?d00001 diff --git a/public/stylesheets/south-street/images/ui-bg_highlight-soft_95_ffedad_1x100.png b/public/stylesheets/south-street/images/ui-bg_highlight-soft_95_ffedad_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..b4cb8241c998d7240a5ece7f5073515217bb38af GIT binary patch literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3Ja)XlH!`a&kOf9780gZtXMVJLDj6#OCvV z`DeV1S^|aD<|dxZj$BSA>&k4??ktmdAbP56rQ~wGh$nAZ8k8GF=Ilzk)id??&->>+ z4)>IPUaDW6a?A3d{^R=&C38g7T3vG|O7c!-593nj)s|J4^{&sbJRmIF>7uyalV1#I OFN3G6pUXO@geCyAgE#vC literal 0 HcmV?d00001 diff --git a/public/stylesheets/south-street/images/ui-bg_inset-soft_15_2b2922_1x100.png b/public/stylesheets/south-street/images/ui-bg_inset-soft_15_2b2922_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..8568394c6728273ad913200e4ba74c3ee8723794 GIT binary patch literal 119 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0l%1!GV~E7myZyU)4=9Knc_XbF zd*t6|$IlK;eOf_Muj|fUytkbFL3;qV!bM%}l$AHt6g4I$+o)?S)c^hSsx(jiapvNV T6s_YxlNdZ*{an^LB{Ts5?W`w^ literal 0 HcmV?d00001 diff --git a/public/stylesheets/south-street/images/ui-icons_808080_256x240.png b/public/stylesheets/south-street/images/ui-icons_808080_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..69ba6d81a0e807f9190e3e780ce3ce70d6c1e8a6 GIT binary patch literal 4369 zcmd^?`8O2)_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~GmT~uvF^hEEgT(ahrR?5hM!w z<@?HsG!Qg3zaV+-xQ3ldtad!U<6iGz_enGH*2akP_r)o1D&8p^5M)_c8IIj6Wy*7HJo&CBLuo~nj>(63pZzO(Vv^ZuB3 zMYigjkwA;FEy|G}1jpiMj6|NTm7Uyiw=@FDE*nX<>jR!W@9XIyf%$Fd*J5*D0Z0Lm z9}ZQxyT|x5ftNy?V>EbJz-K>bV9gs9RaXUP<^=;e?&Fqxj;6{ieR-a-@HycA1KMKhql8GOmcxwZ?_-(3hMK^^a*(gaFvBH ziIC!fgH4$W*NbKIaY&T?%&13``KbD@S-0`xQ%v3TV+B!;RC7O!+1a9QCA$H@3tR;k z)SSoR7(s4)f{zM}eWgFN{(ZH5d1O}l)f$ruT!)Q&NImXyZsTzOf9TwctcSfr+M)aJ z5otO+$jvm-P4)ykH)x|cO5xeb>?!`qGw$(>&axqLL6yoB${vsMXgL_-bz@2J_tS92 zdvZG-+vKl@K4Vr(EL{WQt@Z+Ea-hxX0}nTSZxnpi^#Kn8Ox8FgIS|hc}KJQ4tm*HO16ui{(O9} z1YN)GjiQt6fGq`Cj+^`zUf?8hk^(T{{cOQGWFP98am}is28A!5%{R#ENv8fCN!j69 zlMEK(2z?|BY=Je$XD9mB-Kkem*(d-j^9j$2#6r$Dz?s)-TCDCGCs z8>6Pvj{Y+YIeFA@qY22V$)awy@q!9A4rgk5b9TcC;s9Ig^G|6nDP+5=Fzg&?(L=vc zCbGd>fSu~@6!94td+o#d@sid!EIX$rx7*cawe6 z`dScJ+$HssdOjE)O#Ybs56vm-FQ$7yuJJD^Zqk%hMaIgAJ<2yb_MFQte_i;62ScT$ zpjifYyR_E=rQ+>H)pmlr-Udzg*-!|ssw(D7wJvC+Sf8bb9;;q8#z?0p!!bsd{wy|5 zpBaMHE-Ve>i#LLjHRaMLtp%9&(HCng7Sw96jVv!#0k%?F^K7&=T)mnYn)D9(i;4x5 z^NJTJwq~pv;kH@#ejTd*48~(J(r6j34|m`h9fEDj0im)~+%I5XphWymhT;_Zty|Q& zzjPg#-ufAHZ1M*Gccw?Kf|8Pnhtb0`!{N`Bqsa37J+>wC$!e z00k+2Egzz;rbcWoUB%Jvp8W1}$XD%e3>4y;;OZ1ccT-O#uW6Ys@C}Pa`nZrNKzR(2 z4e%3)@QI4SE&E!lW`5y14QhbepBG%_XBV-O(%5tj)@9#|;sC-MNev!zGDHk}JdpGC`iJF#8=8-P$Xoku_=Dw%Cv3{U7L>gf zRQ?<$t`cZ*MP5GQmbmx#!+*!zu>0MewRO9GFGS{b^m_fJ-N0?j@EqoFf>$khj+E|@ z7r3We&^tR^YZrxKe*d22agXqCO0l44&kqCv{u)T|(lv`~PK@DvE z{QI_TlCH5z*gR!>LO)k67{^R+vWx24U2^2ODXpwT;6y+6+$5m)_*w4WY&#do9dCeE z)>p+Ykdhq($DhmMiaYXey!@N%L26uz($aJ!QT{B^Wu}U$^9e#5)=c+XF9@Ill?ZmM zlNgHiz*9!vDc&uxOo;ZVxb`Q!Sk0*gnfxWzmbZh4(=%CD%qP?0=);n$&zaW_$UKV9 z8axdcN#AyZ{P)wj?V{P}vM)YY!>6@}^>U+iv$`9>nMTCPjN>z%yF&3yf%>+T@0vh4 zlC8Xa6zeo?%=o3}M8{aebLHcO{^1Ar8qiM=Gquf?Jo)q5`-+?sUpg?QXyEUpWSm+n z$K-UyqkIwHLquru~o(OF)hhz$Y*|X>ZIbswnxRvr~ z2=rdOGVuD|xRlpAZE<0!X1F(%Anpl^@V^D3vbM}qxe|NI;TTiZy7(IM;R69RkA>a& z6gwYE2sREzQ_LHmWqB+ogMk(fMaSFeoDq-!HkFB_nXt5+2ncFuk9BQL1I&oB1zZi) zYW{6_&-Ip1l*OVRA##1ILQS;5R{-K^0wGTiJbVSi@LA^$D$;@J>^G{6@&+%4{b3(s zC~LEHiTv(0b#zxt?YJ0r_~pUZM~mQ(??(n#>&tD%+@nq=Abj5*8R!~Ul1`G~=qFJ4 zfl|m8ZDCYgtr`4LcOpgiJYX9qRY5;DcWti~PmS$VB$E-Zt^f4)vLDOe_3XTq5^ylW zJ9PKm!V-8sAOJXnUfuFNIf0R9tK-pNs2hO04zr620}5B(Ok>yB)Of-3sP59qfQNbm zA4{w!2@cB;GbR(~szVrbO%(w=5S!X`o@o@x++wbN_tMPT0Vc)*I;Fgsbf^*g0 z2Di?HTApwKq3+YwfNsqd3iP%{hyK1iyuVZc@*0tO_3+N0#GFsz>8MjeJ2UJ%L!%hi zGYYAthH`E+ywA*u{(eJ=ia3h*%k?779rk-K<0VZAPkl;TFUbmei|$fqWO8!_zIvqt z$ly$VrlH46nnpX~X5Yk0iBJl;=WuA4>~X4-f&K0yWf42h&0b30t@NYX$7egQ1Fp!a zbui-D6cWCWV&|R1CY@G8(qOmWjWeX3eX7UggZPGimA}soOuQdXe4uZ#2>5zN>qlI0 z9xk}lE=tNpX1m6*nFr2EQ3xs79!^sCldDJYE$m(qYv3q7>}1R7?iZW7>$~*%zKaC| z=$N?ME$>#+%T&MZC`dW1wUl6Z)JgyCn~V%K&i0H|iwE%$>xsZW3tTfZxIUePci@p;cRu|d=ItIwF z1clVHy{hH?@SD|(Zfqi^0DQ1hczHN7xq85h)rzQqLHMX2^IkuK7FB!kI40s$|CY7~ zNX^{_UjN8}L%Med;|+=4RNTMozn8KT;2tb77bUPCmioh+rZBfIiM6f_P34cQ__o1G zWqQp3VL~~pE5?qODf%iiQQ3f42YF@09tQ*$4v_EKUx;t1KCPCBtgqg z@+Tn;O)a0uky_%jm+WjNB?=~VyH>V#L!*=l*@OS6SVyt_UEH&NA=?V2stHPyKkVNy z&jg<#cjros){#ji)dK z%)We0L_478=HZ8-@xnwsKrWs8)x`MB;(Y`Cmu2c-&SH(vN-F(*e`l?c%+l$|y_AJJ zhcDGnwLvN+bu;_sX|1AiePhx@u&%P$hf*xE+O=~D?_(_KGWQ!158YL-y9$*6mmPo;Rp*Dl5lm-mVM2i`h- zM@nxv590_tvMwPD_{l=b$iOm|+|S{D9&P%zeT$GgX6Akl-tfUF>tL@Ld!B&{pN39t zH>3Vhqkr}2Yul+jb7UiouWVGPNsxX7Ueba+9|~dz?d*QM$ng0DZfO0`7fAy?2yMm| zcnRzUhZ&IcwgjH9cuU!w+VStYa{p*)4IgBf|E8)sqMYtB2KH_}SfsFq(c9i(Q6S3U oBo%DI*Kv;w;*%(i9W@e?xU!ZvX%Q literal 0 HcmV?d00001 diff --git a/public/stylesheets/south-street/images/ui-icons_847e71_256x240.png b/public/stylesheets/south-street/images/ui-icons_847e71_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..71838ca82dad7628918d5a67ffc6270f09280dce GIT binary patch literal 5355 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 literal 0 HcmV?d00001 diff --git a/public/stylesheets/south-street/images/ui-icons_8dc262_256x240.png b/public/stylesheets/south-street/images/ui-icons_8dc262_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..0f580253b66af1463c33cb9a1c1448751368385b GIT binary patch literal 5355 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 ZzDNn=DA|H+{NFG0k*1+Wt(sHZ{{RH~MV|lw literal 0 HcmV?d00001 diff --git a/public/stylesheets/south-street/images/ui-icons_cd0a0a_256x240.png b/public/stylesheets/south-street/images/ui-icons_cd0a0a_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..2ab019b73ec11a485fa09378f3a0e155194f6a5d GIT binary patch literal 4369 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 oBo%DI*Kv;w;*%(i9W@e@>#j(*OVf literal 0 HcmV?d00001 diff --git a/public/stylesheets/south-street/images/ui-icons_ffffff_256x240.png b/public/stylesheets/south-street/images/ui-icons_ffffff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..42f8f992c727ddaa617da224a522e463df690387 GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/public/stylesheets/south-street/jquery-ui.css b/public/stylesheets/south-street/jquery-ui.css new file mode 100644 index 00000000..9924eec1 --- /dev/null +++ b/public/stylesheets/south-street/jquery-ui.css @@ -0,0 +1,342 @@ +/* + * jQuery UI CSS Framework 1.8.14 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + +/* + * jQuery UI CSS Framework 1.8.14 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=segoe%20ui,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=ece8da&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=100&borderColorHeader=d4ccb0&fcHeader=433f38&iconColorHeader=847e71&bgColorContent=f5f3e5&bgTextureContent=04_highlight_hard.png&bgImgOpacityContent=100&borderColorContent=dfd9c3&fcContent=312e25&iconColorContent=808080&bgColorDefault=459e00&bgTextureDefault=04_highlight_hard.png&bgImgOpacityDefault=15&borderColorDefault=327E04&fcDefault=ffffff&iconColorDefault=eeeeee&bgColorHover=67b021&bgTextureHover=03_highlight_soft.png&bgImgOpacityHover=25&borderColorHover=327E04&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=fafaf4&bgTextureActive=04_highlight_hard.png&bgImgOpacityActive=100&borderColorActive=d4ccb0&fcActive=459e00&iconColorActive=8DC262&bgColorHighlight=fcf0ba&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=e8e1b5&fcHighlight=363636&iconColorHighlight=8DC262&bgColorError=ffedad&bgTextureError=03_highlight_soft.png&bgImgOpacityError=95&borderColorError=e3a345&fcError=cd5c0a&iconColorError=cd0a0a&bgColorOverlay=2b2922&bgTextureOverlay=05_inset_soft.png&bgImgOpacityOverlay=15&opacityOverlay=90&bgColorShadow=cccccc&bgTextureShadow=04_highlight_hard.png&bgImgOpacityShadow=95&opacityShadow=20&thicknessShadow=12px&offsetTopShadow=-12px&offsetLeftShadow=-12px&cornerRadiusShadow=10px + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: segoe ui, Arial, sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: segoe ui, Arial, sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #dfd9c3; background: #f5f3e5 url(images/ui-bg_highlight-hard_100_f5f3e5_1x100.png) 50% top repeat-x; color: #312e25; } +.ui-widget-content a { color: #312e25; } +.ui-widget-header { border: 1px solid #d4ccb0; background: #ece8da url(images/ui-bg_gloss-wave_100_ece8da_500x100.png) 50% 50% repeat-x; color: #433f38; font-weight: bold; } +.ui-widget-header a { color: #433f38; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #327e04; background: #459e00 url(images/ui-bg_highlight-hard_15_459e00_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #ffffff; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #ffffff; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #327e04; background: #67b021 url(images/ui-bg_highlight-soft_25_67b021_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #ffffff; } +.ui-state-hover a, .ui-state-hover a:hover { color: #ffffff; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #d4ccb0; background: #fafaf4 url(images/ui-bg_highlight-hard_100_fafaf4_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #459e00; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #459e00; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #e8e1b5; background: #fcf0ba url(images/ui-bg_glass_55_fcf0ba_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #e3a345; background: #ffedad url(images/ui-bg_highlight-soft_95_ffedad_1x100.png) 50% top repeat-x; color: #cd5c0a; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd5c0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd5c0a; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_808080_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_808080_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_847e71_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_eeeeee_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_8dc262_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_8dc262_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; -khtml-border-top-left-radius: 6px; border-top-left-radius: 6px; } +.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; -khtml-border-top-right-radius: 6px; border-top-right-radius: 6px; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; -khtml-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; } +.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; -khtml-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; } + +/* Overlays */ +.ui-widget-overlay { background: #2b2922 url(images/ui-bg_inset-soft_15_2b2922_1x100.png) 50% bottom repeat-x; opacity: .90;filter:Alpha(Opacity=90); } +.ui-widget-shadow { margin: -12px 0 0 -12px; padding: 12px; background: #cccccc url(images/ui-bg_highlight-hard_95_cccccc_1x100.png) 50% top repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 10px; -khtml-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; }/* + * jQuery UI Autocomplete 1.8.14 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete#theming + */ +.ui-autocomplete { position: absolute; cursor: default; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* + * jQuery UI Menu 1.8.14 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu#theming + */ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; + float: left; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} From 884ad2d5b8a18486868a40fcbedeb6267e630a73 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 17 Jul 2011 17:24:29 -0400 Subject: [PATCH 19/69] user:owns in item search --- app/controllers/items_controller.rb | 2 +- app/models/item.rb | 40 +++++++++++++++++++----- app/views/closet_hangers/index.html.haml | 2 +- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index b5e12c80..37006fd2 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -10,7 +10,7 @@ class ItemsController < ApplicationController else per_page = nil end - @items = Item.search(@query).alphabetize.paginate :page => params[:page], :per_page => per_page + @items = Item.search(@query, current_user).alphabetize.paginate :page => params[:page], :per_page => per_page assign_closeted! respond_to do |format| format.html { render } diff --git a/app/models/item.rb b/app/models/item.rb index 7c426deb..608f8109 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -43,6 +43,8 @@ class Item < ActiveRecord::Base scope :sitemap, select([:id, :name]).order(:id).limit(49999) + scope :with_closet_hangers, joins(:closet_hangers) + def closeted? !!@closeted end @@ -118,7 +120,7 @@ class Item < ActiveRecord::Base @supported_species ||= species_support_ids.blank? ? Species.all : species_support_ids.sort.map { |id| Species.find(id) } end - def self.search(query) + def self.search(query, user=nil) raise SearchError, "Please provide a search query" unless query query = query.strip raise SearchError, "Search queries should be at least 3 characters" if query.length < 3 @@ -146,7 +148,7 @@ class Item < ActiveRecord::Base limited_filters_used << condition.filter end end - condition.narrow(scope) + condition.narrow(scope, user) end end @@ -616,6 +618,7 @@ class Item < ActiveRecord::Base name = name.to_s SearchFilterScopes << name LimitedSearchFilters << name if options[:limit] + (class << self; self; end).instance_eval do if options[:full] define_method "search_filter_#{name}", &options[:full] @@ -633,9 +636,9 @@ class Item < ActiveRecord::Base search_filter name, options, &block end - def self.search_filter_block(options, positive) - Proc.new { |str, scope| - condition = yield(str) + def self.search_filter_block(options, positive, &block) + Proc.new { |str, user, scope| + condition = block.arity == 1 ? block.call(str) : block.call(str, user) condition = "!(#{condition.to_sql})" unless positive scope = scope.send(options[:scope]) if options[:scope] scope.where(condition) @@ -664,6 +667,27 @@ class Item < ActiveRecord::Base filter end + def self.validate_user_condition(adjective, user) + unless adjective == "owns" + raise SearchError, "We don't understand user:#{adjective}. " + + "Did you mean user:owns?" + end + + unless user + raise SearchError, "It looks like you're not logged in, so you don't own any items." + end + end + + single_search_filter :user, :full => lambda { |adjective, user, scope| + validate_user_condition(adjective, user) + scope.joins(:closet_hangers).where(ClosetHanger.arel_table[:user_id].eq(user.id)) + } + + single_search_filter :not_user do |adjective, user| + validate_user_condition(adjective, user) + arel_table[:id].not_in(user.closeted_items.map(&:id)) + end + search_filter :only do |species_name| begin id = Species.require_by_name(species_name).id @@ -694,7 +718,7 @@ class Item < ActiveRecord::Base SwfAsset.arel_table[:zone_id].in(zone_set.map(&:id)) end - single_search_filter :not_type, :full => lambda { |zone_set_name, scope| + single_search_filter :not_type, :full => lambda { |zone_set_name, user, scope| zone_set = Zone::ItemZoneSets[zone_set_name] raise SearchError, "Type \"#{zone_set_name}\" does not exist" unless zone_set psa = ParentSwfAssetRelationship.arel_table.alias @@ -742,10 +766,10 @@ class Item < ActiveRecord::Base @positive = !@positive end - def narrow(scope) + def narrow(scope, user) if SearchFilterScopes.include?(filter) polarized_filter = @positive ? filter : "not_#{filter}" - Item.send("search_filter_#{polarized_filter}", self, scope) + Item.send("search_filter_#{polarized_filter}", self, user, scope) else raise SearchError, "Filter #{filter} does not exist" end diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index c8d4beab..fc3af06d 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -3,7 +3,7 @@ - content_for :before_flashes do = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' = form_tag items_path, :method => :get, :id => 'closet-hangers-items-search', 'data-current-user-id' => current_user.id do - = search_field_tag :q, nil, :placeholder => "Search items" + = search_field_tag :q, nil, :placeholder => "Find items to add" = submit_tag 'Search', :name => nil - else - title "#{@user.name}'s Items" From f2d6a454c5497ea633aaa80e3414dc14c35a7d84 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 17 Jul 2011 17:28:45 -0400 Subject: [PATCH 20/69] explain user:owns on item search --- app/helpers/items_helper.rb | 4 ++++ app/views/items/index.html.haml | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb index b2868693..5bc3a23c 100644 --- a/app/helpers/items_helper.rb +++ b/app/helpers/items_helper.rb @@ -71,6 +71,10 @@ module ItemsHelper sprintf(NeoitemsURLFormat, CGI::escape(item.name)) end + def your_items_path + user_signed_in? ? user_closet_hangers_path(current_user) : login_path + end + private def build_on_pet_types(species, special_color=nil, &block) diff --git a/app/views/items/index.html.haml b/app/views/items/index.html.haml index 999a3096..f02d4fa3 100644 --- a/app/views/items/index.html.haml +++ b/app/views/items/index.html.haml @@ -20,6 +20,11 @@ %dd returns any item with the word "kreludor" and the phrase "altador cup" in it, but not the word "background" + %dt hat user:owns + %dd + returns + = link_to 'items that you own', your_items_path + with the word "hat" %dt blue is:nc %dd returns any NC Mall item with the word "blue" in it %dt collar -is:pb From e0c00cc8eda045e5a93cc0a1ab7a7133f31d2b44 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 17 Jul 2011 17:52:40 -0400 Subject: [PATCH 21/69] Your Items link on wardrobe --- app/stylesheets/outfits/_edit.sass | 9 +- app/views/outfits/edit.html.haml | 1 + public/javascripts/outfits/edit.js | 7 ++ public/stylesheets/compiled/screen.css | 150 ++++++++++++++----------- 4 files changed, 100 insertions(+), 67 deletions(-) diff --git a/app/stylesheets/outfits/_edit.sass b/app/stylesheets/outfits/_edit.sass index bcefb3a6..167a2064 100644 --- a/app/stylesheets/outfits/_edit.sass +++ b/app/stylesheets/outfits/_edit.sass @@ -313,9 +313,14 @@ body.outfits-edit margin: 0 1em 0 0 input +inline-block + &[type=submit] + margin-right: 2em + #preview-search-form-your-items + display: none + font-size: 85% + margin-right: 1em #preview-search-form-pagination +inline-block - margin-left: 2em a, span margin: 0 .25em .current @@ -558,6 +563,8 @@ body.outfits-edit display: block #save-outfit, #save-current-outfit, #save-outfit-copy, #current-outfit-permalink, #shared-outfit-permalink, #share-outfit, #shared-outfit-url display: none + #preview-search-form-your-items + +inline-block &.user-not-signed-in #save-outfit-not-signed-in diff --git a/app/views/outfits/edit.html.haml b/app/views/outfits/edit.html.haml index ba42560b..09e8f65d 100644 --- a/app/views/outfits/edit.html.haml +++ b/app/views/outfits/edit.html.haml @@ -91,6 +91,7 @@ %h2 Add an item %input{:name => "query", :placeholder => "Search items...", :type => "search"}/ %input{:type => "submit", :value => "Go"}/ + %a#preview-search-form-your-items{:href => '#'} Your Items #preview-search-form-pagination %a#preview-search-form-clear{:href => "#"} clear %dl#preview-search-form-help diff --git a/public/javascripts/outfits/edit.js b/public/javascripts/outfits/edit.js index 239bfbe5..f1008704 100644 --- a/public/javascripts/outfits/edit.js +++ b/public/javascripts/outfits/edit.js @@ -863,6 +863,7 @@ View.Search = function (wardrobe) { loading_el = $('#preview-search-form-loading'), no_results_el = $('#preview-search-form-no-results'), no_results_span = no_results_el.children('span'), + your_items_el = $('#preview-search-form-your-items'), PAGINATION = { INNER_WINDOW: 4, OUTER_WINDOW: 1, @@ -927,6 +928,12 @@ View.Search = function (wardrobe) { form.submit(); }); + your_items_el.click(function (e) { + e.preventDefault(); + input_el.val('user:owns'); + form.submit(); + }); + wardrobe.search.bind('startRequest', function () { loading_el.delay(1000).show('slow'); }); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index abf1b935..4037da2a 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -1491,6 +1491,16 @@ body.outfits-edit #preview-search-form input { *vertical-align: auto; } /* line 316, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-search-form input[type=submit] { + margin-right: 2em; +} +/* line 318, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-search-form-your-items { + display: none; + font-size: 85%; + margin-right: 1em; +} +/* line 322, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-pagination { display: -moz-inline-box; -moz-box-orient: vertical; @@ -1498,55 +1508,54 @@ body.outfits-edit #preview-search-form-pagination { vertical-align: middle; *display: inline; *vertical-align: auto; - margin-left: 2em; } -/* line 319, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 324, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-pagination a, body.outfits-edit #preview-search-form-pagination span { margin: 0 0.25em; } -/* line 321, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 326, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-pagination .current { font-weight: bold; } -/* line 323, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 328, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-clear { display: none; font-size: 87.5%; margin-left: 2em; } -/* line 327, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 332, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-loading { display: none; font-size: 75%; font-style: italic; margin-left: 2em; } -/* line 333, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 338, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-no-results { display: none; } -/* line 335, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 340, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-help { font-size: 87.5%; margin-left: 2em; } -/* line 338, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 343, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .search-helper { font-family: inherit; } -/* line 340, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 345, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .possible-error { display: none; } -/* line 343, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 348, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #fullscreen-copyright { display: none; } -/* line 345, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 350, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen { height: 100%; } -/* line 348, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 353, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #container { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; @@ -1559,19 +1568,19 @@ body.outfits-edit.fullscreen #container { position: relative; width: 80%; } -/* line 356, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 361, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen h1 { display: none; } -/* line 358, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 363, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #short-url-response { position: static; } -/* line 360, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 365, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview { width: 100%; } -/* line 362, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 367, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-sidebar { float: right; height: 100%; @@ -1579,12 +1588,12 @@ body.outfits-edit.fullscreen #preview-sidebar { position: relative; width: 400px; } -/* line 368, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 373, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-sidebar.viewing-saving-outfit { height: auto; max-height: 100%; } -/* line 371, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 376, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-search-form { bottom: 1.5em; left: 0; @@ -1593,7 +1602,7 @@ body.outfits-edit.fullscreen #preview-search-form { position: absolute; width: 100%; } -/* line 379, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 384, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-search-form-help div { display: -moz-inline-box; -moz-box-orient: vertical; @@ -1603,27 +1612,27 @@ body.outfits-edit.fullscreen #preview-search-form-help div { *vertical-align: auto; width: 48%; } -/* line 382, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 387, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #footer { bottom: 0; left: 0; position: absolute; width: 100%; } -/* line 387, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 392, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #footer ul, body.outfits-edit.fullscreen #footer p, body.outfits-edit.fullscreen #footer li { display: inline; } -/* line 389, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 394, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #footer ul { margin-right: 2em; } -/* line 392, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 397, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object { padding: 6px; position: relative; } -/* line 395, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 400, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object ul { display: none; left: 0; @@ -1631,11 +1640,11 @@ body.outfits-edit .object ul { position: absolute; top: 0; } -/* line 401, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 406, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object ul li { margin-bottom: 0.25em; } -/* line 403, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 408, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object ul li a { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1676,11 +1685,11 @@ body.outfits-edit .object ul li a:active { body.outfits-edit .object ul li a:hover { background-color: #999999; } -/* line 406, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 411, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object:hover ul, body.outfits-edit .object:hover .object-info { display: block; } -/* line 413, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 418, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .nc-icon { background: url('/images/nc.png?1310666180') no-repeat; height: 16px; @@ -1690,14 +1699,14 @@ body.outfits-edit .nc-icon { top: 64px; width: 16px; } -/* line 421, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 426, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .nc-icon:hover { -moz-opacity: 0.5; -webkit-opacity: 0.5; -o-opacity: 0.5; -khtml-opacity: 0.5; } -/* line 424, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 429, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object-info { -moz-border-radius: 12px; -webkit-border-radius: 12px; @@ -1714,26 +1723,26 @@ body.outfits-edit .object-info { top: 0; width: 16px; } -/* line 435, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 440, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object-info span { font-family: "Droid Serif", Georgia, "Times New Roman", Times, serif; font-weight: bold; position: relative; top: -2px; } -/* line 441, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 446, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object-info:hover { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 444, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 449, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits { display: none; text-align: left; } -/* line 447, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 452, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul { margin-left: 24px; margin-right: 24px; @@ -1744,7 +1753,7 @@ body.outfits-edit #preview-outfits > ul { margin-bottom: 1em; min-height: 16px; } -/* line 456, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 461, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li { padding: 0.25em 0; } @@ -1923,18 +1932,18 @@ body.outfits-edit #preview-outfits > ul > li.renaming:hover .outfit-rename-butto body.outfits-edit #preview-outfits > ul > li:hover .outfit-rename-button { display: inline; } -/* line 458, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 463, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul.loaded { background: transparent; } -/* line 461, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 466, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .preview-sidebar-nav { float: right; font-size: 85%; margin-right: 24px; margin-top: 1em; } -/* line 468, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 473, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-success, body.outfits-edit #save-error, body.outfits-edit #outfit-not-found, body.outfits-edit #preview-sidebar-donation-request { margin-left: 24px; margin-right: 24px; @@ -1942,7 +1951,7 @@ body.outfits-edit #save-success, body.outfits-edit #save-error, body.outfits-edi margin-top: 1em; text-align: center; } -/* line 475, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 480, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar-donation-request { background: #e6efc2; border: 1px solid #c6d880; @@ -1950,23 +1959,23 @@ body.outfits-edit #preview-sidebar-donation-request { font-size: 85%; padding: 1em; } -/* line 480, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 485, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar-donation-request-no-thanks { margin-left: 1em; } -/* line 483, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 488, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-success { background: #e6efc2; border: 1px solid #c6d880; color: #264409; } -/* line 486, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 491, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-error, body.outfits-edit #outfit-not-found { background: #fbe3e4; border: 1px solid #fbc2c4; color: #8a1f11; } -/* line 489, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 494, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #userbar-message { -moz-opacity: 0.5; -webkit-opacity: 0.5; @@ -1974,7 +1983,7 @@ body.outfits-edit #userbar-message { -khtml-opacity: 0.5; display: none; } -/* line 493, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 498, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit { padding: 0.25em 0; margin-left: 24px; @@ -2156,33 +2165,33 @@ body.outfits-edit #new-outfit.renaming:hover .outfit-rename-button { body.outfits-edit #new-outfit:hover .outfit-rename-button { display: inline; } -/* line 497, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 502, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit h4 { display: inline; } -/* line 499, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 504, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit h4:hover { text-decoration: none; } -/* line 501, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 506, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit .outfit-star { margin-top: 0.5em; } -/* line 504, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 509, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit-name { font: inherit; line-height: 1; } -/* line 508, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 513, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-saving-outfit { display: none; padding-bottom: 1em; } -/* line 512, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 517, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-type-form, body.outfits-edit #pet-state-form, body.outfits-edit #preview-swf, body.outfits-edit #preview-search-form { position: relative; } -/* line 515, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 520, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .control-overlay { height: 100%; left: 0; @@ -2191,11 +2200,11 @@ body.outfits-edit .control-overlay { width: 100%; z-index: 5; } -/* line 523, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 528, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar-nav-outfits, body.outfits-edit #save-outfit-signed-in { display: none; } -/* line 526, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 531, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form { padding: 0.25em 0; display: none; @@ -2377,7 +2386,7 @@ body.outfits-edit form#save-outfit-form.renaming:hover .outfit-rename-button { body.outfits-edit form#save-outfit-form:hover .outfit-rename-button { display: inline; } -/* line 532, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 537, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-star, body.outfits-edit form#save-outfit-form input, body.outfits-edit form#save-outfit-form button { display: -moz-inline-box; -moz-box-orient: vertical; @@ -2388,51 +2397,60 @@ body.outfits-edit form#save-outfit-form .outfit-star, body.outfits-edit form#sav float: none; vertical-align: top; } -/* line 537, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 542, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-star { margin-top: 0.25em; } -/* line 540, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 545, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .outfit-url { font-size: 75%; } -/* line 544, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 549, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #preview-sidebar-nav-outfits { display: block; } -/* line 546, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 551, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit { display: inline-block; } -/* line 550, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 555, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-outfit { display: none; } -/* line 552, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 557, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-current-outfit, body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-outfit-copy { display: inline-block; } -/* line 554, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 559, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #current-outfit-permalink { display: inline-block; } -/* line 557, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 562, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit-form { display: block; } -/* line 559, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 564, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-current-outfit, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit-copy, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #current-outfit-permalink, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #shared-outfit-permalink, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #share-outfit, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #shared-outfit-url { display: none; } -/* line 563, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 566, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit.user-signed-in #preview-search-form-your-items { + display: -moz-inline-box; + -moz-box-orient: vertical; + display: inline-block; + vertical-align: middle; + *display: inline; + *vertical-align: auto; +} +/* line 570, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-not-signed-in #save-outfit-not-signed-in { display: inline-block; } -/* line 567, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 574, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper.shared-outfit #shared-outfit-permalink, body.outfits-edit #save-outfit-wrapper.shared-outfit #shared-outfit-url { display: inline-block; } -/* line 569, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 576, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper.shared-outfit #current-outfit-permalink { display: none !important; } From 02ef70f749a86fbae46c3223cb2c4f7530e128f1 Mon Sep 17 00:00:00 2001 From: Matchu Date: Wed, 20 Jul 2011 12:39:18 -0400 Subject: [PATCH 22/69] simplify closet hangers view, replace user_is?(@user) with !public_perspective? --- app/controllers/application_controller.rb | 6 +++++- app/controllers/closet_hangers_controller.rb | 1 + app/helpers/application_helper.rb | 4 ---- app/helpers/closet_hangers_helper.rb | 4 ++++ app/views/closet_hangers/index.html.haml | 8 ++++---- 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 6c9a3e5e..d7e2fc80 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,7 +1,7 @@ class ApplicationController < ActionController::Base protect_from_forgery - helper_method :can_use_image_mode? + helper_method :can_use_image_mode?, :user_is? def authenticate_user! # too lazy to change references to login_path redirect_to(login_path) unless user_signed_in? @@ -18,5 +18,9 @@ class ApplicationController < ActionController::Base def on_access_denied render :file => 'public/403.html', :layout => false, :status => :forbidden end + + def user_is?(user) + user_signed_in? && user == current_user + end end diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index e57c75db..87435307 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -14,6 +14,7 @@ class ClosetHangersController < ApplicationController def index @user = User.find params[:user_id] @closet_hangers = @user.closet_hangers.alphabetical_by_item_name.includes(:item) + @public_perspective = params.has_key?(:public) || !user_is?(@user) end # Since the user does not care about the idea of a hanger, but rather the diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 1bc47e4a..dd5a1f82 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -101,9 +101,5 @@ module ApplicationHelper def title(value) content_for :title, value end - - def user_is?(user) - user_signed_in? && user == current_user - end end diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index a6c002f7..d5f173ae 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -1,2 +1,6 @@ module ClosetHangersHelper + def public_perspective? + @public_perspective + end end + diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index fc3af06d..0bf4cd89 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -1,4 +1,4 @@ -- if user_is?(@user) +- unless public_perspective? - title 'Your Items' - content_for :before_flashes do = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' @@ -8,15 +8,15 @@ - else - title "#{@user.name}'s Items" -#closet-hangers{:class => user_is?(@user) ? 'current-user' : nil} +#closet-hangers{:class => public_perspective? ? nil : 'current-user'} - if !@closet_hangers.empty? - - if user_is?(@user) + - unless public_perspective? %p These are the items you own. Hover over an item to remove it from the list or to change the quantity. = render :partial => 'closet_hanger', :collection => @closet_hangers, :locals => {:show_controls => user_is?(@user)} - else - - if user_is?(@user) + - unless public_perspective? %p You haven't tracked any items on Dress to Impress. %p Here you can keep track of what items you already own, so that as you From c5103b6557087b66082660de7ccda43bb6ae8cfa Mon Sep 17 00:00:00 2001 From: Matchu Date: Wed, 20 Jul 2011 15:16:22 -0400 Subject: [PATCH 23/69] neomail link on closets --- app/controllers/application_controller.rb | 4 ++ app/controllers/closet_hangers_controller.rb | 10 +-- app/controllers/users_controller.rb | 19 ++++++ app/helpers/closet_hangers_helper.rb | 6 ++ app/models/user.rb | 2 + app/stylesheets/closet_hangers/_index.sass | 26 +++++++- app/views/closet_hangers/index.html.haml | 29 ++++++--- config/routes.rb | 2 +- ...720183722_add_neopets_username_to_users.rb | 9 +++ db/schema.rb | 4 +- public/images/neomail.png | Bin 0 -> 754 bytes public/stylesheets/compiled/screen.css | 58 +++++++++++++----- 12 files changed, 137 insertions(+), 32 deletions(-) create mode 100644 db/migrate/20110720183722_add_neopets_username_to_users.rb create mode 100644 public/images/neomail.png diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d7e2fc80..5f2d3a89 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -19,6 +19,10 @@ class ApplicationController < ActionController::Base render :file => 'public/403.html', :layout => false, :status => :forbidden end + def redirect_back!(default=:back) + redirect_to(params[:return_to] || default) + end + def user_is?(user) user_signed_in? && user == current_user end diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 87435307..fdc53c07 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -36,7 +36,7 @@ class ClosetHangersController < ApplicationController respond_to do |format| format.html { flash[:success] = "Success! You own #{@closet_hanger.quantity} #{@item.name.pluralize}." - redirect_back! + redirect_back!(@item) } format.json { render :json => true } @@ -45,7 +45,7 @@ class ClosetHangersController < ApplicationController respond_to do |format| format.html { flash[:alert] = "We couldn't save how many of this item you own: #{@closet_hanger.errors.full_messages.to_sentence}" - redirect_back! + redirect_back!(@item) } format.json { render :json => {:errors => @closet_hanger.errors.full_messages}, :status => :unprocessable_entity } @@ -75,11 +75,7 @@ class ClosetHangersController < ApplicationController def redirect_after_destroy! flash[:success] = "Success! You do not own #{@item.name}." - redirect_back! - end - - def redirect_back! - redirect_to params[:return_to] || @item + redirect_back!(@item) end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 70ed203d..e76b953c 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,24 @@ class UsersController < ApplicationController + before_filter :find_and_authorize_user!, :only => [:update] + def top_contributors @users = User.top_contributors.paginate :page => params[:page], :per_page => 20 end + + def update + @user.update_attributes params[:user] + flash[:success] = "Settings successfully saved" + redirect_back! user_closet_hangers_path(@user) + end + + protected + + def find_and_authorize_user! + if current_user.id == params[:id].to_i + @user = current_user + else + raise AccessDenied + end + end end + diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index d5f173ae..a7d77982 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -1,4 +1,10 @@ +require 'cgi' + module ClosetHangersHelper + def send_neomail_url(user) + "http://www.neopets.com/neomessages.phtml?type=send&recipient=#{CGI.escape @user.neopets_username}" + end + def public_perspective? @public_perspective end diff --git a/app/models/user.rb b/app/models/user.rb index 1bdad3ab..a2ab633f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -11,6 +11,8 @@ class User < ActiveRecord::Base devise :rememberable + attr_accessible :neopets_username + def contribute!(pet) new_contributions = [] new_points = 0 diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 2b61baf3..7fd8aa3d 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -4,7 +4,7 @@ body.closet_hangers-index #title float: left - margin-bottom: .5em + margin-bottom: 0 .flash clear: both @@ -28,6 +28,30 @@ body.closet_hangers-index repeat: no-repeat padding-left: $icon-width + 4px + #closet-hangers-contact + clear: both + font-size: 85% + margin-bottom: 1em + margin-left: 2em + min-height: image-height("neomail.png") + + a + background: + image: image-url("neomail.png") + position: left center + repeat: no-repeat + padding-left: image-width("neomail.png") + 2px + + input[type=text] + width: 10em + + label + font-weight: bold + margin-right: .5em + + &:after + content: ":" + #closet-hangers clear: both text-align: center diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 0bf4cd89..1b44a3da 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -8,15 +8,27 @@ - else - title "#{@user.name}'s Items" +- content_for :before_flashes do + #closet-hangers-contact + - if public_perspective? + - if @user.neopets_username? + = link_to "Neomail #{@user.neopets_username}", send_neomail_url(@user) + - else + = form_for @user do |f| + = f.label :neopets_username + = f.text_field :neopets_username + = f.submit "Save" + #closet-hangers{:class => public_perspective? ? nil : 'current-user'} - - if !@closet_hangers.empty? - - unless public_perspective? + - if public_perspective? + - if @closet_hangers.empty? + %p #{@user.name} hasn't tracked any items on Dress to Impress. + - else + - unless @closet_hangers.empty? %p These are the items you own. Hover over an item to remove it from the list or to change the quantity. - = render :partial => 'closet_hanger', :collection => @closet_hangers, :locals => {:show_controls => user_is?(@user)} - - else - - unless public_perspective? + - else %p You haven't tracked any items on Dress to Impress. %p Here you can keep track of what items you already own, so that as you @@ -27,8 +39,11 @@ It's easy to get started! = link_to "Just import your Neopets closet in a few quick steps.", new_closet_page_path Have fun! - - else - %p #{@user.name} hasn't tracked any items on Dress to Impress. + %p + You can share + = link_to "this page", request.fullpath + with the world, and they'll be able to see what items you own. + = render :partial => 'closet_hanger', :collection => @closet_hangers, :locals => {:show_controls => user_is?(@user)} - content_for :stylesheets do = stylesheet_link_tag 'south-street/jquery-ui' diff --git a/config/routes.rb b/config/routes.rb index f3fe0d21..e8c8d245 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -35,7 +35,7 @@ OpenneoImpressItems::Application.routes.draw do |map| match '/logout' => 'sessions#destroy', :as => :logout match '/users/authorize' => 'sessions#create' - resources :user, :only => [] do + resources :users, :path => 'user', :only => [:update] do resources :contributions, :only => [:index] resources :closet_hangers, :only => [:index], :path => 'closet' diff --git a/db/migrate/20110720183722_add_neopets_username_to_users.rb b/db/migrate/20110720183722_add_neopets_username_to_users.rb new file mode 100644 index 00000000..5cef44b9 --- /dev/null +++ b/db/migrate/20110720183722_add_neopets_username_to_users.rb @@ -0,0 +1,9 @@ +class AddNeopetsUsernameToUsers < ActiveRecord::Migration + def self.up + add_column :users, :neopets_username, :string + end + + def self.down + remove_column :users, :neopets_username + end +end diff --git a/db/schema.rb b/db/schema.rb index 931e3818..6b144a06 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20110712232259) do +ActiveRecord::Schema.define(:version => 20110720183722) do create_table "auth_servers", :force => true do |t| t.string "short_name", :limit => 10, :null => false @@ -177,6 +177,7 @@ ActiveRecord::Schema.define(:version => 20110712232259) do t.boolean "forum_admin", :default => false, :null => false t.boolean "forum_moderator" t.boolean "image_mode_tester", :default => false, :null => false + t.string "neopets_username" end create_table "zones", :force => true do |t| @@ -187,3 +188,4 @@ ActiveRecord::Schema.define(:version => 20110712232259) do end end + diff --git a/public/images/neomail.png b/public/images/neomail.png new file mode 100644 index 0000000000000000000000000000000000000000..4a6c5d396ad024567a769d1f2285c525bef8c88b GIT binary patch literal 754 zcmV~0d>kmp9&fG9>#5EaEn(MD9Xvl47<{Rb2T3D!0$wpy4@P!Tnn zB0fxQ2!aPL_fZ@!=Wv9zmj8jnf5JO`<=MmZs@#@p z5O*{}9L5B6J+L7ORza<+9h)-B~<&cwIhUkd?cp4is-ziNrfY^u-7xdbFt=#%1534Oi8ajBBo}VZvCxd1 zTu*VtX+~P45)Om?dG5aS`PPW(%?lDPBwaz$6C^$8$_Q#plJTjpbgj;_rYi*?oK~m+ zDD`C->dkZKh0j6|Q^-0bJxIFHnHJOo$@r8{VNIUWU>31rp3@BVvYIZG2D0>Yuj2Y- zg?b?AObc>pK`oG+zkPsr3x_BTWXX8H*w}0@e;@>?SdsP&!-HMidhRn*4VkHi+<58} zTg6ae0~aSoNqRq(^;(g}0#Yiz)&q*YIg-f)mmeJA&3%nD3aJ$X-6L%1+fEQRIeTL* zS5K6|3cOaNtTtBowSZzzj!ZfM7L<|f+jtyp4ccf7mf6J$n}&ALkZlfLEYRoNvtG0Q zzJh|U~_Rdjkv}0kGt_?V}5$?sXN`N zTt|nOa)sx)IIf_-7XW**;!X9`USPjuUUsJrREk)6q*M9ZHEb zl2A!T3LBjrrTx74{FsUNcVA1zw%IWoiGNMw=s9P8>+qh!B*saR2}S literal 0 HcmV?d00001 diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 4037da2a..b7596113 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -552,7 +552,7 @@ div.jGrowl div.jGrowl-closer { /* line 5, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #title { float: left; - margin-bottom: 0.5em; + margin-bottom: 0; } /* line 9, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .flash { @@ -611,11 +611,39 @@ body.closet_hangers-index #closet-hangers-items-search input[type=search].loadin padding-left: 20px; } /* line 31, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-contact { + clear: both; + font-size: 85%; + margin-bottom: 1em; + margin-left: 2em; + min-height: 16px; +} +/* line 38, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-contact a { + background-image: url('/images/neomail.png?1311187553'); + background-position: left center; + background-repeat: no-repeat; + padding-left: 18px; +} +/* line 45, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-contact input[type=text], body.closet_hangers-index #closet-hangers-contact body.pets-bulk #bulk-pets-form textarea, body.pets-bulk #bulk-pets-form body.closet_hangers-index #closet-hangers-contact textarea { + width: 10em; +} +/* line 48, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-contact label { + font-weight: bold; + margin-right: 0.5em; +} +/* line 52, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-contact label:after { + content: ":"; +} +/* line 55, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers { clear: both; text-align: center; } -/* line 36, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 60, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -629,26 +657,26 @@ body.closet_hangers-index #closet-hangers .object .quantity { text-align: left; top: 60px; } -/* line 46, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 70, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { font-size: 16px; font-weight: bold; } -/* line 50, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 74, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object form { display: none; } -/* line 55, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 79, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover form { display: inline; } -/* line 58, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 82, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 63, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 87, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -689,7 +717,7 @@ body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-han body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 66, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 90, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -699,33 +727,33 @@ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity { top: 56px; padding: 0; } -/* line 72, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 96, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity span { display: none; } -/* line 75, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 99, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 79, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 103, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 84, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 108, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user.js .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 87, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 111, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user.js .object:hover .quantity input[type=submit] { display: none; } -/* line 90, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 114, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user.js .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 94, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 118, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers.current-user.js .object.loading .quantity span:after { content: "…"; } From 8f646b4a107b45dc5420d54f5b50fd9dc1ba2ef6 Mon Sep 17 00:00:00 2001 From: Matchu Date: Wed, 20 Jul 2011 15:22:00 -0400 Subject: [PATCH 24/69] closet importer gets back to your items link --- app/stylesheets/closet_pages/_new.sass | 13 ++++++ app/views/closet_pages/new.html.haml | 2 + public/stylesheets/compiled/screen.css | 60 ++++++++++++++++++++++---- 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/app/stylesheets/closet_pages/_new.sass b/app/stylesheets/closet_pages/_new.sass index 90357610..ceb49654 100644 --- a/app/stylesheets/closet_pages/_new.sass +++ b/app/stylesheets/closet_pages/_new.sass @@ -1,7 +1,20 @@ body.closet_pages-new, body.closet_pages-create + #title + float: left + + .flash + clear: both + + #back-to-items + +awesome-button + margin: + left: 1em + top: .75em + #closet-page-form +clearfix + clear: both margin-bottom: 1em #closet-page-frame-wrapper diff --git a/app/views/closet_pages/new.html.haml b/app/views/closet_pages/new.html.haml index fd7aec84..ae504a69 100644 --- a/app/views/closet_pages/new.html.haml +++ b/app/views/closet_pages/new.html.haml @@ -1,4 +1,6 @@ - title "Closet Importer, Page #{@closet_page.index}" +- content_for :before_flashes do + = link_to 'Back to Your Items', user_closet_hangers_path(current_user), :id => 'back-to-items' = form_for @closet_page, :html => {:id => 'closet-page-form'} do |f| #closet-page-frame-wrapper diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index b7596113..75465c48 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -759,55 +759,97 @@ body.closet_hangers-index #closet-hangers.current-user.js .object.loading .quant } /* line 3, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new #title, body.closet_pages-create #title { + float: left; +} +/* line 6, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new .flash, body.closet_pages-create .flash { + clear: both; +} +/* line 9, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new #back-to-items, body.closet_pages-create #back-to-items { + /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + background: #006400 url('/images/alert-overlay.png?1296599919') repeat-x; + border: 0; + display: inline-block; + padding: 0.5em 0.75em 0.45em; + color: white; + text-decoration: none; + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); + border-bottom: 1px solid rgba(0, 0, 0, 0.25); + position: relative; + font-weight: bold; + line-height: 1; + margin-left: 1em; + margin-top: 0.75em; +} +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_pages-new #back-to-items:hover, body.closet_pages-create #back-to-items:hover { + background-color: #005300; +} +/* line 53, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_pages-new #back-to-items:hover, body.closet_pages-create #back-to-items:hover { + color: white; +} +/* line 55, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_pages-new #back-to-items:active, body.closet_pages-create #back-to-items:active { + top: 1px; +} +/* line 15, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new #closet-page-form, body.closet_pages-create #closet-page-form { overflow: hidden; display: inline-block; + clear: both; margin-bottom: 1em; } /* line 8, ../../../app/stylesheets/partials/clean/_mixins.sass */ body.closet_pages-new #closet-page-form, body.closet_pages-create #closet-page-form { display: block; } -/* line 7, ../../../app/stylesheets/closet_pages/_new.sass */ +/* line 20, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new #closet-page-frame-wrapper, body.closet_pages-create #closet-page-frame-wrapper { float: left; margin-right: 2%; width: 48%; } -/* line 12, ../../../app/stylesheets/closet_pages/_new.sass */ +/* line 25, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new #closet-page-frame, body.closet_pages-create #closet-page-frame { height: 19em; width: 100%; } -/* line 16, ../../../app/stylesheets/closet_pages/_new.sass */ +/* line 29, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new #closet-page-source, body.closet_pages-create #closet-page-source { float: left; width: 50%; } -/* line 20, ../../../app/stylesheets/closet_pages/_new.sass */ +/* line 33, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new #closet-page-source label, body.closet_pages-create #closet-page-source label { font-weight: bold; } -/* line 23, ../../../app/stylesheets/closet_pages/_new.sass */ +/* line 36, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new #closet-page-source textarea, body.closet_pages-create #closet-page-source textarea { height: 19em; } -/* line 27, ../../../app/stylesheets/closet_pages/_new.sass */ +/* line 40, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new ol, body.closet_pages-create ol { padding-left: 1em; } -/* line 30, ../../../app/stylesheets/closet_pages/_new.sass */ +/* line 43, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new ol > li, body.closet_pages-create ol > li { margin-bottom: 1em; } -/* line 33, ../../../app/stylesheets/closet_pages/_new.sass */ +/* line 46, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new ol ul, body.closet_pages-create ol ul { font-size: 85%; margin-bottom: 1em; margin-top: 0; padding-left: 1em; } -/* line 40, ../../../app/stylesheets/closet_pages/_new.sass */ +/* line 53, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new ol p, body.closet_pages-create ol p { margin: 0; } From 01ba06b1b4002eff0854bc002e3ae56bc12afa06 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 22 Jul 2011 14:02:04 -0400 Subject: [PATCH 25/69] closet neopets username --- app/controllers/users_controller.rb | 22 ++++- app/stylesheets/closet_hangers/_index.sass | 45 ++++++++- app/views/closet_hangers/index.html.haml | 10 ++ public/javascripts/closet_hangers/index.js | 58 +++++++++++- public/stylesheets/compiled/screen.css | 104 +++++++++++++++------ 5 files changed, 200 insertions(+), 39 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index e76b953c..7a7d7750 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -6,9 +6,25 @@ class UsersController < ApplicationController end def update - @user.update_attributes params[:user] - flash[:success] = "Settings successfully saved" - redirect_back! user_closet_hangers_path(@user) + success = @user.update_attributes params[:user] + respond_to do |format| + format.html { + if success + flash[:success] = "Settings successfully saved" + redirect_back! user_closet_hangers_path(@user) + else + flash[:alert] = "Error saving user settings: #{@user.errors.full_messages.to_sentence}" + end + } + + format.json { + if success + render :json => true + else + render :json => {:errors => @user.errors.full_messages}, :status => :unprocessable_entity + end + } + end end protected diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 7fd8aa3d..e5f396d7 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -52,6 +52,31 @@ body.closet_hangers-index &:after content: ":" + #edit-contact-link, #cancel-contact-link + cursor: pointer + display: none + text-decoration: underline + + &:hover + text-decoration: none + + #edit-contact-link + #contact-link-has-value + display: none + + #contact-link-no-value + display: inline + + &.has-value + #contact-link-has-value + display: inline + + #contact-link-no-value + display: none + + #cancel-contact-link + margin-left: 1em + #closet-hangers clear: both text-align: center @@ -74,7 +99,8 @@ body.closet_hangers-index form display: none - &.current-user + &.current-user + #closet-hangers .object:hover form display: inline @@ -103,7 +129,8 @@ body.closet_hangers-index input[type=submit] font-size: 85% - &.js + &.js + #closet-hangers .object:hover .quantity input[type=number] width: 2.5em @@ -118,3 +145,17 @@ body.closet_hangers-index .quantity span:after content: "…" + #closet-hangers-contact + form + display: none + + #edit-contact-link, #cancel-contact-link + display: inline + + &.editing + form + display: block + + #edit-contact-link + display: none + diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 1b44a3da..f3754dcb 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -1,5 +1,6 @@ - unless public_perspective? - title 'Your Items' + - add_body_class 'current-user' - content_for :before_flashes do = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' = form_tag items_path, :method => :get, :id => 'closet-hangers-items-search', 'data-current-user-id' => current_user.id do @@ -14,10 +15,19 @@ - if @user.neopets_username? = link_to "Neomail #{@user.neopets_username}", send_neomail_url(@user) - else + %span#edit-contact-link{:class => @user.neopets_username? ? 'has-value' : nil} + %span#contact-link-no-value + Add your Neopets username + %span#contact-link-has-value + Edit + = surround '"' do + Neomail + %span= @user.neopets_username = form_for @user do |f| = f.label :neopets_username = f.text_field :neopets_username = f.submit "Save" + %span#cancel-contact-link cancel #closet-hangers{:class => public_perspective? ? nil : 'current-user'} - if public_perspective? diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index b26eb31e..bc2cbeca 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -1,7 +1,9 @@ (function () { - var hangersElQuery = '#closet-hangers.current-user'; + var body = $(document.body).addClass("js"); + if(!body.hasClass("current-user")) return false; + + var hangersElQuery = '#closet-hangers'; var hangersEl = $(hangersElQuery); - hangersEl.addClass('js'); $.fn.disableForms = function () { return this.data("formsDisabled", true).find("input").attr("disabled", "disabled").end(); @@ -29,7 +31,7 @@ }); } - function handleHangerError(xhr, action) { + function handleSaveError(xhr, action) { try { var data = $.parseJSON(xhr.responseText); } catch(e) { @@ -76,7 +78,7 @@ input.revertValue(); span.text(input.val()); - handleHangerError(xhr, "updating the quantity"); + handleSaveError(xhr, "updating the quantity"); } }); } @@ -147,7 +149,7 @@ itemsSearchField.val(""); }, error: function (xhr) { - handleHangerError(xhr, "adding the item"); + handleSaveError(xhr, "adding the item"); } }); }, @@ -168,5 +170,51 @@ .append( "Add " + item.label + "" ) .appendTo( ul ); } + + var contactEl = $('#closet-hangers-contact'); + var editContactLink = $('#edit-contact-link'); + var contactForm = contactEl.children('form'); + var cancelContactLink = $('#cancel-contact-link'); + var contactFormUsername = contactForm.children('input[type=text]'); + var editContactLinkUsername = $('#contact-link-has-value span'); + + function closeContactForm() { + contactEl.removeClass('editing'); + } + + editContactLink.click(function () { + contactEl.addClass('editing'); + contactFormUsername.focus(); + }); + + cancelContactLink.click(closeContactForm); + + contactForm.submit(function (e) { + var data = contactForm.serialize(); + contactForm.disableForms(); + $.ajax({ + url: contactForm.attr('action') + '.json', + type: 'post', + data: data, + dataType: 'json', + complete: function () { + contactForm.enableForms(); + }, + success: function () { + var newName = contactFormUsername.val(); + if(newName.length > 0) { + editContactLink.addClass('has-value'); + editContactLinkUsername.text(newName); + } else { + editContactLink.removeClass('has-value'); + } + closeContactForm(); + }, + error: function (xhr) { + handleSaveError(xhr, 'saving Neopets username'); + } + }); + e.preventDefault(); + }); })(); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 75465c48..9a3d13da 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -639,11 +639,41 @@ body.closet_hangers-index #closet-hangers-contact label:after { content: ":"; } /* line 55, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #edit-contact-link, body.closet_hangers-index #cancel-contact-link { + cursor: pointer; + display: none; + text-decoration: underline; +} +/* line 60, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #edit-contact-link:hover, body.closet_hangers-index #cancel-contact-link:hover { + text-decoration: none; +} +/* line 64, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #edit-contact-link #contact-link-has-value { + display: none; +} +/* line 67, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #edit-contact-link #contact-link-no-value { + display: inline; +} +/* line 71, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #edit-contact-link.has-value #contact-link-has-value { + display: inline; +} +/* line 74, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #edit-contact-link.has-value #contact-link-no-value { + display: none; +} +/* line 77, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #cancel-contact-link { + margin-left: 1em; +} +/* line 80, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers { clear: both; text-align: center; } -/* line 60, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 85, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -657,27 +687,27 @@ body.closet_hangers-index #closet-hangers .object .quantity { text-align: left; top: 60px; } -/* line 70, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 95, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { font-size: 16px; font-weight: bold; } -/* line 74, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 99, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object form { display: none; } -/* line 79, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover form { +/* line 105, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 82, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy { +/* line 108, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 87, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input { +/* line 113, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; -webkit-border-radius: 5px; @@ -702,23 +732,23 @@ body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-han font-size: 80%; } /* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input:hover { +body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #005300; } /* line 53, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input:hover { +body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { color: white; } /* line 55, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input:active { +body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:active { top: 1px; } /* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover .closet-hanger-destroy input:hover { +body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 90, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity { +/* line 116, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; @@ -727,36 +757,52 @@ body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity { top: 56px; padding: 0; } -/* line 96, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity span { +/* line 122, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 99, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity input[type=number] { +/* line 125, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 103, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user .object:hover .quantity input[type=submit] { +/* line 129, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 108, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user.js .object:hover .quantity input[type=number] { +/* line 135, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 111, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user.js .object:hover .quantity input[type=submit] { +/* line 138, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 114, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user.js .object.loading { +/* line 141, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 118, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers.current-user.js .object.loading .quantity span:after { +/* line 145, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } +/* line 149, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #closet-hangers-contact form { + display: none; +} +/* line 152, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #closet-hangers-contact #edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { + display: inline; +} +/* line 156, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { + display: block; +} +/* line 159, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #closet-hangers-contact.editing #edit-contact-link { + display: none; +} /* line 3, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new #title, body.closet_pages-create #title { From 85af53417bf788777fa4ddbb154d6bdf14139b2b Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 22 Jul 2011 15:31:23 -0400 Subject: [PATCH 26/69] distinguish between owning and wanting an item --- app/controllers/closet_hangers_controller.rb | 13 +++++---- app/controllers/items_controller.rb | 7 +++-- app/models/closet_hanger.rb | 11 +++++-- app/stylesheets/items/_show.sass | 18 +++++------- app/views/items/show.html.haml | 29 ++++++++++--------- ...10722180616_add_owned_to_closet_hangers.rb | 10 +++++++ db/schema.rb | 5 ++-- public/stylesheets/compiled/screen.css | 26 ++++++++--------- 8 files changed, 71 insertions(+), 48 deletions(-) create mode 100644 db/migrate/20110722180616_add_owned_to_closet_hangers.rb diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index fdc53c07..a082025e 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -13,7 +13,7 @@ class ClosetHangersController < ApplicationController def index @user = User.find params[:user_id] - @closet_hangers = @user.closet_hangers.alphabetical_by_item_name.includes(:item) + @closet_hangers = @user.closet_hangers.owned_before_wanted.alphabetical_by_item_name.includes(:item) @public_perspective = params.has_key?(:public) || !user_is?(@user) end @@ -28,14 +28,17 @@ class ClosetHangersController < ApplicationController # expectations, though, and I can't really think of a genuinely RESTful way # to pull this off. def update - @closet_hanger = current_user.closet_hangers.find_or_initialize_by_item_id(@item.id) + owned = (params[:closet_hanger][:owned] == 'true') if params[:closet_hanger] + owned ||= true + + @closet_hanger = current_user.closet_hangers.find_or_initialize_by_item_id_and_owned(@item.id, owned) @closet_hanger.attributes = params[:closet_hanger] unless @closet_hanger.quantity == 0 # save the hanger, new record or not if @closet_hanger.save respond_to do |format| format.html { - flash[:success] = "Success! You own #{@closet_hanger.quantity} #{@item.name.pluralize}." + flash[:success] = "Success! You #{@closet_hanger.verb(:you)} #{@closet_hanger.quantity} #{@item.name.pluralize}." redirect_back!(@item) } @@ -44,7 +47,7 @@ class ClosetHangersController < ApplicationController else respond_to do |format| format.html { - flash[:alert] = "We couldn't save how many of this item you own: #{@closet_hanger.errors.full_messages.to_sentence}" + flash[:alert] = "We couldn't save how many of this item you #{@closet_hanger.verb(:you)}: #{@closet_hanger.errors.full_messages.to_sentence}" redirect_back!(@item) } @@ -74,7 +77,7 @@ class ClosetHangersController < ApplicationController end def redirect_after_destroy! - flash[:success] = "Success! You do not own #{@item.name}." + flash[:success] = "Success! You do not #{@closet_hanger.verb(:you)} #{@item.name}." redirect_back!(@item) end end diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 37006fd2..aac96188 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -40,8 +40,11 @@ class ItemsController < ApplicationController def show @item = Item.find params[:id] if user_signed_in? - @hanger = current_user.closet_hangers.find_or_initialize_by_item_id(@item.id) - @hanger.quantity ||= 1 + @hangers = [true, false].map do |owned| + hanger = current_user.closet_hangers.find_or_initialize_by_item_id_and_owned(@item.id, owned) + hanger.quantity ||= 1 + hanger + end end end diff --git a/app/models/closet_hanger.rb b/app/models/closet_hanger.rb index 4556c605..8ffb94c7 100644 --- a/app/models/closet_hanger.rb +++ b/app/models/closet_hanger.rb @@ -2,12 +2,19 @@ class ClosetHanger < ActiveRecord::Base belongs_to :item belongs_to :user - attr_accessible :quantity + attr_accessible :owned, :quantity - validates :item_id, :uniqueness => {:scope => :user_id} + validates :item_id, :uniqueness => {:scope => [:user_id, :owned]} validates :quantity, :numericality => {:greater_than => 0} validates_presence_of :item, :user scope :alphabetical_by_item_name, joins(:item).order(Item.arel_table[:name]) + scope :owned_before_wanted, order(arel_table[:owned].desc) + + def verb(subject=:someone) + base = (owned?) ? 'own' : 'want' + base + 's' if subject != :you + base + end end diff --git a/app/stylesheets/items/_show.sass b/app/stylesheets/items/_show.sass index 7bc4d7d6..9f98674a 100644 --- a/app/stylesheets/items/_show.sass +++ b/app/stylesheets/items/_show.sass @@ -63,25 +63,23 @@ body.items-show height: 16px width: 16px - #closet-hanger-form + #closet-hangers border: 1px solid $module-border-color float: right font-size: 85% - padding: 1em .5em .5em + padding: 1em width: 18em label, header display: block font-weight: bold + header + font-size: 125% + + form + padding: .5em 0 + input[type=number] width: 4em - #closet-hanger-form-your-items - display: block - margin-top: .5em - text-align: right - - p - font-family: $main-font - diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index 201982d5..2cb6576c 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -12,19 +12,22 @@ == Rarity: #{@item.rarity_index} (#{@item.rarity}) = link_to 'NeoItems', neoitems_url_for(@item), :class => 'button' - - if @hanger - = form_for(@hanger, :url => user_item_closet_hanger_path(current_user, @item), :html => {:id => 'closet-hanger-form'}) do |f| - - if @hanger.new_record? - %header Do you own this item? - %p - We can help you track your closet. - = f.hidden_field :quantity - = f.submit "I own this item!" - - else - = f.label :quantity, "How many of these do you own?" - = f.number_field :quantity, :min => 0, :required => true - = f.submit "Save" - = link_to 'Your Items →'.html_safe, user_closet_hangers_path(current_user), :id => 'closet-hanger-form-your-items' + - if @hangers + #closet-hangers + %header + Track this in + = link_to 'Your Items', user_closet_hangers_path(current_user) + - @hangers.each do |hanger| + = form_for(hanger, :url => user_item_closet_hanger_path(current_user, @item)) do |f| + - if hanger.new_record? + = f.hidden_field :quantity + = f.hidden_field :owned + = f.submit "I #{hanger.verb(:you)} this item!" + - else + = f.hidden_field :owned + = f.label :quantity, "How many of these do you #{hanger.verb(:you)}?" + = f.number_field :quantity, :min => 0, :required => true + = f.submit "Save" %p= @item.description #item-zones diff --git a/db/migrate/20110722180616_add_owned_to_closet_hangers.rb b/db/migrate/20110722180616_add_owned_to_closet_hangers.rb new file mode 100644 index 00000000..faa4d4cf --- /dev/null +++ b/db/migrate/20110722180616_add_owned_to_closet_hangers.rb @@ -0,0 +1,10 @@ +class AddOwnedToClosetHangers < ActiveRecord::Migration + def self.up + add_column :closet_hangers, :owned, :boolean, :null => false, :default => true + end + + def self.down + remove_column :closet_hangers, :owned + end +end + diff --git a/db/schema.rb b/db/schema.rb index 6b144a06..05893ef1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20110720183722) do +ActiveRecord::Schema.define(:version => 20110722180616) do create_table "auth_servers", :force => true do |t| t.string "short_name", :limit => 10, :null => false @@ -26,6 +26,7 @@ ActiveRecord::Schema.define(:version => 20110720183722) do t.integer "quantity" t.datetime "created_at" t.datetime "updated_at" + t.boolean "owned", :default => true, :null => false end create_table "contributions", :force => true do |t| @@ -177,6 +178,7 @@ ActiveRecord::Schema.define(:version => 20110720183722) do t.boolean "forum_admin", :default => false, :null => false t.boolean "forum_moderator" t.boolean "image_mode_tester", :default => false, :null => false + t.text "closet_description", :null => false t.string "neopets_username" end @@ -188,4 +190,3 @@ ActiveRecord::Schema.define(:version => 20110720183722) do end end - diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 9a3d13da..1b9c0a33 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -620,7 +620,7 @@ body.closet_hangers-index #closet-hangers-contact { } /* line 38, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-contact a { - background-image: url('/images/neomail.png?1311187553'); + background-image: url('/images/neomail.png?1311362308'); background-position: left center; background-repeat: no-repeat; padding-left: 18px; @@ -1202,31 +1202,29 @@ body.items-show .nc-icon { width: 16px; } /* line 66, ../../../app/stylesheets/items/_show.sass */ -body.items-show #closet-hanger-form { +body.items-show #closet-hangers { border: 1px solid #006600; float: right; font-size: 85%; - padding: 1em 0.5em 0.5em; + padding: 1em; width: 18em; } /* line 73, ../../../app/stylesheets/items/_show.sass */ -body.items-show #closet-hanger-form label, body.items-show #closet-hanger-form header { +body.items-show #closet-hangers label, body.items-show #closet-hangers header { display: block; font-weight: bold; } /* line 77, ../../../app/stylesheets/items/_show.sass */ -body.items-show #closet-hanger-form input[type=number] { - width: 4em; +body.items-show #closet-hangers header { + font-size: 125%; } /* line 80, ../../../app/stylesheets/items/_show.sass */ -body.items-show #closet-hanger-form #closet-hanger-form-your-items { - display: block; - margin-top: 0.5em; - text-align: right; +body.items-show #closet-hangers form { + padding: 0.5em 0; } -/* line 85, ../../../app/stylesheets/items/_show.sass */ -body.items-show #closet-hanger-form p { - font-family: "Droid Sans", Helvetica, Arial, Verdana, sans-serif; +/* line 83, ../../../app/stylesheets/items/_show.sass */ +body.items-show #closet-hangers input[type=number] { + width: 4em; } @import url(../shared/jquery.jgrowl.css); @@ -1807,7 +1805,7 @@ body.outfits-edit .object:hover ul, body.outfits-edit .object:hover .object-info } /* line 418, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .nc-icon { - background: url('/images/nc.png?1310666180') no-repeat; + background: url('/images/nc.png?1311362308') no-repeat; height: 16px; position: absolute; right: 16px; From b1670b1595dc940b46be7c41452c10f2eef8e341 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 22 Jul 2011 16:17:13 -0400 Subject: [PATCH 27/69] fix bug with adding/removing wanted items --- app/controllers/closet_hangers_controller.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index a082025e..692d65d1 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -28,7 +28,12 @@ class ClosetHangersController < ApplicationController # expectations, though, and I can't really think of a genuinely RESTful way # to pull this off. def update - owned = (params[:closet_hanger][:owned] == 'true') if params[:closet_hanger] + if params[:closet_hanger] + owned = case params[:closet_hanger][:owned] + when 'true' then true + when 'false' then false + end + end owned ||= true @closet_hanger = current_user.closet_hangers.find_or_initialize_by_item_id_and_owned(@item.id, owned) From 6d155ecaf1dff13aee1b8211958365ef45f5c1a6 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 22 Jul 2011 16:18:15 -0400 Subject: [PATCH 28/69] show owned/wanted icons and search filters --- app/helpers/items_helper.rb | 23 ++++++--- app/models/item.rb | 57 +++++++++++++++++----- app/models/user.rb | 10 +++- app/stylesheets/_layout.sass | 14 ++++-- app/views/items/_item_link.html.haml | 2 +- public/images/{closeted.png => owned.png} | Bin public/images/wanted.png | Bin 0 -> 671 bytes public/stylesheets/compiled/screen.css | 35 +++++++------ 8 files changed, 101 insertions(+), 40 deletions(-) rename public/images/{closeted.png => owned.png} (100%) create mode 100644 public/images/wanted.png diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb index 5bc3a23c..f01fb43b 100644 --- a/app/helpers/items_helper.rb +++ b/app/helpers/items_helper.rb @@ -48,15 +48,26 @@ module ItemsHelper end end - def closeted_icon_for(item) - if item.closeted? - image_tag( - 'closeted.png', + def closeted_icons_for(item) + content = ''.html_safe + + if item.owned? + content << image_tag( + 'owned.png', :title => 'You own this', - :alt => 'Closet', - :class => 'closeted-icon' + :alt => 'Own' ) end + + if item.wanted? + content << image_tag( + 'wanted.png', + :title => 'You want this', + :alt => 'Want' + ) + end + + content_tag :div, content, :class => 'closeted-icons' end def list_zones(zones, method=:label) diff --git a/app/models/item.rb b/app/models/item.rb index 608f8109..6db699cb 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -10,7 +10,7 @@ class Item < ActiveRecord::Base has_many :swf_assets, :through => :parent_swf_asset_relationships, :source => :object_asset, :conditions => {:type => SwfAssetType} - attr_writer :closeted, :current_body_id + attr_writer :current_body_id, :owned, :wanted NCRarities = [0, 500] PAINTBRUSH_SET_DESCRIPTION = 'This item is part of a deluxe paint brush set!' @@ -46,13 +46,21 @@ class Item < ActiveRecord::Base scope :with_closet_hangers, joins(:closet_hangers) def closeted? - !!@closeted + @owned || @wanted end def nc? NCRarities.include?(rarity_index) end + def owned? + @owned + end + + def wanted? + @wanted + end + def restricted_zones unless @restricted_zones @restricted_zones = [] @@ -639,7 +647,10 @@ class Item < ActiveRecord::Base def self.search_filter_block(options, positive, &block) Proc.new { |str, user, scope| condition = block.arity == 1 ? block.call(str) : block.call(str, user) - condition = "!(#{condition.to_sql})" unless positive + unless positive + condition = condition.to_sql if condition.respond_to?(:to_sql) + condition = "!(#{condition})" + end scope = scope.send(options[:scope]) if options[:scope] scope.where(condition) } @@ -667,25 +678,45 @@ class Item < ActiveRecord::Base filter end - def self.validate_user_condition(adjective, user) - unless adjective == "owns" + USER_ADJECTIVES = { + 'own' => true, + 'owns' => true, + 'owned' => true, + 'want' => false, + 'wants' => false, + 'wanted' => false, + 'all' => nil, + 'items' => nil + } + def self.parse_user_adjective(adjective, user) + unless USER_ADJECTIVES.has_key?(adjective) raise SearchError, "We don't understand user:#{adjective}. " + - "Did you mean user:owns?" + "Find items you own with user:owns, items you want with user:wants, or " + + "both with user:all" end unless user raise SearchError, "It looks like you're not logged in, so you don't own any items." end + + USER_ADJECTIVES[adjective] end - single_search_filter :user, :full => lambda { |adjective, user, scope| - validate_user_condition(adjective, user) - scope.joins(:closet_hangers).where(ClosetHanger.arel_table[:user_id].eq(user.id)) - } + search_filter :user do |adjective, user| + # Though joins may seem more efficient here for the positive case, we need + # to be able to handle cases like "user:owns user:wants", which breaks on + # the JOIN approach. Just have to look up the IDs in advance. - single_search_filter :not_user do |adjective, user| - validate_user_condition(adjective, user) - arel_table[:id].not_in(user.closeted_items.map(&:id)) + owned_value = parse_user_adjective(adjective, user) + hangers = ClosetHanger.arel_table + items = user.closeted_items + items = items.where(ClosetHanger.arel_table[:owned].eq(owned_value)) unless owned_value.nil? + item_ids = items.map(&:id) + # Though it's best to do arel_table[:id].in(item_ids), it breaks in this + # version of Arel, and other conditions will overwrite this one. Since IDs + # are guaranteed to be integers, let's just build our own string condition + # and be done with it. + "id IN (#{item_ids.join(',')})" end search_filter :only do |species_name| diff --git a/app/models/user.rb b/app/models/user.rb index a2ab633f..20f027b4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -49,8 +49,14 @@ class User < ActiveRecord::Base # versa, and everything stays a lovely O(n) items_by_id = {} items.each { |item| items_by_id[item.id] = item } - closeted_item_ids = closeted_items.where(:id => items_by_id.keys).map(&:id) - closeted_item_ids.each { |id| items_by_id[id].closeted = true } + closet_hangers.where(:item_id => items_by_id.keys).each do |hanger| + item = items_by_id[hanger.item_id] + if hanger.owned? + item.owned = true + else + item.wanted = true + end + end end def self.find_or_create_from_remote_auth_data(user_data) diff --git a/app/stylesheets/_layout.sass b/app/stylesheets/_layout.sass index 9a3eaaf7..81cb2731 100644 --- a/app/stylesheets/_layout.sass +++ b/app/stylesheets/_layout.sass @@ -178,19 +178,25 @@ ul.buttons // (quantity form in user items) +opacity(1) - .nc-icon, .closeted-icon + .nc-icon, .closeted-icons +opacity(1) - height: $nc-icon-size + background: rgba(255, 255, 255, 0.75) + line-height: 1 position: absolute top: $object-img-size - $nc-icon-size - width: $nc-icon-size &:hover +opacity(0.5) + background: transparent + + .nc-icon, .closeted-icons img + display: inline + height: $nc-icon-size + width: $nc-icon-size .nc-icon right: ($object-width - $object-img-size) / 2 + $object-padding - .closeted-icon + .closeted-icons left: ($object-width - $object-img-size) / 2 + $object-padding dt diff --git a/app/views/items/_item_link.html.haml b/app/views/items/_item_link.html.haml index 107b7ed9..ed1fd79f 100644 --- a/app/views/items/_item_link.html.haml +++ b/app/views/items/_item_link.html.haml @@ -2,5 +2,5 @@ = image_tag item.thumbnail_url, :alt => item.description, :title => item.description = item.name = nc_icon_for(item) - = closeted_icon_for(item) + = closeted_icons_for(item) diff --git a/public/images/closeted.png b/public/images/owned.png similarity index 100% rename from public/images/closeted.png rename to public/images/owned.png diff --git a/public/images/wanted.png b/public/images/wanted.png new file mode 100644 index 0000000000000000000000000000000000000000..003924f5eaf9d04277db6731c060eea3f91afbe0 GIT binary patch literal 671 zcmV;Q0$}}#P))~3#~Ygh$29>KGa1bdH!g|-+n z%l(K(260cnR7PZA*&f5ViJWk2f?gO&<^&{{2pC@~psYOx{~+*b81ROHwh-W{t3t5R zfUAcy8L&$R7VqU%llVxB*$-TP4VVK!!+YQ{1?q!9``6#^&vyc*d<{N4Fv7TFIs?*V zVE#eNEVW7OU_j1YAe-u>mqKrV*3ZC0Dhr{9JVTgBH3a zw-MOd1e_w^+FNRU0B}<`6@-^H`-eRI8uYrge*@EsyqvK^`lfvjY@_h@W`KJMSbKop zAHe;7z(u1Nuh*cfdJEdlt!IEw0o1wyC*2TZt#4=mjuUi~!k&*bMpx`-Zr%6cESDIq zaoS|ycJT@Z=oCP8Ci0}*C*evrP)&0?`y^ Date: Fri, 22 Jul 2011 17:06:21 -0400 Subject: [PATCH 29/69] wardrobe now works with owned/wanted --- app/models/item.rb | 3 ++- app/stylesheets/outfits/_edit.sass | 4 ++-- app/views/outfits/edit.html.haml | 3 ++- public/javascripts/outfits/edit.js | 14 +++++++++----- public/stylesheets/compiled/screen.css | 4 ++-- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/app/models/item.rb b/app/models/item.rb index 6db699cb..09d36126 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -168,7 +168,8 @@ class Item < ActiveRecord::Base :thumbnail_url => thumbnail_url, :zones_restrict => zones_restrict, :rarity_index => rarity_index, - :closeted => closeted? + :owned => owned?, + :wanted => wanted? } end diff --git a/app/stylesheets/outfits/_edit.sass b/app/stylesheets/outfits/_edit.sass index 167a2064..e4ebed1d 100644 --- a/app/stylesheets/outfits/_edit.sass +++ b/app/stylesheets/outfits/_edit.sass @@ -315,7 +315,7 @@ body.outfits-edit +inline-block &[type=submit] margin-right: 2em - #preview-search-form-your-items + .preview-search-form-your-items display: none font-size: 85% margin-right: 1em @@ -563,7 +563,7 @@ body.outfits-edit display: block #save-outfit, #save-current-outfit, #save-outfit-copy, #current-outfit-permalink, #shared-outfit-permalink, #share-outfit, #shared-outfit-url display: none - #preview-search-form-your-items + .preview-search-form-your-items +inline-block &.user-not-signed-in diff --git a/app/views/outfits/edit.html.haml b/app/views/outfits/edit.html.haml index 09e8f65d..ec8cb115 100644 --- a/app/views/outfits/edit.html.haml +++ b/app/views/outfits/edit.html.haml @@ -91,7 +91,8 @@ %h2 Add an item %input{:name => "query", :placeholder => "Search items...", :type => "search"}/ %input{:type => "submit", :value => "Go"}/ - %a#preview-search-form-your-items{:href => '#'} Your Items + %a.preview-search-form-your-items{:href => '#', 'data-search-value' => 'owns'} Items you own + %a.preview-search-form-your-items{:href => '#', 'data-search-value' => 'wants'} Items you want #preview-search-form-pagination %a#preview-search-form-clear{:href => "#"} clear %dl#preview-search-form-help diff --git a/public/javascripts/outfits/edit.js b/public/javascripts/outfits/edit.js index f1008704..a7e766fe 100644 --- a/public/javascripts/outfits/edit.js +++ b/public/javascripts/outfits/edit.js @@ -102,8 +102,12 @@ Partial.ItemSet = function ItemSet(wardrobe, selector) { ) { $('
      ', {'class': 'nc-icon', text: 'NC', title: 'NC'}).appendTo(li); } - if(item.closeted) { - $('', {'class': 'closeted-icon', alt: 'Closet', title: 'You own this', src: '/images/closeted.png'}).appendTo(li); + if(item.owned || item.wanted) { + var iconsWrapper = $('
      ', {'class': 'closeted-icons'}).appendTo(li); + if(item.owned) { + $('', {alt: 'Own', title: 'You own this', src: '/images/owned.png'}).appendTo(iconsWrapper); + $('', {alt: 'Want', title: 'You want this', src: '/images/wanted.png'}).appendTo(iconsWrapper); + } } li.append(img).append(controls).append(info_link).append(item.name).appendTo(ul); } @@ -863,7 +867,7 @@ View.Search = function (wardrobe) { loading_el = $('#preview-search-form-loading'), no_results_el = $('#preview-search-form-no-results'), no_results_span = no_results_el.children('span'), - your_items_el = $('#preview-search-form-your-items'), + your_items_links = $('.preview-search-form-your-items'), PAGINATION = { INNER_WINDOW: 4, OUTER_WINDOW: 1, @@ -928,9 +932,9 @@ View.Search = function (wardrobe) { form.submit(); }); - your_items_el.click(function (e) { + your_items_links.click(function (e) { e.preventDefault(); - input_el.val('user:owns'); + input_el.val('user:' + this.getAttribute('data-search-value')); form.submit(); }); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 13c5cdab..42438842 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -1616,7 +1616,7 @@ body.outfits-edit #preview-search-form input[type=submit] { margin-right: 2em; } /* line 318, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-search-form-your-items { +body.outfits-edit .preview-search-form-your-items { display: none; font-size: 85%; margin-right: 1em; @@ -2555,7 +2555,7 @@ body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit display: none; } /* line 566, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit.user-signed-in #preview-search-form-your-items { +body.outfits-edit.user-signed-in .preview-search-form-your-items { display: -moz-inline-box; -moz-box-orient: vertical; display: inline-block; From d9f94ae3fa8d9c32dc6adf121626413520a1a8f2 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 22 Jul 2011 17:55:05 -0400 Subject: [PATCH 30/69] Your Items page aware of wanting items --- app/controllers/closet_hangers_controller.rb | 24 ++++---- app/helpers/closet_hangers_helper.rb | 14 +++++ app/models/closet_hanger.rb | 8 ++- app/stylesheets/closet_hangers/_index.sass | 12 ++++ .../closet_hangers/_closet_hanger.html.haml | 2 + app/views/closet_hangers/index.html.haml | 55 +++++++++++-------- public/javascripts/closet_hangers/index.js | 7 ++- public/stylesheets/compiled/screen.css | 48 ++++++++++------ 8 files changed, 116 insertions(+), 54 deletions(-) diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 692d65d1..09f3cf59 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -3,7 +3,8 @@ class ClosetHangersController < ApplicationController before_filter :find_item, :only => [:destroy, :create, :update] def destroy - @closet_hanger = current_user.closet_hangers.find_by_item_id!(@item.id) + raise ActiveRecord::RecordNotFound unless params[:closet_hanger] + @closet_hanger = current_user.closet_hangers.find_by_item_id_and_owned!(@item.id, owned) @closet_hanger.destroy respond_to do |format| format.html { redirect_after_destroy! } @@ -13,7 +14,8 @@ class ClosetHangersController < ApplicationController def index @user = User.find params[:user_id] - @closet_hangers = @user.closet_hangers.owned_before_wanted.alphabetical_by_item_name.includes(:item) + @closet_hangers_by_owned = @user.closet_hangers.owned_before_wanted. + alphabetical_by_item_name.includes(:item).group_by(&:owned) @public_perspective = params.has_key?(:public) || !user_is?(@user) end @@ -28,14 +30,6 @@ class ClosetHangersController < ApplicationController # expectations, though, and I can't really think of a genuinely RESTful way # to pull this off. def update - if params[:closet_hanger] - owned = case params[:closet_hanger][:owned] - when 'true' then true - when 'false' then false - end - end - owned ||= true - @closet_hanger = current_user.closet_hangers.find_or_initialize_by_item_id_and_owned(@item.id, owned) @closet_hanger.attributes = params[:closet_hanger] @@ -81,6 +75,16 @@ class ClosetHangersController < ApplicationController @item = Item.find params[:item_id] end + def owned + owned = true + if params[:closet_hanger] + owned = case params[:closet_hanger][:owned] + when 'true', '1' then true + when 'false', '0' then false + end + end + end + def redirect_after_destroy! flash[:success] = "Success! You do not #{@closet_hanger.verb(:you)} #{@item.name}." redirect_back!(@item) diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index a7d77982..449853ae 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -1,12 +1,26 @@ require 'cgi' module ClosetHangersHelper + def closet_hanger_verb(owned) + ClosetHanger.verb(closet_hanger_subject, owned) + end + def send_neomail_url(user) "http://www.neopets.com/neomessages.phtml?type=send&recipient=#{CGI.escape @user.neopets_username}" end + def closet_hanger_subject + public_perspective? ? @user.name : :you + end + def public_perspective? @public_perspective end + + def render_closet_hangers(owned) + render :partial => 'closet_hanger', + :collection => @closet_hangers_by_owned[owned], + :locals => {:show_controls => !public_perspective?} + end end diff --git a/app/models/closet_hanger.rb b/app/models/closet_hanger.rb index 8ffb94c7..fbf5731d 100644 --- a/app/models/closet_hanger.rb +++ b/app/models/closet_hanger.rb @@ -12,8 +12,12 @@ class ClosetHanger < ActiveRecord::Base scope :owned_before_wanted, order(arel_table[:owned].desc) def verb(subject=:someone) - base = (owned?) ? 'own' : 'want' - base + 's' if subject != :you + self.class.verb(subject, owned?) + end + + def self.verb(subject, owned) + base = (owned) ? 'own' : 'want' + base << 's' unless subject == :you base end end diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index e5f396d7..5228a683 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -99,6 +99,18 @@ body.closet_hangers-index form display: none + h3 + border-bottom: 1px solid $soft-border-color + cursor: pointer + font-size: 250% + margin-bottom: .25em + padding: .25em 0 + + .closet-hangers-group + border-top: 1px solid $module-border-color + margin-bottom: 2em + padding-bottom: 1em + &.current-user #closet-hangers .object:hover diff --git a/app/views/closet_hangers/_closet_hanger.html.haml b/app/views/closet_hangers/_closet_hanger.html.haml index 17015c5b..ad7dd007 100644 --- a/app/views/closet_hangers/_closet_hanger.html.haml +++ b/app/views/closet_hangers/_closet_hanger.html.haml @@ -6,10 +6,12 @@ - if show_controls = form_for closet_hanger, :url => user_item_closet_hanger_path(current_user, closet_hanger.item), :html => {:class => 'closet-hanger-update'} do |f| = return_to_field_tag + = f.hidden_field :owned = f.number_field :quantity, :min => 0, :required => true, :title => "You own #{pluralize closet_hanger.quantity, closet_hanger.item.name}" = f.submit "Save" - if show_controls = form_tag user_item_closet_hanger_path(current_user, closet_hanger.item), :method => :delete, :class => 'closet-hanger-destroy' do = return_to_field_tag + = hidden_field_tag 'closet_hanger[owned]', closet_hanger.owned = submit_tag "Remove" diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index f3754dcb..b3415fd2 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -29,31 +29,38 @@ = f.submit "Save" %span#cancel-contact-link cancel +- unless @closet_hangers_by_owned.empty? + %p + These are the items you are tracking on Dress to Impress. Hover over an + item to remove it from the list or to change the quantity. + + %p + You can share + = link_to "this page", request.fullpath + with the world, and they'll be able to see what items you own. + #closet-hangers{:class => public_perspective? ? nil : 'current-user'} - - if public_perspective? - - if @closet_hangers.empty? - %p #{@user.name} hasn't tracked any items on Dress to Impress. - - else - - unless @closet_hangers.empty? - %p - These are the items you own. Hover over an item to remove it from the - list or to change the quantity. - - else - %p You haven't tracked any items on Dress to Impress. - %p - Here you can keep track of what items you already own, so that as you - design fancy outfits you can know what you have and what you still - need. And, who knows? Maybe some day this page will include wishlists - and up-for-trade items. We'll see what happens. - %p - It's easy to get started! - = link_to "Just import your Neopets closet in a few quick steps.", new_closet_page_path - Have fun! - %p - You can share - = link_to "this page", request.fullpath - with the world, and they'll be able to see what items you own. - = render :partial => 'closet_hanger', :collection => @closet_hangers, :locals => {:show_controls => user_is?(@user)} + - [true, false].each do |owned| + .closet-hangers-group{'data-owned' => owned.to_s} + %h3 Items #{closet_hanger_subject} #{closet_hanger_verb(owned)} + .closet-hangers-group-content + - if public_perspective? + - unless @closet_hangers_by_owned[owned] + %p #{@user.name} hasn't tracked any items on Dress to Impress. + - else + - unless @closet_hangers_by_owned[owned] + %p + You haven't tracked any #{closet_hanger_verb(owned)} items on Dress + to Impress. It's worth doing, since you can share this list with your + friends and keep track of what items you still need as you create new + outfits. + %p + It's easy to get started! + = link_to "Just import your Neopets closet in a few quick steps.", new_closet_page_path + You can also add an item from its + = link_to 'Infinite Closet', items_path + page. Have fun! + = render_closet_hangers(owned) - content_for :stylesheets do = stylesheet_link_tag 'south-street/jquery-ui' diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index bc2cbeca..f6d64b0e 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -102,7 +102,7 @@ $(hangersElQuery + " form.closet-hanger-destroy").live("submit", function (e) { e.preventDefault(); var form = $(this); - var button = form.children("input").val("Removing…"); + var button = form.children("input[type=submit]").val("Removing…"); var objectWrapper = form.closest(".object").addClass("loading"); var data = form.serialize(); // get data before disabling inputs objectWrapper.addClass("loading").disableForms(); @@ -216,5 +216,10 @@ }); e.preventDefault(); }); + + + $('div.closet-hangers-group h3').click(function () { + $(this).next().toggle(); + }); })(); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 42438842..b49c75a3 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -627,7 +627,7 @@ body.closet_hangers-index #closet-hangers-contact { } /* line 38, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-contact a { - background-image: url('/images/neomail.png?1311362308'); + background-image: url('/images/neomail.png?1311369565'); background-position: left center; background-repeat: no-repeat; padding-left: 18px; @@ -703,17 +703,31 @@ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_ha body.closet_hangers-index #closet-hangers .object form { display: none; } -/* line 105, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 102, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index h3 { + border-bottom: 1px solid #aaddaa; + cursor: pointer; + font-size: 250%; + margin-bottom: 0.25em; + padding: 0.25em 0; +} +/* line 109, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-hangers-group { + border-top: 1px solid #006600; + margin-bottom: 2em; + padding-bottom: 1em; +} +/* line 117, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 108, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 120, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 113, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 125, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -754,7 +768,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 116, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 128, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -764,49 +778,49 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 56px; padding: 0; } -/* line 122, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 134, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 125, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 137, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 129, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 141, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 135, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 147, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 138, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 150, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 141, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 153, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 145, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 157, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 149, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 161, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 152, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 164, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact #edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 156, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 168, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 159, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 171, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing #edit-contact-link { display: none; } @@ -1812,7 +1826,7 @@ body.outfits-edit .object:hover ul, body.outfits-edit .object:hover .object-info } /* line 418, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .nc-icon { - background: url('/images/nc.png?1311362308') no-repeat; + background: url('/images/nc.png?1311369565') no-repeat; height: 16px; position: absolute; right: 16px; From 7476314953615488de6d1a522e6d288cae3647f7 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 22 Jul 2011 18:06:46 -0400 Subject: [PATCH 31/69] show/hide hints on Your Items headers --- app/stylesheets/closet_hangers/_index.sass | 36 ++++++++++- app/views/closet_hangers/index.html.haml | 5 +- public/javascripts/closet_hangers/index.js | 4 +- public/stylesheets/compiled/screen.css | 71 ++++++++++++++++------ 4 files changed, 92 insertions(+), 24 deletions(-) diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 5228a683..c60a9e18 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -99,12 +99,28 @@ body.closet_hangers-index form display: none - h3 + header border-bottom: 1px solid $soft-border-color - cursor: pointer - font-size: 250% + display: block margin-bottom: .25em padding: .25em 0 + position: relative + + h3 + font-size: 250% + margin: 0 + + span + color: $soft-text-color + display: none + font-size: 85% + position: absolute + right: 1em + bottom: 0 + + &:hover span + color: inherit + text-decoration: underline .closet-hangers-group border-top: 1px solid $module-border-color @@ -171,3 +187,17 @@ body.closet_hangers-index #edit-contact-link display: none + .closet-hangers-group + header + cursor: pointer + + .hide + display: block + + &.hidden + header .hide, .closet-hangers-group-content + display: none + + header .show + display: block + diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index b3415fd2..1bb23d5f 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -42,7 +42,10 @@ #closet-hangers{:class => public_perspective? ? nil : 'current-user'} - [true, false].each do |owned| .closet-hangers-group{'data-owned' => owned.to_s} - %h3 Items #{closet_hanger_subject} #{closet_hanger_verb(owned)} + %header + %h3 Items #{closet_hanger_subject} #{closet_hanger_verb(owned)} + %span.show click to show + %span.hide click to hide .closet-hangers-group-content - if public_perspective? - unless @closet_hangers_by_owned[owned] diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index f6d64b0e..c6d50b38 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -218,8 +218,8 @@ }); - $('div.closet-hangers-group h3').click(function () { - $(this).next().toggle(); + $('div.closet-hangers-group header').click(function () { + $(this).parent().toggleClass('hidden'); }); })(); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index b49c75a3..78eb5185 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -704,30 +704,49 @@ body.closet_hangers-index #closet-hangers .object form { display: none; } /* line 102, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index h3 { +body.closet_hangers-index header { border-bottom: 1px solid #aaddaa; - cursor: pointer; - font-size: 250%; + display: block; margin-bottom: 0.25em; padding: 0.25em 0; + position: relative; } /* line 109, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index header h3 { + font-size: 250%; + margin: 0; +} +/* line 113, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index header span { + color: #448844; + display: none; + font-size: 85%; + position: absolute; + right: 1em; + bottom: 0; +} +/* line 121, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index header:hover span { + color: inherit; + text-decoration: underline; +} +/* line 125, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group { border-top: 1px solid #006600; margin-bottom: 2em; padding-bottom: 1em; } -/* line 117, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 133, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 120, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 136, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 125, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 141, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -768,7 +787,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 128, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 144, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -778,52 +797,68 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 56px; padding: 0; } -/* line 134, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 150, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 137, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 153, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 141, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 157, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 147, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 163, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 150, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 166, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 153, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 169, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 157, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 173, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 161, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 177, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 164, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact #edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 168, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 184, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 171, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing #edit-contact-link { display: none; } +/* line 191, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js .closet-hangers-group header { + cursor: pointer; +} +/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { + display: block; +} +/* line 198, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { + display: none; +} +/* line 201, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { + display: block; +} /* line 3, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new #title, body.closet_pages-create #title { From 6203caf186819b5d433fda5c78c0d2c047bbe1fb Mon Sep 17 00:00:00 2001 From: Matchu Date: Mon, 25 Jul 2011 14:06:07 -0400 Subject: [PATCH 32/69] Your Items autocompleter can add to both owned and wanted --- app/stylesheets/closet_hangers/_index.sass | 11 +- app/views/closet_hangers/index.html.haml | 7 +- public/javascripts/closet_hangers/index.js | 141 +++++++++++++++------ public/stylesheets/compiled/screen.css | 48 +++---- 4 files changed, 137 insertions(+), 70 deletions(-) diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index c60a9e18..5a4ab6d1 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -20,7 +20,7 @@ body.closet_hangers-index #closet-hangers-items-search float: right - input[type=search] + input[name=q] &.loading background: image: url(/images/loading.gif) @@ -110,7 +110,7 @@ body.closet_hangers-index font-size: 250% margin: 0 - span + span.show, span.hide color: $soft-text-color display: none font-size: 85% @@ -118,9 +118,10 @@ body.closet_hangers-index right: 1em bottom: 0 - &:hover span - color: inherit - text-decoration: underline + &:hover + span.show, span.hide + color: inherit + text-decoration: underline .closet-hangers-group border-top: 1px solid $module-border-color diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 1bb23d5f..f229cc2e 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -4,7 +4,7 @@ - content_for :before_flashes do = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' = form_tag items_path, :method => :get, :id => 'closet-hangers-items-search', 'data-current-user-id' => current_user.id do - = search_field_tag :q, nil, :placeholder => "Find items to add" + = text_field_tag :q, nil, :placeholder => "Find items to add" = submit_tag 'Search', :name => nil - else - title "#{@user.name}'s Items" @@ -43,7 +43,10 @@ - [true, false].each do |owned| .closet-hangers-group{'data-owned' => owned.to_s} %header - %h3 Items #{closet_hanger_subject} #{closet_hanger_verb(owned)} + %h3 + Items + = closet_hanger_subject + %span.verb= closet_hanger_verb(owned) %span.show click to show %span.hide click to hide .closet-hangers-group-content diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index c6d50b38..fc7acd23 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -1,4 +1,28 @@ (function () { + /* + + Hanger groups + + */ + + var hangerGroups = []; + + $('div.closet-hangers-group').each(function () { + var el = $(this); + hangerGroups[hangerGroups.length] = { + label: el.find('span.verb').text(), + owned: (el.attr('data-owned') == 'true') + }; + }).find('header').click(function () { + $(this).parent().toggleClass('hidden'); + }); + + /* + + Hanger forms + + */ + var body = $(document.body).addClass("js"); if(!body.hasClass("current-user")) return false; @@ -124,53 +148,97 @@ }); }); + /* + + Search, autocomplete + + */ + $('input, textarea').placeholder(); var itemsSearchForm = $("#closet-hangers-items-search[data-current-user-id]"); - var itemsSearchField = itemsSearchForm.children("input[type=search]"); + var itemsSearchField = itemsSearchForm.children("input[name=q]"); itemsSearchField.autocomplete({ select: function (e, ui) { - var item = ui.item; - itemsSearchField.addClass("loading"); + if(ui.item.is_item) { + // Let the autocompleter finish up this search before starting a new one + setTimeout(function () { itemsSearchField.autocomplete("search", ui.item) }, 0); + } else { + var item = ui.item.item; + var group = ui.item.group; - $.ajax({ - url: "/user/" + itemsSearchForm.data("current-user-id") + "/items/" + item.id + "/closet_hanger", - type: "post", - data: {closet_hanger: {quantity: 1}, return_to: window.location.pathname + window.location.search}, - complete: function () { - itemsSearchField.removeClass("loading"); - }, - success: function (html) { - var doc = $(html); - hangersEl.html( doc.find('#closet-hangers').html() ); - quantityInputs().storeValue(); // since all the quantity inputs are new, gotta store initial value again - doc.find('.flash').hide().insertBefore(hangersEl).show(500).delay(5000).hide(250); - itemsSearchField.val(""); - }, - error: function (xhr) { - handleSaveError(xhr, "adding the item"); - } - }); + itemsSearchField.addClass("loading"); + + var closetHanger = { + quantity: 1, + owned: group.owned + }; + + $.ajax({ + url: "/user/" + itemsSearchForm.data("current-user-id") + "/items/" + item.id + "/closet_hanger", + type: "post", + data: {closet_hanger: closetHanger, return_to: window.location.pathname + window.location.search}, + complete: function () { + itemsSearchField.removeClass("loading"); + }, + success: function (html) { + var doc = $(html); + hangersEl.html( doc.find('#closet-hangers').html() ); + quantityInputs().storeValue(); // since all the quantity inputs are new, gotta store initial value again + doc.find('.flash').hide().insertBefore(hangersEl).show(500).delay(5000).hide(250); + itemsSearchField.val(""); + }, + error: function (xhr) { + handleSaveError(xhr, "adding the item"); + } + }); + } }, source: function (input, callback) { - $.getJSON("/items.json?q=" + input.term, function (data) { - var output = []; - var items = data.items; - for(var i in items) { - items[i].label = items[i].name; - output[output.length] = items[i]; + if(typeof input.term == 'string') { // user-typed query + $.getJSON("/items.json?q=" + input.term, function (data) { + var output = []; + var items = data.items; + for(var i in items) { + items[i].label = items[i].name; + items[i].is_item = true; + output[output.length] = items[i]; + } + callback(output); + }); + } else { // item was chosen, now choose a group to insert + var groupInserts = []; + for(var i in hangerGroups) { + groupInserts[groupInserts.length] = { + group: hangerGroups[i], + item: input.term, + label: input.term.label + } } - callback(output); - }) + callback(groupInserts); + } } - }).data( "autocomplete" )._renderItem = function( ul, item ) { - return $( "
    • " ) - .data( "item.autocomplete", item ) - .append( "
      Add " + item.label + "" ) - .appendTo( ul ); + }); + + var autocompleter = itemsSearchField.data("autocomplete"); + + autocompleter._renderItem = function( ul, item ) { + var li = $("
    • ").data("item.autocomplete", item); + if(item.is_item) { // these are items from the server + li.append("
      Add " + item.label + ""); + } else { // these are group inserts + li.append("I " + item.group.label + " the " + item.item.label + ""); + } + return li.appendTo(ul); } + /* + + Contact Neopets username form + + */ + var contactEl = $('#closet-hangers-contact'); var editContactLink = $('#edit-contact-link'); var contactForm = contactEl.children('form'); @@ -216,10 +284,5 @@ }); e.preventDefault(); }); - - - $('div.closet-hangers-group header').click(function () { - $(this).parent().toggleClass('hidden'); - }); })(); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 78eb5185..73b6ea0e 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -611,7 +611,7 @@ body.closet_hangers-index #closet-hangers-items-search { float: right; } /* line 24, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers-items-search input[type=search].loading { +body.closet_hangers-index #closet-hangers-items-search input[name=q].loading { background-image: url(/images/loading.gif); background-position: 2px center; background-repeat: no-repeat; @@ -717,7 +717,7 @@ body.closet_hangers-index header h3 { margin: 0; } /* line 113, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index header span { +body.closet_hangers-index header span.show, body.closet_hangers-index header span.hide { color: #448844; display: none; font-size: 85%; @@ -725,28 +725,28 @@ body.closet_hangers-index header span { right: 1em; bottom: 0; } -/* line 121, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index header:hover span { +/* line 122, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index header:hover span.show, body.closet_hangers-index header:hover span.hide { color: inherit; text-decoration: underline; } -/* line 125, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 126, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group { border-top: 1px solid #006600; margin-bottom: 2em; padding-bottom: 1em; } -/* line 133, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 134, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 136, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 137, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 141, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 142, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -787,7 +787,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 144, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 145, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -797,65 +797,65 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 56px; padding: 0; } -/* line 150, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 151, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 153, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 154, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 157, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 158, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 163, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 164, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 166, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 167, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 169, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 170, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 173, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 174, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 177, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 178, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 181, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact #edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 184, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 185, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 188, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing #edit-contact-link { display: none; } -/* line 191, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 192, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header { cursor: pointer; } -/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 195, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 198, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 199, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 201, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 202, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } From 2983849b1f691c726e63bcae46231f5529b7ae8f Mon Sep 17 00:00:00 2001 From: Matchu Date: Mon, 25 Jul 2011 14:15:23 -0400 Subject: [PATCH 33/69] closet page importer also warns to log in in another window --- app/helpers/closet_pages_helper.rb | 8 ++++++++ app/views/closet_pages/new.html.haml | 19 ++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/app/helpers/closet_pages_helper.rb b/app/helpers/closet_pages_helper.rb index dab106d2..1ed8454c 100644 --- a/app/helpers/closet_pages_helper.rb +++ b/app/helpers/closet_pages_helper.rb @@ -1,2 +1,10 @@ module ClosetPagesHelper + def link_to_neopets_login(content) + link_to content, neopets_login_url, :target => "_blank" + end + + def neopets_login_url + "http://www.neopets.com/loginpage.phtml" + end end + diff --git a/app/views/closet_pages/new.html.haml b/app/views/closet_pages/new.html.haml index ae504a69..fc2b9c35 100644 --- a/app/views/closet_pages/new.html.haml +++ b/app/views/closet_pages/new.html.haml @@ -20,13 +20,18 @@ 1. Check the framed Neopets.com window on the left, pointing to [page #{@closet_page.index} of your closet][cp]. - * **Log in if you haven't already.** If you're logged into - Neopets, but not in this frame, enable "third-party cookies" in your - browser. (Most have that on by default.) - * **Confirm that the page is, in fact, your closet.** Don't just trust a - website when they tell you to copy-paste the source code of another site. - Instead, check that the page is what it is supposed to be and does not - contain any information you didn't mean to give out. + * **Confirm that you're logged in.** If you're logged into + Neopets, but the above frame says that you're not, try enabling + "third-party cookies" in your browser. (Most have that on by default.) + * **If you haven't logged in, #{link_to_neopets_login "do so in another window"}.** + It's never a good idea to log in inside of a frame, unless you're a + web programmer pro who can check that the frame does, in fact, point + to Neopets.com. To be safe, + #{link_to_neopets_login "pull up another window, check the URL, and log in safely"}. + * **Confirm that the page is, in fact, your closet.** Similarly, don't + just trust a website when they tell you to copy-paste the source code + of another site. Instead, check that the page is what it is supposed to + be and does not contain any information you didn't mean to give out. 2. View the frame's source code. * **In Google Chrome,** right-click the frame and choose **View Frame Source**. From c3279f0512fbd29c970a592ff955aa63cd76e2a7 Mon Sep 17 00:00:00 2001 From: Matchu Date: Mon, 25 Jul 2011 14:22:26 -0400 Subject: [PATCH 34/69] keep track of the closet page we are importing, even if it errored out --- app/controllers/closet_pages_controller.rb | 2 +- app/views/closet_pages/new.html.haml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/closet_pages_controller.rb b/app/controllers/closet_pages_controller.rb index 9e1a1860..c0912883 100644 --- a/app/controllers/closet_pages_controller.rb +++ b/app/controllers/closet_pages_controller.rb @@ -7,8 +7,8 @@ class ClosetPagesController < ApplicationController def create if params[:closet_page] && params[:closet_page][:source] + @closet_page.index = params[:closet_page][:index] @closet_page.source = params[:closet_page][:source] - @index = @closet_page.index saved_counts = @closet_page.save_hangers! diff --git a/app/views/closet_pages/new.html.haml b/app/views/closet_pages/new.html.haml index fc2b9c35..d8975049 100644 --- a/app/views/closet_pages/new.html.haml +++ b/app/views/closet_pages/new.html.haml @@ -3,6 +3,7 @@ = link_to 'Back to Your Items', user_closet_hangers_path(current_user), :id => 'back-to-items' = form_for @closet_page, :html => {:id => 'closet-page-form'} do |f| + = f.hidden_field :index #closet-page-frame-wrapper %span %strong Page #{@closet_page.index} From c592459d02d2ff7bcf4f055ee79a626424c7658e Mon Sep 17 00:00:00 2001 From: Matchu Date: Tue, 26 Jul 2011 18:41:15 -0400 Subject: [PATCH 35/69] improve Your Items copy given the different groups --- app/helpers/closet_hangers_helper.rb | 4 +- app/models/closet_hanger.rb | 4 +- app/stylesheets/closet_hangers/_index.sass | 12 +-- app/views/closet_hangers/index.html.haml | 32 +++++--- public/javascripts/closet_hangers/index.js | 2 +- public/stylesheets/compiled/screen.css | 89 +++++++++++----------- 6 files changed, 79 insertions(+), 64 deletions(-) diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index 449853ae..3691ddf4 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -1,8 +1,8 @@ require 'cgi' module ClosetHangersHelper - def closet_hanger_verb(owned) - ClosetHanger.verb(closet_hanger_subject, owned) + def closet_hanger_verb(owned, positive=true) + ClosetHanger.verb(closet_hanger_subject, owned, positive) end def send_neomail_url(user) diff --git a/app/models/closet_hanger.rb b/app/models/closet_hanger.rb index fbf5731d..6d23f634 100644 --- a/app/models/closet_hanger.rb +++ b/app/models/closet_hanger.rb @@ -15,9 +15,9 @@ class ClosetHanger < ActiveRecord::Base self.class.verb(subject, owned?) end - def self.verb(subject, owned) + def self.verb(subject, owned, positive=true) base = (owned) ? 'own' : 'want' - base << 's' unless subject == :you + base << 's' if positive && subject != :you base end end diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 5a4ab6d1..37a3eb09 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -52,15 +52,17 @@ body.closet_hangers-index &:after content: ":" - #edit-contact-link, #cancel-contact-link - cursor: pointer + #edit-contact-link-to-replace-form, #cancel-contact-link display: none + + .edit-contact-link, #cancel-contact-link + cursor: pointer text-decoration: underline &:hover text-decoration: none - #edit-contact-link + #edit-contact-link-to-replace-form #contact-link-has-value display: none @@ -178,14 +180,14 @@ body.closet_hangers-index form display: none - #edit-contact-link, #cancel-contact-link + .edit-contact-link, #cancel-contact-link display: inline &.editing form display: block - #edit-contact-link + .edit-contact-link display: none .closet-hangers-group diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index f229cc2e..5bd84a10 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -15,7 +15,7 @@ - if @user.neopets_username? = link_to "Neomail #{@user.neopets_username}", send_neomail_url(@user) - else - %span#edit-contact-link{:class => @user.neopets_username? ? 'has-value' : nil} + %span#edit-contact-link-to-replace-form.edit-contact-link{:class => @user.neopets_username? ? 'has-value' : nil} %span#contact-link-no-value Add your Neopets username %span#contact-link-has-value @@ -37,7 +37,11 @@ %p You can share = link_to "this page", request.fullpath - with the world, and they'll be able to see what items you own. + with the world, and they'll be able to see what items you own and want. + It's also a good idea to + %span.edit-contact-link add your Neopets username + so that when other users see your items they will know how to contact you for + trades. #closet-hangers{:class => public_perspective? ? nil : 'current-user'} - [true, false].each do |owned| @@ -52,20 +56,26 @@ .closet-hangers-group-content - if public_perspective? - unless @closet_hangers_by_owned[owned] - %p #{@user.name} hasn't tracked any items on Dress to Impress. + %p #{@user.name} doesn't seem to #{closet_hanger_verb(owned, false)} anything. - else - unless @closet_hangers_by_owned[owned] %p - You haven't tracked any #{closet_hanger_verb(owned)} items on Dress - to Impress. It's worth doing, since you can share this list with your - friends and keep track of what items you still need as you create new - outfits. + You haven't tracked any items you #{closet_hanger_verb(owned)} on + Dress to Impress. As you browse the site and create outfits, we'll + use this list to tell you what items you #{closet_hanger_verb(owned)}, + and you can share this page with your friends, too. %p - It's easy to get started! - = link_to "Just import your Neopets closet in a few quick steps.", new_closet_page_path - You can also add an item from its + It's easy to get started! Use the search form at the top of the + page to find items to add, or add an item from its = link_to 'Infinite Closet', items_path - page. Have fun! + page. + - if owned + %p + You can even + = succeed ',' do + = link_to "import your Neopets closet in a few quick steps", new_closet_page_path + so why not? + %p Have fun! = render_closet_hangers(owned) - content_for :stylesheets do diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index fc7acd23..9ce9a744 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -240,7 +240,7 @@ */ var contactEl = $('#closet-hangers-contact'); - var editContactLink = $('#edit-contact-link'); + var editContactLink = $('.edit-contact-link'); var contactForm = contactEl.children('form'); var cancelContactLink = $('#cancel-contact-link'); var contactFormUsername = contactForm.children('input[type=text]'); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 73b6ea0e..6623574a 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -646,41 +646,44 @@ body.closet_hangers-index #closet-hangers-contact label:after { content: ":"; } /* line 55, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #edit-contact-link, body.closet_hangers-index #cancel-contact-link { - cursor: pointer; +body.closet_hangers-index #edit-contact-link-to-replace-form, body.closet_hangers-index #cancel-contact-link { display: none; +} +/* line 58, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .edit-contact-link, body.closet_hangers-index #cancel-contact-link { + cursor: pointer; text-decoration: underline; } -/* line 60, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #edit-contact-link:hover, body.closet_hangers-index #cancel-contact-link:hover { +/* line 62, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .edit-contact-link:hover, body.closet_hangers-index #cancel-contact-link:hover { text-decoration: none; } -/* line 64, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #edit-contact-link #contact-link-has-value { +/* line 66, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #edit-contact-link-to-replace-form #contact-link-has-value { display: none; } -/* line 67, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #edit-contact-link #contact-link-no-value { +/* line 69, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #edit-contact-link-to-replace-form #contact-link-no-value { display: inline; } -/* line 71, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #edit-contact-link.has-value #contact-link-has-value { +/* line 73, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #edit-contact-link-to-replace-form.has-value #contact-link-has-value { display: inline; } -/* line 74, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #edit-contact-link.has-value #contact-link-no-value { +/* line 76, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #edit-contact-link-to-replace-form.has-value #contact-link-no-value { display: none; } -/* line 77, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 79, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #cancel-contact-link { margin-left: 1em; } -/* line 80, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 82, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers { clear: both; text-align: center; } -/* line 85, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 87, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -694,16 +697,16 @@ body.closet_hangers-index #closet-hangers .object .quantity { text-align: left; top: 60px; } -/* line 95, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 97, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { font-size: 16px; font-weight: bold; } -/* line 99, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 101, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object form { display: none; } -/* line 102, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 104, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index header { border-bottom: 1px solid #aaddaa; display: block; @@ -711,12 +714,12 @@ body.closet_hangers-index header { padding: 0.25em 0; position: relative; } -/* line 109, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 111, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index header h3 { font-size: 250%; margin: 0; } -/* line 113, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 115, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index header span.show, body.closet_hangers-index header span.hide { color: #448844; display: none; @@ -725,28 +728,28 @@ body.closet_hangers-index header span.show, body.closet_hangers-index header spa right: 1em; bottom: 0; } -/* line 122, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 124, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index header:hover span.show, body.closet_hangers-index header:hover span.hide { color: inherit; text-decoration: underline; } -/* line 126, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 128, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group { border-top: 1px solid #006600; margin-bottom: 2em; padding-bottom: 1em; } -/* line 134, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 136, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 137, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 139, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 142, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 144, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -787,7 +790,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 145, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 147, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -797,65 +800,65 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 56px; padding: 0; } -/* line 151, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 153, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 154, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 156, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 158, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 160, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 164, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 166, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 167, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 169, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 170, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 172, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 174, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 176, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 178, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 181, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index.current-user.js #closet-hangers-contact #edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { +/* line 183, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 185, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 188, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index.current-user.js #closet-hangers-contact.editing #edit-contact-link { +/* line 190, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 192, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header { cursor: pointer; } -/* line 195, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 197, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 199, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 201, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 202, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 204, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } From 033e71e9bfcf5ca746bb7106d5652ac449b35878 Mon Sep 17 00:00:00 2001 From: Matchu Date: Tue, 26 Jul 2011 18:49:52 -0400 Subject: [PATCH 36/69] parameterize user params like items, plus a cleaner parameterization scheme --- app/models/item.rb | 11 ++--------- app/models/pretty_param.rb | 11 +++++++++++ app/models/user.rb | 2 ++ 3 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 app/models/pretty_param.rb diff --git a/app/models/item.rb b/app/models/item.rb index 09d36126..ff025ad4 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -1,6 +1,8 @@ # requires item sweeper at bottom class Item < ActiveRecord::Base + include PrettyParam + SwfAssetType = 'object' has_many :closet_hangers @@ -173,15 +175,6 @@ class Item < ActiveRecord::Base } end - URL_CHAR_BLACKLIST = /[^a-z0-9\-]/i - def name_for_url - name.downcase.gsub(' ', '-').gsub(URL_CHAR_BLACKLIST, '') - end - - def to_param - "#{id}-#{name_for_url}" - end - before_create do self.sold_in_mall ||= false true diff --git a/app/models/pretty_param.rb b/app/models/pretty_param.rb new file mode 100644 index 00000000..c24bd71a --- /dev/null +++ b/app/models/pretty_param.rb @@ -0,0 +1,11 @@ +module PrettyParam + BLACKLIST = /[^a-z0-9]/i + def name_for_param + name.split(BLACKLIST).select { |word| !word.blank? }.join('-') + end + + def to_param + "#{id}-#{name_for_param}" + end +end + diff --git a/app/models/user.rb b/app/models/user.rb index 20f027b4..b83b251c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,6 @@ class User < ActiveRecord::Base + include PrettyParam + DefaultAuthServerId = 1 PreviewTopContributorsCount = 3 From e6c419c7e057ddab2bd033b84af36c4087a0bc1b Mon Sep 17 00:00:00 2001 From: Matchu Date: Tue, 26 Jul 2011 18:56:14 -0400 Subject: [PATCH 37/69] give user paths a canonical tag --- app/helpers/application_helper.rb | 4 ++++ app/views/closet_hangers/index.html.haml | 2 ++ app/views/contributions/index.html.haml | 4 ++++ app/views/items/show.html.haml | 3 +-- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index dd5a1f82..b253f37f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -29,6 +29,10 @@ module ApplicationHelper content_tag(:div, html, :class => 'campaign-progress-wrapper') end + def canonical_path(resource) + content_for :meta, tag(:link, :rel => 'canonical', :href => url_for(resource)) + end + def flashes raw(flash.inject('') do |html, pair| key, value = pair diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 5bd84a10..92c26f57 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -9,6 +9,8 @@ - else - title "#{@user.name}'s Items" +- canonical_path user_closet_hangers_path(@user) + - content_for :before_flashes do #closet-hangers-contact - if public_perspective? diff --git a/app/views/contributions/index.html.haml b/app/views/contributions/index.html.haml index 95bd7de2..7de1fd3a 100644 --- a/app/views/contributions/index.html.haml +++ b/app/views/contributions/index.html.haml @@ -1,4 +1,7 @@ - title 'Recent Contributions' +- if @user + - canonical_path user_contributions_path(@user) + %ul.buttons - if @user %li= link_to 'Recent Contributions', contributions_path, :class => 'button' @@ -15,3 +18,4 @@ = will_paginate @contributions %ul.contributions= render @contributions = will_paginate @contributions + diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index 2cb6576c..28845458 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -1,6 +1,5 @@ - title @item.name -- content_for :meta do - %link{:rel => 'canonical', :href => url_for(@item)} +- canonical_path @item - cache "items_show_#{@item.id}_main_content" do %header#item-header From 605fb88046139b7dfaad92322694d41d3916e561 Mon Sep 17 00:00:00 2001 From: Matchu Date: Tue, 26 Jul 2011 18:57:44 -0400 Subject: [PATCH 38/69] move userbar contributions link to points, since user now has more public profiles --- app/views/layouts/application.html.haml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index b3e99087..4f89cbbd 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -42,10 +42,10 @@ = image_tag 'image_mode_icon.png', :alt => 'Image Mode' Welcome to Image Mode! %span - Hey, - = succeed '!' do - = link_to current_user.name, user_contributions_path(current_user) - == You have #{current_user.points} points. + Hey, #{current_user.name}! + You have + = succeed '.' do + = link_to "#{current_user.points} points", user_contributions_path(current_user) = link_to 'Items', user_closet_hangers_path(current_user) = link_to 'Outfits', current_user_outfits_path = link_to 'Settings', Openneo::Auth.remote_settings_url From b86ce67c0227bfc57d23a2a47add418f817d7198 Mon Sep 17 00:00:00 2001 From: Matchu Date: Tue, 26 Jul 2011 20:27:23 -0400 Subject: [PATCH 39/69] first pass at closet lists, including form --- app/controllers/application_controller.rb | 4 + app/controllers/closet_hangers_controller.rb | 4 - app/controllers/closet_lists_controller.rb | 19 +++ app/helpers/closet_lists_helper.rb | 9 ++ app/models/closet_hanger.rb | 9 +- app/models/closet_list.rb | 22 ++++ app/models/user.rb | 1 + app/stylesheets/_layout.sass | 5 +- app/stylesheets/closet_lists/_form.sass | 28 +++++ app/stylesheets/screen.sass | 1 + app/views/closet_lists/_form.html.haml | 17 +++ app/views/closet_lists/new.html.haml | 3 + config/routes.rb | 5 + .../20110726231143_create_closet_lists.rb | 21 ++++ db/schema.rb | 14 ++- public/stylesheets/compiled/screen.css | 113 ++++++++++++------ .../closet_lists_controller_spec.rb | 19 +++ spec/helpers/closet_lists_helper_spec.rb | 15 +++ spec/models/closet_list_spec.rb | 5 + .../closet_lists/create.html.erb_spec.rb | 5 + spec/views/closet_lists/new.html.erb_spec.rb | 5 + 21 files changed, 278 insertions(+), 46 deletions(-) create mode 100644 app/controllers/closet_lists_controller.rb create mode 100644 app/helpers/closet_lists_helper.rb create mode 100644 app/models/closet_list.rb create mode 100644 app/stylesheets/closet_lists/_form.sass create mode 100644 app/views/closet_lists/_form.html.haml create mode 100644 app/views/closet_lists/new.html.haml create mode 100644 db/migrate/20110726231143_create_closet_lists.rb create mode 100644 spec/controllers/closet_lists_controller_spec.rb create mode 100644 spec/helpers/closet_lists_helper_spec.rb create mode 100644 spec/models/closet_list_spec.rb create mode 100644 spec/views/closet_lists/create.html.erb_spec.rb create mode 100644 spec/views/closet_lists/new.html.erb_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 5f2d3a89..c52db242 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -7,6 +7,10 @@ class ApplicationController < ActionController::Base redirect_to(login_path) unless user_signed_in? end + def authorize_user! + raise AccessDenied unless user_signed_in? && current_user.id == params[:user_id].to_i + end + def can_use_image_mode? user_signed_in? && current_user.image_mode_tester? end diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 09f3cf59..2c3b079f 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -67,10 +67,6 @@ class ClosetHangersController < ApplicationController protected - def authorize_user! - raise AccessDenied unless user_signed_in? && current_user.id == params[:user_id].to_i - end - def find_item @item = Item.find params[:item_id] end diff --git a/app/controllers/closet_lists_controller.rb b/app/controllers/closet_lists_controller.rb new file mode 100644 index 00000000..7409d05d --- /dev/null +++ b/app/controllers/closet_lists_controller.rb @@ -0,0 +1,19 @@ +class ClosetListsController < ApplicationController + before_filter :authorize_user! + + def new + @closet_list = current_user.closet_lists.build + end + + def create + @closet_list = current_user.closet_lists.build params[:closet_list] + if @closet_list.save + flash[:success] = "Successfully saved \"#{@closet_list.name}\"" + redirect_to user_closet_hangers_path(current_user) + else + flash.now[:alert] = "We can't save this list because: #{@closet_list.errors.full_messages.to_sentence}" + render :action => :new + end + end +end + diff --git a/app/helpers/closet_lists_helper.rb b/app/helpers/closet_lists_helper.rb new file mode 100644 index 00000000..fbcfd38b --- /dev/null +++ b/app/helpers/closet_lists_helper.rb @@ -0,0 +1,9 @@ +module ClosetListsHelper + def hangers_owned_options + @hangers_owned_options ||= [true, false].map do |owned| + verb = ClosetHanger.verb(:i, owned) + ["items I #{verb}", owned] + end + end +end + diff --git a/app/models/closet_hanger.rb b/app/models/closet_hanger.rb index 6d23f634..c70ec426 100644 --- a/app/models/closet_hanger.rb +++ b/app/models/closet_hanger.rb @@ -1,5 +1,6 @@ class ClosetHanger < ActiveRecord::Base belongs_to :item + belongs_to :list, :class_name => 'ClosetList' belongs_to :user attr_accessible :owned, :quantity @@ -11,13 +12,19 @@ class ClosetHanger < ActiveRecord::Base scope :alphabetical_by_item_name, joins(:item).order(Item.arel_table[:name]) scope :owned_before_wanted, order(arel_table[:owned].desc) + before_validation :set_owned_by_list + + def set_owned_by_list + self.owned = list.hangers_owned if list? + end + def verb(subject=:someone) self.class.verb(subject, owned?) end def self.verb(subject, owned, positive=true) base = (owned) ? 'own' : 'want' - base << 's' if positive && subject != :you + base << 's' if positive && subject != :you && subject != :i base end end diff --git a/app/models/closet_list.rb b/app/models/closet_list.rb new file mode 100644 index 00000000..d0c14151 --- /dev/null +++ b/app/models/closet_list.rb @@ -0,0 +1,22 @@ +class ClosetList < ActiveRecord::Base + belongs_to :user + has_many :hangers, :class_name => 'ClosetHanger' + + attr_accessible :description, :hangers_owned, :name + + validates :name, :presence => true, :uniqueness => {:scope => :user_id} + validates :user, :presence => true + validates :hangers_owned, :inclusion => {:in => [true, false], :message => "can't be blank"} + + after_save :sync_hangers_owned! + + def sync_hangers_owned! + if hangers_owned_changed? + hangers.each do |hanger| + hanger.owned = hangers_owned + hanger.save! + end + end + end +end + diff --git a/app/models/user.rb b/app/models/user.rb index b83b251c..82adbfc4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -5,6 +5,7 @@ class User < ActiveRecord::Base PreviewTopContributorsCount = 3 has_many :closet_hangers + has_many :closet_lists has_many :closeted_items, :through => :closet_hangers, :source => :item has_many :contributions has_many :outfits diff --git a/app/stylesheets/_layout.sass b/app/stylesheets/_layout.sass index 81cb2731..c4477add 100644 --- a/app/stylesheets/_layout.sass +++ b/app/stylesheets/_layout.sass @@ -76,7 +76,7 @@ $container_width: 800px input, button, select, label cursor: pointer -input[type=text], input[type=password], input[type=search], input[type=number], select +input[type=text], input[type=password], input[type=search], input[type=number], select, textarea +border-radius(3px) background: #fff border: 1px solid $input-border-color @@ -85,6 +85,9 @@ input[type=text], input[type=password], input[type=search], input[type=number], &:focus, &:active color: inherit +textarea + font: inherit + a.button, input[type=submit], button +awesome-button &.loud diff --git a/app/stylesheets/closet_lists/_form.sass b/app/stylesheets/closet_lists/_form.sass new file mode 100644 index 00000000..1c1295bb --- /dev/null +++ b/app/stylesheets/closet_lists/_form.sass @@ -0,0 +1,28 @@ +body.closet_lists-new, body.closet_lists-create + + form ul.fields + list-style: none + + label + float: left + font-weight: bold + margin-right: 1em + + li + padding: 0.75em 0 + width: 25em + + input, textarea, select + clear: both + display: block + margin-top: .25em + width: 80% + + textarea + height: 12em + + .hint + display: block + font: + size: 85% + diff --git a/app/stylesheets/screen.sass b/app/stylesheets/screen.sass index a7ebbc88..df1111c4 100644 --- a/app/stylesheets/screen.sass +++ b/app/stylesheets/screen.sass @@ -7,6 +7,7 @@ @import partials/jquery.jgrowl @import closet_hangers/index +@import closet_lists/form @import closet_pages/new @import contributions/index @import items diff --git a/app/views/closet_lists/_form.html.haml b/app/views/closet_lists/_form.html.haml new file mode 100644 index 00000000..8c5e229f --- /dev/null +++ b/app/views/closet_lists/_form.html.haml @@ -0,0 +1,17 @@ += form_for [@closet_list.user, @closet_list] do |f| + %ul.fields + %li + = f.label :name + %span.hint Like "up for trade" or "NC wishlist" + = f.text_field :name, :required => true + %li + = f.label :hangers_owned, 'This is a list for…'.html_safe + = f.select :hangers_owned, hangers_owned_options + %li + = f.label :description + %span.hint + Why are these items in a list? What are your terms for trading? + Or you can leave this blank. + = f.text_area :description + = f.submit 'Save list' + diff --git a/app/views/closet_lists/new.html.haml b/app/views/closet_lists/new.html.haml new file mode 100644 index 00000000..af941cfe --- /dev/null +++ b/app/views/closet_lists/new.html.haml @@ -0,0 +1,3 @@ +- title 'Create an items list' += render 'form' + diff --git a/config/routes.rb b/config/routes.rb index e8c8d245..d5f9f611 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,8 @@ OpenneoImpressItems::Application.routes.draw do |map| + get "closet_lists/new" + + get "closet_lists/create" + root :to => 'outfits#new' devise_for :users @@ -38,6 +42,7 @@ OpenneoImpressItems::Application.routes.draw do |map| resources :users, :path => 'user', :only => [:update] do resources :contributions, :only => [:index] resources :closet_hangers, :only => [:index], :path => 'closet' + resources :closet_lists, :only => [:new, :create], :path => 'closet/lists' resources :items, :only => [] do resource :closet_hanger, :only => [:create, :update, :destroy] diff --git a/db/migrate/20110726231143_create_closet_lists.rb b/db/migrate/20110726231143_create_closet_lists.rb new file mode 100644 index 00000000..272cbb71 --- /dev/null +++ b/db/migrate/20110726231143_create_closet_lists.rb @@ -0,0 +1,21 @@ +class CreateClosetLists < ActiveRecord::Migration + def self.up + create_table :closet_lists do |t| + t.string :name + t.text :description + t.integer :user_id + t.boolean :hangers_owned, :null => false + + t.timestamps + end + + add_column :closet_hangers, :closet_list_id, :integer + end + + def self.down + drop_table :closet_lists + + remove_column :closet_hangers, :closet_list_id + end +end + diff --git a/db/schema.rb b/db/schema.rb index 05893ef1..2b6d18c2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20110722180616) do +ActiveRecord::Schema.define(:version => 20110726231143) do create_table "auth_servers", :force => true do |t| t.string "short_name", :limit => 10, :null => false @@ -26,7 +26,17 @@ ActiveRecord::Schema.define(:version => 20110722180616) do t.integer "quantity" t.datetime "created_at" t.datetime "updated_at" - t.boolean "owned", :default => true, :null => false + t.boolean "owned", :default => true, :null => false + t.integer "closet_list_id" + end + + create_table "closet_lists", :force => true do |t| + t.string "name" + t.text "description" + t.integer "user_id" + t.boolean "hangers_owned", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "contributions", :force => true do |t| diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 6623574a..43e89f3d 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -97,7 +97,7 @@ input, button, select, label { } /* line 79, ../../../app/stylesheets/_layout.sass */ -input[type=text], body.pets-bulk #bulk-pets-form textarea, input[type=password], input[type=search], input[type=number], select { +input[type=text], body.pets-bulk #bulk-pets-form textarea, input[type=password], input[type=search], input[type=number], select, textarea { -moz-border-radius: 3px; -webkit-border-radius: 3px; background: white; @@ -106,11 +106,16 @@ input[type=text], body.pets-bulk #bulk-pets-form textarea, input[type=password], padding: 0.25em; } /* line 85, ../../../app/stylesheets/_layout.sass */ -input[type=text]:focus, body.pets-bulk #bulk-pets-form textarea:focus, input[type=text]:active, body.pets-bulk #bulk-pets-form textarea:active, input[type=password]:focus, input[type=password]:active, input[type=search]:focus, input[type=search]:active, input[type=number]:focus, input[type=number]:active, select:focus, select:active { +input[type=text]:focus, body.pets-bulk #bulk-pets-form textarea:focus, input[type=text]:active, body.pets-bulk #bulk-pets-form textarea:active, input[type=password]:focus, input[type=password]:active, input[type=search]:focus, input[type=search]:active, input[type=number]:focus, input[type=number]:active, select:focus, select:active, textarea:focus, textarea:active { color: inherit; } /* line 88, ../../../app/stylesheets/_layout.sass */ +textarea { + font: inherit; +} + +/* line 91, ../../../app/stylesheets/_layout.sass */ a.button, input[type=submit], button { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -141,7 +146,7 @@ a.button:hover, input[type=submit]:hover, button:hover { a.button:active, input[type=submit]:active, button:active { top: 1px; } -/* line 90, ../../../app/stylesheets/_layout.sass */ +/* line 93, ../../../app/stylesheets/_layout.sass */ a.button.loud, input[type=submit].loud, button.loud { background: #ff5c00 url('/images/alert-overlay.png?1296599919') repeat-x; font-size: 125%; @@ -157,21 +162,21 @@ a.button:after { content: " >>"; } -/* line 96, ../../../app/stylesheets/_layout.sass */ +/* line 99, ../../../app/stylesheets/_layout.sass */ ul.buttons { margin-bottom: 1em; } -/* line 98, ../../../app/stylesheets/_layout.sass */ +/* line 101, ../../../app/stylesheets/_layout.sass */ ul.buttons li { list-style: none; margin: 0 0.5em; } -/* line 101, ../../../app/stylesheets/_layout.sass */ +/* line 104, ../../../app/stylesheets/_layout.sass */ ul.buttons li, ul.buttons li form { display: inline; } -/* line 104, ../../../app/stylesheets/_layout.sass */ +/* line 107, ../../../app/stylesheets/_layout.sass */ #footer { clear: both; font-size: 75%; @@ -179,65 +184,65 @@ ul.buttons li, ul.buttons li form { padding-top: 2em; text-align: center; } -/* line 110, ../../../app/stylesheets/_layout.sass */ +/* line 113, ../../../app/stylesheets/_layout.sass */ #footer ul, #footer div { display: inline; margin: 0 1em; } -/* line 113, ../../../app/stylesheets/_layout.sass */ +/* line 116, ../../../app/stylesheets/_layout.sass */ #footer li, #footer div ul { display: inline; margin: 0 0.5em; } -/* line 117, ../../../app/stylesheets/_layout.sass */ +/* line 120, ../../../app/stylesheets/_layout.sass */ .success, .alert, .warning { margin-bottom: 1em; padding: 0.25em 0.5em; text-align: center; } -/* line 122, ../../../app/stylesheets/_layout.sass */ +/* line 125, ../../../app/stylesheets/_layout.sass */ .success { background: #e6efc2; border: 1px solid #c6d880; color: #264409; } -/* line 125, ../../../app/stylesheets/_layout.sass */ +/* line 128, ../../../app/stylesheets/_layout.sass */ .alert { background: #fbe3e4; border: 1px solid #fbc2c4; color: #8a1f11; } -/* line 128, ../../../app/stylesheets/_layout.sass */ +/* line 131, ../../../app/stylesheets/_layout.sass */ .warning { background: #fff6bf; border: 1px solid #ffd324; color: #514721; } -/* line 131, ../../../app/stylesheets/_layout.sass */ +/* line 134, ../../../app/stylesheets/_layout.sass */ #userbar { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; position: absolute; right: 0; top: 0; } -/* line 136, ../../../app/stylesheets/_layout.sass */ +/* line 139, ../../../app/stylesheets/_layout.sass */ #userbar > * { display: inline; margin: 0 0.25em; } -/* line 140, ../../../app/stylesheets/_layout.sass */ +/* line 143, ../../../app/stylesheets/_layout.sass */ #userbar-image-mode { font-weight: bold; margin-right: 1em; text-decoration: none; } -/* line 144, ../../../app/stylesheets/_layout.sass */ +/* line 147, ../../../app/stylesheets/_layout.sass */ #userbar-image-mode img { bottom: -2px; height: 16px; @@ -245,25 +250,25 @@ ul.buttons li, ul.buttons li form { width: 16px; } -/* line 147, ../../../app/stylesheets/_layout.sass */ +/* line 150, ../../../app/stylesheets/_layout.sass */ #userbar-log-in { text-decoration: none; } -/* line 149, ../../../app/stylesheets/_layout.sass */ +/* line 152, ../../../app/stylesheets/_layout.sass */ #userbar-log-in img { margin-bottom: -4px; margin-right: 0.25em; } -/* line 153, ../../../app/stylesheets/_layout.sass */ +/* line 156, ../../../app/stylesheets/_layout.sass */ #userbar-log-in span { text-decoration: underline; } -/* line 155, ../../../app/stylesheets/_layout.sass */ +/* line 158, ../../../app/stylesheets/_layout.sass */ #userbar-log-in:hover span { text-decoration: none; } -/* line 158, ../../../app/stylesheets/_layout.sass */ +/* line 161, ../../../app/stylesheets/_layout.sass */ .object { display: -moz-inline-box; -moz-box-orient: vertical; @@ -278,32 +283,32 @@ ul.buttons li, ul.buttons li form { vertical-align: top; width: 100px; } -/* line 166, ../../../app/stylesheets/_layout.sass */ +/* line 169, ../../../app/stylesheets/_layout.sass */ .object a { text-decoration: none; } -/* line 168, ../../../app/stylesheets/_layout.sass */ +/* line 171, ../../../app/stylesheets/_layout.sass */ .object a img { -moz-opacity: 0.75; -webkit-opacity: 0.75; -o-opacity: 0.75; -khtml-opacity: 0.75; } -/* line 170, ../../../app/stylesheets/_layout.sass */ +/* line 173, ../../../app/stylesheets/_layout.sass */ .object img { display: block; height: 80px; margin: 0 auto; width: 80px; } -/* line 175, ../../../app/stylesheets/_layout.sass */ +/* line 178, ../../../app/stylesheets/_layout.sass */ .object:hover img, .object a:hover img { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 181, ../../../app/stylesheets/_layout.sass */ +/* line 184, ../../../app/stylesheets/_layout.sass */ .object .nc-icon, .object .closeted-icons { -moz-opacity: 1; -webkit-opacity: 1; @@ -314,7 +319,7 @@ ul.buttons li, ul.buttons li form { position: absolute; top: 64px; } -/* line 187, ../../../app/stylesheets/_layout.sass */ +/* line 190, ../../../app/stylesheets/_layout.sass */ .object .nc-icon:hover, .object .closeted-icons:hover { -moz-opacity: 0.5; -webkit-opacity: 0.5; @@ -322,32 +327,32 @@ ul.buttons li, ul.buttons li form { -khtml-opacity: 0.5; background: transparent; } -/* line 191, ../../../app/stylesheets/_layout.sass */ +/* line 194, ../../../app/stylesheets/_layout.sass */ .object .nc-icon, .object .closeted-icons img { display: inline; height: 16px; width: 16px; } -/* line 196, ../../../app/stylesheets/_layout.sass */ +/* line 199, ../../../app/stylesheets/_layout.sass */ .object .nc-icon { right: 18px; } -/* line 199, ../../../app/stylesheets/_layout.sass */ +/* line 202, ../../../app/stylesheets/_layout.sass */ .object .closeted-icons { left: 18px; } -/* line 202, ../../../app/stylesheets/_layout.sass */ +/* line 205, ../../../app/stylesheets/_layout.sass */ dt { font-weight: bold; } -/* line 205, ../../../app/stylesheets/_layout.sass */ +/* line 208, ../../../app/stylesheets/_layout.sass */ dd { margin: 0 0 1.5em 1em; } -/* line 208, ../../../app/stylesheets/_layout.sass */ +/* line 211, ../../../app/stylesheets/_layout.sass */ #home-link { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 175%; @@ -358,21 +363,21 @@ dd { position: absolute; top: 0; } -/* line 218, ../../../app/stylesheets/_layout.sass */ +/* line 221, ../../../app/stylesheets/_layout.sass */ #home-link:hover { background: #eeffee; text-decoration: none; } -/* line 221, ../../../app/stylesheets/_layout.sass */ +/* line 224, ../../../app/stylesheets/_layout.sass */ #home-link span:before { content: "<< "; } -/* line 225, ../../../app/stylesheets/_layout.sass */ +/* line 228, ../../../app/stylesheets/_layout.sass */ .pagination a, .pagination span { margin: 0 0.5em; } -/* line 227, ../../../app/stylesheets/_layout.sass */ +/* line 230, ../../../app/stylesheets/_layout.sass */ .pagination .current { font-weight: bold; } @@ -863,6 +868,38 @@ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .s display: block; } +/* line 3, ../../../app/stylesheets/closet_lists/_form.sass */ +body.closet_lists-new form ul.fields, body.closet_lists-create form ul.fields { + list-style: none; +} +/* line 6, ../../../app/stylesheets/closet_lists/_form.sass */ +body.closet_lists-new form ul.fields label, body.closet_lists-create form ul.fields label { + float: left; + font-weight: bold; + margin-right: 1em; +} +/* line 11, ../../../app/stylesheets/closet_lists/_form.sass */ +body.closet_lists-new form ul.fields li, body.closet_lists-create form ul.fields li { + padding: 0.75em 0; + width: 25em; +} +/* line 15, ../../../app/stylesheets/closet_lists/_form.sass */ +body.closet_lists-new form ul.fields input, body.closet_lists-new form ul.fields textarea, body.closet_lists-new form ul.fields select, body.closet_lists-create form ul.fields input, body.closet_lists-create form ul.fields textarea, body.closet_lists-create form ul.fields select { + clear: both; + display: block; + margin-top: 0.25em; + width: 80%; +} +/* line 21, ../../../app/stylesheets/closet_lists/_form.sass */ +body.closet_lists-new form ul.fields textarea, body.closet_lists-create form ul.fields textarea { + height: 12em; +} +/* line 24, ../../../app/stylesheets/closet_lists/_form.sass */ +body.closet_lists-new form ul.fields .hint, body.closet_lists-create form ul.fields .hint { + display: block; + font-size: 85%; +} + /* line 3, ../../../app/stylesheets/closet_pages/_new.sass */ body.closet_pages-new #title, body.closet_pages-create #title { float: left; diff --git a/spec/controllers/closet_lists_controller_spec.rb b/spec/controllers/closet_lists_controller_spec.rb new file mode 100644 index 00000000..075e1270 --- /dev/null +++ b/spec/controllers/closet_lists_controller_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +describe ClosetListsController do + + describe "GET 'new'" do + it "should be successful" do + get 'new' + response.should be_success + end + end + + describe "GET 'create'" do + it "should be successful" do + get 'create' + response.should be_success + end + end + +end diff --git a/spec/helpers/closet_lists_helper_spec.rb b/spec/helpers/closet_lists_helper_spec.rb new file mode 100644 index 00000000..2678a281 --- /dev/null +++ b/spec/helpers/closet_lists_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the ClosetListsHelper. For example: +# +# describe ClosetListsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe ClosetListsHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/closet_list_spec.rb b/spec/models/closet_list_spec.rb new file mode 100644 index 00000000..1e43990d --- /dev/null +++ b/spec/models/closet_list_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe ClosetList do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/views/closet_lists/create.html.erb_spec.rb b/spec/views/closet_lists/create.html.erb_spec.rb new file mode 100644 index 00000000..cdb8c9b1 --- /dev/null +++ b/spec/views/closet_lists/create.html.erb_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe "closet_lists/create.html.erb" do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/views/closet_lists/new.html.erb_spec.rb b/spec/views/closet_lists/new.html.erb_spec.rb new file mode 100644 index 00000000..98ce1cfd --- /dev/null +++ b/spec/views/closet_lists/new.html.erb_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe "closet_lists/new.html.erb" do + pending "add some examples to (or delete) #{__FILE__}" +end From 358840076cc2317e99d7b5f09dcc5de36ef4d110 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 29 Jul 2011 10:52:04 -0400 Subject: [PATCH 40/69] closet lists, round one --- Gemfile | 2 + Gemfile.lock | 5 +- app/controllers/closet_hangers_controller.rb | 11 +- app/controllers/closet_lists_controller.rb | 44 +- app/helpers/application_helper.rb | 5 + app/helpers/closet_hangers_helper.rb | 51 ++- app/helpers/closet_lists_helper.rb | 21 + app/models/closet_hanger.rb | 6 +- app/models/closet_list.rb | 5 +- app/stylesheets/_layout.sass | 3 - app/stylesheets/closet_hangers/_index.sass | 121 ++++-- app/stylesheets/closet_lists/_form.sass | 3 +- app/stylesheets/items/_show.sass | 5 +- app/stylesheets/partials/_secondary_nav.sass | 12 + .../closet_hangers/_closet_hanger.html.haml | 2 +- app/views/closet_hangers/index.html.haml | 37 +- app/views/closet_lists/_closet_list.html.haml | 16 + app/views/closet_lists/_form.html.haml | 11 + app/views/closet_lists/edit.html.haml | 3 + app/views/items/show.html.haml | 3 + config/routes.rb | 2 +- .../20110726231143_create_closet_lists.rb | 4 +- db/schema.rb | 4 +- public/javascripts/closet_hangers/index.js | 20 +- public/stylesheets/compiled/screen.css | 385 ++++++++++++------ vendor/cache/sanitize-2.0.3.gem | Bin 0 -> 14336 bytes 26 files changed, 581 insertions(+), 200 deletions(-) create mode 100644 app/stylesheets/partials/_secondary_nav.sass create mode 100644 app/views/closet_lists/_closet_list.html.haml create mode 100644 app/views/closet_lists/edit.html.haml create mode 100644 vendor/cache/sanitize-2.0.3.gem diff --git a/Gemfile b/Gemfile index ab837d3b..9c29670d 100644 --- a/Gemfile +++ b/Gemfile @@ -35,6 +35,8 @@ gem "character-encodings", "~> 0.4.1", :platforms => :ruby_18 gem "nokogiri", "~> 1.5.0" +gem 'sanitize', '~> 2.0.3' + group :development_async do # async wrappers gem 'eventmachine', :git => 'git://github.com/eventmachine/eventmachine.git' diff --git a/Gemfile.lock b/Gemfile.lock index 1554d6b9..487b8a40 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -165,9 +165,11 @@ GEM ruby-hmac (0.4.0) rufus-scheduler (2.0.9) tzinfo (>= 0.3.23) + sanitize (2.0.3) + nokogiri (< 1.6, >= 1.4.4) sinatra (1.2.6) rack (~> 1.1) - tilt (>= 1.2.2, < 2.0) + tilt (< 2.0, >= 1.2.2) swf_converter (0.0.3) thor (0.14.6) tilt (1.3.2) @@ -215,6 +217,7 @@ DEPENDENCIES resque-scheduler (~> 2.0.0.d) right_aws (~> 2.1.0) rspec-rails (~> 2.0.0.beta.22) + sanitize (~> 2.0.3) swf_converter (~> 0.0.3) whenever (~> 0.6.2) will_paginate (~> 3.0.pre2) diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 2c3b079f..3598d232 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -14,8 +14,11 @@ class ClosetHangersController < ApplicationController def index @user = User.find params[:user_id] - @closet_hangers_by_owned = @user.closet_hangers.owned_before_wanted. - alphabetical_by_item_name.includes(:item).group_by(&:owned) + @closet_lists_by_owned = @user.closet_lists.alphabetical. + includes(:hangers => :item).group_by(&:hangers_owned) + @unlisted_closet_hangers_by_owned = @user.closet_hangers.unlisted. + owned_before_wanted.alphabetical_by_item_name.includes(:item). + group_by(&:owned) @public_perspective = params.has_key?(:public) || !user_is?(@user) end @@ -37,7 +40,9 @@ class ClosetHangersController < ApplicationController if @closet_hanger.save respond_to do |format| format.html { - flash[:success] = "Success! You #{@closet_hanger.verb(:you)} #{@closet_hanger.quantity} #{@item.name.pluralize}." + message = "Success! You #{@closet_hanger.verb(:you)} #{@closet_hanger.quantity} #{@item.name.pluralize}" + message << " in the \"#{@closet_hanger.list.name}\" list" if @closet_hanger.list + flash[:success] = "#{message}." redirect_back!(@item) } diff --git a/app/controllers/closet_lists_controller.rb b/app/controllers/closet_lists_controller.rb index 7409d05d..55bb75ce 100644 --- a/app/controllers/closet_lists_controller.rb +++ b/app/controllers/closet_lists_controller.rb @@ -1,19 +1,49 @@ class ClosetListsController < ApplicationController before_filter :authorize_user! - - def new - @closet_list = current_user.closet_lists.build - end + before_filter :find_closet_list, :only => [:edit, :update, :destroy] def create @closet_list = current_user.closet_lists.build params[:closet_list] if @closet_list.save - flash[:success] = "Successfully saved \"#{@closet_list.name}\"" - redirect_to user_closet_hangers_path(current_user) + save_successful! else - flash.now[:alert] = "We can't save this list because: #{@closet_list.errors.full_messages.to_sentence}" + save_failed! render :action => :new end end + + def destroy + @closet_list.destroy + flash[:success] = "Successfully deleted \"#{@closet_list.name}\"" + redirect_to user_closet_hangers_path(current_user) + end + + def new + @closet_list = current_user.closet_lists.build params[:closet_list] + end + + def update + if @closet_list.update_attributes(params[:closet_list]) + save_successful! + else + save_failed! + render :action => :edit + end + end + + protected + + def find_closet_list + @closet_list = current_user.closet_lists.find params[:id] + end + + def save_failed! + flash.now[:alert] = "We can't save this list because: #{@closet_list.errors.full_messages.to_sentence}" + end + + def save_successful! + flash[:success] = "Successfully saved \"#{@closet_list.name}\"" + redirect_to user_closet_hangers_path(current_user) + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index b253f37f..516dab4a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -94,6 +94,11 @@ module ApplicationHelper hidden_field_tag :return_to, request.fullpath end + def secondary_nav(&block) + content_for :before_flashes, + content_tag(:nav, :id => 'secondary-nav', &block) + end + def show_title_header? params[:controller] != 'items' end diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index 3691ddf4..2e6a5296 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -13,14 +13,57 @@ module ClosetHangersHelper public_perspective? ? @user.name : :you end + # Do we have either unlisted hangers that are owned/wanted, or non-empty + # owned/wanted lists? + def has_hangers?(owned) + # If we have unlisted hangers of this type, pass. + return true if @unlisted_closet_hangers_by_owned.has_key?(owned) + + # Additionally, if we have no lists of this type, fail. + lists = @closet_lists_by_owned[owned] + return false unless lists + + # If any of those lists are non-empty, pass. + lists.each do |list| + return true unless list.hangers.empty? + end + + # Otherwise, all of the lists are empty. Fail. + return false + end + + def has_lists?(owned) + @closet_lists_by_owned.has_key?(owned) + end + + def link_to_add_closet_list(content, options) + owned = options.delete(:owned) + path = new_user_closet_list_path current_user, + :closet_list => {:hangers_owned => owned} + link_to(content, path, options) + end + def public_perspective? @public_perspective end - def render_closet_hangers(owned) - render :partial => 'closet_hanger', - :collection => @closet_hangers_by_owned[owned], - :locals => {:show_controls => !public_perspective?} + def render_closet_lists(lists) + if lists + render :partial => 'closet_lists/closet_list', :collection => lists, + :locals => {:show_controls => !public_perspective?} + end + end + + def render_unlisted_closet_hangers(owned) + if @unlisted_closet_hangers_by_owned[owned] + content = render :partial => 'closet_hanger', + :collection => @unlisted_closet_hangers_by_owned[owned], + :locals => {:show_controls => !public_perspective?} + if has_lists?(owned) + content = content_tag(:header, content_tag(:h4, '(Not in a list)')) + content + end + content_tag(:div, content, :class => 'closet-list unlisted') + end end end diff --git a/app/helpers/closet_lists_helper.rb b/app/helpers/closet_lists_helper.rb index fbcfd38b..fff481e3 100644 --- a/app/helpers/closet_lists_helper.rb +++ b/app/helpers/closet_lists_helper.rb @@ -1,9 +1,30 @@ module ClosetListsHelper + def closet_list_delete_confirmation(closet_list) + "Are you sure you want to delete \"#{closet_list.name}\"?".tap do |msg| + unless closet_list.hangers.empty? + msg << " Even if you do, we'll remember that you " + + ClosetHanger.verb(closet_list.hangers_owned, :you) + + " these items." + end + end + end + + def closet_list_description_format(list) + md = RDiscount.new(list.description) + Sanitize.clean(md.to_html, Sanitize::Config::BASIC).html_safe + end + def hangers_owned_options @hangers_owned_options ||= [true, false].map do |owned| verb = ClosetHanger.verb(:i, owned) ["items I #{verb}", owned] end end + + def render_sorted_hangers(list, show_controls) + render :partial => 'closet_hanger', + :collection => list.hangers.sort { |x,y| x.item.name <=> y.item.name }, + :locals => {:show_controls => show_controls} + end end diff --git a/app/models/closet_hanger.rb b/app/models/closet_hanger.rb index c70ec426..dfef7c7f 100644 --- a/app/models/closet_hanger.rb +++ b/app/models/closet_hanger.rb @@ -3,7 +3,7 @@ class ClosetHanger < ActiveRecord::Base belongs_to :list, :class_name => 'ClosetList' belongs_to :user - attr_accessible :owned, :quantity + attr_accessible :list_id, :owned, :quantity validates :item_id, :uniqueness => {:scope => [:user_id, :owned]} validates :quantity, :numericality => {:greater_than => 0} @@ -11,11 +11,13 @@ class ClosetHanger < ActiveRecord::Base scope :alphabetical_by_item_name, joins(:item).order(Item.arel_table[:name]) scope :owned_before_wanted, order(arel_table[:owned].desc) + scope :unlisted, where(:list_id => nil) before_validation :set_owned_by_list def set_owned_by_list - self.owned = list.hangers_owned if list? + self.owned = list.hangers_owned if list_id? + true end def verb(subject=:someone) diff --git a/app/models/closet_list.rb b/app/models/closet_list.rb index d0c14151..d74fd956 100644 --- a/app/models/closet_list.rb +++ b/app/models/closet_list.rb @@ -1,6 +1,7 @@ class ClosetList < ActiveRecord::Base belongs_to :user - has_many :hangers, :class_name => 'ClosetHanger' + has_many :hangers, :class_name => 'ClosetHanger', :foreign_key => 'list_id', + :dependent => :nullify attr_accessible :description, :hangers_owned, :name @@ -8,6 +9,8 @@ class ClosetList < ActiveRecord::Base validates :user, :presence => true validates :hangers_owned, :inclusion => {:in => [true, false], :message => "can't be blank"} + scope :alphabetical, order(:name) + after_save :sync_hangers_owned! def sync_hangers_owned! diff --git a/app/stylesheets/_layout.sass b/app/stylesheets/_layout.sass index c4477add..bed2cd43 100644 --- a/app/stylesheets/_layout.sass +++ b/app/stylesheets/_layout.sass @@ -93,9 +93,6 @@ a.button, input[type=submit], button &.loud +loud-awesome-button -a.button - +arrowed-awesome-button - ul.buttons margin-bottom: 1em li diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 37a3eb09..57b3c14e 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -1,21 +1,16 @@ @import "partials/context_button" @import "partials/icon" +@import "partials/secondary_nav" body.closet_hangers-index + +secondary-nav + #title - float: left margin-bottom: 0 - .flash - clear: both - - #import-link, #closet-hangers-items-search - margin-top: .75em - #import-link +awesome-button +loud-awesome-button-color - margin-left: 2em #closet-hangers-items-search float: right @@ -101,35 +96,87 @@ body.closet_hangers-index form display: none - header - border-bottom: 1px solid $soft-border-color - display: block - margin-bottom: .25em - padding: .25em 0 - position: relative - - h3 - font-size: 250% - margin: 0 - - span.show, span.hide - color: $soft-text-color - display: none - font-size: 85% - position: absolute - right: 1em - bottom: 0 - - &:hover - span.show, span.hide - color: inherit - text-decoration: underline + .quantity-1 + display: none .closet-hangers-group border-top: 1px solid $module-border-color margin-bottom: 2em padding-bottom: 1em + > header + border-bottom: 1px solid $soft-border-color + display: block + margin-bottom: .25em + padding: .25em 0 + position: relative + + h3 + font-size: 250% + margin: 0 + + .add-closet-list + +awesome-button + bottom: 50% + margin-bottom: -1em + position: absolute + right: 1em + + &:active + margin-bottom: -1.1em + top: auto + + span.show, span.hide + color: $soft-text-color + display: none + font-size: 85% + left: 1em + position: absolute + top: 1em + + &:hover + color: inherit + text-decoration: underline + + .closet-list + border-bottom: 1px solid $soft-border-color + padding: .5em 0 + + header + display: block + position: relative + + h4 + +header-text + font-size: 150% + margin: 0 auto + + .empty-list + font-style: italic + + .closet-list-controls + display: none + position: absolute + right: 1em + top: 0 + + a, input[type=submit] + +context-button + + form + display: inline + + &.unlisted + h4 + font-style: italic + + &:hover + .closet-list-controls + display: block + + &:last-child + border-bottom: 0 + &.current-user #closet-hangers .object:hover @@ -163,6 +210,8 @@ body.closet_hangers-index &.js #closet-hangers .object:hover .quantity + display: block + input[type=number] width: 2.5em @@ -173,8 +222,11 @@ body.closet_hangers-index background: $module-bg-color outline: 1px solid $module-border-color - .quantity span:after - content: "…" + .quantity + display: block + + span:after + content: "…" #closet-hangers-contact form @@ -192,7 +244,8 @@ body.closet_hangers-index .closet-hangers-group header - cursor: pointer + .show, .hide + cursor: pointer .hide display: block diff --git a/app/stylesheets/closet_lists/_form.sass b/app/stylesheets/closet_lists/_form.sass index 1c1295bb..4d85c2ec 100644 --- a/app/stylesheets/closet_lists/_form.sass +++ b/app/stylesheets/closet_lists/_form.sass @@ -1,4 +1,5 @@ -body.closet_lists-new, body.closet_lists-create +body.closet_lists-new, body.closet_lists-create, body.closet_lists-edit, body.closet_lists-update + +secondary-nav form ul.fields list-style: none diff --git a/app/stylesheets/items/_show.sass b/app/stylesheets/items/_show.sass index 9f98674a..98df4601 100644 --- a/app/stylesheets/items/_show.sass +++ b/app/stylesheets/items/_show.sass @@ -68,7 +68,7 @@ body.items-show float: right font-size: 85% padding: 1em - width: 18em + width: 21em label, header display: block @@ -80,6 +80,9 @@ body.items-show form padding: .5em 0 + select + width: 9em + input[type=number] width: 4em diff --git a/app/stylesheets/partials/_secondary_nav.sass b/app/stylesheets/partials/_secondary_nav.sass new file mode 100644 index 00000000..f4f501e1 --- /dev/null +++ b/app/stylesheets/partials/_secondary_nav.sass @@ -0,0 +1,12 @@ +=secondary-nav + #title + float: left + margin-right: .5em + + .flash + clear: both + + #secondary-nav + display: block + margin-top: .75em + diff --git a/app/views/closet_hangers/_closet_hanger.html.haml b/app/views/closet_hangers/_closet_hanger.html.haml index ad7dd007..44a20148 100644 --- a/app/views/closet_hangers/_closet_hanger.html.haml +++ b/app/views/closet_hangers/_closet_hanger.html.haml @@ -1,7 +1,7 @@ - show_controls ||= false # we could do user check here, but may as well do it once .object = render :partial => 'items/item_link', :locals => {:item => closet_hanger.item} - .quantity + .quantity{:class => "quantity-#{closet_hanger.quantity}"} %span= closet_hanger.quantity - if show_controls = form_for closet_hanger, :url => user_item_closet_hanger_path(current_user, closet_hanger.item), :html => {:class => 'closet-hanger-update'} do |f| diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 92c26f57..6e921a1d 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -1,7 +1,7 @@ - unless public_perspective? - title 'Your Items' - add_body_class 'current-user' - - content_for :before_flashes do + - secondary_nav do = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' = form_tag items_path, :method => :get, :id => 'closet-hangers-items-search', 'data-current-user-id' => current_user.id do = text_field_tag :q, nil, :placeholder => "Find items to add" @@ -31,19 +31,18 @@ = f.submit "Save" %span#cancel-contact-link cancel -- unless @closet_hangers_by_owned.empty? - %p - These are the items you are tracking on Dress to Impress. Hover over an - item to remove it from the list or to change the quantity. +%p + These are the items you are tracking on Dress to Impress. Hover over an + item to remove it from the list or to change the quantity. - %p - You can share - = link_to "this page", request.fullpath - with the world, and they'll be able to see what items you own and want. - It's also a good idea to - %span.edit-contact-link add your Neopets username - so that when other users see your items they will know how to contact you for - trades. +%p + You can share + = link_to "this page", request.fullpath + with the world, and they'll be able to see what items you own and want. + It's also a good idea to + %span.edit-contact-link add your Neopets username + so that when other users see your items they will know how to contact you for + trades. #closet-hangers{:class => public_perspective? ? nil : 'current-user'} - [true, false].each do |owned| @@ -53,14 +52,17 @@ Items = closet_hanger_subject %span.verb= closet_hanger_verb(owned) - %span.show click to show - %span.hide click to hide + %span.toggle.show show + %span.toggle.hide hide + = link_to_add_closet_list 'Add new list', :owned => owned, :class => 'add-closet-list' .closet-hangers-group-content + = render_closet_lists(@closet_lists_by_owned[owned]) + = render_unlisted_closet_hangers(owned) - if public_perspective? - - unless @closet_hangers_by_owned[owned] + - unless has_hangers?(owned) %p #{@user.name} doesn't seem to #{closet_hanger_verb(owned, false)} anything. - else - - unless @closet_hangers_by_owned[owned] + - unless has_hangers?(owned) %p You haven't tracked any items you #{closet_hanger_verb(owned)} on Dress to Impress. As you browse the site and create outfits, we'll @@ -78,7 +80,6 @@ = link_to "import your Neopets closet in a few quick steps", new_closet_page_path so why not? %p Have fun! - = render_closet_hangers(owned) - content_for :stylesheets do = stylesheet_link_tag 'south-street/jquery-ui' diff --git a/app/views/closet_lists/_closet_list.html.haml b/app/views/closet_lists/_closet_list.html.haml new file mode 100644 index 00000000..56a6cc19 --- /dev/null +++ b/app/views/closet_lists/_closet_list.html.haml @@ -0,0 +1,16 @@ +.closet-list + %header + - if show_controls + .closet-list-controls + = link_to 'Edit', edit_user_closet_list_path(closet_list.user, closet_list) + = form_tag user_closet_list_path(closet_list.user, closet_list), :method => 'delete' do + = submit_tag 'Delete', :confirm => closet_list_delete_confirmation(closet_list) + %h4= closet_list.name + + - if closet_list.description? + = closet_list_description_format closet_list + - unless closet_list.hangers.empty? + = render_sorted_hangers(closet_list, show_controls) + - else + %span.empty-list This list is empty. + diff --git a/app/views/closet_lists/_form.html.haml b/app/views/closet_lists/_form.html.haml index 8c5e229f..d4d43c03 100644 --- a/app/views/closet_lists/_form.html.haml +++ b/app/views/closet_lists/_form.html.haml @@ -1,3 +1,6 @@ +- secondary_nav do + = link_to 'Back to Your Items', user_closet_hangers_path(current_user), :class => 'button' + = form_for [@closet_list.user, @closet_list] do |f| %ul.fields %li @@ -13,5 +16,13 @@ Why are these items in a list? What are your terms for trading? Or you can leave this blank. = f.text_area :description + %span.hint + We + = surround '_' do + %em support + = surround '**' do + %strong Markdown + and + some HTML. = f.submit 'Save list' diff --git a/app/views/closet_lists/edit.html.haml b/app/views/closet_lists/edit.html.haml new file mode 100644 index 00000000..d5ed6893 --- /dev/null +++ b/app/views/closet_lists/edit.html.haml @@ -0,0 +1,3 @@ +- title "Editing list \"#{@closet_list.name}\"" += render 'form' + diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index 28845458..15219b1a 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -26,6 +26,9 @@ = f.hidden_field :owned = f.label :quantity, "How many of these do you #{hanger.verb(:you)}?" = f.number_field :quantity, :min => 0, :required => true + - lists = current_user.closet_lists.where(:hangers_owned => hanger.owned).all + - unless lists.empty? + = f.collection_select :list_id, lists, :id, :name, :include_blank => 'Not in a list' = f.submit "Save" %p= @item.description diff --git a/config/routes.rb b/config/routes.rb index d5f9f611..49cf66c8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -42,7 +42,7 @@ OpenneoImpressItems::Application.routes.draw do |map| resources :users, :path => 'user', :only => [:update] do resources :contributions, :only => [:index] resources :closet_hangers, :only => [:index], :path => 'closet' - resources :closet_lists, :only => [:new, :create], :path => 'closet/lists' + resources :closet_lists, :only => [:new, :create, :edit, :update, :destroy], :path => 'closet/lists' resources :items, :only => [] do resource :closet_hanger, :only => [:create, :update, :destroy] diff --git a/db/migrate/20110726231143_create_closet_lists.rb b/db/migrate/20110726231143_create_closet_lists.rb index 272cbb71..85ec7f33 100644 --- a/db/migrate/20110726231143_create_closet_lists.rb +++ b/db/migrate/20110726231143_create_closet_lists.rb @@ -9,13 +9,13 @@ class CreateClosetLists < ActiveRecord::Migration t.timestamps end - add_column :closet_hangers, :closet_list_id, :integer + add_column :closet_hangers, :list_id, :integer end def self.down drop_table :closet_lists - remove_column :closet_hangers, :closet_list_id + remove_column :closet_hangers, :list_id end end diff --git a/db/schema.rb b/db/schema.rb index 2b6d18c2..c8547726 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -26,8 +26,8 @@ ActiveRecord::Schema.define(:version => 20110726231143) do t.integer "quantity" t.datetime "created_at" t.datetime "updated_at" - t.boolean "owned", :default => true, :null => false - t.integer "closet_list_id" + t.boolean "owned", :default => true, :null => false + t.integer "list_id" end create_table "closet_lists", :force => true do |t| diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index 9ce9a744..f2636a2c 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -13,8 +13,10 @@ label: el.find('span.verb').text(), owned: (el.attr('data-owned') == 'true') }; - }).find('header').click(function () { - $(this).parent().toggleClass('hidden'); + }); + + $('div.closet-hangers-group span.toggle').live('click', function () { + $(this).closest('.closet-hangers-group').toggleClass('hidden'); }); /* @@ -78,7 +80,9 @@ var input = form.children("input[type=number]"); if(input.hasChanged()) { var objectWrapper = form.closest(".object").addClass("loading"); - var span = objectWrapper.find("span").text(input.val()); + var newQuantity = input.val(); + var span = objectWrapper.find("span").text(newQuantity); + span.parent().attr('class', 'quantity quantity-' + newQuantity); var data = form.serialize(); // get data before disabling inputs objectWrapper.disableForms(); form.data('loading', true); @@ -284,5 +288,15 @@ }); e.preventDefault(); }); + + /* + + Hanger list controls + + */ + + $('input[type=submit][data-confirm]').live('click', function (e) { + if(!confirm(this.getAttribute('data-confirm'))) e.preventDefault(); + }); })(); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 43e89f3d..6929cf3a 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -157,26 +157,21 @@ a.button.loud:hover, input[type=submit].loud:hover, button.loud:hover { background-color: #ee4b00; } -/* line 87, ../../../app/stylesheets/partials/clean/_mixins.sass */ -a.button:after { - content: " >>"; -} - -/* line 99, ../../../app/stylesheets/_layout.sass */ +/* line 96, ../../../app/stylesheets/_layout.sass */ ul.buttons { margin-bottom: 1em; } -/* line 101, ../../../app/stylesheets/_layout.sass */ +/* line 98, ../../../app/stylesheets/_layout.sass */ ul.buttons li { list-style: none; margin: 0 0.5em; } -/* line 104, ../../../app/stylesheets/_layout.sass */ +/* line 101, ../../../app/stylesheets/_layout.sass */ ul.buttons li, ul.buttons li form { display: inline; } -/* line 107, ../../../app/stylesheets/_layout.sass */ +/* line 104, ../../../app/stylesheets/_layout.sass */ #footer { clear: both; font-size: 75%; @@ -184,65 +179,65 @@ ul.buttons li, ul.buttons li form { padding-top: 2em; text-align: center; } -/* line 113, ../../../app/stylesheets/_layout.sass */ +/* line 110, ../../../app/stylesheets/_layout.sass */ #footer ul, #footer div { display: inline; margin: 0 1em; } -/* line 116, ../../../app/stylesheets/_layout.sass */ +/* line 113, ../../../app/stylesheets/_layout.sass */ #footer li, #footer div ul { display: inline; margin: 0 0.5em; } -/* line 120, ../../../app/stylesheets/_layout.sass */ +/* line 117, ../../../app/stylesheets/_layout.sass */ .success, .alert, .warning { margin-bottom: 1em; padding: 0.25em 0.5em; text-align: center; } -/* line 125, ../../../app/stylesheets/_layout.sass */ +/* line 122, ../../../app/stylesheets/_layout.sass */ .success { background: #e6efc2; border: 1px solid #c6d880; color: #264409; } -/* line 128, ../../../app/stylesheets/_layout.sass */ +/* line 125, ../../../app/stylesheets/_layout.sass */ .alert { background: #fbe3e4; border: 1px solid #fbc2c4; color: #8a1f11; } -/* line 131, ../../../app/stylesheets/_layout.sass */ +/* line 128, ../../../app/stylesheets/_layout.sass */ .warning { background: #fff6bf; border: 1px solid #ffd324; color: #514721; } -/* line 134, ../../../app/stylesheets/_layout.sass */ +/* line 131, ../../../app/stylesheets/_layout.sass */ #userbar { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; position: absolute; right: 0; top: 0; } -/* line 139, ../../../app/stylesheets/_layout.sass */ +/* line 136, ../../../app/stylesheets/_layout.sass */ #userbar > * { display: inline; margin: 0 0.25em; } -/* line 143, ../../../app/stylesheets/_layout.sass */ +/* line 140, ../../../app/stylesheets/_layout.sass */ #userbar-image-mode { font-weight: bold; margin-right: 1em; text-decoration: none; } -/* line 147, ../../../app/stylesheets/_layout.sass */ +/* line 144, ../../../app/stylesheets/_layout.sass */ #userbar-image-mode img { bottom: -2px; height: 16px; @@ -250,25 +245,25 @@ ul.buttons li, ul.buttons li form { width: 16px; } -/* line 150, ../../../app/stylesheets/_layout.sass */ +/* line 147, ../../../app/stylesheets/_layout.sass */ #userbar-log-in { text-decoration: none; } -/* line 152, ../../../app/stylesheets/_layout.sass */ +/* line 149, ../../../app/stylesheets/_layout.sass */ #userbar-log-in img { margin-bottom: -4px; margin-right: 0.25em; } -/* line 156, ../../../app/stylesheets/_layout.sass */ +/* line 153, ../../../app/stylesheets/_layout.sass */ #userbar-log-in span { text-decoration: underline; } -/* line 158, ../../../app/stylesheets/_layout.sass */ +/* line 155, ../../../app/stylesheets/_layout.sass */ #userbar-log-in:hover span { text-decoration: none; } -/* line 161, ../../../app/stylesheets/_layout.sass */ +/* line 158, ../../../app/stylesheets/_layout.sass */ .object { display: -moz-inline-box; -moz-box-orient: vertical; @@ -283,32 +278,32 @@ ul.buttons li, ul.buttons li form { vertical-align: top; width: 100px; } -/* line 169, ../../../app/stylesheets/_layout.sass */ +/* line 166, ../../../app/stylesheets/_layout.sass */ .object a { text-decoration: none; } -/* line 171, ../../../app/stylesheets/_layout.sass */ +/* line 168, ../../../app/stylesheets/_layout.sass */ .object a img { -moz-opacity: 0.75; -webkit-opacity: 0.75; -o-opacity: 0.75; -khtml-opacity: 0.75; } -/* line 173, ../../../app/stylesheets/_layout.sass */ +/* line 170, ../../../app/stylesheets/_layout.sass */ .object img { display: block; height: 80px; margin: 0 auto; width: 80px; } -/* line 178, ../../../app/stylesheets/_layout.sass */ +/* line 175, ../../../app/stylesheets/_layout.sass */ .object:hover img, .object a:hover img { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 184, ../../../app/stylesheets/_layout.sass */ +/* line 181, ../../../app/stylesheets/_layout.sass */ .object .nc-icon, .object .closeted-icons { -moz-opacity: 1; -webkit-opacity: 1; @@ -319,7 +314,7 @@ ul.buttons li, ul.buttons li form { position: absolute; top: 64px; } -/* line 190, ../../../app/stylesheets/_layout.sass */ +/* line 187, ../../../app/stylesheets/_layout.sass */ .object .nc-icon:hover, .object .closeted-icons:hover { -moz-opacity: 0.5; -webkit-opacity: 0.5; @@ -327,32 +322,32 @@ ul.buttons li, ul.buttons li form { -khtml-opacity: 0.5; background: transparent; } -/* line 194, ../../../app/stylesheets/_layout.sass */ +/* line 191, ../../../app/stylesheets/_layout.sass */ .object .nc-icon, .object .closeted-icons img { display: inline; height: 16px; width: 16px; } -/* line 199, ../../../app/stylesheets/_layout.sass */ +/* line 196, ../../../app/stylesheets/_layout.sass */ .object .nc-icon { right: 18px; } -/* line 202, ../../../app/stylesheets/_layout.sass */ +/* line 199, ../../../app/stylesheets/_layout.sass */ .object .closeted-icons { left: 18px; } -/* line 205, ../../../app/stylesheets/_layout.sass */ +/* line 202, ../../../app/stylesheets/_layout.sass */ dt { font-weight: bold; } -/* line 208, ../../../app/stylesheets/_layout.sass */ +/* line 205, ../../../app/stylesheets/_layout.sass */ dd { margin: 0 0 1.5em 1em; } -/* line 211, ../../../app/stylesheets/_layout.sass */ +/* line 208, ../../../app/stylesheets/_layout.sass */ #home-link { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 175%; @@ -363,21 +358,21 @@ dd { position: absolute; top: 0; } -/* line 221, ../../../app/stylesheets/_layout.sass */ +/* line 218, ../../../app/stylesheets/_layout.sass */ #home-link:hover { background: #eeffee; text-decoration: none; } -/* line 224, ../../../app/stylesheets/_layout.sass */ +/* line 221, ../../../app/stylesheets/_layout.sass */ #home-link span:before { content: "<< "; } -/* line 228, ../../../app/stylesheets/_layout.sass */ +/* line 225, ../../../app/stylesheets/_layout.sass */ .pagination a, .pagination span { margin: 0 0.5em; } -/* line 230, ../../../app/stylesheets/_layout.sass */ +/* line 227, ../../../app/stylesheets/_layout.sass */ .pagination .current { font-weight: bold; } @@ -561,20 +556,25 @@ div.jGrowl div.jGrowl-closer { } } -/* line 5, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 2, ../../../app/stylesheets/partials/_secondary_nav.sass */ body.closet_hangers-index #title { float: left; - margin-bottom: 0; + margin-right: 0.5em; } -/* line 9, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 6, ../../../app/stylesheets/partials/_secondary_nav.sass */ body.closet_hangers-index .flash { clear: both; } -/* line 12, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #import-link, body.closet_hangers-index #closet-hangers-items-search { +/* line 9, ../../../app/stylesheets/partials/_secondary_nav.sass */ +body.closet_hangers-index #secondary-nav { + display: block; margin-top: 0.75em; } -/* line 15, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 8, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #title { + margin-bottom: 0; +} +/* line 11, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #import-link { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -593,7 +593,6 @@ body.closet_hangers-index #import-link { font-weight: bold; line-height: 1; background: #ff5c00 url('/images/alert-overlay.png?1296599919') repeat-x; - margin-left: 2em; } /* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ body.closet_hangers-index #import-link:hover { @@ -611,18 +610,18 @@ body.closet_hangers-index #import-link:active { body.closet_hangers-index #import-link:hover { background-color: #ee4b00; } -/* line 20, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 15, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-items-search { float: right; } -/* line 24, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 19, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-items-search input[name=q].loading { background-image: url(/images/loading.gif); background-position: 2px center; background-repeat: no-repeat; padding-left: 20px; } -/* line 31, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 26, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-contact { clear: both; font-size: 85%; @@ -630,65 +629,65 @@ body.closet_hangers-index #closet-hangers-contact { margin-left: 2em; min-height: 16px; } -/* line 38, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 33, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-contact a { - background-image: url('/images/neomail.png?1311369565'); + background-image: url('/images/neomail.png?1311877030'); background-position: left center; background-repeat: no-repeat; padding-left: 18px; } -/* line 45, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 40, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-contact input[type=text], body.closet_hangers-index #closet-hangers-contact body.pets-bulk #bulk-pets-form textarea, body.pets-bulk #bulk-pets-form body.closet_hangers-index #closet-hangers-contact textarea { width: 10em; } -/* line 48, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 43, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-contact label { font-weight: bold; margin-right: 0.5em; } -/* line 52, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 47, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-contact label:after { content: ":"; } -/* line 55, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 50, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #edit-contact-link-to-replace-form, body.closet_hangers-index #cancel-contact-link { display: none; } -/* line 58, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 53, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .edit-contact-link, body.closet_hangers-index #cancel-contact-link { cursor: pointer; text-decoration: underline; } -/* line 62, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 57, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .edit-contact-link:hover, body.closet_hangers-index #cancel-contact-link:hover { text-decoration: none; } -/* line 66, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 61, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #edit-contact-link-to-replace-form #contact-link-has-value { display: none; } -/* line 69, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 64, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #edit-contact-link-to-replace-form #contact-link-no-value { display: inline; } -/* line 73, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 68, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #edit-contact-link-to-replace-form.has-value #contact-link-has-value { display: inline; } -/* line 76, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 71, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #edit-contact-link-to-replace-form.has-value #contact-link-no-value { display: none; } -/* line 79, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 74, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #cancel-contact-link { margin-left: 1em; } -/* line 82, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 77, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers { clear: both; text-align: center; } -/* line 87, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 82, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -702,59 +701,187 @@ body.closet_hangers-index #closet-hangers .object .quantity { text-align: left; top: 60px; } -/* line 97, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 92, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { font-size: 16px; font-weight: bold; } -/* line 101, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 96, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object form { display: none; } -/* line 104, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index header { +/* line 99, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers .object .quantity-1 { + display: none; +} +/* line 102, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-hangers-group { + border-top: 1px solid #006600; + margin-bottom: 2em; + padding-bottom: 1em; +} +/* line 107, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-hangers-group > header { border-bottom: 1px solid #aaddaa; display: block; margin-bottom: 0.25em; padding: 0.25em 0; position: relative; } -/* line 111, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index header h3 { +/* line 114, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-hangers-group > header h3 { font-size: 250%; margin: 0; } -/* line 115, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index header span.show, body.closet_hangers-index header span.hide { +/* line 118, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-hangers-group > header .add-closet-list { + /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + background: #006400 url('/images/alert-overlay.png?1296599919') repeat-x; + border: 0; + display: inline-block; + padding: 0.5em 0.75em 0.45em; + color: white; + text-decoration: none; + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); + border-bottom: 1px solid rgba(0, 0, 0, 0.25); + position: relative; + font-weight: bold; + line-height: 1; + bottom: 50%; + margin-bottom: -1em; + position: absolute; + right: 1em; +} +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index .closet-hangers-group > header .add-closet-list:hover { + background-color: #005300; +} +/* line 53, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index .closet-hangers-group > header .add-closet-list:hover { + color: white; +} +/* line 55, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index .closet-hangers-group > header .add-closet-list:active { + top: 1px; +} +/* line 125, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-hangers-group > header .add-closet-list:active { + margin-bottom: -1.1em; + top: auto; +} +/* line 129, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-hangers-group > header span.show, body.closet_hangers-index .closet-hangers-group > header span.hide { color: #448844; display: none; font-size: 85%; + left: 1em; position: absolute; - right: 1em; - bottom: 0; + top: 1em; } -/* line 124, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index header:hover span.show, body.closet_hangers-index header:hover span.hide { +/* line 137, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-hangers-group > header span.show:hover, body.closet_hangers-index .closet-hangers-group > header span.hide:hover { color: inherit; text-decoration: underline; } -/* line 128, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index .closet-hangers-group { - border-top: 1px solid #006600; - margin-bottom: 2em; - padding-bottom: 1em; +/* line 141, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list { + border-bottom: 1px solid #aaddaa; + padding: 0.5em 0; } -/* line 136, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 145, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list header { + display: block; + position: relative; +} +/* line 149, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list h4 { + font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; + font-size: 150%; + margin: 0 auto; +} +/* line 154, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .empty-list { + font-style: italic; +} +/* line 157, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .closet-list-controls { + display: none; + position: absolute; + right: 1em; + top: 0; +} +/* line 163, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .closet-list-controls a, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit] { + /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + background: #006400 url('/images/alert-overlay.png?1296599919') repeat-x; + border: 0; + display: inline-block; + padding: 0.5em 0.75em 0.45em; + color: white; + text-decoration: none; + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); + border-bottom: 1px solid rgba(0, 0, 0, 0.25); + position: relative; + font-weight: bold; + line-height: 1; + background: #aaaaaa url('/images/alert-overlay.png?1296599919') repeat-x; + -moz-opacity: 0.9; + -webkit-opacity: 0.9; + -o-opacity: 0.9; + -khtml-opacity: 0.9; + font-size: 80%; +} +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index .closet-list .closet-list-controls a:hover, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:hover { + background-color: #005300; +} +/* line 53, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index .closet-list .closet-list-controls a:hover, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:hover { + color: white; +} +/* line 55, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index .closet-list .closet-list-controls a:active, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:active { + top: 1px; +} +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index .closet-list .closet-list-controls a:hover, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:hover { + background-color: #999999; +} +/* line 166, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .closet-list-controls form { + display: inline; +} +/* line 170, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list.unlisted h4 { + font-style: italic; +} +/* line 174, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list:hover .closet-list-controls { + display: block; +} +/* line 177, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list:last-child { + border-bottom: 0; +} +/* line 183, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 139, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 186, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 144, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 191, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -795,7 +922,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 147, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -805,97 +932,119 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 56px; padding: 0; } -/* line 153, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 200, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 156, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 203, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 160, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 207, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 166, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 212, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { + display: block; +} +/* line 215, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 169, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 218, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 172, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 221, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 176, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 225, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { + display: block; +} +/* line 228, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 232, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 183, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 235, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 239, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 190, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 242, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index.current-user.js .closet-hangers-group header { +/* line 247, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 197, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 250, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 201, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 254, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 204, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 257, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } -/* line 3, ../../../app/stylesheets/closet_lists/_form.sass */ -body.closet_lists-new form ul.fields, body.closet_lists-create form ul.fields { +/* line 2, ../../../app/stylesheets/partials/_secondary_nav.sass */ +body.closet_lists-new #title, body.closet_lists-create #title, body.closet_lists-edit #title, body.closet_lists-update #title { + float: left; + margin-right: 0.5em; +} +/* line 6, ../../../app/stylesheets/partials/_secondary_nav.sass */ +body.closet_lists-new .flash, body.closet_lists-create .flash, body.closet_lists-edit .flash, body.closet_lists-update .flash { + clear: both; +} +/* line 9, ../../../app/stylesheets/partials/_secondary_nav.sass */ +body.closet_lists-new #secondary-nav, body.closet_lists-create #secondary-nav, body.closet_lists-edit #secondary-nav, body.closet_lists-update #secondary-nav { + display: block; + margin-top: 0.75em; +} +/* line 4, ../../../app/stylesheets/closet_lists/_form.sass */ +body.closet_lists-new form ul.fields, body.closet_lists-create form ul.fields, body.closet_lists-edit form ul.fields, body.closet_lists-update form ul.fields { list-style: none; } -/* line 6, ../../../app/stylesheets/closet_lists/_form.sass */ -body.closet_lists-new form ul.fields label, body.closet_lists-create form ul.fields label { +/* line 7, ../../../app/stylesheets/closet_lists/_form.sass */ +body.closet_lists-new form ul.fields label, body.closet_lists-create form ul.fields label, body.closet_lists-edit form ul.fields label, body.closet_lists-update form ul.fields label { float: left; font-weight: bold; margin-right: 1em; } -/* line 11, ../../../app/stylesheets/closet_lists/_form.sass */ -body.closet_lists-new form ul.fields li, body.closet_lists-create form ul.fields li { +/* line 12, ../../../app/stylesheets/closet_lists/_form.sass */ +body.closet_lists-new form ul.fields li, body.closet_lists-create form ul.fields li, body.closet_lists-edit form ul.fields li, body.closet_lists-update form ul.fields li { padding: 0.75em 0; width: 25em; } -/* line 15, ../../../app/stylesheets/closet_lists/_form.sass */ -body.closet_lists-new form ul.fields input, body.closet_lists-new form ul.fields textarea, body.closet_lists-new form ul.fields select, body.closet_lists-create form ul.fields input, body.closet_lists-create form ul.fields textarea, body.closet_lists-create form ul.fields select { +/* line 16, ../../../app/stylesheets/closet_lists/_form.sass */ +body.closet_lists-new form ul.fields input, body.closet_lists-new form ul.fields textarea, body.closet_lists-new form ul.fields select, body.closet_lists-create form ul.fields input, body.closet_lists-create form ul.fields textarea, body.closet_lists-create form ul.fields select, body.closet_lists-edit form ul.fields input, body.closet_lists-edit form ul.fields textarea, body.closet_lists-edit form ul.fields select, body.closet_lists-update form ul.fields input, body.closet_lists-update form ul.fields textarea, body.closet_lists-update form ul.fields select { clear: both; display: block; margin-top: 0.25em; width: 80%; } -/* line 21, ../../../app/stylesheets/closet_lists/_form.sass */ -body.closet_lists-new form ul.fields textarea, body.closet_lists-create form ul.fields textarea { +/* line 22, ../../../app/stylesheets/closet_lists/_form.sass */ +body.closet_lists-new form ul.fields textarea, body.closet_lists-create form ul.fields textarea, body.closet_lists-edit form ul.fields textarea, body.closet_lists-update form ul.fields textarea { height: 12em; } -/* line 24, ../../../app/stylesheets/closet_lists/_form.sass */ -body.closet_lists-new form ul.fields .hint, body.closet_lists-create form ul.fields .hint { +/* line 25, ../../../app/stylesheets/closet_lists/_form.sass */ +body.closet_lists-new form ul.fields .hint, body.closet_lists-create form ul.fields .hint, body.closet_lists-edit form ul.fields .hint, body.closet_lists-update form ul.fields .hint { display: block; font-size: 85%; } @@ -1303,7 +1452,7 @@ body.items-show #closet-hangers { float: right; font-size: 85%; padding: 1em; - width: 18em; + width: 21em; } /* line 73, ../../../app/stylesheets/items/_show.sass */ body.items-show #closet-hangers label, body.items-show #closet-hangers header { @@ -1319,6 +1468,10 @@ body.items-show #closet-hangers form { padding: 0.5em 0; } /* line 83, ../../../app/stylesheets/items/_show.sass */ +body.items-show #closet-hangers select { + width: 9em; +} +/* line 86, ../../../app/stylesheets/items/_show.sass */ body.items-show #closet-hangers input[type=number] { width: 4em; } @@ -1901,7 +2054,7 @@ body.outfits-edit .object:hover ul, body.outfits-edit .object:hover .object-info } /* line 418, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .nc-icon { - background: url('/images/nc.png?1311369565') no-repeat; + background: url('/images/nc.png?1311877029') no-repeat; height: 16px; position: absolute; right: 16px; diff --git a/vendor/cache/sanitize-2.0.3.gem b/vendor/cache/sanitize-2.0.3.gem new file mode 100644 index 0000000000000000000000000000000000000000..8d81d81e0e5b80e7383837f3e704a1f9e07d90a2 GIT binary patch literal 14336 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 literal 0 HcmV?d00001 From d893b0ab4175124596b8121baee5ddcf04f5091f Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 29 Jul 2011 11:25:17 -0400 Subject: [PATCH 41/69] Your Items autocomplete supports lists --- app/controllers/closet_hangers_controller.rb | 3 +- app/stylesheets/closet_hangers/_index.sass | 4 ++ app/views/closet_hangers/index.html.haml | 4 +- app/views/closet_lists/_closet_list.html.haml | 2 +- public/javascripts/closet_hangers/index.js | 39 +++++++++++++-- public/stylesheets/compiled/screen.css | 47 ++++++++++--------- 6 files changed, 68 insertions(+), 31 deletions(-) diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 3598d232..c459e763 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -40,7 +40,8 @@ class ClosetHangersController < ApplicationController if @closet_hanger.save respond_to do |format| format.html { - message = "Success! You #{@closet_hanger.verb(:you)} #{@closet_hanger.quantity} #{@item.name.pluralize}" + message = "Success! You #{@closet_hanger.verb(:you)} #{@closet_hanger.quantity} " + message << ((@closet_hanger.quantity > 1) ? @item.name.pluralize : @item.name) message << " in the \"#{@closet_hanger.list.name}\" list" if @closet_hanger.list flash[:success] = "#{message}." redirect_back!(@item) diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 57b3c14e..d758fc9c 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -177,6 +177,10 @@ body.closet_hangers-index &:last-child border-bottom: 0 + .closet-list-autocomplete-item a + font-size: 85% + padding-left: 2em + &.current-user #closet-hangers .object:hover diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 6e921a1d..92d0588f 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -49,9 +49,7 @@ .closet-hangers-group{'data-owned' => owned.to_s} %header %h3 - Items - = closet_hanger_subject - %span.verb= closet_hanger_verb(owned) + Items #{closet_hanger_subject} #{closet_hanger_verb(owned)} %span.toggle.show show %span.toggle.hide hide = link_to_add_closet_list 'Add new list', :owned => owned, :class => 'add-closet-list' diff --git a/app/views/closet_lists/_closet_list.html.haml b/app/views/closet_lists/_closet_list.html.haml index 56a6cc19..5da0a035 100644 --- a/app/views/closet_lists/_closet_list.html.haml +++ b/app/views/closet_lists/_closet_list.html.haml @@ -1,4 +1,4 @@ -.closet-list +.closet-list{'data-id' => closet_list.id} %header - if show_controls .closet-list-controls diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index f2636a2c..897863ff 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -9,8 +9,22 @@ $('div.closet-hangers-group').each(function () { var el = $(this); + var lists = []; + + el.find('div.closet-list').each(function () { + var el = $(this); + var id = el.attr('data-id'); + if(id) { + lists[lists.length] = { + id: parseInt(id, 10), + label: el.find('h4').text() + } + } + }); + hangerGroups[hangerGroups.length] = { - label: el.find('span.verb').text(), + label: el.find('h3').text(), + lists: lists, owned: (el.attr('data-owned') == 'true') }; }); @@ -176,7 +190,8 @@ var closetHanger = { quantity: 1, - owned: group.owned + owned: group.owned, + list_id: ui.item.list ? ui.item.list.id : '' }; $.ajax({ @@ -212,13 +227,24 @@ callback(output); }); } else { // item was chosen, now choose a group to insert - var groupInserts = []; + var groupInserts = [], group; for(var i in hangerGroups) { + group = hangerGroups[i]; + groupInserts[groupInserts.length] = { - group: hangerGroups[i], + group: group, item: input.term, label: input.term.label } + + for(var i = 0; i < group.lists.length; i++) { + groupInserts[groupInserts.length] = { + group: group, + item: input.term, + label: input.term.label, + list: group.lists[i] + } + } } callback(groupInserts); } @@ -231,8 +257,11 @@ var li = $("
    • ").data("item.autocomplete", item); if(item.is_item) { // these are items from the server li.append("Add " + item.label + ""); + } else if(item.list) { // these are list inserts + li.append("Add to " + item.list.label + ""). + addClass("closet-list-autocomplete-item"); } else { // these are group inserts - li.append("I " + item.group.label + " the " + item.item.label + ""); + li.append("Add to " + item.group.label + ""); } return li.appendTo(ul); } diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 6929cf3a..f1c41c04 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -871,17 +871,22 @@ body.closet_hangers-index .closet-list:hover .closet-list-controls { body.closet_hangers-index .closet-list:last-child { border-bottom: 0; } -/* line 183, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list-autocomplete-item a { + font-size: 85%; + padding-left: 2em; +} +/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 186, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 190, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 191, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 195, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -922,7 +927,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 198, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -932,73 +937,73 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 56px; padding: 0; } -/* line 200, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 204, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 203, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 207, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 207, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 211, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 212, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 216, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { display: block; } -/* line 215, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 219, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 218, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 222, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 221, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 225, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 225, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 229, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { display: block; } -/* line 228, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 232, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 232, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 236, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 235, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 239, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 239, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 243, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 242, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 246, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 247, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 251, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 250, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 254, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 254, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 258, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 257, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 261, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } From 811d6df6978d7e966698306975332a443d011e52 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 29 Jul 2011 13:29:32 -0400 Subject: [PATCH 42/69] only show Add New List if user has permission --- app/views/closet_hangers/index.html.haml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 92d0588f..8426ba9d 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -52,7 +52,8 @@ Items #{closet_hanger_subject} #{closet_hanger_verb(owned)} %span.toggle.show show %span.toggle.hide hide - = link_to_add_closet_list 'Add new list', :owned => owned, :class => 'add-closet-list' + - unless public_perspective? + = link_to_add_closet_list 'Add new list', :owned => owned, :class => 'add-closet-list' .closet-hangers-group-content = render_closet_lists(@closet_lists_by_owned[owned]) = render_unlisted_closet_hangers(owned) From c76c261444cd00532ae735971dcb35bd75c5622a Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 29 Jul 2011 13:47:01 -0400 Subject: [PATCH 43/69] validate that closet hanger list belongs to the same user --- app/models/closet_hanger.rb | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/app/models/closet_hanger.rb b/app/models/closet_hanger.rb index dfef7c7f..e70569c5 100644 --- a/app/models/closet_hanger.rb +++ b/app/models/closet_hanger.rb @@ -9,17 +9,14 @@ class ClosetHanger < ActiveRecord::Base validates :quantity, :numericality => {:greater_than => 0} validates_presence_of :item, :user + validate :list_belongs_to_user + scope :alphabetical_by_item_name, joins(:item).order(Item.arel_table[:name]) scope :owned_before_wanted, order(arel_table[:owned].desc) scope :unlisted, where(:list_id => nil) before_validation :set_owned_by_list - def set_owned_by_list - self.owned = list.hangers_owned if list_id? - true - end - def verb(subject=:someone) self.class.verb(subject, owned?) end @@ -29,5 +26,22 @@ class ClosetHanger < ActiveRecord::Base base << 's' if positive && subject != :you && subject != :i base end + + protected + + def list_belongs_to_user + if list_id? + if list + errors.add(:list_id, "must belong to you") unless list.user_id == user_id + else + errors.add(:list, "must exist") + end + end + end + + def set_owned_by_list + self.owned = list.hangers_owned if list + true + end end From 48ee76550579a19b0a48cafd3d31b1ad7e9bf367 Mon Sep 17 00:00:00 2001 From: Matchu Date: Fri, 29 Jul 2011 23:26:48 -0400 Subject: [PATCH 44/69] Your Items autocompleter is totally chill with moving items around to different lists --- app/stylesheets/closet_hangers/_index.sass | 12 +++-- .../closet_hangers/_closet_hanger.html.haml | 2 +- public/javascripts/closet_hangers/index.js | 45 ++++++++++++---- public/stylesheets/compiled/screen.css | 51 ++++++++++--------- 4 files changed, 74 insertions(+), 36 deletions(-) diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index d758fc9c..cda8d60b 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -177,9 +177,15 @@ body.closet_hangers-index &:last-child border-bottom: 0 - .closet-list-autocomplete-item a - font-size: 85% - padding-left: 2em + .closet-hangers-group-autocomplete-item, .closet-list-autocomplete-item + span + font-style: italic + padding: .2em .4em + + .closet-list-autocomplete-item + a, span + font-size: 85% + padding-left: 2em &.current-user #closet-hangers diff --git a/app/views/closet_hangers/_closet_hanger.html.haml b/app/views/closet_hangers/_closet_hanger.html.haml index 44a20148..ad7d3bec 100644 --- a/app/views/closet_hangers/_closet_hanger.html.haml +++ b/app/views/closet_hangers/_closet_hanger.html.haml @@ -1,5 +1,5 @@ - show_controls ||= false # we could do user check here, but may as well do it once -.object +.object{'data-item-id' => closet_hanger.item_id} = render :partial => 'items/item_link', :locals => {:item => closet_hanger.item} .quantity{:class => "quantity-#{closet_hanger.quantity}"} %span= closet_hanger.quantity diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index 897863ff..74047135 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -189,11 +189,12 @@ itemsSearchField.addClass("loading"); var closetHanger = { - quantity: 1, owned: group.owned, list_id: ui.item.list ? ui.item.list.id : '' }; + if(!item.hangerInGroup) closetHanger.quantity = 1; + $.ajax({ url: "/user/" + itemsSearchForm.data("current-user-id") + "/items/" + item.id + "/closet_hanger", type: "post", @@ -228,21 +229,29 @@ }); } else { // item was chosen, now choose a group to insert var groupInserts = [], group; + var item = input.term, itemEl, hangerInGroup, currentListId; for(var i in hangerGroups) { group = hangerGroups[i]; + itemEl = $('div.closet-hangers-group[data-owned=' + group.owned + '] div.object[data-item-id=' + item.id + ']'); + hangerInGroup = itemEl.length > 0; + currentListId = itemEl.closest('.closet-list').attr('data-id'); groupInserts[groupInserts.length] = { group: group, - item: input.term, - label: input.term.label + item: item, + label: item.label, + hangerInGroup: hangerInGroup, + hangerInList: !!currentListId } for(var i = 0; i < group.lists.length; i++) { groupInserts[groupInserts.length] = { group: group, - item: input.term, - label: input.term.label, - list: group.lists[i] + item: item, + label: item.label, + list: group.lists[i], + hangerInGroup: hangerInGroup, + currentListId: currentListId } } } @@ -258,10 +267,28 @@ if(item.is_item) { // these are items from the server li.append("Add " + item.label + ""); } else if(item.list) { // these are list inserts - li.append("Add to " + item.list.label + ""). - addClass("closet-list-autocomplete-item"); + if(item.hangerInGroup) { + if(item.currentListId == item.list.id) { + li.append("It's in " + item.list.label + " now"); + } else { + li.append("Move to " + item.list.label + ""); + } + } else { + li.append("Add to " + item.list.label + ""); + } + li.addClass("closet-list-autocomplete-item"); } else { // these are group inserts - li.append("Add to " + item.group.label + ""); + if(item.hangerInGroup) { + var groupName = item.group.label; + if(item.hangerInList) { + li.append("Move to " + groupName.replace(/\s+$/, '') + ", no list"); + } else { + li.append("It's in " + groupName + " now"); + } + } else { + li.append("Add to " + item.group.label + ""); + } + li.addClass('closet-hangers-group-autocomplete-item'); } return li.appendTo(ul); } diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index f1c41c04..746f4c08 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -871,22 +871,27 @@ body.closet_hangers-index .closet-list:hover .closet-list-controls { body.closet_hangers-index .closet-list:last-child { border-bottom: 0; } -/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index .closet-list-autocomplete-item a { +/* line 181, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-hangers-group-autocomplete-item span, body.closet_hangers-index .closet-list-autocomplete-item span { + font-style: italic; + padding: 0.2em 0.4em; +} +/* line 186, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list-autocomplete-item a, body.closet_hangers-index .closet-list-autocomplete-item span { font-size: 85%; padding-left: 2em; } -/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 193, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 190, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 196, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 195, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 201, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -927,7 +932,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 198, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 204, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -937,73 +942,73 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 56px; padding: 0; } -/* line 204, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 210, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 207, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 213, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 211, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 217, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 216, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 222, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { display: block; } -/* line 219, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 225, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 222, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 228, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 225, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 231, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 229, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 235, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { display: block; } -/* line 232, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 238, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 236, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 242, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 239, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 245, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 243, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 249, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 246, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 252, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 251, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 257, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 254, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 260, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 258, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 264, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 261, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 267, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } From 9a7b13dc5da9d889992c0c13e072b9a5aabe8193 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sat, 30 Jul 2011 13:40:41 -0400 Subject: [PATCH 45/69] drag and drop on Your Items <3 --- app/helpers/closet_hangers_helper.rb | 3 +- app/stylesheets/closet_hangers/_index.sass | 20 +++ .../closet_hangers/_closet_hanger.html.haml | 1 + app/views/closet_hangers/index.html.haml | 35 +++-- app/views/closet_lists/_closet_list.html.haml | 12 +- app/views/items/_item_link.html.haml | 2 +- public/javascripts/closet_hangers/index.js | 123 +++++++++++++++--- public/javascripts/jquery.ui.js | 94 +++++++++++++ public/stylesheets/compiled/screen.css | 79 +++++++---- 9 files changed, 312 insertions(+), 57 deletions(-) diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index 2e6a5296..81b954eb 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -56,9 +56,10 @@ module ClosetHangersHelper def render_unlisted_closet_hangers(owned) if @unlisted_closet_hangers_by_owned[owned] - content = render :partial => 'closet_hanger', + hangers_content = render :partial => 'closet_hanger', :collection => @unlisted_closet_hangers_by_owned[owned], :locals => {:show_controls => !public_perspective?} + content = content_tag(:div, hangers_content, :class => 'closet-list-hangers') if has_lists?(owned) content = content_tag(:header, content_tag(:h4, '(Not in a list)')) + content end diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index cda8d60b..80b96451 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -177,6 +177,26 @@ body.closet_hangers-index &:last-child border-bottom: 0 + &.droppable-active + +border-radius(1em) + +module + border-bottom-width: 1px + border-style: dotted + margin: 1em 0 + + .object + // totally hiding these elements causes the original element to change + // position, throwing off the drag + +opacity(.25) + &.ui-draggable-dragging + +opacity(1) + + .closet-list-controls + display: none + + .closet-list-hangers + overflow: hidden + .closet-hangers-group-autocomplete-item, .closet-list-autocomplete-item span font-style: italic diff --git a/app/views/closet_hangers/_closet_hanger.html.haml b/app/views/closet_hangers/_closet_hanger.html.haml index ad7d3bec..3e92dcba 100644 --- a/app/views/closet_hangers/_closet_hanger.html.haml +++ b/app/views/closet_hangers/_closet_hanger.html.haml @@ -6,6 +6,7 @@ - if show_controls = form_for closet_hanger, :url => user_item_closet_hanger_path(current_user, closet_hanger.item), :html => {:class => 'closet-hanger-update'} do |f| = return_to_field_tag + = f.hidden_field :list_id = f.hidden_field :owned = f.number_field :quantity, :min => 0, :required => true, :title => "You own #{pluralize closet_hanger.quantity, closet_hanger.item.name}" = f.submit "Save" diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 8426ba9d..7a1b84f7 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -31,22 +31,33 @@ = f.submit "Save" %span#cancel-contact-link cancel -%p - These are the items you are tracking on Dress to Impress. Hover over an - item to remove it from the list or to change the quantity. +- unless public_perspective? + %p + These are the items you are tracking on Dress to Impress. Hover over an + item to remove it from the list or to change the quantity. -%p - You can share - = link_to "this page", request.fullpath - with the world, and they'll be able to see what items you own and want. - It's also a good idea to - %span.edit-contact-link add your Neopets username - so that when other users see your items they will know how to contact you for - trades. + %p + %strong + You can share + = link_to "this page", request.fullpath + with the world, + and they'll be able to see what items you own and want. + It's also a good idea to + %span.edit-contact-link add your Neopets username + so that when other users see your items they will know how to contact you for + trades. + + %p + You can also make lists of items. + %strong + = link_to 'Get started with an Up For Trade list', + new_user_closet_list_path(@user, :closet_list => {:hangers_owned => true, :name => 'Up For Trade'}) + then start adding to it! You can use the search form at the top to find + items, and you can also drag-and-drop items in and out of lists. Enjoy! #closet-hangers{:class => public_perspective? ? nil : 'current-user'} - [true, false].each do |owned| - .closet-hangers-group{'data-owned' => owned.to_s} + .closet-hangers-group{'data-owned' => owned.to_s, :id => "closet-hangers-group-#{owned}"} %header %h3 Items #{closet_hanger_subject} #{closet_hanger_verb(owned)} diff --git a/app/views/closet_lists/_closet_list.html.haml b/app/views/closet_lists/_closet_list.html.haml index 5da0a035..7b67f5b4 100644 --- a/app/views/closet_lists/_closet_list.html.haml +++ b/app/views/closet_lists/_closet_list.html.haml @@ -1,4 +1,4 @@ -.closet-list{'data-id' => closet_list.id} +.closet-list{'data-id' => closet_list.id, :id => "closet-list-#{closet_list.id}"} %header - if show_controls .closet-list-controls @@ -9,8 +9,10 @@ - if closet_list.description? = closet_list_description_format closet_list - - unless closet_list.hangers.empty? - = render_sorted_hangers(closet_list, show_controls) - - else - %span.empty-list This list is empty. + + .closet-list-hangers + - unless closet_list.hangers.empty? + = render_sorted_hangers(closet_list, show_controls) + - else + %span.empty-list This list is empty. diff --git a/app/views/items/_item_link.html.haml b/app/views/items/_item_link.html.haml index ed1fd79f..e9f95056 100644 --- a/app/views/items/_item_link.html.haml +++ b/app/views/items/_item_link.html.haml @@ -1,6 +1,6 @@ = link_to item_path(item, :q => @query) do = image_tag item.thumbnail_url, :alt => item.description, :title => item.description - = item.name + %span.name= item.name = nc_icon_for(item) = closeted_icons_for(item) diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index 74047135..5e1803f0 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -1,4 +1,16 @@ (function () { + var hangersInitCallbacks = []; + + function onHangersInit(callback) { + hangersInitCallbacks[hangersInitCallbacks.length] = callback; + } + + function hangersInit() { + for(var i = 0; i < hangersInitCallbacks.length; i++) { + hangersInitCallbacks[i](); + } + } + /* Hanger groups @@ -39,6 +51,14 @@ */ + $.fn.liveDraggable = function (opts) { + this.live("mouseover", function() { + if (!$(this).data("init")) { + $(this).data("init", true).draggable(opts); + } + }); + }; + var body = $(document.body).addClass("js"); if(!body.hasClass("current-user")) return false; @@ -54,23 +74,36 @@ } $.fn.hasChanged = function () { - return this.data('previousValue') != this.val(); + return this.attr('data-previous-value') != this.val(); } $.fn.revertValue = function () { return this.each(function () { var el = $(this); - el.val(el.data('previousValue')); + el.val(el.attr('data-previous-value')); }); } $.fn.storeValue = function () { return this.each(function () { var el = $(this); - el.data('previousValue', el.val()); + el.attr('data-previous-value', el.val()); }); } + $.fn.insertIntoSortedList = function (list, compare) { + var newChild = this, inserted = false; + list.children().each(function () { + if(compare(newChild, $(this)) < 1) { + newChild.insertBefore(this); + inserted = true; + return false; + } + }); + if(!inserted) newChild.appendTo(list); + return this; + } + function handleSaveError(xhr, action) { try { var data = $.parseJSON(xhr.responseText); @@ -89,24 +122,41 @@ objectWrapper.hide(250); } + function compareItemsByName(a, b) { + return a.find('span.name').text().localeCompare(b.find('span.name').text()); + } + + function moveItemToList(item, listId) { + if(listId) { + var list = $('#closet-list-' + listId); + } else { + var list = item.closest('.closet-hangers-group').find('div.closet-list.unlisted'); + } + var hangersWrapper = list.find('div.closet-list-hangers'); + item.insertIntoSortedList(hangersWrapper, compareItemsByName); + } + function submitUpdateForm(form) { if(form.data('loading')) return false; - var input = form.children("input[type=number]"); - if(input.hasChanged()) { + var quantityEl = form.children("input[name=closet_hanger\[quantity\]]"); + var listEl = form.children("input[name=closet_hanger\[list_id\]]"); + var listChanged = listEl.hasChanged(); + if(listChanged || quantityEl.hasChanged()) { var objectWrapper = form.closest(".object").addClass("loading"); - var newQuantity = input.val(); - var span = objectWrapper.find("span").text(newQuantity); - span.parent().attr('class', 'quantity quantity-' + newQuantity); + var newQuantity = quantityEl.val(); + var quantitySpan = objectWrapper.find(".quantity span").text(newQuantity); + quantitySpan.parent().attr('class', 'quantity quantity-' + newQuantity); var data = form.serialize(); // get data before disabling inputs objectWrapper.disableForms(); form.data('loading', true); + if(listChanged) moveItemToList(objectWrapper, listEl.val()); $.ajax({ url: form.attr("action") + ".json", type: "post", data: data, dataType: "json", complete: function (data) { - if(input.val() == 0) { + if(quantityEl.val() == 0) { objectRemoved(objectWrapper); } else { objectWrapper.removeClass("loading").enableForms(); @@ -114,11 +164,14 @@ form.data('loading', false); }, success: function () { - input.storeValue(); + quantityEl.storeValue(); + listEl.storeValue(); }, error: function (xhr) { - input.revertValue(); - span.text(input.val()); + quantityEl.revertValue(); + listEl.revertValue(); + if(listChanged) moveItemToList(objectWrapper, listEl.val()); + quantitySpan.text(quantityEl.val()); handleSaveError(xhr, "updating the quantity"); } @@ -131,14 +184,23 @@ submitUpdateForm($(this)); }); - function quantityInputs() { return $(hangersElQuery + ' input[type=number]') } + function editableInputs() { return $(hangersElQuery).find('input[name=closet_hanger\[quantity\]], input[name=closet_hanger\[list_id\]]') } - quantityInputs().live('change', function () { + $(hangersElQuery + 'input[name=closet_hanger\[quantity\]]').live('change', function () { submitUpdateForm($(this).parent()); }).storeValue(); + onHangersInit(function () { + editableInputs().storeValue(); + }); + $(hangersElQuery + ' div.object').live('mouseleave', function () { submitUpdateForm($(this).find('form.closet-hanger-update')); + }).liveDraggable({ + appendTo: '#closet-hangers', + distance: 20, + helper: "clone", + revert: "invalid" }); $(hangersElQuery + " form.closet-hanger-destroy").live("submit", function (e) { @@ -205,7 +267,7 @@ success: function (html) { var doc = $(html); hangersEl.html( doc.find('#closet-hangers').html() ); - quantityInputs().storeValue(); // since all the quantity inputs are new, gotta store initial value again + hangersInit(); doc.find('.flash').hide().insertBefore(hangersEl).show(500).delay(5000).hide(250); itemsSearchField.val(""); }, @@ -354,5 +416,36 @@ $('input[type=submit][data-confirm]').live('click', function (e) { if(!confirm(this.getAttribute('data-confirm'))) e.preventDefault(); }); + + /* + Closet list droppable + */ + + onHangersInit(function () { + $('.closet-hangers-group').each(function () { + var group = $(this); + group.find('div.closet-list').droppable({ + accept: '#' + group.attr('id') + ' div.object', + activate: function () { + $(this).find('.closet-list-hangers').animate({opacity: 0, height: 100}, 250); + }, + activeClass: 'droppable-active', + deactivate: function () { + $(this).find('.closet-list-hangers').css('height', 'auto').animate({opacity: 1}, 250); + }, + drop: function (e, ui) { + var form = ui.draggable.find('form.closet-hanger-update'); + form.find('input[name=closet_hanger\[list_id\]]').val(this.getAttribute('data-id')); + submitUpdateForm(form); + } + }); + }); + }); + + /* + Initialize + */ + + hangersInit(); })(); diff --git a/public/javascripts/jquery.ui.js b/public/javascripts/jquery.ui.js index dad0f2e5..ee5f624e 100644 --- a/public/javascripts/jquery.ui.js +++ b/public/javascripts/jquery.ui.js @@ -30,6 +30,23 @@ e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g this._getCreateOptions(),a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")}, widget:function(){return this.element},option:function(a,c){var d=a;if(arguments.length===0)return b.extend({},this.options);if(typeof a==="string"){if(c===j)return this.options[a];d={};d[a]=c}this._setOptions(d);return this},_setOptions:function(a){var c=this;b.each(a,function(d,e){c._setOption(d,e)});return this},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this}, enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery); +;/*! + * jQuery UI Mouse 1.8.14 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function(b){var d=false;b(document).mousedown(function(){d=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(c){return a._mouseDown(c)}).bind("click."+this.widgetName,function(c){if(true===b.data(c.target,a.widgetName+".preventClickEvent")){b.removeData(c.target,a.widgetName+".preventClickEvent");c.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+ +this.widgetName)},_mouseDown:function(a){if(!d){this._mouseStarted&&this._mouseUp(a);this._mouseDownEvent=a;var c=this,f=a.which==1,g=typeof this.options.cancel=="string"?b(a.target).closest(this.options.cancel).length:false;if(!f||g||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){c.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!== +false;if(!this._mouseStarted){a.preventDefault();return true}}true===b.data(a.target,this.widgetName+".preventClickEvent")&&b.removeData(a.target,this.widgetName+".preventClickEvent");this._mouseMoveDelegate=function(e){return c._mouseMove(e)};this._mouseUpDelegate=function(e){return c._mouseUp(e)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);a.preventDefault();return d=true}},_mouseMove:function(a){if(b.browser.msie&& +!(document.documentMode>=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted= +false;a.target==this._mouseDownEvent.target&&b.data(a.target,this.widgetName+".preventClickEvent",true);this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery); ;/* * jQuery UI Position 1.8.14 * @@ -46,6 +63,83 @@ m/2;i.left=Math.round(i.left);i.top=Math.round(i.top);r={left:i.left-p,top:i.top d>0?b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();b.top=d>0?b.top-d:Math.max(b.top-a.collisionPosition.top,b.top)}},flip:{left:function(b,a){if(a.at[0]!=="center"){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();var g=a.my[0]==="left"?-a.elemWidth:a.my[0]==="right"?a.elemWidth:0,e=a.at[0]==="left"?a.targetWidth:-a.targetWidth,h=-2*a.offset[0];b.left+= a.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!=="center"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]==="top"?-a.elemHeight:a.my[1]==="bottom"?a.elemHeight:0,e=a.at[1]==="top"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,"position")))b.style.position="relative";var d=c(b), g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"left",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};"using"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery); +;/* + * jQuery UI Draggable 1.8.14 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Draggables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper== +"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b= +this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;d(b.iframeFix===true?"iframe":b.iframeFix).each(function(){d('
      ').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")});return true},_mouseStart:function(a){var b=this.options;this.helper= +this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}); +this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions();d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);d.ui.ddmanager&&d.ui.ddmanager.dragStart(this,a);return true}, +_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b= +false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if((!this.element[0]||!this.element[0].parentNode)&&this.options.helper=="original")return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element,b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration, +10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},_mouseUp:function(a){this.options.iframeFix===true&&d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)});d.ui.ddmanager&&d.ui.ddmanager.dragStop(this,a);return d.ui.mouse.prototype._mouseUp.call(this,a)},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle|| +!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone().removeAttr("id"):this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&& +a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent= +this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"), +10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"), +10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[a.containment=="document"?0:d(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,a.containment=="document"?0:d(window).scrollTop()-this.offset.relative.top-this.offset.parent.top, +(a.containment=="document"?0:d(window).scrollLeft())+d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a.containment=="document"?0:d(window).scrollTop())+(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&a.containment.constructor!=Array){a=d(a.containment);var b=a[0];if(b){a.offset();var c=d(b).css("overflow")!= +"hidden";this.containment=[(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0),(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0),(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"), +10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom];this.relative_container=a}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+ +this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&& +!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,h=a.pageY;if(this.originalPosition){var g;if(this.containment){if(this.relative_container){g=this.relative_container.offset();g=[this.containment[0]+g.left,this.containment[1]+g.top,this.containment[2]+g.left,this.containment[3]+g.top]}else g=this.containment;if(a.pageX-this.offset.click.leftg[2])e=g[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>g[3])h=g[3]+this.offset.click.top}if(b.grid){h=b.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/b.grid[1])*b.grid[1]:this.originalPageY;h=g?!(h-this.offset.click.topg[3])?h:!(h-this.offset.click.topg[2])?e:!(e-this.offset.click.left=0;i--){var j=c.snapElements[i].left,l=j+c.snapElements[i].width,k=c.snapElements[i].top,m=k+c.snapElements[i].height;if(j-e=j&&f<=l||h>=j&&h<=l||fl)&&(e>= +i&&e<=k||g>=i&&g<=k||ek);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f Date: Sat, 30 Jul 2011 19:45:28 -0400 Subject: [PATCH 46/69] privacy for unlisted hangers --- app/controllers/closet_hangers_controller.rb | 13 +- app/helpers/closet_hangers_helper.rb | 23 ++-- app/models/closet_visibility.rb | 54 ++++++++ app/models/user.rb | 11 +- app/stylesheets/closet_hangers/_index.sass | 36 +++++- app/views/closet_hangers/index.html.haml | 11 +- ..._add_closet_hangers_visibility_to_users.rb | 12 ++ db/schema.rb | 20 +-- public/stylesheets/compiled/screen.css | 117 ++++++++++++------ 9 files changed, 235 insertions(+), 62 deletions(-) create mode 100644 app/models/closet_visibility.rb create mode 100644 db/migrate/20110730174148_add_closet_hangers_visibility_to_users.rb diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index c459e763..2d9dd540 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -16,9 +16,16 @@ class ClosetHangersController < ApplicationController @user = User.find params[:user_id] @closet_lists_by_owned = @user.closet_lists.alphabetical. includes(:hangers => :item).group_by(&:hangers_owned) - @unlisted_closet_hangers_by_owned = @user.closet_hangers.unlisted. - owned_before_wanted.alphabetical_by_item_name.includes(:item). - group_by(&:owned) + + visible_groups = @user.closet_hangers_groups_visible_to(current_user) + unless visible_groups.empty? + @unlisted_closet_hangers_by_owned = @user.closet_hangers.unlisted. + owned_before_wanted.alphabetical_by_item_name.includes(:item). + where(:owned => [visible_groups]).group_by(&:owned) + else + @unlisted_closet_hangers_by_owned = {} + end + @public_perspective = params.has_key?(:public) || !user_is?(@user) end diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index 81b954eb..d3f7b47d 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -13,6 +13,16 @@ module ClosetHangersHelper public_perspective? ? @user.name : :you end + def hangers_group_visibility_field_name(owned) + owned ? :owned_closet_hangers_visibility : :wanted_closet_hangers_visibility + end + + def hangers_group_visibility_choices(owned) + ClosetVisibility.levels.map do |level| + [level.description("these items"), level.id] + end + end + # Do we have either unlisted hangers that are owned/wanted, or non-empty # owned/wanted lists? def has_hangers?(owned) @@ -55,16 +65,9 @@ module ClosetHangersHelper end def render_unlisted_closet_hangers(owned) - if @unlisted_closet_hangers_by_owned[owned] - hangers_content = render :partial => 'closet_hanger', - :collection => @unlisted_closet_hangers_by_owned[owned], - :locals => {:show_controls => !public_perspective?} - content = content_tag(:div, hangers_content, :class => 'closet-list-hangers') - if has_lists?(owned) - content = content_tag(:header, content_tag(:h4, '(Not in a list)')) + content - end - content_tag(:div, content, :class => 'closet-list unlisted') - end + hangers_content = render :partial => 'closet_hanger', + :collection => @unlisted_closet_hangers_by_owned[owned], + :locals => {:show_controls => !public_perspective?} end end diff --git a/app/models/closet_visibility.rb b/app/models/closet_visibility.rb new file mode 100644 index 00000000..d2c675f0 --- /dev/null +++ b/app/models/closet_visibility.rb @@ -0,0 +1,54 @@ +module ClosetVisibility + class Level + attr_accessor :id, :name + attr_writer :description + + def initialize(data) + data.each do |key, value| + send("#{key}=", value) + end + end + + def description(subject=nil) + if subject + @description.sub('$SUBJECT', subject).capitalize + else + @description + end + end + end + + LEVELS = [ + Level.new( + :id => 0, + :name => :private, + :description => "Only you can see $SUBJECT" + ), + Level.new( + :id => 1, + :name => :public, + :description => "Anyone who visits this page can see $SUBJECT" + ), + Level.new( + :id => 2, + :name => :advertised, + :description => "$SUBJECT will be publicly listed for trades" + ) + ] + + LEVELS_BY_NAME = {}.tap do |levels_by_name| + LEVELS.each do |level| + levels_by_name[level.id] = level + levels_by_name[level.name] = level + end + end + + def self.[](id) + LEVELS_BY_NAME[id] + end + + def self.levels + LEVELS + end +end + diff --git a/app/models/user.rb b/app/models/user.rb index 82adbfc4..12ffecbf 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -14,7 +14,8 @@ class User < ActiveRecord::Base devise :rememberable - attr_accessible :neopets_username + attr_accessible :neopets_username, :owned_closet_hangers_visibility, + :wanted_closet_hangers_visibility def contribute!(pet) new_contributions = [] @@ -62,6 +63,14 @@ class User < ActiveRecord::Base end end + def closet_hangers_groups_visible_to(user) + return [true, false] if user == self + [].tap do |groups| + groups << true if owned_closet_hangers_visibility >= ClosetVisibility[:public].id + groups << false if wanted_closet_hangers_visibility >= ClosetVisibility[:public].id + end + end + def self.find_or_create_from_remote_auth_data(user_data) user = find_or_initialize_by_remote_id_and_auth_server_id( user_data['id'], diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 80b96451..78cdab24 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -141,6 +141,30 @@ body.closet_hangers-index .closet-list border-bottom: 1px solid $soft-border-color padding: .5em 0 + position: relative + + .visibility-form + +inline-block + margin: 0 auto + position: relative + + input, select + font-size: 85% + margin: + bottom: 0 + top: 0 + + select + border-color: $background-color + + input[type=submit] + left: 100% + position: absolute + top: 0 + visibility: hidden + + &:active + top: 1px header display: block @@ -149,6 +173,7 @@ body.closet_hangers-index h4 +header-text font-size: 150% + line-height: 1 margin: 0 auto .empty-list @@ -168,12 +193,21 @@ body.closet_hangers-index &.unlisted h4 - font-style: italic + font: + size: 125% + style: italic &:hover .closet-list-controls display: block + .visibility-form + input[type=submit] + visibility: visible + + select + border-color: $soft-border-color + &:last-child border-bottom: 0 diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 7a1b84f7..90dae381 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -67,7 +67,16 @@ = link_to_add_closet_list 'Add new list', :owned => owned, :class => 'add-closet-list' .closet-hangers-group-content = render_closet_lists(@closet_lists_by_owned[owned]) - = render_unlisted_closet_hangers(owned) + - if @unlisted_closet_hangers_by_owned[owned] + .closet-list.unlisted + - if has_lists?(owned) + %header + %h4 (Not in a list) + = form_for @user, :html => {:class => 'visibility-form'} do |f| + = f.select hangers_group_visibility_field_name(owned), + hangers_group_visibility_choices(owned) + = f.submit "Save" + .closet-list-hangers= render_unlisted_closet_hangers(owned) - if public_perspective? - unless has_hangers?(owned) %p #{@user.name} doesn't seem to #{closet_hanger_verb(owned, false)} anything. diff --git a/db/migrate/20110730174148_add_closet_hangers_visibility_to_users.rb b/db/migrate/20110730174148_add_closet_hangers_visibility_to_users.rb new file mode 100644 index 00000000..77281cef --- /dev/null +++ b/db/migrate/20110730174148_add_closet_hangers_visibility_to_users.rb @@ -0,0 +1,12 @@ +class AddClosetHangersVisibilityToUsers < ActiveRecord::Migration + def self.up + add_column :users, :owned_closet_hangers_visibility, :integer, :null => false, :default => 1 + add_column :users, :wanted_closet_hangers_visibility, :integer, :null => false, :default => 1 + end + + def self.down + remove_column :users, :wanted_closet_hangers_visibility + remove_column :users, :owned_closet_hangers_visibility + end +end + diff --git a/db/schema.rb b/db/schema.rb index c8547726..59c49369 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20110726231143) do +ActiveRecord::Schema.define(:version => 20110730174148) do create_table "auth_servers", :force => true do |t| t.string "short_name", :limit => 10, :null => false @@ -178,18 +178,20 @@ ActiveRecord::Schema.define(:version => 20110726231143) do end create_table "users", :force => true do |t| - t.string "name", :limit => 20, :null => false - t.integer "auth_server_id", :limit => 1, :null => false - t.integer "remote_id", :null => false - t.integer "points", :default => 0, :null => false - t.boolean "beta", :default => false, :null => false + t.string "name", :limit => 20, :null => false + t.integer "auth_server_id", :limit => 1, :null => false + t.integer "remote_id", :null => false + t.integer "points", :default => 0, :null => false + t.boolean "beta", :default => false, :null => false t.string "remember_token" t.datetime "remember_created_at" - t.boolean "forum_admin", :default => false, :null => false + t.boolean "forum_admin", :default => false, :null => false t.boolean "forum_moderator" - t.boolean "image_mode_tester", :default => false, :null => false - t.text "closet_description", :null => false + t.boolean "image_mode_tester", :default => false, :null => false + t.text "closet_description", :null => false t.string "neopets_username" + t.integer "owned_closet_hangers_visibility", :default => 1, :null => false + t.integer "wanted_closet_hangers_visibility", :default => 1, :null => false end create_table "zones", :force => true do |t| diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 7eed2692..5d6fe689 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -791,30 +791,64 @@ body.closet_hangers-index .closet-hangers-group > header span.show:hover, body.c body.closet_hangers-index .closet-list { border-bottom: 1px solid #aaddaa; padding: 0.5em 0; + position: relative; } -/* line 145, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 146, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .visibility-form { + display: -moz-inline-box; + -moz-box-orient: vertical; + display: inline-block; + vertical-align: middle; + *display: inline; + *vertical-align: auto; + margin: 0 auto; + position: relative; +} +/* line 151, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .visibility-form input, body.closet_hangers-index .closet-list .visibility-form select { + font-size: 85%; + margin-bottom: 0; + margin-top: 0; +} +/* line 157, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .visibility-form select { + border-color: white; +} +/* line 160, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .visibility-form input[type=submit] { + left: 100%; + position: absolute; + top: 0; + visibility: hidden; +} +/* line 166, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .visibility-form input[type=submit]:active { + top: 1px; +} +/* line 169, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list header { display: block; position: relative; } -/* line 149, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 173, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list h4 { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 150%; + line-height: 1; margin: 0 auto; } -/* line 154, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 179, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .empty-list { font-style: italic; } -/* line 157, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 182, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls { display: none; position: absolute; right: 1em; top: 0; } -/* line 163, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 188, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls a, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -855,23 +889,32 @@ body.closet_hangers-index .closet-list .closet-list-controls a:active, body.clos body.closet_hangers-index .closet-list .closet-list-controls a:hover, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:hover { background-color: #999999; } -/* line 166, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 191, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls form { display: inline; } -/* line 170, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 195, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.unlisted h4 { + font-size: 125%; font-style: italic; } -/* line 174, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 201, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .closet-list-controls { display: block; } -/* line 177, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 205, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list:hover .visibility-form input[type=submit] { + visibility: visible; +} +/* line 208, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list:hover .visibility-form select { + border-color: #aaddaa; +} +/* line 211, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:last-child { border-bottom: 0; } -/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 214, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active { -moz-border-radius: 1em; -webkit-border-radius: 1em; @@ -882,49 +925,49 @@ body.closet_hangers-index .closet-list.droppable-active { border-style: dotted; margin: 1em 0; } -/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 221, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object { -moz-opacity: 0.25; -webkit-opacity: 0.25; -o-opacity: 0.25; -khtml-opacity: 0.25; } -/* line 191, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 225, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object.ui-draggable-dragging { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 228, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-controls { display: none; } -/* line 197, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 231, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-hangers { overflow: hidden; } -/* line 201, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 235, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group-autocomplete-item span, body.closet_hangers-index .closet-list-autocomplete-item span { font-style: italic; padding: 0.2em 0.4em; } -/* line 206, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 240, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list-autocomplete-item a, body.closet_hangers-index .closet-list-autocomplete-item span { font-size: 85%; padding-left: 2em; } -/* line 213, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 247, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 216, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 250, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 221, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 255, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -965,7 +1008,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 224, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 258, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -975,73 +1018,73 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 56px; padding: 0; } -/* line 230, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 264, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 233, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 267, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 237, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 271, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 242, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 276, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { display: block; } -/* line 245, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 279, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 248, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 282, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 251, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 285, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 255, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 289, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { display: block; } -/* line 258, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 292, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 262, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 296, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 265, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 299, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 269, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 303, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 272, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 306, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 277, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 311, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 280, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 314, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 284, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 318, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 287, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 321, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } From bbb4e02b750a789df77e8a61aeb5a20476880b20 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sat, 30 Jul 2011 19:45:49 -0400 Subject: [PATCH 47/69] bug fix for floats on closet_lists#edit --- app/stylesheets/closet_lists/_form.sass | 1 + 1 file changed, 1 insertion(+) diff --git a/app/stylesheets/closet_lists/_form.sass b/app/stylesheets/closet_lists/_form.sass index 4d85c2ec..21f916d5 100644 --- a/app/stylesheets/closet_lists/_form.sass +++ b/app/stylesheets/closet_lists/_form.sass @@ -2,6 +2,7 @@ body.closet_lists-new, body.closet_lists-create, body.closet_lists-edit, body.cl +secondary-nav form ul.fields + clear: both list-style: none label From 0e522fa371a4e0384e14c565d87a4804836ee0d4 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sat, 30 Jul 2011 19:47:04 -0400 Subject: [PATCH 48/69] better handle list emptiness for drag-n-drop --- app/controllers/closet_hangers_controller.rb | 7 +- app/helpers/closet_hangers_helper.rb | 5 ++ app/stylesheets/closet_hangers/_index.sass | 7 +- app/views/closet_hangers/index.html.haml | 24 ++--- app/views/closet_lists/_closet_list.html.haml | 12 +-- public/javascripts/closet_hangers/index.js | 25 ++++-- public/stylesheets/compiled/screen.css | 90 ++++++++++--------- 7 files changed, 101 insertions(+), 69 deletions(-) diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 2d9dd540..4bd30974 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -14,10 +14,13 @@ class ClosetHangersController < ApplicationController def index @user = User.find params[:user_id] + @public_perspective = params.has_key?(:public) || !user_is?(@user) + @perspective_user = current_user unless @public_perspective + @closet_lists_by_owned = @user.closet_lists.alphabetical. includes(:hangers => :item).group_by(&:hangers_owned) - visible_groups = @user.closet_hangers_groups_visible_to(current_user) + visible_groups = @user.closet_hangers_groups_visible_to(@perspective_user) unless visible_groups.empty? @unlisted_closet_hangers_by_owned = @user.closet_hangers.unlisted. owned_before_wanted.alphabetical_by_item_name.includes(:item). @@ -25,8 +28,6 @@ class ClosetHangersController < ApplicationController else @unlisted_closet_hangers_by_owned = {} end - - @public_perspective = params.has_key?(:public) || !user_is?(@user) end # Since the user does not care about the idea of a hanger, but rather the diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index d3f7b47d..90c2d527 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -69,5 +69,10 @@ module ClosetHangersHelper :collection => @unlisted_closet_hangers_by_owned[owned], :locals => {:show_controls => !public_perspective?} end + + def unlisted_hangers_count(owned) + hangers = @unlisted_closet_hangers_by_owned[owned] + hangers ? hangers.size : 0 + end end diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 78cdab24..3fc13c8a 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -145,7 +145,7 @@ body.closet_hangers-index .visibility-form +inline-block - margin: 0 auto + margin: 0 auto 1em position: relative input, select @@ -177,6 +177,7 @@ body.closet_hangers-index margin: 0 auto .empty-list + display: none font-style: italic .closet-list-controls @@ -191,6 +192,10 @@ body.closet_hangers-index form display: inline + &[data-hangers-count="0"] + .empty-list + display: block + &.unlisted h4 font: diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 90dae381..586ed835 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -67,16 +67,20 @@ = link_to_add_closet_list 'Add new list', :owned => owned, :class => 'add-closet-list' .closet-hangers-group-content = render_closet_lists(@closet_lists_by_owned[owned]) - - if @unlisted_closet_hangers_by_owned[owned] - .closet-list.unlisted - - if has_lists?(owned) - %header - %h4 (Not in a list) - = form_for @user, :html => {:class => 'visibility-form'} do |f| - = f.select hangers_group_visibility_field_name(owned), - hangers_group_visibility_choices(owned) - = f.submit "Save" - .closet-list-hangers= render_unlisted_closet_hangers(owned) + .closet-list.unlisted{'data-hangers-count' => unlisted_hangers_count(owned)} + - if has_lists?(owned) + %header + %h4 (Not in a list) + .closet-list-content + - unless public_perspective? + = form_for @user, :html => {:class => 'visibility-form'} do |f| + = f.select hangers_group_visibility_field_name(owned), + hangers_group_visibility_choices(owned) + = f.submit "Save" + .closet-list-hangers + = render_unlisted_closet_hangers(owned) + %span.empty-list + All the items you #{closet_hanger_verb owned} are in lists. - if public_perspective? - unless has_hangers?(owned) %p #{@user.name} doesn't seem to #{closet_hanger_verb(owned, false)} anything. diff --git a/app/views/closet_lists/_closet_list.html.haml b/app/views/closet_lists/_closet_list.html.haml index 7b67f5b4..040bbf04 100644 --- a/app/views/closet_lists/_closet_list.html.haml +++ b/app/views/closet_lists/_closet_list.html.haml @@ -1,4 +1,4 @@ -.closet-list{'data-id' => closet_list.id, :id => "closet-list-#{closet_list.id}"} +.closet-list{'data-id' => closet_list.id, 'data-hangers-count' => closet_list.hangers.count, :id => "closet-list-#{closet_list.id}"} %header - if show_controls .closet-list-controls @@ -10,9 +10,9 @@ - if closet_list.description? = closet_list_description_format closet_list - .closet-list-hangers - - unless closet_list.hangers.empty? - = render_sorted_hangers(closet_list, show_controls) - - else - %span.empty-list This list is empty. + .closet-list-content + .closet-list-hangers + - unless closet_list.hangers.empty? + = render_sorted_hangers(closet_list, show_controls) + %span.empty-list This list is empty. diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index 5e1803f0..a0e0ee9c 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -126,14 +126,25 @@ return a.find('span.name').text().localeCompare(b.find('span.name').text()); } - function moveItemToList(item, listId) { - if(listId) { - var list = $('#closet-list-' + listId); + function findList(id, item) { + if(id) { + return $('#closet-list-' + id); } else { - var list = item.closest('.closet-hangers-group').find('div.closet-list.unlisted'); + return item.closest('.closet-hangers-group').find('div.closet-list.unlisted'); } - var hangersWrapper = list.find('div.closet-list-hangers'); + } + + function updateListHangersCount(el) { + el.attr('data-hangers-count', el.find('div.object').length); + } + + function moveItemToList(item, listId) { + var newList = findList(listId, item); + var oldList = item.closest('div.closet-list'); + var hangersWrapper = newList.find('div.closet-list-hangers'); item.insertIntoSortedList(hangersWrapper, compareItemsByName); + updateListHangersCount(oldList); + updateListHangersCount(newList); } function submitUpdateForm(form) { @@ -427,11 +438,11 @@ group.find('div.closet-list').droppable({ accept: '#' + group.attr('id') + ' div.object', activate: function () { - $(this).find('.closet-list-hangers').animate({opacity: 0, height: 100}, 250); + $(this).find('.closet-list-content').animate({opacity: 0, height: 100}, 250); }, activeClass: 'droppable-active', deactivate: function () { - $(this).find('.closet-list-hangers').css('height', 'auto').animate({opacity: 1}, 250); + $(this).find('.closet-list-content').css('height', 'auto').animate({opacity: 1}, 250); }, drop: function (e, ui) { var form = ui.draggable.find('form.closet-hanger-update'); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 5d6fe689..6003dc47 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -801,7 +801,7 @@ body.closet_hangers-index .closet-list .visibility-form { vertical-align: middle; *display: inline; *vertical-align: auto; - margin: 0 auto; + margin: 0 auto 1em; position: relative; } /* line 151, ../../../app/stylesheets/closet_hangers/_index.sass */ @@ -839,16 +839,17 @@ body.closet_hangers-index .closet-list h4 { } /* line 179, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .empty-list { + display: none; font-style: italic; } -/* line 182, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 183, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls { display: none; position: absolute; right: 1em; top: 0; } -/* line 188, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 189, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls a, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -889,32 +890,36 @@ body.closet_hangers-index .closet-list .closet-list-controls a:active, body.clos body.closet_hangers-index .closet-list .closet-list-controls a:hover, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:hover { background-color: #999999; } -/* line 191, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 192, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls form { display: inline; } -/* line 195, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 196, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list[data-hangers-count="0"] .empty-list { + display: block; +} +/* line 200, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.unlisted h4 { font-size: 125%; font-style: italic; } -/* line 201, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 206, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .closet-list-controls { display: block; } -/* line 205, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 210, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form input[type=submit] { visibility: visible; } -/* line 208, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 213, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form select { border-color: #aaddaa; } -/* line 211, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 216, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:last-child { border-bottom: 0; } -/* line 214, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 219, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active { -moz-border-radius: 1em; -webkit-border-radius: 1em; @@ -925,49 +930,49 @@ body.closet_hangers-index .closet-list.droppable-active { border-style: dotted; margin: 1em 0; } -/* line 221, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 226, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object { -moz-opacity: 0.25; -webkit-opacity: 0.25; -o-opacity: 0.25; -khtml-opacity: 0.25; } -/* line 225, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 230, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object.ui-draggable-dragging { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 228, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 233, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-controls { display: none; } -/* line 231, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 236, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-hangers { overflow: hidden; } -/* line 235, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 240, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group-autocomplete-item span, body.closet_hangers-index .closet-list-autocomplete-item span { font-style: italic; padding: 0.2em 0.4em; } -/* line 240, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 245, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list-autocomplete-item a, body.closet_hangers-index .closet-list-autocomplete-item span { font-size: 85%; padding-left: 2em; } -/* line 247, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 252, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 250, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 255, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 255, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 260, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1008,7 +1013,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 258, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 263, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -1018,73 +1023,73 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 56px; padding: 0; } -/* line 264, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 269, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 267, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 272, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 271, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 276, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 276, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 281, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { display: block; } -/* line 279, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 284, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 282, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 287, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 285, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 290, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 289, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 294, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { display: block; } -/* line 292, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 297, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 296, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 301, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 299, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 304, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 303, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 308, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 306, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 311, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 311, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 316, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 314, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 319, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 318, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 323, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 321, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 326, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } @@ -1105,31 +1110,32 @@ body.closet_lists-new #secondary-nav, body.closet_lists-create #secondary-nav, b } /* line 4, ../../../app/stylesheets/closet_lists/_form.sass */ body.closet_lists-new form ul.fields, body.closet_lists-create form ul.fields, body.closet_lists-edit form ul.fields, body.closet_lists-update form ul.fields { + clear: both; list-style: none; } -/* line 7, ../../../app/stylesheets/closet_lists/_form.sass */ +/* line 8, ../../../app/stylesheets/closet_lists/_form.sass */ body.closet_lists-new form ul.fields label, body.closet_lists-create form ul.fields label, body.closet_lists-edit form ul.fields label, body.closet_lists-update form ul.fields label { float: left; font-weight: bold; margin-right: 1em; } -/* line 12, ../../../app/stylesheets/closet_lists/_form.sass */ +/* line 13, ../../../app/stylesheets/closet_lists/_form.sass */ body.closet_lists-new form ul.fields li, body.closet_lists-create form ul.fields li, body.closet_lists-edit form ul.fields li, body.closet_lists-update form ul.fields li { padding: 0.75em 0; width: 25em; } -/* line 16, ../../../app/stylesheets/closet_lists/_form.sass */ +/* line 17, ../../../app/stylesheets/closet_lists/_form.sass */ body.closet_lists-new form ul.fields input, body.closet_lists-new form ul.fields textarea, body.closet_lists-new form ul.fields select, body.closet_lists-create form ul.fields input, body.closet_lists-create form ul.fields textarea, body.closet_lists-create form ul.fields select, body.closet_lists-edit form ul.fields input, body.closet_lists-edit form ul.fields textarea, body.closet_lists-edit form ul.fields select, body.closet_lists-update form ul.fields input, body.closet_lists-update form ul.fields textarea, body.closet_lists-update form ul.fields select { clear: both; display: block; margin-top: 0.25em; width: 80%; } -/* line 22, ../../../app/stylesheets/closet_lists/_form.sass */ +/* line 23, ../../../app/stylesheets/closet_lists/_form.sass */ body.closet_lists-new form ul.fields textarea, body.closet_lists-create form ul.fields textarea, body.closet_lists-edit form ul.fields textarea, body.closet_lists-update form ul.fields textarea { height: 12em; } -/* line 25, ../../../app/stylesheets/closet_lists/_form.sass */ +/* line 26, ../../../app/stylesheets/closet_lists/_form.sass */ body.closet_lists-new form ul.fields .hint, body.closet_lists-create form ul.fields .hint, body.closet_lists-edit form ul.fields .hint, body.closet_lists-update form ul.fields .hint { display: block; font-size: 85%; From 34a4ef201a835daaf1c2807d03a5a9eabd9759f6 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sat, 30 Jul 2011 22:08:38 -0400 Subject: [PATCH 49/69] privacy dropdowns moved to be more out of the way --- app/helpers/closet_hangers_helper.rb | 10 +- app/models/closet_visibility.rb | 2 +- app/stylesheets/closet_hangers/_index.sass | 31 +++-- app/views/closet_hangers/index.html.haml | 9 +- public/javascripts/closet_hangers/index.js | 26 +++++ public/stylesheets/compiled/screen.css | 127 ++++++++++++--------- 6 files changed, 135 insertions(+), 70 deletions(-) diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index 90c2d527..f05c0f02 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -19,10 +19,18 @@ module ClosetHangersHelper def hangers_group_visibility_choices(owned) ClosetVisibility.levels.map do |level| - [level.description("these items"), level.id] + [level.name.to_s.humanize, level.id] end end + def closet_visibility_descriptions + content = '' + ClosetVisibility.levels.each do |level| + content << content_tag(:li, level.description('these items'), 'data-id' => level.id) + end + content_tag :ul, content.html_safe, :class => 'visibility-descriptions' + end + # Do we have either unlisted hangers that are owned/wanted, or non-empty # owned/wanted lists? def has_hangers?(owned) diff --git a/app/models/closet_visibility.rb b/app/models/closet_visibility.rb index d2c675f0..d32c579b 100644 --- a/app/models/closet_visibility.rb +++ b/app/models/closet_visibility.rb @@ -31,7 +31,7 @@ module ClosetVisibility ), Level.new( :id => 2, - :name => :advertised, + :name => :trading, :description => "$SUBJECT will be publicly listed for trades" ) ] diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 3fc13c8a..f7de1cef 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -144,12 +144,15 @@ body.closet_hangers-index position: relative .visibility-form - +inline-block - margin: 0 auto 1em - position: relative + font-size: 85% + left: .5em + position: absolute + text-align: left + top: .25em + z-index: 10 input, select - font-size: 85% + font-size: inherit margin: bottom: 0 top: 0 @@ -158,14 +161,25 @@ body.closet_hangers-index border-color: $background-color input[type=submit] - left: 100% - position: absolute - top: 0 visibility: hidden &:active top: 1px + .visibility-descriptions + +opacity(.75) + background: $background-color + font-style: italic + list-style: none + padding: 0 .5em + + li + display: none + + &:hover + .visibility-descriptions li.current + display: block + header display: block position: relative @@ -174,7 +188,8 @@ body.closet_hangers-index +header-text font-size: 150% line-height: 1 - margin: 0 auto + margin: 0 auto .67em + width: 50% .empty-list display: none diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 586ed835..c1a0cf3c 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -68,15 +68,16 @@ .closet-hangers-group-content = render_closet_lists(@closet_lists_by_owned[owned]) .closet-list.unlisted{'data-hangers-count' => unlisted_hangers_count(owned)} - - if has_lists?(owned) - %header - %h4 (Not in a list) - .closet-list-content + %header - unless public_perspective? = form_for @user, :html => {:class => 'visibility-form'} do |f| = f.select hangers_group_visibility_field_name(owned), hangers_group_visibility_choices(owned) = f.submit "Save" + = closet_visibility_descriptions + - if has_lists?(owned) + %h4 (Not in a list) + .closet-list-content .closet-list-hangers = render_unlisted_closet_hangers(owned) %span.empty-list diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index a0e0ee9c..a290e83e 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -429,7 +429,9 @@ }); /* + Closet list droppable + */ onHangersInit(function () { @@ -454,7 +456,31 @@ }); /* + + Visibility Descriptions + + */ + + function updateVisibilityDescription() { + var descriptions = $(this).closest('.visibility-form'). + find('ul.visibility-descriptions'); + + descriptions.children('li.current').removeClass('current'); + descriptions.children('li[data-id=' + $(this).val() + ']').addClass('current'); + } + + function visibilitySelects() { return $('form.visibility-form select') } + + visibilitySelects().live('change', updateVisibilityDescription); + + onHangersInit(function () { + visibilitySelects().each(updateVisibilityDescription); + }); + + /* + Initialize + */ hangersInit(); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 6003dc47..2ef5f584 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -795,30 +795,25 @@ body.closet_hangers-index .closet-list { } /* line 146, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form { - display: -moz-inline-box; - -moz-box-orient: vertical; - display: inline-block; - vertical-align: middle; - *display: inline; - *vertical-align: auto; - margin: 0 auto 1em; - position: relative; -} -/* line 151, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index .closet-list .visibility-form input, body.closet_hangers-index .closet-list .visibility-form select { font-size: 85%; + left: 0.5em; + position: absolute; + text-align: left; + top: 0.25em; + z-index: 10; +} +/* line 154, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .visibility-form input, body.closet_hangers-index .closet-list .visibility-form select { + font-size: inherit; margin-bottom: 0; margin-top: 0; } -/* line 157, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 160, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form select { border-color: white; } -/* line 160, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 163, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit] { - left: 100%; - position: absolute; - top: 0; visibility: hidden; } /* line 166, ../../../app/stylesheets/closet_hangers/_index.sass */ @@ -826,30 +821,50 @@ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:activ top: 1px; } /* line 169, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions { + -moz-opacity: 0.75; + -webkit-opacity: 0.75; + -o-opacity: 0.75; + -khtml-opacity: 0.75; + background: white; + font-style: italic; + list-style: none; + padding: 0 0.5em; +} +/* line 176, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions li { + display: none; +} +/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .visibility-form:hover .visibility-descriptions li.current { + display: block; +} +/* line 183, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list header { display: block; position: relative; } -/* line 173, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list h4 { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 150%; line-height: 1; - margin: 0 auto; + margin: 0 auto 0.67em; + width: 50%; } -/* line 179, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .empty-list { display: none; font-style: italic; } -/* line 183, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 198, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls { display: none; position: absolute; right: 1em; top: 0; } -/* line 189, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 204, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls a, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -890,36 +905,36 @@ body.closet_hangers-index .closet-list .closet-list-controls a:active, body.clos body.closet_hangers-index .closet-list .closet-list-controls a:hover, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:hover { background-color: #999999; } -/* line 192, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 207, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls form { display: inline; } -/* line 196, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 211, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list[data-hangers-count="0"] .empty-list { display: block; } -/* line 200, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 215, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.unlisted h4 { font-size: 125%; font-style: italic; } -/* line 206, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 221, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .closet-list-controls { display: block; } -/* line 210, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 225, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form input[type=submit] { visibility: visible; } -/* line 213, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 228, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form select { border-color: #aaddaa; } -/* line 216, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 231, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:last-child { border-bottom: 0; } -/* line 219, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 234, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active { -moz-border-radius: 1em; -webkit-border-radius: 1em; @@ -930,49 +945,49 @@ body.closet_hangers-index .closet-list.droppable-active { border-style: dotted; margin: 1em 0; } -/* line 226, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 241, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object { -moz-opacity: 0.25; -webkit-opacity: 0.25; -o-opacity: 0.25; -khtml-opacity: 0.25; } -/* line 230, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 245, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object.ui-draggable-dragging { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 233, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 248, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-controls { display: none; } -/* line 236, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 251, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-hangers { overflow: hidden; } -/* line 240, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 255, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group-autocomplete-item span, body.closet_hangers-index .closet-list-autocomplete-item span { font-style: italic; padding: 0.2em 0.4em; } -/* line 245, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 260, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list-autocomplete-item a, body.closet_hangers-index .closet-list-autocomplete-item span { font-size: 85%; padding-left: 2em; } -/* line 252, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 267, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 255, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 270, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 260, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 275, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1013,7 +1028,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 263, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 278, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -1023,73 +1038,73 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 56px; padding: 0; } -/* line 269, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 284, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 272, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 287, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 276, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 291, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 281, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 296, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { display: block; } -/* line 284, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 299, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 287, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 302, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 290, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 305, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 294, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 309, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { display: block; } -/* line 297, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 312, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 301, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 316, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 304, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 319, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 308, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 323, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 311, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 326, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 316, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 331, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 319, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 334, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 323, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 338, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 326, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 341, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } From 23250be38416f06e4d0a8dce8578527b76549864 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sat, 30 Jul 2011 22:13:48 -0400 Subject: [PATCH 50/69] hide visibility form when drag-n-dropping --- app/stylesheets/closet_hangers/_index.sass | 3 ++ public/stylesheets/compiled/screen.css | 50 ++++++++++++---------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index f7de1cef..09d1341d 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -251,6 +251,9 @@ body.closet_hangers-index .closet-list-hangers overflow: hidden + .visibility-form + display: none + .closet-hangers-group-autocomplete-item, .closet-list-autocomplete-item span font-style: italic diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 2ef5f584..43de3536 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -967,27 +967,31 @@ body.closet_hangers-index .closet-list.droppable-active .closet-list-controls { body.closet_hangers-index .closet-list.droppable-active .closet-list-hangers { overflow: hidden; } -/* line 255, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 254, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list.droppable-active .visibility-form { + display: none; +} +/* line 258, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group-autocomplete-item span, body.closet_hangers-index .closet-list-autocomplete-item span { font-style: italic; padding: 0.2em 0.4em; } -/* line 260, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 263, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list-autocomplete-item a, body.closet_hangers-index .closet-list-autocomplete-item span { font-size: 85%; padding-left: 2em; } -/* line 267, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 270, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 270, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 273, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 275, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 278, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1028,7 +1032,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 278, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 281, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -1038,73 +1042,73 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 56px; padding: 0; } -/* line 284, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 287, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 287, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 290, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 291, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 294, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 296, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 299, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { display: block; } -/* line 299, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 302, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 302, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 305, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 305, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 308, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 309, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 312, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { display: block; } -/* line 312, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 315, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 316, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 319, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 319, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 322, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 323, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 326, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 326, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 329, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 331, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 334, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 334, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 337, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 338, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 341, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 341, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 344, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } From ad45d755da6f239f06ebcb1085cda47adc9faed2 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sat, 30 Jul 2011 22:17:42 -0400 Subject: [PATCH 51/69] visibility form submit is a context button --- app/stylesheets/closet_hangers/_index.sass | 2 + public/stylesheets/compiled/screen.css | 129 ++++++++++++++------- 2 files changed, 86 insertions(+), 45 deletions(-) diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 09d1341d..7d82c72a 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -161,6 +161,8 @@ body.closet_hangers-index border-color: $background-color input[type=submit] + +context-button + font-size: inherit visibility: hidden &:active diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 43de3536..d3aacccd 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -814,13 +814,52 @@ body.closet_hangers-index .closet-list .visibility-form select { } /* line 163, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit] { + /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + background: #006400 url('/images/alert-overlay.png?1296599919') repeat-x; + border: 0; + display: inline-block; + padding: 0.5em 0.75em 0.45em; + color: white; + text-decoration: none; + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); + border-bottom: 1px solid rgba(0, 0, 0, 0.25); + position: relative; + font-weight: bold; + line-height: 1; + background: #aaaaaa url('/images/alert-overlay.png?1296599919') repeat-x; + -moz-opacity: 0.9; + -webkit-opacity: 0.9; + -o-opacity: 0.9; + -khtml-opacity: 0.9; + font-size: 80%; + font-size: inherit; visibility: hidden; } -/* line 166, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index .closet-list .visibility-form input[type=submit]:hover { + background-color: #005300; +} +/* line 53, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index .closet-list .visibility-form input[type=submit]:hover { + color: white; +} +/* line 55, ../../../app/stylesheets/partials/clean/_mixins.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:active { top: 1px; } -/* line 169, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index .closet-list .visibility-form input[type=submit]:hover { + background-color: #999999; +} +/* line 168, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index .closet-list .visibility-form input[type=submit]:active { + top: 1px; +} +/* line 171, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -831,20 +870,20 @@ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions list-style: none; padding: 0 0.5em; } -/* line 176, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 178, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions li { display: none; } -/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 182, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form:hover .visibility-descriptions li.current { display: block; } -/* line 183, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 185, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list header { display: block; position: relative; } -/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 189, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list h4 { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 150%; @@ -852,19 +891,19 @@ body.closet_hangers-index .closet-list h4 { margin: 0 auto 0.67em; width: 50%; } -/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 196, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .empty-list { display: none; font-style: italic; } -/* line 198, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 200, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls { display: none; position: absolute; right: 1em; top: 0; } -/* line 204, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 206, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls a, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -905,36 +944,36 @@ body.closet_hangers-index .closet-list .closet-list-controls a:active, body.clos body.closet_hangers-index .closet-list .closet-list-controls a:hover, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:hover { background-color: #999999; } -/* line 207, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 209, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls form { display: inline; } -/* line 211, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 213, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list[data-hangers-count="0"] .empty-list { display: block; } -/* line 215, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 217, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.unlisted h4 { font-size: 125%; font-style: italic; } -/* line 221, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 223, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .closet-list-controls { display: block; } -/* line 225, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 227, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form input[type=submit] { visibility: visible; } -/* line 228, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 230, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form select { border-color: #aaddaa; } -/* line 231, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 233, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:last-child { border-bottom: 0; } -/* line 234, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 236, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active { -moz-border-radius: 1em; -webkit-border-radius: 1em; @@ -945,53 +984,53 @@ body.closet_hangers-index .closet-list.droppable-active { border-style: dotted; margin: 1em 0; } -/* line 241, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 243, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object { -moz-opacity: 0.25; -webkit-opacity: 0.25; -o-opacity: 0.25; -khtml-opacity: 0.25; } -/* line 245, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 247, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object.ui-draggable-dragging { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 248, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 250, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-controls { display: none; } -/* line 251, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 253, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-hangers { overflow: hidden; } -/* line 254, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 256, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .visibility-form { display: none; } -/* line 258, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 260, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group-autocomplete-item span, body.closet_hangers-index .closet-list-autocomplete-item span { font-style: italic; padding: 0.2em 0.4em; } -/* line 263, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 265, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list-autocomplete-item a, body.closet_hangers-index .closet-list-autocomplete-item span { font-size: 85%; padding-left: 2em; } -/* line 270, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 272, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 273, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 275, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 0; } -/* line 278, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 280, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1032,7 +1071,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 281, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 283, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -1042,73 +1081,73 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 56px; padding: 0; } -/* line 287, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 289, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 290, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 292, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 294, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 296, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 299, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 301, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { display: block; } -/* line 302, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 304, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 305, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 307, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 308, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 310, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 312, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 314, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { display: block; } -/* line 315, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 317, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 319, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 321, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 322, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 324, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 326, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 328, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 329, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 331, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 334, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 336, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 337, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 339, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 341, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 343, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 344, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 346, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } From 0c92bf5987e0024e1f8d129a6d5ceeecb7a47fb1 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sat, 30 Jul 2011 22:34:27 -0400 Subject: [PATCH 52/69] set list visibility in closet_lists#edit --- app/controllers/closet_hangers_controller.rb | 12 ++++++++++-- app/helpers/closet_hangers_helper.rb | 4 ++-- app/models/closet_list.rb | 7 ++++++- app/models/closet_visibility.rb | 4 ++++ app/stylesheets/closet_lists/_form.sass | 2 +- app/views/closet_hangers/index.html.haml | 2 +- app/views/closet_lists/_form.html.haml | 3 +++ .../20110731021808_add_visibility_to_closet_lists.rb | 10 ++++++++++ db/schema.rb | 5 +++-- public/stylesheets/compiled/screen.css | 2 +- 10 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 db/migrate/20110731021808_add_visibility_to_closet_lists.rb diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 4bd30974..ef21d496 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -17,8 +17,16 @@ class ClosetHangersController < ApplicationController @public_perspective = params.has_key?(:public) || !user_is?(@user) @perspective_user = current_user unless @public_perspective - @closet_lists_by_owned = @user.closet_lists.alphabetical. - includes(:hangers => :item).group_by(&:hangers_owned) + @closet_lists_by_owned = @user.closet_lists. + alphabetical.includes(:hangers => :item) + unless @perspective_user == @user + # If we run this when the user matches, we'll end up with effectively: + # WHERE belongs_to_user AND (is_public OR belongs_to_user) + # and it's a bit silly to put the SQL server through a condition that's + # always true. + @closet_lists_by_owned = @closet_lists_by_owned.visible_to(@perspective_user) + end + @closet_lists_by_owned = @closet_lists_by_owned.group_by(&:hangers_owned) visible_groups = @user.closet_hangers_groups_visible_to(@perspective_user) unless visible_groups.empty? diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index f05c0f02..65026331 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -17,9 +17,9 @@ module ClosetHangersHelper owned ? :owned_closet_hangers_visibility : :wanted_closet_hangers_visibility end - def hangers_group_visibility_choices(owned) + def closet_visibility_choices(*args) ClosetVisibility.levels.map do |level| - [level.name.to_s.humanize, level.id] + [level.send(*args), level.id] end end diff --git a/app/models/closet_list.rb b/app/models/closet_list.rb index d74fd956..10358be3 100644 --- a/app/models/closet_list.rb +++ b/app/models/closet_list.rb @@ -3,13 +3,18 @@ class ClosetList < ActiveRecord::Base has_many :hangers, :class_name => 'ClosetHanger', :foreign_key => 'list_id', :dependent => :nullify - attr_accessible :description, :hangers_owned, :name + attr_accessible :description, :hangers_owned, :name, :visibility validates :name, :presence => true, :uniqueness => {:scope => :user_id} validates :user, :presence => true validates :hangers_owned, :inclusion => {:in => [true, false], :message => "can't be blank"} scope :alphabetical, order(:name) + scope :visible_to, lambda { |user| + condition = arel_table[:visibility].gteq(ClosetVisibility[:public].id) + condition = condition.or(arel_table[:user_id].eq(user.id)) if user + where(condition) + } after_save :sync_hangers_owned! diff --git a/app/models/closet_visibility.rb b/app/models/closet_visibility.rb index d32c579b..4cbc0e9a 100644 --- a/app/models/closet_visibility.rb +++ b/app/models/closet_visibility.rb @@ -16,6 +16,10 @@ module ClosetVisibility @description end end + + def human_name + name.to_s.humanize + end end LEVELS = [ diff --git a/app/stylesheets/closet_lists/_form.sass b/app/stylesheets/closet_lists/_form.sass index 21f916d5..2c451ef9 100644 --- a/app/stylesheets/closet_lists/_form.sass +++ b/app/stylesheets/closet_lists/_form.sass @@ -12,7 +12,7 @@ body.closet_lists-new, body.closet_lists-create, body.closet_lists-edit, body.cl li padding: 0.75em 0 - width: 25em + width: 35em input, textarea, select clear: both diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index c1a0cf3c..914b259e 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -72,7 +72,7 @@ - unless public_perspective? = form_for @user, :html => {:class => 'visibility-form'} do |f| = f.select hangers_group_visibility_field_name(owned), - hangers_group_visibility_choices(owned) + closet_visibility_choices(:human_name) = f.submit "Save" = closet_visibility_descriptions - if has_lists?(owned) diff --git a/app/views/closet_lists/_form.html.haml b/app/views/closet_lists/_form.html.haml index d4d43c03..fb84c0d2 100644 --- a/app/views/closet_lists/_form.html.haml +++ b/app/views/closet_lists/_form.html.haml @@ -10,6 +10,9 @@ %li = f.label :hangers_owned, 'This is a list for…'.html_safe = f.select :hangers_owned, hangers_owned_options + %li + = f.label :visibility, 'Who can see this list?' + = f.select :visibility, closet_visibility_choices(:description, 'Items in this list') %li = f.label :description %span.hint diff --git a/db/migrate/20110731021808_add_visibility_to_closet_lists.rb b/db/migrate/20110731021808_add_visibility_to_closet_lists.rb new file mode 100644 index 00000000..68d62874 --- /dev/null +++ b/db/migrate/20110731021808_add_visibility_to_closet_lists.rb @@ -0,0 +1,10 @@ +class AddVisibilityToClosetLists < ActiveRecord::Migration + def self.up + add_column :closet_lists, :visibility, :integer, :null => false, :default => 1 + end + + def self.down + remove_column :closet_lists, :visibility + end +end + diff --git a/db/schema.rb b/db/schema.rb index 59c49369..b966ec98 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20110730174148) do +ActiveRecord::Schema.define(:version => 20110731021808) do create_table "auth_servers", :force => true do |t| t.string "short_name", :limit => 10, :null => false @@ -34,9 +34,10 @@ ActiveRecord::Schema.define(:version => 20110730174148) do t.string "name" t.text "description" t.integer "user_id" - t.boolean "hangers_owned", :null => false + t.boolean "hangers_owned", :null => false t.datetime "created_at" t.datetime "updated_at" + t.integer "visibility", :default => 1, :null => false end create_table "contributions", :force => true do |t| diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index d3aacccd..bdc51640 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -1180,7 +1180,7 @@ body.closet_lists-new form ul.fields label, body.closet_lists-create form ul.fie /* line 13, ../../../app/stylesheets/closet_lists/_form.sass */ body.closet_lists-new form ul.fields li, body.closet_lists-create form ul.fields li, body.closet_lists-edit form ul.fields li, body.closet_lists-update form ul.fields li { padding: 0.75em 0; - width: 25em; + width: 35em; } /* line 17, ../../../app/stylesheets/closet_lists/_form.sass */ body.closet_lists-new form ul.fields input, body.closet_lists-new form ul.fields textarea, body.closet_lists-new form ul.fields select, body.closet_lists-create form ul.fields input, body.closet_lists-create form ul.fields textarea, body.closet_lists-create form ul.fields select, body.closet_lists-edit form ul.fields input, body.closet_lists-edit form ul.fields textarea, body.closet_lists-edit form ul.fields select, body.closet_lists-update form ul.fields input, body.closet_lists-update form ul.fields textarea, body.closet_lists-update form ul.fields select { From 11b7ae74dba40fd5a436d9e0e61c4fc1cc93ceb1 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sat, 30 Jul 2011 22:47:06 -0400 Subject: [PATCH 53/69] list visibility forms on Your Items --- app/helpers/closet_hangers_helper.rb | 4 ++-- app/views/closet_lists/_closet_list.html.haml | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index 65026331..81aa3577 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -23,10 +23,10 @@ module ClosetHangersHelper end end - def closet_visibility_descriptions + def closet_visibility_descriptions(subject='these items') content = '' ClosetVisibility.levels.each do |level| - content << content_tag(:li, level.description('these items'), 'data-id' => level.id) + content << content_tag(:li, level.description(subject), 'data-id' => level.id) end content_tag :ul, content.html_safe, :class => 'visibility-descriptions' end diff --git a/app/views/closet_lists/_closet_list.html.haml b/app/views/closet_lists/_closet_list.html.haml index 040bbf04..a78183a4 100644 --- a/app/views/closet_lists/_closet_list.html.haml +++ b/app/views/closet_lists/_closet_list.html.haml @@ -1,6 +1,10 @@ .closet-list{'data-id' => closet_list.id, 'data-hangers-count' => closet_list.hangers.count, :id => "closet-list-#{closet_list.id}"} %header - if show_controls + = form_for [closet_list.user, closet_list], :html => {:class => 'visibility-form'} do |f| + = f.select :visibility, closet_visibility_choices(:human_name) + = f.submit "Save" + = closet_visibility_descriptions('items in this list') .closet-list-controls = link_to 'Edit', edit_user_closet_list_path(closet_list.user, closet_list) = form_tag user_closet_list_path(closet_list.user, closet_list), :method => 'delete' do From b9700e3d7cda660172c83882c8e06787cc24228e Mon Sep 17 00:00:00 2001 From: Matchu Date: Sat, 30 Jul 2011 23:03:43 -0400 Subject: [PATCH 54/69] show owns/wanted items on somene elses items list --- app/controllers/closet_hangers_controller.rb | 15 ++ app/stylesheets/_layout.sass | 3 +- app/stylesheets/closet_hangers/_index.sass | 13 +- .../closet_hangers/_closet_hanger.html.haml | 2 +- public/javascripts/closet_hangers/index.js | 2 +- public/stylesheets/compiled/screen.css | 142 +++++++++--------- 6 files changed, 97 insertions(+), 80 deletions(-) diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index ef21d496..95ea986e 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -36,6 +36,21 @@ class ClosetHangersController < ApplicationController else @unlisted_closet_hangers_by_owned = {} end + + if @public_perspective + items = [] + @closet_lists_by_owned.each do |owned, lists| + lists.each do |list| + list.hangers.each { |hanger| items << hanger.item } + end + end + + @unlisted_closet_hangers_by_owned.each do |owned, hangers| + hangers.each { |hanger| items << hanger.item } + end + + current_user.assign_closeted_to_items!(items) + end end # Since the user does not care about the idea of a hanger, but rather the diff --git a/app/stylesheets/_layout.sass b/app/stylesheets/_layout.sass index bed2cd43..e2e50bbc 100644 --- a/app/stylesheets/_layout.sass +++ b/app/stylesheets/_layout.sass @@ -196,8 +196,9 @@ ul.buttons .nc-icon right: ($object-width - $object-img-size) / 2 + $object-padding + $closeted-icons-left: ($object-width - $object-img-size) / 2 + $object-padding .closeted-icons - left: ($object-width - $object-img-size) / 2 + $object-padding + left: $closeted-icons-left dt font-weight: bold diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 7d82c72a..9cbb500a 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -82,12 +82,12 @@ body.closet_hangers-index .quantity +opacity(.75) background: white - padding: 2px 4px + padding: 6px 4px 4px position: absolute left: ($object-width - $object-img-size) / 2 + $object-padding line-height: 1 text-align: left - top: $object-img-size - 20px + top: 0 span, input[type=number] font-size: 16px @@ -96,8 +96,9 @@ body.closet_hangers-index form display: none - .quantity-1 - display: none + &[data-quantity="1"] + .quantity + display: none .closet-hangers-group border-top: 1px solid $module-border-color @@ -275,7 +276,7 @@ body.closet_hangers-index .closet-hanger-destroy position: absolute right: ($object-width - $object-img-size) / 2 + $object-padding - top: 0 + top: $object-img-size - 28px input +context-button @@ -283,7 +284,7 @@ body.closet_hangers-index .quantity +opacity(1) background: transparent - top: $object-img-size - 24px + top: 0 padding: 0 span diff --git a/app/views/closet_hangers/_closet_hanger.html.haml b/app/views/closet_hangers/_closet_hanger.html.haml index 3e92dcba..63c6a936 100644 --- a/app/views/closet_hangers/_closet_hanger.html.haml +++ b/app/views/closet_hangers/_closet_hanger.html.haml @@ -1,5 +1,5 @@ - show_controls ||= false # we could do user check here, but may as well do it once -.object{'data-item-id' => closet_hanger.item_id} +.object{'data-item-id' => closet_hanger.item_id, 'data-quantity' => closet_hanger.quantity} = render :partial => 'items/item_link', :locals => {:item => closet_hanger.item} .quantity{:class => "quantity-#{closet_hanger.quantity}"} %span= closet_hanger.quantity diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index a290e83e..01e2d841 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -156,7 +156,7 @@ var objectWrapper = form.closest(".object").addClass("loading"); var newQuantity = quantityEl.val(); var quantitySpan = objectWrapper.find(".quantity span").text(newQuantity); - quantitySpan.parent().attr('class', 'quantity quantity-' + newQuantity); + objectWrapper.attr('data-quantity', newQuantity); var data = form.serialize(); // get data before disabling inputs objectWrapper.disableForms(); form.data('loading', true); diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index bdc51640..d0950786 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -332,22 +332,22 @@ ul.buttons li, ul.buttons li form { .object .nc-icon { right: 18px; } -/* line 199, ../../../app/stylesheets/_layout.sass */ +/* line 200, ../../../app/stylesheets/_layout.sass */ .object .closeted-icons { left: 18px; } -/* line 202, ../../../app/stylesheets/_layout.sass */ +/* line 203, ../../../app/stylesheets/_layout.sass */ dt { font-weight: bold; } -/* line 205, ../../../app/stylesheets/_layout.sass */ +/* line 206, ../../../app/stylesheets/_layout.sass */ dd { margin: 0 0 1.5em 1em; } -/* line 208, ../../../app/stylesheets/_layout.sass */ +/* line 209, ../../../app/stylesheets/_layout.sass */ #home-link { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 175%; @@ -358,21 +358,21 @@ dd { position: absolute; top: 0; } -/* line 218, ../../../app/stylesheets/_layout.sass */ +/* line 219, ../../../app/stylesheets/_layout.sass */ #home-link:hover { background: #eeffee; text-decoration: none; } -/* line 221, ../../../app/stylesheets/_layout.sass */ +/* line 222, ../../../app/stylesheets/_layout.sass */ #home-link span:before { content: "<< "; } -/* line 225, ../../../app/stylesheets/_layout.sass */ +/* line 226, ../../../app/stylesheets/_layout.sass */ .pagination a, .pagination span { margin: 0 0.5em; } -/* line 227, ../../../app/stylesheets/_layout.sass */ +/* line 228, ../../../app/stylesheets/_layout.sass */ .pagination .current { font-weight: bold; } @@ -694,12 +694,12 @@ body.closet_hangers-index #closet-hangers .object .quantity { -o-opacity: 0.75; -khtml-opacity: 0.75; background: white; - padding: 2px 4px; + padding: 6px 4px 4px; position: absolute; left: 18px; line-height: 1; text-align: left; - top: 60px; + top: 0; } /* line 92, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { @@ -710,17 +710,17 @@ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_ha body.closet_hangers-index #closet-hangers .object form { display: none; } -/* line 99, ../../../app/stylesheets/closet_hangers/_index.sass */ -body.closet_hangers-index #closet-hangers .object .quantity-1 { +/* line 100, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers .object[data-quantity="1"] .quantity { display: none; } -/* line 102, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 103, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group { border-top: 1px solid #006600; margin-bottom: 2em; padding-bottom: 1em; } -/* line 107, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 108, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header { border-bottom: 1px solid #aaddaa; display: block; @@ -728,12 +728,12 @@ body.closet_hangers-index .closet-hangers-group > header { padding: 0.25em 0; position: relative; } -/* line 114, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 115, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header h3 { font-size: 250%; margin: 0; } -/* line 118, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 119, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header .add-closet-list { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -768,12 +768,12 @@ body.closet_hangers-index .closet-hangers-group > header .add-closet-list:hover body.closet_hangers-index .closet-hangers-group > header .add-closet-list:active { top: 1px; } -/* line 125, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 126, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header .add-closet-list:active { margin-bottom: -1.1em; top: auto; } -/* line 129, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 130, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header span.show, body.closet_hangers-index .closet-hangers-group > header span.hide { color: #448844; display: none; @@ -782,18 +782,18 @@ body.closet_hangers-index .closet-hangers-group > header span.show, body.closet_ position: absolute; top: 1em; } -/* line 137, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 138, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header span.show:hover, body.closet_hangers-index .closet-hangers-group > header span.hide:hover { color: inherit; text-decoration: underline; } -/* line 141, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 142, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list { border-bottom: 1px solid #aaddaa; padding: 0.5em 0; position: relative; } -/* line 146, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 147, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form { font-size: 85%; left: 0.5em; @@ -802,17 +802,17 @@ body.closet_hangers-index .closet-list .visibility-form { top: 0.25em; z-index: 10; } -/* line 154, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 155, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input, body.closet_hangers-index .closet-list .visibility-form select { font-size: inherit; margin-bottom: 0; margin-top: 0; } -/* line 160, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 161, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form select { border-color: white; } -/* line 163, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 164, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -855,11 +855,11 @@ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:activ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:hover { background-color: #999999; } -/* line 168, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 169, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:active { top: 1px; } -/* line 171, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 172, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -870,20 +870,20 @@ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions list-style: none; padding: 0 0.5em; } -/* line 178, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 179, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions li { display: none; } -/* line 182, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 183, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form:hover .visibility-descriptions li.current { display: block; } -/* line 185, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 186, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list header { display: block; position: relative; } -/* line 189, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 190, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list h4 { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 150%; @@ -891,19 +891,19 @@ body.closet_hangers-index .closet-list h4 { margin: 0 auto 0.67em; width: 50%; } -/* line 196, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 197, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .empty-list { display: none; font-style: italic; } -/* line 200, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 201, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls { display: none; position: absolute; right: 1em; top: 0; } -/* line 206, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 207, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls a, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -944,36 +944,36 @@ body.closet_hangers-index .closet-list .closet-list-controls a:active, body.clos body.closet_hangers-index .closet-list .closet-list-controls a:hover, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:hover { background-color: #999999; } -/* line 209, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 210, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls form { display: inline; } -/* line 213, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 214, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list[data-hangers-count="0"] .empty-list { display: block; } -/* line 217, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 218, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.unlisted h4 { font-size: 125%; font-style: italic; } -/* line 223, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 224, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .closet-list-controls { display: block; } -/* line 227, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 228, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form input[type=submit] { visibility: visible; } -/* line 230, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 231, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form select { border-color: #aaddaa; } -/* line 233, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 234, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:last-child { border-bottom: 0; } -/* line 236, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 237, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active { -moz-border-radius: 1em; -webkit-border-radius: 1em; @@ -984,53 +984,53 @@ body.closet_hangers-index .closet-list.droppable-active { border-style: dotted; margin: 1em 0; } -/* line 243, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 244, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object { -moz-opacity: 0.25; -webkit-opacity: 0.25; -o-opacity: 0.25; -khtml-opacity: 0.25; } -/* line 247, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 248, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object.ui-draggable-dragging { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 250, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 251, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-controls { display: none; } -/* line 253, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 254, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-hangers { overflow: hidden; } -/* line 256, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 257, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .visibility-form { display: none; } -/* line 260, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 261, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group-autocomplete-item span, body.closet_hangers-index .closet-list-autocomplete-item span { font-style: italic; padding: 0.2em 0.4em; } -/* line 265, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 266, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list-autocomplete-item a, body.closet_hangers-index .closet-list-autocomplete-item span { font-size: 85%; padding-left: 2em; } -/* line 272, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 273, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 275, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 276, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; - top: 0; + top: 52px; } -/* line 280, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 281, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1071,83 +1071,83 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 283, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 284, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; background: transparent; - top: 56px; + top: 0; padding: 0; } -/* line 289, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 290, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 292, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 293, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 296, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 297, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 301, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 302, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { display: block; } -/* line 304, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 305, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 307, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 308, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 310, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 311, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 314, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 315, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { display: block; } -/* line 317, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 318, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 321, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 322, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 324, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 325, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 328, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 329, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 331, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 332, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 336, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 337, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 339, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 340, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 343, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 344, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 346, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 347, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } From 824a806140c80dae2d350613d5301ebadd02b6da Mon Sep 17 00:00:00 2001 From: Matchu Date: Sat, 30 Jul 2011 23:05:55 -0400 Subject: [PATCH 55/69] remove ajax-deleted Your Items from the DOM so autocomplete recognizes that its gone --- public/javascripts/closet_hangers/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index 01e2d841..d5d7d637 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -119,7 +119,7 @@ } function objectRemoved(objectWrapper) { - objectWrapper.hide(250); + objectWrapper.hide(250, $.proxy(objectWrapper, 'remove')); } function compareItemsByName(a, b) { From 28c9d1b3d89d68bf50a0b13924abb44683c70438 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sat, 30 Jul 2011 23:07:58 -0400 Subject: [PATCH 56/69] hide list description on drag-n-drop --- app/views/closet_lists/_closet_list.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/closet_lists/_closet_list.html.haml b/app/views/closet_lists/_closet_list.html.haml index a78183a4..40005b79 100644 --- a/app/views/closet_lists/_closet_list.html.haml +++ b/app/views/closet_lists/_closet_list.html.haml @@ -11,10 +11,10 @@ = submit_tag 'Delete', :confirm => closet_list_delete_confirmation(closet_list) %h4= closet_list.name - - if closet_list.description? - = closet_list_description_format closet_list - .closet-list-content + - if closet_list.description? + = closet_list_description_format closet_list + .closet-list-hangers - unless closet_list.hangers.empty? = render_sorted_hangers(closet_list, show_controls) From 137aeac8d419552f1b68f612683fc183d08b1dac Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 31 Jul 2011 00:19:28 -0400 Subject: [PATCH 57/69] show traders on items#show --- app/controllers/closet_hangers_controller.rb | 2 +- app/controllers/items_controller.rb | 8 +- app/helpers/items_helper.rb | 6 ++ app/models/closet_hanger.rb | 11 +++ app/stylesheets/items/_show.sass | 57 ++++++++++++- app/views/items/show.html.haml | 35 +++++++- public/javascripts/items/show.js | 20 +++++ public/stylesheets/compiled/screen.css | 85 +++++++++++++++++--- 8 files changed, 205 insertions(+), 19 deletions(-) diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 95ea986e..7f8470cd 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -37,7 +37,7 @@ class ClosetHangersController < ApplicationController @unlisted_closet_hangers_by_owned = {} end - if @public_perspective + if @public_perspective && user_signed_in? items = [] @closet_lists_by_owned.each do |owned, lists| lists.each do |list| diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index aac96188..05ff567b 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -39,8 +39,14 @@ class ItemsController < ApplicationController def show @item = Item.find params[:id] + + @trading_closet_hangers_by_owned = { + true => @item.closet_hangers.owned_trading.newest.includes(:user), + false => @item.closet_hangers.wanted_trading.newest.includes(:user) + } + if user_signed_in? - @hangers = [true, false].map do |owned| + @current_user_hangers = [true, false].map do |owned| hanger = current_user.closet_hangers.find_or_initialize_by_item_id_and_owned(@item.id, owned) hanger.quantity ||= 1 hanger diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb index f01fb43b..e3dfef65 100644 --- a/app/helpers/items_helper.rb +++ b/app/helpers/items_helper.rb @@ -82,6 +82,12 @@ module ItemsHelper sprintf(NeoitemsURLFormat, CGI::escape(item.name)) end + def render_trading_closet_hangers(owned) + @trading_closet_hangers_by_owned[owned].map do |hanger| + link_to hanger.user.name, user_closet_hangers_path(hanger.user) + end.to_sentence.html_safe + end + def your_items_path user_signed_in? ? user_closet_hangers_path(current_user) : login_path end diff --git a/app/models/closet_hanger.rb b/app/models/closet_hanger.rb index e70569c5..e873f6cb 100644 --- a/app/models/closet_hanger.rb +++ b/app/models/closet_hanger.rb @@ -12,9 +12,20 @@ class ClosetHanger < ActiveRecord::Base validate :list_belongs_to_user scope :alphabetical_by_item_name, joins(:item).order(Item.arel_table[:name]) + scope :newest, order(arel_table[:created_at].desc) scope :owned_before_wanted, order(arel_table[:owned].desc) scope :unlisted, where(:list_id => nil) + {:owned => true, :wanted => false}.each do |name, owned| + scope "#{name}_trading", joins(:user).includes(:list). + where(:owned => owned). + where(( + User.arel_table["#{name}_closet_hangers_visibility"].gteq(ClosetVisibility[:trading].id) + ).or( + ClosetList.arel_table[:visibility].gteq(ClosetVisibility[:trading].id) + )) + end + before_validation :set_owned_by_list def verb(subject=:someone) diff --git a/app/stylesheets/items/_show.sass b/app/stylesheets/items/_show.sass index 98df4601..c52f9a88 100644 --- a/app/stylesheets/items/_show.sass +++ b/app/stylesheets/items/_show.sass @@ -50,8 +50,51 @@ body.items-show font: family: $text-font size: 85% - p:first-child - margin-bottom: .25em + margin-bottom: 1em + + p + display: inline + + &:first-child + margin-right: 1em + #trade-hangers + font-size: 85% + text-align: left + + p + position: relative + + &:first-child + margin-bottom: .5em + + &.overflows + .toggle + display: block + + &.showing-more + .toggle + .less + display: block + + .more + display: none + + .toggle + background: white + bottom: 0 + cursor: pointer + display: none + font-family: $main-font + padding: 0 1em + position: absolute + right: 0 + + &:hover + text-decoration: underline + + .less + display: none + #item-preview-header margin-top: 3em h3, a @@ -67,6 +110,7 @@ body.items-show border: 1px solid $module-border-color float: right font-size: 85% + margin-left: 1em padding: 1em width: 21em @@ -86,3 +130,12 @@ body.items-show input[type=number] width: 4em + &.js + #trade-hangers + p + max-height: 3em + overflow: hidden + + &.showing-more + max-height: none + diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index 15219b1a..1a9d7970 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -11,12 +11,12 @@ == Rarity: #{@item.rarity_index} (#{@item.rarity}) = link_to 'NeoItems', neoitems_url_for(@item), :class => 'button' - - if @hangers + - if @current_user_hangers #closet-hangers %header Track this in = link_to 'Your Items', user_closet_hangers_path(current_user) - - @hangers.each do |hanger| + - @current_user_hangers.each do |hanger| = form_for(hanger, :url => user_item_closet_hanger_path(current_user, @item)) do |f| - if hanger.new_record? = f.hidden_field :quantity @@ -43,6 +43,37 @@ - else = list_zones @item.restricted_zones + #trade-hangers + - [true, false].each do |owned| + %p + - unless @trading_closet_hangers_by_owned[owned].empty? + %strong + = pluralize @trading_closet_hangers_by_owned[owned].size, 'user' + - if owned + - if @trading_closet_hangers_by_owned[owned].size == 1 + has + - else + have + this item up for trade: + - else + - if @trading_closet_hangers_by_owned[owned].size == 1 + wants + - else + want + this item: + = render_trading_closet_hangers(owned) + - else + %strong + We don't know anyone who + - if owned + has this item up for trade. + - else + wants this item. + %span.toggle + %span.more more + %span.less less + + #item-preview-header %h3 Preview %a#customize-more.button{:href => '/'} Customize more diff --git a/public/javascripts/items/show.js b/public/javascripts/items/show.js index c913e930..e02d8a48 100644 --- a/public/javascripts/items/show.js +++ b/public/javascripts/items/show.js @@ -260,3 +260,23 @@ window.MainWardrobe = {View: {Outfit: {setFlashIsReady: previewSWFIsReady}}} var SWFLog = $.noop; + +/* + + Trade hangers + +*/ + +$(document.body).addClass('js'); + +$('#trade-hangers p').wrapInner('
      ').each(function () { + var el = $(this); + if(el.height() < el.children().height()) { + el.addClass('overflows'); + } +}); + +$('#trade-hangers .toggle').click(function () { + $(this).closest('p').toggleClass('showing-more'); +}); + diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index d0950786..36cf32db 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -1568,16 +1568,65 @@ body.items-show #item-preview-swf { body.items-show #item-zones { font-family: "Droid Serif", Georgia, "Times New Roman", Times, serif; font-size: 85%; -} -/* line 53, ../../../app/stylesheets/items/_show.sass */ -body.items-show #item-zones p:first-child { - margin-bottom: 0.25em; + margin-bottom: 1em; } /* line 55, ../../../app/stylesheets/items/_show.sass */ +body.items-show #item-zones p { + display: inline; +} +/* line 58, ../../../app/stylesheets/items/_show.sass */ +body.items-show #item-zones p:first-child { + margin-right: 1em; +} +/* line 60, ../../../app/stylesheets/items/_show.sass */ +body.items-show #trade-hangers { + font-size: 85%; + text-align: left; +} +/* line 64, ../../../app/stylesheets/items/_show.sass */ +body.items-show #trade-hangers p { + position: relative; +} +/* line 67, ../../../app/stylesheets/items/_show.sass */ +body.items-show #trade-hangers p:first-child { + margin-bottom: 0.5em; +} +/* line 71, ../../../app/stylesheets/items/_show.sass */ +body.items-show #trade-hangers p.overflows .toggle { + display: block; +} +/* line 76, ../../../app/stylesheets/items/_show.sass */ +body.items-show #trade-hangers p.showing-more .toggle .less { + display: block; +} +/* line 79, ../../../app/stylesheets/items/_show.sass */ +body.items-show #trade-hangers p.showing-more .toggle .more { + display: none; +} +/* line 82, ../../../app/stylesheets/items/_show.sass */ +body.items-show #trade-hangers .toggle { + background: white; + bottom: 0; + cursor: pointer; + display: none; + font-family: "Droid Sans", Helvetica, Arial, Verdana, sans-serif; + padding: 0 1em; + position: absolute; + right: 0; +} +/* line 92, ../../../app/stylesheets/items/_show.sass */ +body.items-show #trade-hangers .toggle:hover { + text-decoration: underline; +} +/* line 95, ../../../app/stylesheets/items/_show.sass */ +body.items-show #trade-hangers .toggle .less { + display: none; +} +/* line 98, ../../../app/stylesheets/items/_show.sass */ body.items-show #item-preview-header { margin-top: 3em; } -/* line 57, ../../../app/stylesheets/items/_show.sass */ +/* line 100, ../../../app/stylesheets/items/_show.sass */ body.items-show #item-preview-header h3, body.items-show #item-preview-header a { display: -moz-inline-box; -moz-box-orient: vertical; @@ -1586,45 +1635,55 @@ body.items-show #item-preview-header h3, body.items-show #item-preview-header a *display: inline; *vertical-align: auto; } -/* line 59, ../../../app/stylesheets/items/_show.sass */ +/* line 102, ../../../app/stylesheets/items/_show.sass */ body.items-show #item-preview-header a { font-size: 85%; margin: -1.5em 0 0 1em; } -/* line 62, ../../../app/stylesheets/items/_show.sass */ +/* line 105, ../../../app/stylesheets/items/_show.sass */ body.items-show .nc-icon { height: 16px; width: 16px; } -/* line 66, ../../../app/stylesheets/items/_show.sass */ +/* line 109, ../../../app/stylesheets/items/_show.sass */ body.items-show #closet-hangers { border: 1px solid #006600; float: right; font-size: 85%; + margin-left: 1em; padding: 1em; width: 21em; } -/* line 73, ../../../app/stylesheets/items/_show.sass */ +/* line 117, ../../../app/stylesheets/items/_show.sass */ body.items-show #closet-hangers label, body.items-show #closet-hangers header { display: block; font-weight: bold; } -/* line 77, ../../../app/stylesheets/items/_show.sass */ +/* line 121, ../../../app/stylesheets/items/_show.sass */ body.items-show #closet-hangers header { font-size: 125%; } -/* line 80, ../../../app/stylesheets/items/_show.sass */ +/* line 124, ../../../app/stylesheets/items/_show.sass */ body.items-show #closet-hangers form { padding: 0.5em 0; } -/* line 83, ../../../app/stylesheets/items/_show.sass */ +/* line 127, ../../../app/stylesheets/items/_show.sass */ body.items-show #closet-hangers select { width: 9em; } -/* line 86, ../../../app/stylesheets/items/_show.sass */ +/* line 130, ../../../app/stylesheets/items/_show.sass */ body.items-show #closet-hangers input[type=number] { width: 4em; } +/* line 135, ../../../app/stylesheets/items/_show.sass */ +body.items-show.js #trade-hangers p { + max-height: 3em; + overflow: hidden; +} +/* line 139, ../../../app/stylesheets/items/_show.sass */ +body.items-show.js #trade-hangers p.showing-more { + max-height: none; +} @import url(../shared/jquery.jgrowl.css); /* line 113, ../../../app/stylesheets/outfits/_edit.sass */ From 2dd280c45050805e8620d9ea10d7eacaf2f85e10 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 31 Jul 2011 00:22:36 -0400 Subject: [PATCH 58/69] grammar fix on closet list deletion confirmation --- app/helpers/closet_lists_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/closet_lists_helper.rb b/app/helpers/closet_lists_helper.rb index fff481e3..e03c6b95 100644 --- a/app/helpers/closet_lists_helper.rb +++ b/app/helpers/closet_lists_helper.rb @@ -3,7 +3,7 @@ module ClosetListsHelper "Are you sure you want to delete \"#{closet_list.name}\"?".tap do |msg| unless closet_list.hangers.empty? msg << " Even if you do, we'll remember that you " + - ClosetHanger.verb(closet_list.hangers_owned, :you) + + ClosetHanger.verb(:you, closet_list.hangers_owned) + " these items." end end From 4f0e7899b73fdb5633cdccb93ad109f9870e2991 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 31 Jul 2011 00:59:29 -0400 Subject: [PATCH 59/69] Your Items intro text polishing --- app/helpers/application_helper.rb | 8 +++ app/views/closet_hangers/index.html.haml | 73 +++++++++++------------- app/views/layouts/application.html.haml | 4 +- 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 516dab4a..9deca063 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -33,6 +33,14 @@ module ApplicationHelper content_for :meta, tag(:link, :rel => 'canonical', :href => url_for(resource)) end + def contact_email + "webmaster@openneo.net" + end + + def feedback_url + "http://openneo.uservoice.com/forums/40720-dress-to-impress" + end + def flashes raw(flash.inject('') do |html, pair| key, value = pair diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 914b259e..4e02d67c 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -32,28 +32,40 @@ %span#cancel-contact-link cancel - unless public_perspective? - %p - These are the items you are tracking on Dress to Impress. Hover over an - item to remove it from the list or to change the quantity. + :markdown + **These are your items! You can track what items you want and own, and + share [this page](#{request.fullpath}) with the world**. Just look up an + item in the search form above to get started. - %p - %strong - You can share - = link_to "this page", request.fullpath - with the world, - and they'll be able to see what items you own and want. - It's also a good idea to - %span.edit-contact-link add your Neopets username - so that when other users see your items they will know how to contact you for - trades. + **You can also sort your items into lists.** + [Building an Up For Trade list is a good place to start][uft]. You can + make lists for trade items with different market values, a private list of + what you need for that next outfit, or whatever you like. You can also + drag-and-drop items in and out of lists. It's pretty fun. - %p - You can also make lists of items. - %strong - = link_to 'Get started with an Up For Trade list', - new_user_closet_list_path(@user, :closet_list => {:hangers_owned => true, :name => 'Up For Trade'}) - then start adding to it! You can use the search form at the top to find - items, and you can also drag-and-drop items in and out of lists. Enjoy! + **Your items also have privacy settings.** + Items can be **private**, so only you can see them. They can be **public**, + so you can share this page with friends. They can even be **trading**, + meaning that we'll mention on the item's [Infinite Closet][ic] page that + you own or want that item. + + **We try to make trading easy.** If there's some item you want, you can + pull up that item's [Infinite Closet][ic] page to see if anyone is offering + it, and see what *that* user wants + in exchange. It's all pretty spiffy. Also, if you plan to trade, your should + add your Neopets username so that + when other users come here they know how to contact you. + + **Have fun!** If you have any [neat ideas][suggestions] or [general praise and + bug reports][mail], we love to hear them. And, if you enjoy this feature, + [please consider donating to keep Dress to Impress running and improving][donate]. + Thanks! + + [donate]: #{donate_path} + [ic]: #{items_path} + [mail]: mailto:#{contact_email} + [suggestions]: #{feedback_url} + [uft]: #{new_user_closet_list_path(@user, :closet_list => {:hangers_owned => true, :name => 'Up For Trade', :visibility => ClosetVisibility[:trading].id})} #closet-hangers{:class => public_perspective? ? nil : 'current-user'} - [true, false].each do |owned| @@ -81,29 +93,10 @@ .closet-list-hangers = render_unlisted_closet_hangers(owned) %span.empty-list - All the items you #{closet_hanger_verb owned} are in lists. + There aren't any items here. - if public_perspective? - unless has_hangers?(owned) %p #{@user.name} doesn't seem to #{closet_hanger_verb(owned, false)} anything. - - else - - unless has_hangers?(owned) - %p - You haven't tracked any items you #{closet_hanger_verb(owned)} on - Dress to Impress. As you browse the site and create outfits, we'll - use this list to tell you what items you #{closet_hanger_verb(owned)}, - and you can share this page with your friends, too. - %p - It's easy to get started! Use the search form at the top of the - page to find items to add, or add an item from its - = link_to 'Infinite Closet', items_path - page. - - if owned - %p - You can even - = succeed ',' do - = link_to "import your Neopets closet in a few quick steps", new_closet_page_path - so why not? - %p Have fun! - content_for :stylesheets do = stylesheet_link_tag 'south-street/jquery-ui' diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 4f89cbbd..6260f49f 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -71,9 +71,9 @@ Contact: %ul %li - %a{:href => "http://openneo.uservoice.com/forums/40720-dress-to-impress"} Suggestions + %a{:href => feedback_url} Suggestions %li - %a{:href => "mailto:webmaster@openneo.net"} Questions, comments, bugs + %a{:href => "mailto:#{contact_email}"} Questions, comments, bugs %p Images © 2000-2010 Neopets, Inc. All Rights Reserved. Used With Permission From 30096f6b0a08272040219dedba9aeaf53cdb0277 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 31 Jul 2011 02:48:16 -0400 Subject: [PATCH 60/69] items petpage export --- app/controllers/closet_hangers_controller.rb | 58 ++++++----- app/helpers/closet_hangers_helper.rb | 20 ++++ app/models/closet_list.rb | 1 + app/stylesheets/closet_hangers/_petpage.sass | 12 +++ app/stylesheets/screen.sass | 1 + .../closet_hangers/_petpage_content.html.haml | 97 +++++++++++++++++++ .../closet_hangers/_petpage_hanger.html.haml | 6 ++ app/views/closet_hangers/petpage.html.haml | 22 +++++ config/routes.rb | 8 +- public/stylesheets/compiled/screen.css | 26 +++++ spec/views/petpages/new.html.erb_spec.rb | 5 + 11 files changed, 233 insertions(+), 23 deletions(-) create mode 100644 app/stylesheets/closet_hangers/_petpage.sass create mode 100644 app/views/closet_hangers/_petpage_content.html.haml create mode 100644 app/views/closet_hangers/_petpage_hanger.html.haml create mode 100644 app/views/closet_hangers/petpage.html.haml create mode 100644 spec/views/petpages/new.html.erb_spec.rb diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 7f8470cd..56c7ea33 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -1,6 +1,7 @@ class ClosetHangersController < ApplicationController - before_filter :authorize_user!, :only => [:destroy, :create, :update] + before_filter :authorize_user!, :only => [:destroy, :create, :update, :petpage] before_filter :find_item, :only => [:destroy, :create, :update] + before_filter :find_user, :only => [:index, :petpage] def destroy raise ActiveRecord::RecordNotFound unless params[:closet_hanger] @@ -13,29 +14,9 @@ class ClosetHangersController < ApplicationController end def index - @user = User.find params[:user_id] @public_perspective = params.has_key?(:public) || !user_is?(@user) - @perspective_user = current_user unless @public_perspective - @closet_lists_by_owned = @user.closet_lists. - alphabetical.includes(:hangers => :item) - unless @perspective_user == @user - # If we run this when the user matches, we'll end up with effectively: - # WHERE belongs_to_user AND (is_public OR belongs_to_user) - # and it's a bit silly to put the SQL server through a condition that's - # always true. - @closet_lists_by_owned = @closet_lists_by_owned.visible_to(@perspective_user) - end - @closet_lists_by_owned = @closet_lists_by_owned.group_by(&:hangers_owned) - - visible_groups = @user.closet_hangers_groups_visible_to(@perspective_user) - unless visible_groups.empty? - @unlisted_closet_hangers_by_owned = @user.closet_hangers.unlisted. - owned_before_wanted.alphabetical_by_item_name.includes(:item). - where(:owned => [visible_groups]).group_by(&:owned) - else - @unlisted_closet_hangers_by_owned = {} - end + find_closet_hangers! if @public_perspective && user_signed_in? items = [] @@ -53,6 +34,11 @@ class ClosetHangersController < ApplicationController end end + def petpage + @public_perspective = true + find_closet_hangers! + end + # Since the user does not care about the idea of a hanger, but rather the # quantity of an item they own, the user would expect a create form to work # even after the record already exists, and an update form to work even after @@ -108,6 +94,34 @@ class ClosetHangersController < ApplicationController @item = Item.find params[:item_id] end + def find_user + @user = User.find params[:user_id] + end + + def find_closet_hangers! + @perspective_user = current_user unless @public_perspective + + @closet_lists_by_owned = @user.closet_lists. + alphabetical.includes(:hangers => :item) + unless @perspective_user == @user + # If we run this when the user matches, we'll end up with effectively: + # WHERE belongs_to_user AND (is_public OR belongs_to_user) + # and it's a bit silly to put the SQL server through a condition that's + # always true. + @closet_lists_by_owned = @closet_lists_by_owned.visible_to(@perspective_user) + end + @closet_lists_by_owned = @closet_lists_by_owned.group_by(&:hangers_owned) + + visible_groups = @user.closet_hangers_groups_visible_to(@perspective_user) + unless visible_groups.empty? + @unlisted_closet_hangers_by_owned = @user.closet_hangers.unlisted. + owned_before_wanted.alphabetical_by_item_name.includes(:item). + where(:owned => [visible_groups]).group_by(&:owned) + else + @unlisted_closet_hangers_by_owned = {} + end + end + def owned owned = true if params[:closet_hanger] diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index 81aa3577..71706cde 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -61,10 +61,30 @@ module ClosetHangersHelper link_to(content, path, options) end + def nc_icon_url + "http://#{request.host}#{image_path 'nc.png'}" + end + + def petpage_item_name(item) + item.name.gsub(/ on/i, ' on') + end + def public_perspective? @public_perspective end + PETPAGE_HANGER_BATCH_SIZE = 5 + def render_batched_petpage_hangers(hangers) + output do |html| + hangers.in_groups_of(PETPAGE_HANGER_BATCH_SIZE) do |batch| + content = batch.map do |hanger| + render 'petpage_hanger', :hanger => hanger if hanger + end.join.html_safe + html << content_tag(:div, content, :class => 'dti-item-row') + end + end + end + def render_closet_lists(lists) if lists render :partial => 'closet_lists/closet_list', :collection => lists, diff --git a/app/models/closet_list.rb b/app/models/closet_list.rb index 10358be3..57722726 100644 --- a/app/models/closet_list.rb +++ b/app/models/closet_list.rb @@ -10,6 +10,7 @@ class ClosetList < ActiveRecord::Base validates :hangers_owned, :inclusion => {:in => [true, false], :message => "can't be blank"} scope :alphabetical, order(:name) + scope :public, where(arel_table[:visibility].gteq(ClosetVisibility[:public].id)) scope :visible_to, lambda { |user| condition = arel_table[:visibility].gteq(ClosetVisibility[:public].id) condition = condition.or(arel_table[:user_id].eq(user.id)) if user diff --git a/app/stylesheets/closet_hangers/_petpage.sass b/app/stylesheets/closet_hangers/_petpage.sass new file mode 100644 index 00000000..5a8a51a8 --- /dev/null +++ b/app/stylesheets/closet_hangers/_petpage.sass @@ -0,0 +1,12 @@ +body.closet_hangers-petpage + +secondary-nav + + #intro + clear: both + + #petpage-output + display: block + height: 30em + margin: 0 auto + width: 50% + diff --git a/app/stylesheets/screen.sass b/app/stylesheets/screen.sass index df1111c4..c8db393f 100644 --- a/app/stylesheets/screen.sass +++ b/app/stylesheets/screen.sass @@ -7,6 +7,7 @@ @import partials/jquery.jgrowl @import closet_hangers/index +@import closet_hangers/petpage @import closet_lists/form @import closet_pages/new @import contributions/index diff --git a/app/views/closet_hangers/_petpage_content.html.haml b/app/views/closet_hangers/_petpage_content.html.haml new file mode 100644 index 00000000..4274acc0 --- /dev/null +++ b/app/views/closet_hangers/_petpage_content.html.haml @@ -0,0 +1,97 @@ +%style{:type => 'text/css'} + :plain + .dti-item-group, .dti-item-list, .dti-unlisted-items { + margin: 0; + padding: 0; + } + + .dti-item-group-header, .dti-item-group, #dti-item-footer { + color: #040; + font-family: Helvetica, Arial, Verdana, sans-serif; + line-height: 1.5; + margin: 0 auto; + text-align: center; + width: 560px; + } + + .dti-item-group-header { + border-top: 1px solid #060; + font-size: 175%; + margin-top: 1em; + } + + .dti-item-group-header, .dti-item-list { + border-bottom: 1px solid #ADA; + } + + .dti-item-group { + list-style: none; + } + + .dti-item-list h3 { + font-size: 150%; + } + + .dti-items { + border-spacing: 10px; + display: table; + } + + .dti-item-row { + display: table-row; + } + + .dti-item { + display: table-cell; + margin: 0 10px; + padding: 8px; + text-align: right; + width: 84px; + } + + .dti-item-thumbnail { + height: 80px; + width: 80px; + } + + .dti-item span { + display: block; + text-align: center; + } + + .dti-item-nc { + margin-top: -16px; + } + + .dti-unlisted-items h3 { + font-style: italic; + } + + #dti-item-footer { + font-size: 85%; + margin-top: 2em; + } + +- [true, false].each do |owned| + - lists = lists_by_owned[owned] + - if lists || unlisted_hangers_by_owned[owned] + %h2.dti-item-group-header Items #OWNER #{ClosetHanger.verb(:someone, owned)} + %ul.dti-item-group + - lists.each do |list| + - unless list.hangers.empty? + %li.dti-item-list + %h3= list.name + - if list.description? + .dti-item-list-desc + = closet_list_description_format list + %div.dti-items + = render_batched_petpage_hangers(list.hangers.sort { |a,b| a.item.name <=> b.item.name }) + %li.dti-unlisted-items + - unless lists.empty? + %h3 (Not in a list) + %div + = render_batched_petpage_hangers(unlisted_hangers_by_owned[owned]) + +#dti-item-footer + I made this list on Dress to Impress. You can, too! + diff --git a/app/views/closet_hangers/_petpage_hanger.html.haml b/app/views/closet_hangers/_petpage_hanger.html.haml new file mode 100644 index 00000000..e3d69b20 --- /dev/null +++ b/app/views/closet_hangers/_petpage_hanger.html.haml @@ -0,0 +1,6 @@ +%div.dti-item + = image_tag hanger.item.thumbnail_url, :alt => nil, :class => 'dti-item-thumbnail' + - if hanger.item.nc? + = image_tag nc_icon_url, :alt => 'NC', :class => 'dti-item-nc', :title => 'This is an NC Mall item' + %span= petpage_item_name hanger.item + diff --git a/app/views/closet_hangers/petpage.html.haml b/app/views/closet_hangers/petpage.html.haml new file mode 100644 index 00000000..6bf770d8 --- /dev/null +++ b/app/views/closet_hangers/petpage.html.haml @@ -0,0 +1,22 @@ +- title 'Export to Petpage' +- secondary_nav do + = link_to 'Back to Your Items', user_closet_hangers_path(current_user), :class => 'button' + +#intro + %p + We took your public lists and created a nice, simple HTML file for your + Neopet's petpage. By default it's styled as a table, but it doesn't have to + be. The HTML is flexible, so, if you're the artsy type, you're free to mess + with the styles all you want! + + %p + Copy the HTML from the box below, then paste it into + = succeed '.' do + = link_to "your pet's page", 'http://www.neopets.com/edithomepage.phtml' + Then head to the Neoboards to show off! Have fun! + +%textarea#petpage-output + = '' + render('petpage_content', + :lists_by_owned => @closet_lists_by_owned, + :unlisted_hangers_by_owned => @unlisted_closet_hangers_by_owned) + diff --git a/config/routes.rb b/config/routes.rb index 49cf66c8..b54352b7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,6 @@ OpenneoImpressItems::Application.routes.draw do |map| + get "petpages/new" + get "closet_lists/new" get "closet_lists/create" @@ -41,7 +43,11 @@ OpenneoImpressItems::Application.routes.draw do |map| resources :users, :path => 'user', :only => [:update] do resources :contributions, :only => [:index] - resources :closet_hangers, :only => [:index], :path => 'closet' + resources :closet_hangers, :only => [:index], :path => 'closet' do + collection do + get :petpage + end + end resources :closet_lists, :only => [:new, :create, :edit, :update, :destroy], :path => 'closet/lists' resources :items, :only => [] do diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 36cf32db..83444aae 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -1152,6 +1152,32 @@ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .s display: block; } +/* line 2, ../../../app/stylesheets/partials/_secondary_nav.sass */ +body.closet_hangers-petpage #title { + float: left; + margin-right: 0.5em; +} +/* line 6, ../../../app/stylesheets/partials/_secondary_nav.sass */ +body.closet_hangers-petpage .flash { + clear: both; +} +/* line 9, ../../../app/stylesheets/partials/_secondary_nav.sass */ +body.closet_hangers-petpage #secondary-nav { + display: block; + margin-top: 0.75em; +} +/* line 4, ../../../app/stylesheets/closet_hangers/_petpage.sass */ +body.closet_hangers-petpage #intro { + clear: both; +} +/* line 7, ../../../app/stylesheets/closet_hangers/_petpage.sass */ +body.closet_hangers-petpage #petpage-output { + display: block; + height: 30em; + margin: 0 auto; + width: 50%; +} + /* line 2, ../../../app/stylesheets/partials/_secondary_nav.sass */ body.closet_lists-new #title, body.closet_lists-create #title, body.closet_lists-edit #title, body.closet_lists-update #title { float: left; diff --git a/spec/views/petpages/new.html.erb_spec.rb b/spec/views/petpages/new.html.erb_spec.rb new file mode 100644 index 00000000..b9434a86 --- /dev/null +++ b/spec/views/petpages/new.html.erb_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe "petpages/new.html.erb" do + pending "add some examples to (or delete) #{__FILE__}" +end From 1ac399cc7afbd93333cda9b6a8344cea90a59b2c Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 31 Jul 2011 02:58:45 -0400 Subject: [PATCH 61/69] link to petpage exporter from Your Items --- app/stylesheets/closet_hangers/_index.sass | 8 ++ app/views/closet_hangers/index.html.haml | 6 +- app/views/closet_hangers/petpage.html.haml | 2 +- app/views/closet_pages/new.html.haml | 2 +- public/stylesheets/compiled/screen.css | 159 +++++++++++++-------- 5 files changed, 113 insertions(+), 64 deletions(-) diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 9cbb500a..563d4221 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -74,6 +74,14 @@ body.closet_hangers-index #cancel-contact-link margin-left: 1em + #closet-hangers-extras + margin-bottom: 1em + text-align: center + + a + +awesome-button + margin: 0 0.5em + #closet-hangers clear: both text-align: center diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 4e02d67c..0170698c 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -2,7 +2,6 @@ - title 'Your Items' - add_body_class 'current-user' - secondary_nav do - = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' = form_tag items_path, :method => :get, :id => 'closet-hangers-items-search', 'data-current-user-id' => current_user.id do = text_field_tag :q, nil, :placeholder => "Find items to add" = submit_tag 'Search', :name => nil @@ -67,6 +66,11 @@ [suggestions]: #{feedback_url} [uft]: #{new_user_closet_list_path(@user, :closet_list => {:hangers_owned => true, :name => 'Up For Trade', :visibility => ClosetVisibility[:trading].id})} +- unless public_perspective? + #closet-hangers-extras + = link_to "Import from Neopets closet", new_closet_page_path + = link_to "Export to Neopets petpage", petpage_user_closet_hangers_path(@user) + #closet-hangers{:class => public_perspective? ? nil : 'current-user'} - [true, false].each do |owned| .closet-hangers-group{'data-owned' => owned.to_s, :id => "closet-hangers-group-#{owned}"} diff --git a/app/views/closet_hangers/petpage.html.haml b/app/views/closet_hangers/petpage.html.haml index 6bf770d8..62e7325a 100644 --- a/app/views/closet_hangers/petpage.html.haml +++ b/app/views/closet_hangers/petpage.html.haml @@ -1,4 +1,4 @@ -- title 'Export to Petpage' +- title 'Export to petpage' - secondary_nav do = link_to 'Back to Your Items', user_closet_hangers_path(current_user), :class => 'button' diff --git a/app/views/closet_pages/new.html.haml b/app/views/closet_pages/new.html.haml index d8975049..e2f6f5d6 100644 --- a/app/views/closet_pages/new.html.haml +++ b/app/views/closet_pages/new.html.haml @@ -1,4 +1,4 @@ -- title "Closet Importer, Page #{@closet_page.index}" +- title "Import from closet, Page #{@closet_page.index}" - content_for :before_flashes do = link_to 'Back to Your Items', user_closet_hangers_path(current_user), :id => 'back-to-items' diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 83444aae..14fe170d 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -683,11 +683,48 @@ body.closet_hangers-index #cancel-contact-link { margin-left: 1em; } /* line 77, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-extras { + margin-bottom: 1em; + text-align: center; +} +/* line 81, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-extras a { + /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + background: #006400 url('/images/alert-overlay.png?1296599919') repeat-x; + border: 0; + display: inline-block; + padding: 0.5em 0.75em 0.45em; + color: white; + text-decoration: none; + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); + border-bottom: 1px solid rgba(0, 0, 0, 0.25); + position: relative; + font-weight: bold; + line-height: 1; + margin: 0 0.5em; +} +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #closet-hangers-extras a:hover { + background-color: #005300; +} +/* line 53, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #closet-hangers-extras a:hover { + color: white; +} +/* line 55, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #closet-hangers-extras a:active { + top: 1px; +} +/* line 85, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers { clear: both; text-align: center; } -/* line 82, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 90, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -701,26 +738,26 @@ body.closet_hangers-index #closet-hangers .object .quantity { text-align: left; top: 0; } -/* line 92, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 100, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { font-size: 16px; font-weight: bold; } -/* line 96, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 104, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object form { display: none; } -/* line 100, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 108, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object[data-quantity="1"] .quantity { display: none; } -/* line 103, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 111, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group { border-top: 1px solid #006600; margin-bottom: 2em; padding-bottom: 1em; } -/* line 108, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 116, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header { border-bottom: 1px solid #aaddaa; display: block; @@ -728,12 +765,12 @@ body.closet_hangers-index .closet-hangers-group > header { padding: 0.25em 0; position: relative; } -/* line 115, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 123, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header h3 { font-size: 250%; margin: 0; } -/* line 119, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 127, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header .add-closet-list { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -768,12 +805,12 @@ body.closet_hangers-index .closet-hangers-group > header .add-closet-list:hover body.closet_hangers-index .closet-hangers-group > header .add-closet-list:active { top: 1px; } -/* line 126, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 134, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header .add-closet-list:active { margin-bottom: -1.1em; top: auto; } -/* line 130, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 138, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header span.show, body.closet_hangers-index .closet-hangers-group > header span.hide { color: #448844; display: none; @@ -782,18 +819,18 @@ body.closet_hangers-index .closet-hangers-group > header span.show, body.closet_ position: absolute; top: 1em; } -/* line 138, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 146, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header span.show:hover, body.closet_hangers-index .closet-hangers-group > header span.hide:hover { color: inherit; text-decoration: underline; } -/* line 142, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 150, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list { border-bottom: 1px solid #aaddaa; padding: 0.5em 0; position: relative; } -/* line 147, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 155, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form { font-size: 85%; left: 0.5em; @@ -802,17 +839,17 @@ body.closet_hangers-index .closet-list .visibility-form { top: 0.25em; z-index: 10; } -/* line 155, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 163, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input, body.closet_hangers-index .closet-list .visibility-form select { font-size: inherit; margin-bottom: 0; margin-top: 0; } -/* line 161, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 169, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form select { border-color: white; } -/* line 164, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 172, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -855,11 +892,11 @@ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:activ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:hover { background-color: #999999; } -/* line 169, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 177, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:active { top: 1px; } -/* line 172, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -870,20 +907,20 @@ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions list-style: none; padding: 0 0.5em; } -/* line 179, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions li { display: none; } -/* line 183, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 191, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form:hover .visibility-descriptions li.current { display: block; } -/* line 186, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list header { display: block; position: relative; } -/* line 190, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 198, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list h4 { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 150%; @@ -891,19 +928,19 @@ body.closet_hangers-index .closet-list h4 { margin: 0 auto 0.67em; width: 50%; } -/* line 197, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 205, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .empty-list { display: none; font-style: italic; } -/* line 201, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 209, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls { display: none; position: absolute; right: 1em; top: 0; } -/* line 207, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 215, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls a, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -944,36 +981,36 @@ body.closet_hangers-index .closet-list .closet-list-controls a:active, body.clos body.closet_hangers-index .closet-list .closet-list-controls a:hover, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:hover { background-color: #999999; } -/* line 210, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 218, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls form { display: inline; } -/* line 214, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 222, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list[data-hangers-count="0"] .empty-list { display: block; } -/* line 218, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 226, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.unlisted h4 { font-size: 125%; font-style: italic; } -/* line 224, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 232, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .closet-list-controls { display: block; } -/* line 228, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 236, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form input[type=submit] { visibility: visible; } -/* line 231, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 239, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form select { border-color: #aaddaa; } -/* line 234, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 242, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:last-child { border-bottom: 0; } -/* line 237, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 245, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active { -moz-border-radius: 1em; -webkit-border-radius: 1em; @@ -984,53 +1021,53 @@ body.closet_hangers-index .closet-list.droppable-active { border-style: dotted; margin: 1em 0; } -/* line 244, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 252, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object { -moz-opacity: 0.25; -webkit-opacity: 0.25; -o-opacity: 0.25; -khtml-opacity: 0.25; } -/* line 248, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 256, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object.ui-draggable-dragging { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 251, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 259, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-controls { display: none; } -/* line 254, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 262, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-hangers { overflow: hidden; } -/* line 257, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 265, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .visibility-form { display: none; } -/* line 261, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 269, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group-autocomplete-item span, body.closet_hangers-index .closet-list-autocomplete-item span { font-style: italic; padding: 0.2em 0.4em; } -/* line 266, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 274, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list-autocomplete-item a, body.closet_hangers-index .closet-list-autocomplete-item span { font-size: 85%; padding-left: 2em; } -/* line 273, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 281, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 276, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 284, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 52px; } -/* line 281, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 289, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1071,7 +1108,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 284, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 292, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -1081,73 +1118,73 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 0; padding: 0; } -/* line 290, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 298, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 293, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 301, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 297, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 305, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 302, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 310, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { display: block; } -/* line 305, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 313, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 308, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 316, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 311, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 319, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 315, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 323, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { display: block; } -/* line 318, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 326, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 322, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 330, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 325, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 333, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 329, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 337, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 332, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 340, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 337, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 345, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 340, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 348, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 344, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 352, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 347, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 355, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } From 359356bcf37cedc33a63adbd40493352f7291013 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 31 Jul 2011 03:03:26 -0400 Subject: [PATCH 62/69] better handle edge cases in petpages --- .../closet_hangers/_petpage_content.html.haml | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/app/views/closet_hangers/_petpage_content.html.haml b/app/views/closet_hangers/_petpage_content.html.haml index 4274acc0..efb0d4c3 100644 --- a/app/views/closet_hangers/_petpage_content.html.haml +++ b/app/views/closet_hangers/_petpage_content.html.haml @@ -77,20 +77,22 @@ - if lists || unlisted_hangers_by_owned[owned] %h2.dti-item-group-header Items #OWNER #{ClosetHanger.verb(:someone, owned)} %ul.dti-item-group - - lists.each do |list| - - unless list.hangers.empty? - %li.dti-item-list - %h3= list.name - - if list.description? - .dti-item-list-desc - = closet_list_description_format list - %div.dti-items - = render_batched_petpage_hangers(list.hangers.sort { |a,b| a.item.name <=> b.item.name }) - %li.dti-unlisted-items - - unless lists.empty? - %h3 (Not in a list) - %div - = render_batched_petpage_hangers(unlisted_hangers_by_owned[owned]) + - if lists + - lists.each do |list| + - unless list.hangers.empty? + %li.dti-item-list + %h3= list.name + - if list.description? + .dti-item-list-desc + = closet_list_description_format list + %div.dti-items + = render_batched_petpage_hangers(list.hangers.sort { |a,b| a.item.name <=> b.item.name }) + - if unlisted_hangers_by_owned[owned] + %li.dti-unlisted-items + - unless lists.blank? + %h3 (Not in a list) + %div + = render_batched_petpage_hangers(unlisted_hangers_by_owned[owned]) #dti-item-footer I made this list on Dress to Impress. You can, too! From 037cb1e95aa1ab74e992c597afdf153e7c8283b3 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 31 Jul 2011 18:45:53 -0400 Subject: [PATCH 63/69] your items link on home --- app/controllers/closet_hangers_controller.rb | 6 +++++- app/helpers/items_helper.rb | 2 +- app/views/outfits/new.html.haml | 12 ++++++------ config/routes.rb | 2 ++ public/images/your_items.png | Bin 0 -> 5312 bytes 5 files changed, 14 insertions(+), 8 deletions(-) create mode 100644 public/images/your_items.png diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 56c7ea33..94e877f9 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -95,7 +95,11 @@ class ClosetHangersController < ApplicationController end def find_user - @user = User.find params[:user_id] + if params[:user_id] + @user = User.find params[:user_id] + else + redirect_to user_closet_hangers_path(current_user) + end end def find_closet_hangers! diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb index e3dfef65..17c760c8 100644 --- a/app/helpers/items_helper.rb +++ b/app/helpers/items_helper.rb @@ -89,7 +89,7 @@ module ItemsHelper end def your_items_path - user_signed_in? ? user_closet_hangers_path(current_user) : login_path + user_signed_in? ? user_closet_hangers_path(current_user) : login_path(:return_to => current_user_items_path) end private diff --git a/app/views/outfits/new.html.haml b/app/views/outfits/new.html.haml index a678108f..c5ba4608 100644 --- a/app/views/outfits/new.html.haml +++ b/app/views/outfits/new.html.haml @@ -29,15 +29,15 @@ - cache :action_suffix => 'sections_and_description' do %ul#sections %li - %a{:href => "http://forum.openneo.net"} - = image_tag 'forum.png' + = link_to image_tag('your_items.png'), your_items_path %h3 - %a{:href => "http://forum.openneo.net/"} Forum + = link_to 'Your Items', your_items_path %div - %h4 Join our community! + %h4 Track and trade! %p - Show off your designs, ask for advice, or play silly forum games - here. + Make lists of the items you own and want, and share them with the + world. + %li %a{:href => items_path} = image_tag 'items.png' diff --git a/config/routes.rb b/config/routes.rb index b54352b7..ffe8538f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -55,6 +55,8 @@ OpenneoImpressItems::Application.routes.draw do |map| end end + match 'users/current-user/closet' => 'closet_hangers#index', :as => :current_user_items + match 'users/top-contributors' => 'users#top_contributors', :as => :top_contributors match 'users/top_contributors' => redirect('/users/top-contributors') diff --git a/public/images/your_items.png b/public/images/your_items.png new file mode 100644 index 0000000000000000000000000000000000000000..87973fc6733cb4fa93d29ae018adab80095216e6 GIT binary patch literal 5312 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 Date: Sun, 31 Jul 2011 19:04:21 -0400 Subject: [PATCH 64/69] hide help for people who have used Your Items before --- app/helpers/closet_hangers_helper.rb | 4 + app/stylesheets/closet_hangers/_index.sass | 15 +- app/views/closet_hangers/index.html.haml | 60 ++++---- public/javascripts/closet_hangers/index.js | 10 ++ public/stylesheets/compiled/screen.css | 170 +++++++++++++-------- 5 files changed, 165 insertions(+), 94 deletions(-) diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb index 71706cde..5649019c 100644 --- a/app/helpers/closet_hangers_helper.rb +++ b/app/helpers/closet_hangers_helper.rb @@ -1,6 +1,10 @@ require 'cgi' module ClosetHangersHelper + def closet_hangers_help_class + 'hidden' unless @user.closet_hangers.empty? + end + def closet_hanger_verb(owned, positive=true) ClosetHanger.verb(closet_hanger_subject, owned, positive) end diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 563d4221..a99145ca 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -74,8 +74,18 @@ body.closet_hangers-index #cancel-contact-link margin-left: 1em + #toggle-help + +awesome-button + cursor: pointer + display: none + + #closet-hangers-help.hidden + display: none + #closet-hangers-extras - margin-bottom: 1em + margin: + bottom: 2em + top: 2em text-align: center a @@ -355,3 +365,6 @@ body.closet_hangers-index header .show display: block + #toggle-help + display: inline + diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 0170698c..f3f400b0 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -2,6 +2,7 @@ - title 'Your Items' - add_body_class 'current-user' - secondary_nav do + %span#toggle-help Need help? = form_tag items_path, :method => :get, :id => 'closet-hangers-items-search', 'data-current-user-id' => current_user.id do = text_field_tag :q, nil, :placeholder => "Find items to add" = submit_tag 'Search', :name => nil @@ -31,40 +32,41 @@ %span#cancel-contact-link cancel - unless public_perspective? - :markdown - **These are your items! You can track what items you want and own, and - share [this page](#{request.fullpath}) with the world**. Just look up an - item in the search form above to get started. + #closet-hangers-help{:class => closet_hangers_help_class} + :markdown + **These are your items! You can track what items you want and own, and + share [this page](#{request.fullpath}) with the world**. Just look up an + item in the search form above to get started. - **You can also sort your items into lists.** - [Building an Up For Trade list is a good place to start][uft]. You can - make lists for trade items with different market values, a private list of - what you need for that next outfit, or whatever you like. You can also - drag-and-drop items in and out of lists. It's pretty fun. + **You can also sort your items into lists.** + [Building an Up For Trade list is a good place to start][uft]. You can + make lists for trade items with different market values, a private list of + what you need for that next outfit, or whatever you like. You can also + drag-and-drop items in and out of lists. It's pretty fun. - **Your items also have privacy settings.** - Items can be **private**, so only you can see them. They can be **public**, - so you can share this page with friends. They can even be **trading**, - meaning that we'll mention on the item's [Infinite Closet][ic] page that - you own or want that item. + **Your items also have privacy settings.** + Items can be **private**, so only you can see them. They can be **public**, + so you can share this page with friends. They can even be **trading**, + meaning that we'll mention on the item's [Infinite Closet][ic] page that + you own or want that item. - **We try to make trading easy.** If there's some item you want, you can - pull up that item's [Infinite Closet][ic] page to see if anyone is offering - it, and see what *that* user wants - in exchange. It's all pretty spiffy. Also, if you plan to trade, your should - add your Neopets username so that - when other users come here they know how to contact you. + **We try to make trading easy.** If there's some item you want, you can + pull up that item's [Infinite Closet][ic] page to see if anyone is offering + it, and see what *that* user wants + in exchange. It's all pretty spiffy. Also, if you plan to trade, your should + add your Neopets username so that + when other users come here they know how to contact you. - **Have fun!** If you have any [neat ideas][suggestions] or [general praise and - bug reports][mail], we love to hear them. And, if you enjoy this feature, - [please consider donating to keep Dress to Impress running and improving][donate]. - Thanks! + **Have fun!** If you have any [neat ideas][suggestions] or [general praise and + bug reports][mail], we love to hear them. And, if you enjoy this feature, + [please consider donating to keep Dress to Impress running and improving][donate]. + Thanks! - [donate]: #{donate_path} - [ic]: #{items_path} - [mail]: mailto:#{contact_email} - [suggestions]: #{feedback_url} - [uft]: #{new_user_closet_list_path(@user, :closet_list => {:hangers_owned => true, :name => 'Up For Trade', :visibility => ClosetVisibility[:trading].id})} + [donate]: #{donate_path} + [ic]: #{items_path} + [mail]: mailto:#{contact_email} + [suggestions]: #{feedback_url} + [uft]: #{new_user_closet_list_path(@user, :closet_list => {:hangers_owned => true, :name => 'Up For Trade', :visibility => ClosetVisibility[:trading].id})} - unless public_perspective? #closet-hangers-extras diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index d5d7d637..86d4f4f5 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -477,6 +477,16 @@ visibilitySelects().each(updateVisibilityDescription); }); + /* + + Help + + */ + + $('#toggle-help').click(function () { + $('#closet-hangers-help').toggleClass('hidden'); + }); + /* Initialize diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index 14fe170d..ebe954f8 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -683,11 +683,49 @@ body.closet_hangers-index #cancel-contact-link { margin-left: 1em; } /* line 77, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #toggle-help { + /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + background: #006400 url('/images/alert-overlay.png?1296599919') repeat-x; + border: 0; + display: inline-block; + padding: 0.5em 0.75em 0.45em; + color: white; + text-decoration: none; + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); + border-bottom: 1px solid rgba(0, 0, 0, 0.25); + position: relative; + font-weight: bold; + line-height: 1; + cursor: pointer; + display: none; +} +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #toggle-help:hover { + background-color: #005300; +} +/* line 53, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #toggle-help:hover { + color: white; +} +/* line 55, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #toggle-help:active { + top: 1px; +} +/* line 82, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-help.hidden { + display: none; +} +/* line 85, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-extras { - margin-bottom: 1em; + margin-bottom: 2em; + margin-top: 2em; text-align: center; } -/* line 81, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 91, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-extras a { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -719,12 +757,12 @@ body.closet_hangers-index #closet-hangers-extras a:hover { body.closet_hangers-index #closet-hangers-extras a:active { top: 1px; } -/* line 85, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 95, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers { clear: both; text-align: center; } -/* line 90, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 100, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -738,26 +776,26 @@ body.closet_hangers-index #closet-hangers .object .quantity { text-align: left; top: 0; } -/* line 100, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 110, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { font-size: 16px; font-weight: bold; } -/* line 104, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 114, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object form { display: none; } -/* line 108, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 118, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object[data-quantity="1"] .quantity { display: none; } -/* line 111, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 121, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group { border-top: 1px solid #006600; margin-bottom: 2em; padding-bottom: 1em; } -/* line 116, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 126, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header { border-bottom: 1px solid #aaddaa; display: block; @@ -765,12 +803,12 @@ body.closet_hangers-index .closet-hangers-group > header { padding: 0.25em 0; position: relative; } -/* line 123, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 133, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header h3 { font-size: 250%; margin: 0; } -/* line 127, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 137, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header .add-closet-list { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -805,12 +843,12 @@ body.closet_hangers-index .closet-hangers-group > header .add-closet-list:hover body.closet_hangers-index .closet-hangers-group > header .add-closet-list:active { top: 1px; } -/* line 134, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 144, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header .add-closet-list:active { margin-bottom: -1.1em; top: auto; } -/* line 138, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 148, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header span.show, body.closet_hangers-index .closet-hangers-group > header span.hide { color: #448844; display: none; @@ -819,18 +857,18 @@ body.closet_hangers-index .closet-hangers-group > header span.show, body.closet_ position: absolute; top: 1em; } -/* line 146, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 156, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header span.show:hover, body.closet_hangers-index .closet-hangers-group > header span.hide:hover { color: inherit; text-decoration: underline; } -/* line 150, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 160, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list { border-bottom: 1px solid #aaddaa; padding: 0.5em 0; position: relative; } -/* line 155, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 165, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form { font-size: 85%; left: 0.5em; @@ -839,17 +877,17 @@ body.closet_hangers-index .closet-list .visibility-form { top: 0.25em; z-index: 10; } -/* line 163, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 173, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input, body.closet_hangers-index .closet-list .visibility-form select { font-size: inherit; margin-bottom: 0; margin-top: 0; } -/* line 169, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 179, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form select { border-color: white; } -/* line 172, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 182, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -892,11 +930,11 @@ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:activ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:hover { background-color: #999999; } -/* line 177, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:active { top: 1px; } -/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 190, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -907,20 +945,20 @@ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions list-style: none; padding: 0 0.5em; } -/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 197, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions li { display: none; } -/* line 191, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 201, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form:hover .visibility-descriptions li.current { display: block; } -/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 204, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list header { display: block; position: relative; } -/* line 198, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 208, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list h4 { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 150%; @@ -928,19 +966,19 @@ body.closet_hangers-index .closet-list h4 { margin: 0 auto 0.67em; width: 50%; } -/* line 205, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 215, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .empty-list { display: none; font-style: italic; } -/* line 209, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 219, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls { display: none; position: absolute; right: 1em; top: 0; } -/* line 215, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 225, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls a, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -981,36 +1019,36 @@ body.closet_hangers-index .closet-list .closet-list-controls a:active, body.clos body.closet_hangers-index .closet-list .closet-list-controls a:hover, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:hover { background-color: #999999; } -/* line 218, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 228, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls form { display: inline; } -/* line 222, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 232, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list[data-hangers-count="0"] .empty-list { display: block; } -/* line 226, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 236, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.unlisted h4 { font-size: 125%; font-style: italic; } -/* line 232, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 242, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .closet-list-controls { display: block; } -/* line 236, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 246, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form input[type=submit] { visibility: visible; } -/* line 239, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 249, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form select { border-color: #aaddaa; } -/* line 242, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 252, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:last-child { border-bottom: 0; } -/* line 245, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 255, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active { -moz-border-radius: 1em; -webkit-border-radius: 1em; @@ -1021,53 +1059,53 @@ body.closet_hangers-index .closet-list.droppable-active { border-style: dotted; margin: 1em 0; } -/* line 252, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 262, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object { -moz-opacity: 0.25; -webkit-opacity: 0.25; -o-opacity: 0.25; -khtml-opacity: 0.25; } -/* line 256, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 266, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object.ui-draggable-dragging { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 259, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 269, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-controls { display: none; } -/* line 262, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 272, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-hangers { overflow: hidden; } -/* line 265, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 275, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .visibility-form { display: none; } -/* line 269, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 279, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group-autocomplete-item span, body.closet_hangers-index .closet-list-autocomplete-item span { font-style: italic; padding: 0.2em 0.4em; } -/* line 274, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 284, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list-autocomplete-item a, body.closet_hangers-index .closet-list-autocomplete-item span { font-size: 85%; padding-left: 2em; } -/* line 281, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 291, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 284, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 294, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 52px; } -/* line 289, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 299, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1108,7 +1146,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 292, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 302, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -1118,76 +1156,80 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 0; padding: 0; } -/* line 298, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 308, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 301, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 311, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 305, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 315, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 310, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 320, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { display: block; } -/* line 313, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 323, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 316, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 326, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 319, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 329, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 323, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 333, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { display: block; } -/* line 326, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 336, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 330, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 340, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 333, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 343, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 337, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 347, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 340, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 350, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 345, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 355, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 348, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 358, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 352, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 362, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 355, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 365, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } +/* line 368, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index.current-user.js #toggle-help { + display: inline; +} /* line 2, ../../../app/stylesheets/partials/_secondary_nav.sass */ body.closet_hangers-petpage #title { From e3cfe9e16c13285649f2314586a3747f672ecf8d Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 31 Jul 2011 19:14:55 -0400 Subject: [PATCH 65/69] redecorate neomail Your Items link --- app/stylesheets/closet_hangers/_index.sass | 13 +- public/images/neomail_edit.png | Bin 0 -> 756 bytes public/stylesheets/compiled/screen.css | 174 +++++++++++---------- 3 files changed, 103 insertions(+), 84 deletions(-) create mode 100644 public/images/neomail_edit.png diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index a99145ca..7b427782 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -25,17 +25,24 @@ body.closet_hangers-index #closet-hangers-contact clear: both - font-size: 85% + color: $soft-text-color margin-bottom: 1em margin-left: 2em min-height: image-height("neomail.png") - a + a, > span + +hover-link background: image: image-url("neomail.png") position: left center repeat: no-repeat - padding-left: image-width("neomail.png") + 2px + color: inherit + float: left + height: 100% + padding-left: image-width("neomail.png") + 4px + + > span + background-image: image-url("neomail_edit.png") input[type=text] width: 10em diff --git a/public/images/neomail_edit.png b/public/images/neomail_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..244f04ae15277e4b20ca9c99f627beadecf23c18 GIT binary patch literal 756 zcmVYCj9)0M$R^4v<1rbljMjA>+a4*Fv?vRhe{~gr z%Dh6QGei@IC{91XUoMy!8piefTprt(G*USyp&U=#>zgJyrzjLP6B&-PJrzNYsRhW}abY-=o|braxZC!={j}CE5Rpfy5PR8yX4z5xy*} ztSSisPRYSHeV<*&Z}a8BIY#Ms7s7Cbbv+>flXm`dkZsR)Ahv@B#N$BW8|H*E=uaL^Dpo+dHYMiN4- zIrR{~4g*QN((=Y<@+z19F(uVfdg9>O-pYU#3dw*eq%<*1foXtY2n@N(Thl^-b{(Zw m7UwhR(d2ir-fuKmCw>B@7##EPk)wG40000 span { + text-decoration: none; background-image: url('/images/neomail.png?1311877030'); background-position: left center; background-repeat: no-repeat; - padding-left: 18px; + color: inherit; + float: left; + height: 100%; + padding-left: 20px; } -/* line 40, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 4, ../../../../../.rvm/gems/ree-1.8.7-2010.02/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/utilities/links/_hover-link.scss */ +body.closet_hangers-index #closet-hangers-contact a:hover, body.closet_hangers-index #closet-hangers-contact > span:hover { + text-decoration: underline; +} +/* line 44, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-contact > span { + background-image: url('/images/neomail_edit.png?1312153508'); +} +/* line 47, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-contact input[type=text], body.closet_hangers-index #closet-hangers-contact body.pets-bulk #bulk-pets-form textarea, body.pets-bulk #bulk-pets-form body.closet_hangers-index #closet-hangers-contact textarea { width: 10em; } -/* line 43, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 50, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-contact label { font-weight: bold; margin-right: 0.5em; } -/* line 47, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 54, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-contact label:after { content: ":"; } -/* line 50, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 57, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #edit-contact-link-to-replace-form, body.closet_hangers-index #cancel-contact-link { display: none; } -/* line 53, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 60, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .edit-contact-link, body.closet_hangers-index #cancel-contact-link { cursor: pointer; text-decoration: underline; } -/* line 57, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 64, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .edit-contact-link:hover, body.closet_hangers-index #cancel-contact-link:hover { text-decoration: none; } -/* line 61, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 68, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #edit-contact-link-to-replace-form #contact-link-has-value { display: none; } -/* line 64, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 71, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #edit-contact-link-to-replace-form #contact-link-no-value { display: inline; } -/* line 68, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 75, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #edit-contact-link-to-replace-form.has-value #contact-link-has-value { display: inline; } -/* line 71, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 78, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #edit-contact-link-to-replace-form.has-value #contact-link-no-value { display: none; } -/* line 74, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 81, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #cancel-contact-link { margin-left: 1em; } -/* line 77, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 84, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #toggle-help { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -715,17 +727,17 @@ body.closet_hangers-index #toggle-help:hover { body.closet_hangers-index #toggle-help:active { top: 1px; } -/* line 82, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 89, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-help.hidden { display: none; } -/* line 85, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 92, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-extras { margin-bottom: 2em; margin-top: 2em; text-align: center; } -/* line 91, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 98, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers-extras a { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -757,12 +769,12 @@ body.closet_hangers-index #closet-hangers-extras a:hover { body.closet_hangers-index #closet-hangers-extras a:active { top: 1px; } -/* line 95, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 102, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers { clear: both; text-align: center; } -/* line 100, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 107, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -776,26 +788,26 @@ body.closet_hangers-index #closet-hangers .object .quantity { text-align: left; top: 0; } -/* line 110, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 117, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { font-size: 16px; font-weight: bold; } -/* line 114, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 121, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object form { display: none; } -/* line 118, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 125, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object[data-quantity="1"] .quantity { display: none; } -/* line 121, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 128, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group { border-top: 1px solid #006600; margin-bottom: 2em; padding-bottom: 1em; } -/* line 126, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 133, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header { border-bottom: 1px solid #aaddaa; display: block; @@ -803,12 +815,12 @@ body.closet_hangers-index .closet-hangers-group > header { padding: 0.25em 0; position: relative; } -/* line 133, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 140, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header h3 { font-size: 250%; margin: 0; } -/* line 137, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 144, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header .add-closet-list { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -843,12 +855,12 @@ body.closet_hangers-index .closet-hangers-group > header .add-closet-list:hover body.closet_hangers-index .closet-hangers-group > header .add-closet-list:active { top: 1px; } -/* line 144, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 151, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header .add-closet-list:active { margin-bottom: -1.1em; top: auto; } -/* line 148, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 155, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header span.show, body.closet_hangers-index .closet-hangers-group > header span.hide { color: #448844; display: none; @@ -857,18 +869,18 @@ body.closet_hangers-index .closet-hangers-group > header span.show, body.closet_ position: absolute; top: 1em; } -/* line 156, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 163, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header span.show:hover, body.closet_hangers-index .closet-hangers-group > header span.hide:hover { color: inherit; text-decoration: underline; } -/* line 160, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 167, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list { border-bottom: 1px solid #aaddaa; padding: 0.5em 0; position: relative; } -/* line 165, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 172, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form { font-size: 85%; left: 0.5em; @@ -877,17 +889,17 @@ body.closet_hangers-index .closet-list .visibility-form { top: 0.25em; z-index: 10; } -/* line 173, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input, body.closet_hangers-index .closet-list .visibility-form select { font-size: inherit; margin-bottom: 0; margin-top: 0; } -/* line 179, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 186, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form select { border-color: white; } -/* line 182, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 189, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -930,11 +942,11 @@ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:activ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:hover { background-color: #999999; } -/* line 187, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:active { top: 1px; } -/* line 190, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 197, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -945,20 +957,20 @@ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions list-style: none; padding: 0 0.5em; } -/* line 197, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 204, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions li { display: none; } -/* line 201, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 208, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form:hover .visibility-descriptions li.current { display: block; } -/* line 204, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 211, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list header { display: block; position: relative; } -/* line 208, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 215, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list h4 { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 150%; @@ -966,19 +978,19 @@ body.closet_hangers-index .closet-list h4 { margin: 0 auto 0.67em; width: 50%; } -/* line 215, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 222, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .empty-list { display: none; font-style: italic; } -/* line 219, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 226, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls { display: none; position: absolute; right: 1em; top: 0; } -/* line 225, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 232, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls a, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1019,36 +1031,36 @@ body.closet_hangers-index .closet-list .closet-list-controls a:active, body.clos body.closet_hangers-index .closet-list .closet-list-controls a:hover, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:hover { background-color: #999999; } -/* line 228, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 235, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls form { display: inline; } -/* line 232, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 239, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list[data-hangers-count="0"] .empty-list { display: block; } -/* line 236, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 243, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.unlisted h4 { font-size: 125%; font-style: italic; } -/* line 242, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 249, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .closet-list-controls { display: block; } -/* line 246, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 253, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form input[type=submit] { visibility: visible; } -/* line 249, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 256, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form select { border-color: #aaddaa; } -/* line 252, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 259, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:last-child { border-bottom: 0; } -/* line 255, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 262, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active { -moz-border-radius: 1em; -webkit-border-radius: 1em; @@ -1059,53 +1071,53 @@ body.closet_hangers-index .closet-list.droppable-active { border-style: dotted; margin: 1em 0; } -/* line 262, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 269, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object { -moz-opacity: 0.25; -webkit-opacity: 0.25; -o-opacity: 0.25; -khtml-opacity: 0.25; } -/* line 266, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 273, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object.ui-draggable-dragging { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 269, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 276, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-controls { display: none; } -/* line 272, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 279, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-hangers { overflow: hidden; } -/* line 275, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 282, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .visibility-form { display: none; } -/* line 279, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 286, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group-autocomplete-item span, body.closet_hangers-index .closet-list-autocomplete-item span { font-style: italic; padding: 0.2em 0.4em; } -/* line 284, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 291, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list-autocomplete-item a, body.closet_hangers-index .closet-list-autocomplete-item span { font-size: 85%; padding-left: 2em; } -/* line 291, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 298, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 294, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 301, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 52px; } -/* line 299, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 306, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1146,7 +1158,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 302, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 309, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -1156,77 +1168,77 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 0; padding: 0; } -/* line 308, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 315, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 311, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 318, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 315, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 322, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 320, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 327, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { display: block; } -/* line 323, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 330, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 326, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 333, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 329, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 336, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 333, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 340, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { display: block; } -/* line 336, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 343, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 340, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 347, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 343, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 350, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 347, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 354, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 350, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 357, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 355, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 362, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 358, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 365, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 362, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 369, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 365, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 372, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } -/* line 368, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 375, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #toggle-help { display: inline; } From 071ba56ae9fc5d3231c16a3b8e765bc07edd05eb Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 31 Jul 2011 19:24:06 -0400 Subject: [PATCH 66/69] public url on Your Items --- app/stylesheets/closet_hangers/_index.sass | 11 ++ app/views/closet_hangers/index.html.haml | 6 + public/javascripts/closet_hangers/index.js | 12 ++ public/stylesheets/compiled/screen.css | 138 ++++++++++++--------- 4 files changed, 105 insertions(+), 62 deletions(-) diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass index 7b427782..9364af11 100644 --- a/app/stylesheets/closet_hangers/_index.sass +++ b/app/stylesheets/closet_hangers/_index.sass @@ -99,6 +99,17 @@ body.closet_hangers-index +awesome-button margin: 0 0.5em + #closet-hangers-share + font-size: 85% + margin-bottom: 1em + + label + font-weight: bold + margin-right: .5em + + input + width: 30em + #closet-hangers clear: both text-align: center diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index f3f400b0..9be85fe2 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -70,9 +70,15 @@ - unless public_perspective? #closet-hangers-extras + #closet-hangers-share + %label{:for => 'closet-hangers-share-box'} Public URL: + %input#closet-hangers-share-box{:type => 'text', :value => user_closet_hangers_url(@user), :readonly => true} + = link_to "Import from Neopets closet", new_closet_page_path = link_to "Export to Neopets petpage", petpage_user_closet_hangers_path(@user) + + #closet-hangers{:class => public_perspective? ? nil : 'current-user'} - [true, false].each do |owned| .closet-hangers-group{'data-owned' => owned.to_s, :id => "closet-hangers-group-#{owned}"} diff --git a/public/javascripts/closet_hangers/index.js b/public/javascripts/closet_hangers/index.js index 86d4f4f5..bfa4a025 100644 --- a/public/javascripts/closet_hangers/index.js +++ b/public/javascripts/closet_hangers/index.js @@ -487,6 +487,18 @@ $('#closet-hangers-help').toggleClass('hidden'); }); + /* + + Share URL + + */ + + $('#closet-hangers-share-box').mouseover(function () { + $(this).focus(); + }).mouseout(function () { + $(this).blur(); + }); + /* Initialize diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index cdca7e8f..ef39858d 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -770,11 +770,25 @@ body.closet_hangers-index #closet-hangers-extras a:active { top: 1px; } /* line 102, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-share { + font-size: 85%; + margin-bottom: 1em; +} +/* line 106, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-share label { + font-weight: bold; + margin-right: 0.5em; +} +/* line 110, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #closet-hangers-share input { + width: 30em; +} +/* line 113, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers { clear: both; text-align: center; } -/* line 107, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 118, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -788,26 +802,26 @@ body.closet_hangers-index #closet-hangers .object .quantity { text-align: left; top: 0; } -/* line 117, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 128, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object .quantity span, body.closet_hangers-index #closet-hangers .object .quantity input[type=number] { font-size: 16px; font-weight: bold; } -/* line 121, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 132, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object form { display: none; } -/* line 125, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 136, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers .object[data-quantity="1"] .quantity { display: none; } -/* line 128, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 139, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group { border-top: 1px solid #006600; margin-bottom: 2em; padding-bottom: 1em; } -/* line 133, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 144, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header { border-bottom: 1px solid #aaddaa; display: block; @@ -815,12 +829,12 @@ body.closet_hangers-index .closet-hangers-group > header { padding: 0.25em 0; position: relative; } -/* line 140, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 151, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header h3 { font-size: 250%; margin: 0; } -/* line 144, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 155, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header .add-closet-list { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -855,12 +869,12 @@ body.closet_hangers-index .closet-hangers-group > header .add-closet-list:hover body.closet_hangers-index .closet-hangers-group > header .add-closet-list:active { top: 1px; } -/* line 151, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 162, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header .add-closet-list:active { margin-bottom: -1.1em; top: auto; } -/* line 155, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 166, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header span.show, body.closet_hangers-index .closet-hangers-group > header span.hide { color: #448844; display: none; @@ -869,18 +883,18 @@ body.closet_hangers-index .closet-hangers-group > header span.show, body.closet_ position: absolute; top: 1em; } -/* line 163, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 174, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group > header span.show:hover, body.closet_hangers-index .closet-hangers-group > header span.hide:hover { color: inherit; text-decoration: underline; } -/* line 167, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 178, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list { border-bottom: 1px solid #aaddaa; padding: 0.5em 0; position: relative; } -/* line 172, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 183, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form { font-size: 85%; left: 0.5em; @@ -889,17 +903,17 @@ body.closet_hangers-index .closet-list .visibility-form { top: 0.25em; z-index: 10; } -/* line 180, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 191, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input, body.closet_hangers-index .closet-list .visibility-form select { font-size: inherit; margin-bottom: 0; margin-top: 0; } -/* line 186, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 197, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form select { border-color: white; } -/* line 189, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 200, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -942,11 +956,11 @@ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:activ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:hover { background-color: #999999; } -/* line 194, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 205, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form input[type=submit]:active { top: 1px; } -/* line 197, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 208, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions { -moz-opacity: 0.75; -webkit-opacity: 0.75; @@ -957,20 +971,20 @@ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions list-style: none; padding: 0 0.5em; } -/* line 204, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 215, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form .visibility-descriptions li { display: none; } -/* line 208, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 219, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .visibility-form:hover .visibility-descriptions li.current { display: block; } -/* line 211, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 222, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list header { display: block; position: relative; } -/* line 215, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 226, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list h4 { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 150%; @@ -978,19 +992,19 @@ body.closet_hangers-index .closet-list h4 { margin: 0 auto 0.67em; width: 50%; } -/* line 222, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 233, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .empty-list { display: none; font-style: italic; } -/* line 226, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 237, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls { display: none; position: absolute; right: 1em; top: 0; } -/* line 232, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 243, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls a, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit] { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1031,36 +1045,36 @@ body.closet_hangers-index .closet-list .closet-list-controls a:active, body.clos body.closet_hangers-index .closet-list .closet-list-controls a:hover, body.closet_hangers-index .closet-list .closet-list-controls input[type=submit]:hover { background-color: #999999; } -/* line 235, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 246, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list .closet-list-controls form { display: inline; } -/* line 239, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 250, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list[data-hangers-count="0"] .empty-list { display: block; } -/* line 243, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 254, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.unlisted h4 { font-size: 125%; font-style: italic; } -/* line 249, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 260, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .closet-list-controls { display: block; } -/* line 253, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 264, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form input[type=submit] { visibility: visible; } -/* line 256, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 267, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:hover .visibility-form select { border-color: #aaddaa; } -/* line 259, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 270, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list:last-child { border-bottom: 0; } -/* line 262, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 273, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active { -moz-border-radius: 1em; -webkit-border-radius: 1em; @@ -1071,53 +1085,53 @@ body.closet_hangers-index .closet-list.droppable-active { border-style: dotted; margin: 1em 0; } -/* line 269, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 280, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object { -moz-opacity: 0.25; -webkit-opacity: 0.25; -o-opacity: 0.25; -khtml-opacity: 0.25; } -/* line 273, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 284, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .object.ui-draggable-dragging { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 276, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 287, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-controls { display: none; } -/* line 279, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 290, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .closet-list-hangers { overflow: hidden; } -/* line 282, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 293, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list.droppable-active .visibility-form { display: none; } -/* line 286, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 297, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-hangers-group-autocomplete-item span, body.closet_hangers-index .closet-list-autocomplete-item span { font-style: italic; padding: 0.2em 0.4em; } -/* line 291, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 302, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index .closet-list-autocomplete-item a, body.closet_hangers-index .closet-list-autocomplete-item span { font-size: 85%; padding-left: 2em; } -/* line 298, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 309, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover form { display: inline; } -/* line 301, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 312, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy { position: absolute; right: 18px; top: 52px; } -/* line 306, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 317, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -1158,7 +1172,7 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-han body.closet_hangers-index.current-user #closet-hangers .object:hover .closet-hanger-destroy input:hover { background-color: #999999; } -/* line 309, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 320, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { -moz-opacity: 1; -webkit-opacity: 1; @@ -1168,77 +1182,77 @@ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity { top: 0; padding: 0; } -/* line 315, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 326, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity span { display: none; } -/* line 318, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 329, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=number] { padding: 2px; width: 2em; } -/* line 322, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 333, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user #closet-hangers .object:hover .quantity input[type=submit] { font-size: 85%; } -/* line 327, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 338, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity { display: block; } -/* line 330, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 341, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=number] { width: 2.5em; } -/* line 333, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 344, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object:hover .quantity input[type=submit] { display: none; } -/* line 336, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 347, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading { background: #eeffee; outline: 1px solid #006600; } -/* line 340, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 351, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity { display: block; } -/* line 343, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 354, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers .object.loading .quantity span:after { content: "…"; } -/* line 347, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 358, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact form { display: none; } -/* line 350, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 361, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact .edit-contact-link, body.closet_hangers-index.current-user.js #closet-hangers-contact #cancel-contact-link { display: inline; } -/* line 354, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 365, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing form { display: block; } -/* line 357, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 368, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #closet-hangers-contact.editing .edit-contact-link { display: none; } -/* line 362, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 373, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .show, body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { cursor: pointer; } -/* line 365, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 376, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group header .hide { display: block; } -/* line 369, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 380, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .hide, body.closet_hangers-index.current-user.js .closet-hangers-group.hidden .closet-hangers-group-content { display: none; } -/* line 372, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 383, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js .closet-hangers-group.hidden header .show { display: block; } -/* line 375, ../../../app/stylesheets/closet_hangers/_index.sass */ +/* line 386, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index.current-user.js #toggle-help { display: inline; } From ceeb59973da8f8be4c10462de8499971c75fbdc4 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 31 Jul 2011 22:13:23 -0400 Subject: [PATCH 67/69] move image mode faq to outfits#edit instead of userbar --- app/stylesheets/outfits/_edit.sass | 3 +- app/views/layouts/application.html.haml | 4 - app/views/outfits/edit.html.haml | 10 +- public/stylesheets/compiled/screen.css | 185 ++++++++++++------------ 4 files changed, 101 insertions(+), 101 deletions(-) diff --git a/app/stylesheets/outfits/_edit.sass b/app/stylesheets/outfits/_edit.sass index e4ebed1d..b29a8a9f 100644 --- a/app/stylesheets/outfits/_edit.sass +++ b/app/stylesheets/outfits/_edit.sass @@ -230,9 +230,10 @@ body.outfits-edit display: none font-size: 85% margin: 0 auto - #preview-mode-image-access-denied + #preview-mode-note display: block font-size: 75% + margin-top: .5em text-align: center text-decoration: none width: 100% diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 6260f49f..cffd5719 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -37,10 +37,6 @@ #userbar - if user_signed_in? - - if can_use_image_mode? - = link_to image_mode_path, :id => 'userbar-image-mode' do - = image_tag 'image_mode_icon.png', :alt => 'Image Mode' - Welcome to Image Mode! %span Hey, #{current_user.name}! You have diff --git a/app/views/outfits/edit.html.haml b/app/views/outfits/edit.html.haml index ec8cb115..75e6dc46 100644 --- a/app/views/outfits/edit.html.haml +++ b/app/views/outfits/edit.html.haml @@ -41,14 +41,16 @@ %li#preview-mode-flash.active Flash - if can_use_image_mode? %li#preview-mode-image Image - - unless can_use_image_mode? - = link_to(donate_path, :id => 'preview-mode-image-access-denied', :target => '_blank') do + - if can_use_image_mode? + %button#preview-download-image Download + = link_to 'Image mode FAQ', image_mode_path, + :id => 'preview-mode-note', :target => '_blank' + - else + = link_to(donate_path, :id => 'preview-mode-note', :target => '_blank') do %strong Image mode is available for early beta testing to users who %em donate at least $5 to help upgrade the server. Thanks! - - if can_use_image_mode? - %button#preview-download-image Download #preview-sidebar - unless can_use_image_mode? #preview-sidebar-donation-request diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index ef39858d..afd962e4 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -2053,19 +2053,20 @@ body.outfits-edit #preview-download-image { margin: 0 auto; } /* line 233, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-mode-image-access-denied { +body.outfits-edit #preview-mode-note { display: block; font-size: 75%; + margin-top: 0.5em; text-align: center; text-decoration: none; width: 100%; } -/* line 239, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-mode-image-access-denied em { +/* line 240, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-mode-note em { font-style: normal; text-decoration: underline; } -/* line 242, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 243, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar { -moz-border-radius: 10px; -webkit-border-radius: 10px; @@ -2077,73 +2078,73 @@ body.outfits-edit #preview-sidebar { overflow: auto; width: 378px; } -/* line 252, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 253, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar.viewing-outfits #preview-closet { display: none; } -/* line 254, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 255, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar.viewing-outfits #preview-outfits { display: block; } -/* line 256, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 257, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar.viewing-saving-outfit { height: auto; max-height: 100%; } -/* line 259, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 260, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar.viewing-saving-outfit #preview-closet { display: none; } -/* line 261, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 262, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar.viewing-saving-outfit #preview-saving-outfit { display: block; } -/* line 264, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 265, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar .sidebar-view h2 { margin-bottom: 0.25em; margin-left: 24px; } -/* line 269, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 270, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet h2 { margin-bottom: 0; } -/* line 271, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 272, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet ul { text-align: center; } -/* line 273, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 274, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object { background: #eeffee; } -/* line 275, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 276, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object img { -moz-opacity: 0.5; -webkit-opacity: 0.5; -o-opacity: 0.5; -khtml-opacity: 0.5; } -/* line 277, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 278, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object.worn { background: transparent; } -/* line 279, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 280, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object.worn img { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 281, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 282, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object.no-assets { background: #fbe3e4; color: #8a1f11; padding-bottom: 1.25em; } -/* line 285, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 286, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object.no-assets .no-assets-message { display: block; } -/* line 287, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 288, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .no-assets-message { background: #f3dbdc; bottom: 0; @@ -2155,7 +2156,7 @@ body.outfits-edit .no-assets-message { position: absolute; width: 100%; } -/* line 297, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 298, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #no-assets-full-message { -moz-border-radius: 5px; -webkit-border-radius: 5px; @@ -2169,12 +2170,12 @@ body.outfits-edit #no-assets-full-message { top: -9999px; width: 30em; } -/* line 308, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 309, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form { clear: both; text-align: left; } -/* line 311, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 312, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form h2 { display: -moz-inline-box; -moz-box-orient: vertical; @@ -2184,7 +2185,7 @@ body.outfits-edit #preview-search-form h2 { *vertical-align: auto; margin: 0 1em 0 0; } -/* line 314, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 315, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form input { display: -moz-inline-box; -moz-box-orient: vertical; @@ -2193,17 +2194,17 @@ body.outfits-edit #preview-search-form input { *display: inline; *vertical-align: auto; } -/* line 316, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 317, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form input[type=submit] { margin-right: 2em; } -/* line 318, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 319, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .preview-search-form-your-items { display: none; font-size: 85%; margin-right: 1em; } -/* line 322, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 323, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-pagination { display: -moz-inline-box; -moz-box-orient: vertical; @@ -2212,53 +2213,53 @@ body.outfits-edit #preview-search-form-pagination { *display: inline; *vertical-align: auto; } -/* line 324, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 325, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-pagination a, body.outfits-edit #preview-search-form-pagination span { margin: 0 0.25em; } -/* line 326, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 327, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-pagination .current { font-weight: bold; } -/* line 328, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 329, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-clear { display: none; font-size: 87.5%; margin-left: 2em; } -/* line 332, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 333, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-loading { display: none; font-size: 75%; font-style: italic; margin-left: 2em; } -/* line 338, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 339, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-no-results { display: none; } -/* line 340, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 341, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-help { font-size: 87.5%; margin-left: 2em; } -/* line 343, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 344, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .search-helper { font-family: inherit; } -/* line 345, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 346, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .possible-error { display: none; } -/* line 348, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 349, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #fullscreen-copyright { display: none; } -/* line 350, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 351, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen { height: 100%; } -/* line 353, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 354, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #container { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; @@ -2271,19 +2272,19 @@ body.outfits-edit.fullscreen #container { position: relative; width: 80%; } -/* line 361, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 362, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen h1 { display: none; } -/* line 363, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 364, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #short-url-response { position: static; } -/* line 365, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 366, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview { width: 100%; } -/* line 367, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 368, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-sidebar { float: right; height: 100%; @@ -2291,12 +2292,12 @@ body.outfits-edit.fullscreen #preview-sidebar { position: relative; width: 400px; } -/* line 373, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 374, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-sidebar.viewing-saving-outfit { height: auto; max-height: 100%; } -/* line 376, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 377, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-search-form { bottom: 1.5em; left: 0; @@ -2305,7 +2306,7 @@ body.outfits-edit.fullscreen #preview-search-form { position: absolute; width: 100%; } -/* line 384, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 385, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-search-form-help div { display: -moz-inline-box; -moz-box-orient: vertical; @@ -2315,27 +2316,27 @@ body.outfits-edit.fullscreen #preview-search-form-help div { *vertical-align: auto; width: 48%; } -/* line 387, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 388, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #footer { bottom: 0; left: 0; position: absolute; width: 100%; } -/* line 392, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 393, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #footer ul, body.outfits-edit.fullscreen #footer p, body.outfits-edit.fullscreen #footer li { display: inline; } -/* line 394, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 395, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #footer ul { margin-right: 2em; } -/* line 397, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 398, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object { padding: 6px; position: relative; } -/* line 400, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 401, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object ul { display: none; left: 0; @@ -2343,11 +2344,11 @@ body.outfits-edit .object ul { position: absolute; top: 0; } -/* line 406, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 407, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object ul li { margin-bottom: 0.25em; } -/* line 408, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 409, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object ul li a { /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ -moz-border-radius: 5px; @@ -2388,11 +2389,11 @@ body.outfits-edit .object ul li a:active { body.outfits-edit .object ul li a:hover { background-color: #999999; } -/* line 411, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 412, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object:hover ul, body.outfits-edit .object:hover .object-info { display: block; } -/* line 418, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 419, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .nc-icon { background: url('/images/nc.png?1311877029') no-repeat; height: 16px; @@ -2402,14 +2403,14 @@ body.outfits-edit .nc-icon { top: 64px; width: 16px; } -/* line 426, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 427, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .nc-icon:hover { -moz-opacity: 0.5; -webkit-opacity: 0.5; -o-opacity: 0.5; -khtml-opacity: 0.5; } -/* line 429, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 430, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object-info { -moz-border-radius: 12px; -webkit-border-radius: 12px; @@ -2426,26 +2427,26 @@ body.outfits-edit .object-info { top: 0; width: 16px; } -/* line 440, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 441, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object-info span { font-family: "Droid Serif", Georgia, "Times New Roman", Times, serif; font-weight: bold; position: relative; top: -2px; } -/* line 446, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 447, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object-info:hover { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 449, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 450, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits { display: none; text-align: left; } -/* line 452, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 453, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul { margin-left: 24px; margin-right: 24px; @@ -2456,7 +2457,7 @@ body.outfits-edit #preview-outfits > ul { margin-bottom: 1em; min-height: 16px; } -/* line 461, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 462, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li { padding: 0.25em 0; } @@ -2635,18 +2636,18 @@ body.outfits-edit #preview-outfits > ul > li.renaming:hover .outfit-rename-butto body.outfits-edit #preview-outfits > ul > li:hover .outfit-rename-button { display: inline; } -/* line 463, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 464, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul.loaded { background: transparent; } -/* line 466, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 467, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .preview-sidebar-nav { float: right; font-size: 85%; margin-right: 24px; margin-top: 1em; } -/* line 473, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 474, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-success, body.outfits-edit #save-error, body.outfits-edit #outfit-not-found, body.outfits-edit #preview-sidebar-donation-request { margin-left: 24px; margin-right: 24px; @@ -2654,7 +2655,7 @@ body.outfits-edit #save-success, body.outfits-edit #save-error, body.outfits-edi margin-top: 1em; text-align: center; } -/* line 480, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 481, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar-donation-request { background: #e6efc2; border: 1px solid #c6d880; @@ -2662,23 +2663,23 @@ body.outfits-edit #preview-sidebar-donation-request { font-size: 85%; padding: 1em; } -/* line 485, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 486, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar-donation-request-no-thanks { margin-left: 1em; } -/* line 488, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 489, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-success { background: #e6efc2; border: 1px solid #c6d880; color: #264409; } -/* line 491, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 492, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-error, body.outfits-edit #outfit-not-found { background: #fbe3e4; border: 1px solid #fbc2c4; color: #8a1f11; } -/* line 494, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 495, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #userbar-message { -moz-opacity: 0.5; -webkit-opacity: 0.5; @@ -2686,7 +2687,7 @@ body.outfits-edit #userbar-message { -khtml-opacity: 0.5; display: none; } -/* line 498, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 499, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit { padding: 0.25em 0; margin-left: 24px; @@ -2868,33 +2869,33 @@ body.outfits-edit #new-outfit.renaming:hover .outfit-rename-button { body.outfits-edit #new-outfit:hover .outfit-rename-button { display: inline; } -/* line 502, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 503, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit h4 { display: inline; } -/* line 504, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 505, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit h4:hover { text-decoration: none; } -/* line 506, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 507, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit .outfit-star { margin-top: 0.5em; } -/* line 509, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 510, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit-name { font: inherit; line-height: 1; } -/* line 513, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 514, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-saving-outfit { display: none; padding-bottom: 1em; } -/* line 517, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 518, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-type-form, body.outfits-edit #pet-state-form, body.outfits-edit #preview-swf, body.outfits-edit #preview-search-form { position: relative; } -/* line 520, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 521, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .control-overlay { height: 100%; left: 0; @@ -2903,11 +2904,11 @@ body.outfits-edit .control-overlay { width: 100%; z-index: 5; } -/* line 528, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 529, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar-nav-outfits, body.outfits-edit #save-outfit-signed-in { display: none; } -/* line 531, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 532, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form { padding: 0.25em 0; display: none; @@ -3089,7 +3090,7 @@ body.outfits-edit form#save-outfit-form.renaming:hover .outfit-rename-button { body.outfits-edit form#save-outfit-form:hover .outfit-rename-button { display: inline; } -/* line 537, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 538, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-star, body.outfits-edit form#save-outfit-form input, body.outfits-edit form#save-outfit-form button { display: -moz-inline-box; -moz-box-orient: vertical; @@ -3100,43 +3101,43 @@ body.outfits-edit form#save-outfit-form .outfit-star, body.outfits-edit form#sav float: none; vertical-align: top; } -/* line 542, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 543, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form .outfit-star { margin-top: 0.25em; } -/* line 545, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 546, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .outfit-url { font-size: 75%; } -/* line 549, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 550, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #preview-sidebar-nav-outfits { display: block; } -/* line 551, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 552, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit { display: inline-block; } -/* line 555, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 556, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-outfit { display: none; } -/* line 557, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 558, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-current-outfit, body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-outfit-copy { display: inline-block; } -/* line 559, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 560, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #current-outfit-permalink { display: inline-block; } -/* line 562, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 563, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit-form { display: block; } -/* line 564, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 565, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-current-outfit, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit-copy, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #current-outfit-permalink, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #shared-outfit-permalink, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #share-outfit, body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #shared-outfit-url { display: none; } -/* line 566, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 567, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-signed-in .preview-search-form-your-items { display: -moz-inline-box; -moz-box-orient: vertical; @@ -3145,15 +3146,15 @@ body.outfits-edit.user-signed-in .preview-search-form-your-items { *display: inline; *vertical-align: auto; } -/* line 570, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 571, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.user-not-signed-in #save-outfit-not-signed-in { display: inline-block; } -/* line 574, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 575, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper.shared-outfit #shared-outfit-permalink, body.outfits-edit #save-outfit-wrapper.shared-outfit #shared-outfit-url { display: inline-block; } -/* line 576, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 577, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper.shared-outfit #current-outfit-permalink { display: none !important; } From dacfc99ce7c99d61ed88e872d5ac58a5c1fe825f Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 31 Jul 2011 22:17:59 -0400 Subject: [PATCH 68/69] allow your_items_path to be cached on home --- app/controllers/closet_hangers_controller.rb | 4 +++- app/helpers/items_helper.rb | 4 ---- config/routes.rb | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb index 94e877f9..b75a5a70 100644 --- a/app/controllers/closet_hangers_controller.rb +++ b/app/controllers/closet_hangers_controller.rb @@ -97,8 +97,10 @@ class ClosetHangersController < ApplicationController def find_user if params[:user_id] @user = User.find params[:user_id] - else + elsif user_signed_in? redirect_to user_closet_hangers_path(current_user) + else + redirect_to login_path(:return_to => request.fullpath) end end diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb index 17c760c8..55540a3a 100644 --- a/app/helpers/items_helper.rb +++ b/app/helpers/items_helper.rb @@ -88,10 +88,6 @@ module ItemsHelper end.to_sentence.html_safe end - def your_items_path - user_signed_in? ? user_closet_hangers_path(current_user) : login_path(:return_to => current_user_items_path) - end - private def build_on_pet_types(species, special_color=nil, &block) diff --git a/config/routes.rb b/config/routes.rb index ffe8538f..7a19db34 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -55,7 +55,7 @@ OpenneoImpressItems::Application.routes.draw do |map| end end - match 'users/current-user/closet' => 'closet_hangers#index', :as => :current_user_items + match 'users/current-user/closet' => 'closet_hangers#index', :as => :your_items match 'users/top-contributors' => 'users#top_contributors', :as => :top_contributors match 'users/top_contributors' => redirect('/users/top-contributors') From 5f4cd9ddbf0869fa7c356ac8531d7eb792394030 Mon Sep 17 00:00:00 2001 From: Matchu Date: Sun, 31 Jul 2011 22:55:29 -0400 Subject: [PATCH 69/69] new! tags to point to Your Items --- app/stylesheets/_layout.sass | 11 +++++ app/stylesheets/outfits/_new.sass | 9 ++++ app/views/layouts/application.html.haml | 2 +- app/views/outfits/new.html.haml | 2 +- public/stylesheets/compiled/screen.css | 58 ++++++++++++++++++------- 5 files changed, 64 insertions(+), 18 deletions(-) diff --git a/app/stylesheets/_layout.sass b/app/stylesheets/_layout.sass index e2e50bbc..29fd2103 100644 --- a/app/stylesheets/_layout.sass +++ b/app/stylesheets/_layout.sass @@ -155,6 +155,17 @@ ul.buttons &:hover span text-decoration: none +#userbar-items-link + +hover-link + background: $module-bg-color + padding: .25em .5em + + &:after + color: red + content: "new!" + font-size: 85% + margin-left: .5em + .object +inline-block margin: $object-padding 0 diff --git a/app/stylesheets/outfits/_new.sass b/app/stylesheets/outfits/_new.sass index aa755dcb..38d55196 100644 --- a/app/stylesheets/outfits/_new.sass +++ b/app/stylesheets/outfits/_new.sass @@ -137,3 +137,12 @@ body.outfits-new #read-more float: right + #your-items-module + h3 + &:after + color: red + content: "new!" + font-size: 85% + font-weight: bold + margin-left: .5em + diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index cffd5719..eb92e9a6 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -42,7 +42,7 @@ You have = succeed '.' do = link_to "#{current_user.points} points", user_contributions_path(current_user) - = link_to 'Items', user_closet_hangers_path(current_user) + = link_to 'Items', user_closet_hangers_path(current_user), :id => 'userbar-items-link' = link_to 'Outfits', current_user_outfits_path = link_to 'Settings', Openneo::Auth.remote_settings_url = link_to 'Log out', logout_path_with_return_to diff --git a/app/views/outfits/new.html.haml b/app/views/outfits/new.html.haml index c5ba4608..1baa4804 100644 --- a/app/views/outfits/new.html.haml +++ b/app/views/outfits/new.html.haml @@ -28,7 +28,7 @@ - cache :action_suffix => 'sections_and_description' do %ul#sections - %li + %li#your-items-module = link_to image_tag('your_items.png'), your_items_path %h3 = link_to 'Your Items', your_items_path diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index afd962e4..906a6599 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -264,6 +264,24 @@ ul.buttons li, ul.buttons li form { } /* line 158, ../../../app/stylesheets/_layout.sass */ +#userbar-items-link { + text-decoration: none; + background: #eeffee; + padding: 0.25em 0.5em; +} +/* line 4, ../../../../../.rvm/gems/ree-1.8.7-2010.02/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/utilities/links/_hover-link.scss */ +#userbar-items-link:hover { + text-decoration: underline; +} +/* line 163, ../../../app/stylesheets/_layout.sass */ +#userbar-items-link:after { + color: red; + content: "new!"; + font-size: 85%; + margin-left: 0.5em; +} + +/* line 169, ../../../app/stylesheets/_layout.sass */ .object { display: -moz-inline-box; -moz-box-orient: vertical; @@ -278,32 +296,32 @@ ul.buttons li, ul.buttons li form { vertical-align: top; width: 100px; } -/* line 166, ../../../app/stylesheets/_layout.sass */ +/* line 177, ../../../app/stylesheets/_layout.sass */ .object a { text-decoration: none; } -/* line 168, ../../../app/stylesheets/_layout.sass */ +/* line 179, ../../../app/stylesheets/_layout.sass */ .object a img { -moz-opacity: 0.75; -webkit-opacity: 0.75; -o-opacity: 0.75; -khtml-opacity: 0.75; } -/* line 170, ../../../app/stylesheets/_layout.sass */ +/* line 181, ../../../app/stylesheets/_layout.sass */ .object img { display: block; height: 80px; margin: 0 auto; width: 80px; } -/* line 175, ../../../app/stylesheets/_layout.sass */ +/* line 186, ../../../app/stylesheets/_layout.sass */ .object:hover img, .object a:hover img { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 181, ../../../app/stylesheets/_layout.sass */ +/* line 192, ../../../app/stylesheets/_layout.sass */ .object .nc-icon, .object .closeted-icons { -moz-opacity: 1; -webkit-opacity: 1; @@ -314,7 +332,7 @@ ul.buttons li, ul.buttons li form { position: absolute; top: 64px; } -/* line 187, ../../../app/stylesheets/_layout.sass */ +/* line 198, ../../../app/stylesheets/_layout.sass */ .object .nc-icon:hover, .object .closeted-icons:hover { -moz-opacity: 0.5; -webkit-opacity: 0.5; @@ -322,32 +340,32 @@ ul.buttons li, ul.buttons li form { -khtml-opacity: 0.5; background: transparent; } -/* line 191, ../../../app/stylesheets/_layout.sass */ +/* line 202, ../../../app/stylesheets/_layout.sass */ .object .nc-icon, .object .closeted-icons img { display: inline; height: 16px; width: 16px; } -/* line 196, ../../../app/stylesheets/_layout.sass */ +/* line 207, ../../../app/stylesheets/_layout.sass */ .object .nc-icon { right: 18px; } -/* line 200, ../../../app/stylesheets/_layout.sass */ +/* line 211, ../../../app/stylesheets/_layout.sass */ .object .closeted-icons { left: 18px; } -/* line 203, ../../../app/stylesheets/_layout.sass */ +/* line 214, ../../../app/stylesheets/_layout.sass */ dt { font-weight: bold; } -/* line 206, ../../../app/stylesheets/_layout.sass */ +/* line 217, ../../../app/stylesheets/_layout.sass */ dd { margin: 0 0 1.5em 1em; } -/* line 209, ../../../app/stylesheets/_layout.sass */ +/* line 220, ../../../app/stylesheets/_layout.sass */ #home-link { font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; font-size: 175%; @@ -358,21 +376,21 @@ dd { position: absolute; top: 0; } -/* line 219, ../../../app/stylesheets/_layout.sass */ +/* line 230, ../../../app/stylesheets/_layout.sass */ #home-link:hover { background: #eeffee; text-decoration: none; } -/* line 222, ../../../app/stylesheets/_layout.sass */ +/* line 233, ../../../app/stylesheets/_layout.sass */ #home-link span:before { content: "<< "; } -/* line 226, ../../../app/stylesheets/_layout.sass */ +/* line 237, ../../../app/stylesheets/_layout.sass */ .pagination a, .pagination span { margin: 0 0.5em; } -/* line 228, ../../../app/stylesheets/_layout.sass */ +/* line 239, ../../../app/stylesheets/_layout.sass */ .pagination .current { font-weight: bold; } @@ -3531,6 +3549,14 @@ body.outfits-new #sections img:hover { body.outfits-new #read-more { float: right; } +/* line 142, ../../../app/stylesheets/outfits/_new.sass */ +body.outfits-new #your-items-module h3:after { + color: red; + content: "new!"; + font-size: 85%; + font-weight: bold; + margin-left: 0.5em; +} /* line 2, ../../../app/stylesheets/partials/_campaign-progress.sass */ body.outfits-show .campaign-progress-wrapper {

      JI{J*vE!kHc`@R^k00WGHVVa}@9fvK7 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 J82Aq{@IO$|8*Bgo literal 0 HcmV?d00001 From d5641dddbba73dbc521d4262c121e98b0cab4e03 Mon Sep 17 00:00:00 2001 From: Matchu Date: Tue, 12 Jul 2011 20:03:04 -0400 Subject: [PATCH 02/69] user closet display --- app/controllers/closet_hangers_controller.rb | 7 +++++++ app/helpers/application_helper.rb | 4 ++++ app/helpers/closet_hangers_helper.rb | 2 ++ app/stylesheets/closet_hangers/index.sass | 4 ++++ app/stylesheets/screen.sass | 1 + .../closet_hangers/_closet_hanger.html.haml | 6 ++++++ app/views/closet_hangers/index.html.haml | 20 +++++++++++++++++++ app/views/items/_item.html.haml | 6 ++---- app/views/items/_item_link.html.haml | 5 +++++ config/routes.rb | 1 + .../compiled/closet_hangers/index.css | 4 ++++ public/stylesheets/compiled/screen.css | 5 +++++ .../closet_hangers_controller_spec.rb | 5 +++++ spec/helpers/closet_hangers_helper_spec.rb | 15 ++++++++++++++ 14 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 app/controllers/closet_hangers_controller.rb create mode 100644 app/helpers/closet_hangers_helper.rb create mode 100644 app/stylesheets/closet_hangers/index.sass create mode 100644 app/views/closet_hangers/_closet_hanger.html.haml create mode 100644 app/views/closet_hangers/index.html.haml create mode 100644 app/views/items/_item_link.html.haml create mode 100644 public/stylesheets/compiled/closet_hangers/index.css create mode 100644 spec/controllers/closet_hangers_controller_spec.rb create mode 100644 spec/helpers/closet_hangers_helper_spec.rb diff --git a/app/controllers/closet_hangers_controller.rb b/app/controllers/closet_hangers_controller.rb new file mode 100644 index 00000000..def5dfbe --- /dev/null +++ b/app/controllers/closet_hangers_controller.rb @@ -0,0 +1,7 @@ +class ClosetHangersController < ApplicationController + def index + @user = User.find params[:user_id] + @closet_hangers = @user.closet_hangers.alphabetical_by_item_name.includes(:item) + end +end + diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index f30b2a73..6c338888 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -97,5 +97,9 @@ module ApplicationHelper def title(value) content_for :title, value end + + def user_is?(user) + user_signed_in? && user == current_user + end end diff --git a/app/helpers/closet_hangers_helper.rb b/app/helpers/closet_hangers_helper.rb new file mode 100644 index 00000000..a6c002f7 --- /dev/null +++ b/app/helpers/closet_hangers_helper.rb @@ -0,0 +1,2 @@ +module ClosetHangersHelper +end diff --git a/app/stylesheets/closet_hangers/index.sass b/app/stylesheets/closet_hangers/index.sass new file mode 100644 index 00000000..ad242282 --- /dev/null +++ b/app/stylesheets/closet_hangers/index.sass @@ -0,0 +1,4 @@ +body.closet_hangers-index + #closet-hangers + text-align: center + diff --git a/app/stylesheets/screen.sass b/app/stylesheets/screen.sass index 2ae499f8..73b7ca23 100644 --- a/app/stylesheets/screen.sass +++ b/app/stylesheets/screen.sass @@ -6,6 +6,7 @@ @import partials/jquery.jgrowl +@import closet_hangers/index @import contributions/index @import items @import items/index diff --git a/app/views/closet_hangers/_closet_hanger.html.haml b/app/views/closet_hangers/_closet_hanger.html.haml new file mode 100644 index 00000000..fce078bb --- /dev/null +++ b/app/views/closet_hangers/_closet_hanger.html.haml @@ -0,0 +1,6 @@ +.object + = render :partial => 'items/item_link', :locals => {:item => closet_hanger.item} + %span.quantity + = surround '(', ')' do + = closet_hanger.quantity + diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml new file mode 100644 index 00000000..1c30b833 --- /dev/null +++ b/app/views/closet_hangers/index.html.haml @@ -0,0 +1,20 @@ +- if user_is?(@user) + - title 'Your Closet' +- else + - title "#{@user.name}'s Closet" +#closet-hangers + - if !@closet_hangers.empty? + = render @closet_hangers + - else + - if user_is?(@user) + %p You don't have any items in your Dress to Impress closet. + %p + Your Dress to Impress closet is a way to keep track of what items you + have in your Neopets closet. Once you load your Neopets closet into + Dress to Impress, as you play with various outfit ideas you can keep + track of what items you already own. And, who knows? Maybe some day + you can use it as a up-for-trade list or wishlist. We'll see what + happens. + - else + %p #{@user.name} doesn't have any items in their Dress to Impress closet. + diff --git a/app/views/items/_item.html.haml b/app/views/items/_item.html.haml index 1634f0be..a3de7727 100644 --- a/app/views/items/_item.html.haml +++ b/app/views/items/_item.html.haml @@ -1,5 +1,3 @@ .object - = link_to item_path(item, :q => @query) do - = image_tag item.thumbnail_url, :alt => item.description, :title => item.description - = item.name - = nc_icon_for(item) + = render :partial => 'item_link', :locals => {:item => item} + diff --git a/app/views/items/_item_link.html.haml b/app/views/items/_item_link.html.haml new file mode 100644 index 00000000..11a3a979 --- /dev/null +++ b/app/views/items/_item_link.html.haml @@ -0,0 +1,5 @@ += link_to item_path(item, :q => @query) do + = image_tag item.thumbnail_url, :alt => item.description, :title => item.description + = item.name + = nc_icon_for(item) + diff --git a/config/routes.rb b/config/routes.rb index 74a89a92..cd3e06ff 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -35,6 +35,7 @@ OpenneoImpressItems::Application.routes.draw do |map| resources :user, :only => [] do resources :contributions, :only => [:index] + resources :closet_hangers, :only => [:index], :path => 'closet' end match 'users/top-contributors' => 'users#top_contributors', :as => :top_contributors match 'users/top_contributors' => redirect('/users/top-contributors') diff --git a/public/stylesheets/compiled/closet_hangers/index.css b/public/stylesheets/compiled/closet_hangers/index.css new file mode 100644 index 00000000..f8ef829f --- /dev/null +++ b/public/stylesheets/compiled/closet_hangers/index.css @@ -0,0 +1,4 @@ +/* line 2, ../../../../app/stylesheets/closet_hangers/index.sass */ +body.closet_hangers-index #closet-hangers { + text-align: center; +} diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index c3504025..d7ae053a 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -538,6 +538,11 @@ div.jGrowl div.jGrowl-closer { } } +/* line 2, ../../../app/stylesheets/closet_hangers/index.sass */ +body.closet_hangers-index #closet-hangers { + text-align: center; +} + /* line 1, ../../../app/stylesheets/contributions/_index.sass */ body.contributions-index { text-align: center; diff --git a/spec/controllers/closet_hangers_controller_spec.rb b/spec/controllers/closet_hangers_controller_spec.rb new file mode 100644 index 00000000..6f79ab79 --- /dev/null +++ b/spec/controllers/closet_hangers_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe ClosetHangersController do + +end diff --git a/spec/helpers/closet_hangers_helper_spec.rb b/spec/helpers/closet_hangers_helper_spec.rb new file mode 100644 index 00000000..74eee5bb --- /dev/null +++ b/spec/helpers/closet_hangers_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the ClosetHangersHelper. For example: +# +# describe ClosetHangersHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe ClosetHangersHelper do + pending "add some examples to (or delete) #{__FILE__}" +end From 6ebacc99dd59faa91c771fc86020e95b60339e6c Mon Sep 17 00:00:00 2001 From: Matchu Date: Tue, 12 Jul 2011 20:51:43 -0400 Subject: [PATCH 03/69] closet page saving backend --- app/controllers/closet_pages_controller.rb | 63 +++++++++++++++++++ app/helpers/closet_pages_helper.rb | 2 + app/models/closet_page.rb | 33 ++++++++-- app/views/closet_pages/new.html.haml | 5 ++ config/routes.rb | 3 + .../closet_pages_controller_spec.rb | 5 ++ spec/helpers/closet_pages_helper_spec.rb | 15 +++++ 7 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 app/controllers/closet_pages_controller.rb create mode 100644 app/helpers/closet_pages_helper.rb create mode 100644 app/views/closet_pages/new.html.haml create mode 100644 spec/controllers/closet_pages_controller_spec.rb create mode 100644 spec/helpers/closet_pages_helper_spec.rb diff --git a/app/controllers/closet_pages_controller.rb b/app/controllers/closet_pages_controller.rb new file mode 100644 index 00000000..02a9624e --- /dev/null +++ b/app/controllers/closet_pages_controller.rb @@ -0,0 +1,63 @@ +class ClosetPagesController < ApplicationController + include ActionView::Helpers::TextHelper + + before_filter :authenticate_user!, :build_closet_page + + rescue_from ClosetPage::ParseError, :with => :on_parse_error + + def create + if params[:closet_page] && params[:closet_page][:source] + @closet_page.source = params[:closet_page][:source] + saved_counts = @closet_page.save_hangers! + + any_created = saved_counts[:created] > 0 + any_updated = saved_counts[:updated] > 0 + if any_created || any_updated + message = "Page #{@closet_page.index} saved! We " + message << "added " + pluralize(saved_counts[:created], 'item') + " to your closet" if any_created + message << " and " if any_created && any_updated + message << "updated the count on " + pluralize(saved_counts[:updated], 'item') if any_updated + message << ". " + else + message = "Success! We checked that page, and we already had all this data recorded. " + end + + unless @closet_page.unknown_item_names.empty? + message << "We also found " + + pluralize(@closet_page.unknown_item_names.size, 'item') + + " we didn't recognize: " + + @closet_page.unknown_item_names.to_sentence + + ". Please put each item on your pet and type its name in on the " + + "home page so we can have a record of it. Thanks! " + end + + if @closet_page.last? + message << "That was the last page of your Neopets closet." + destination = user_closet_hangers_path(current_user) + else + message << "Let's move onto the next page!" + destination = {:action => :new, :page => (@closet_page.index + 1)} + end + + flash[:success] = message + redirect_to destination + else + redirect_to :action => :new + end + end + + def new + end + + protected + + def build_closet_page + @closet_page = ClosetPage.new(current_user) + end + + def on_parse_error + flash[:alert] = "We had trouble reading your source code. Is it a valid HTML document? Make sure you pasted the computery-looking result of right-click > View Source, and not the pretty page itself." + render :action => :new + end +end + diff --git a/app/helpers/closet_pages_helper.rb b/app/helpers/closet_pages_helper.rb new file mode 100644 index 00000000..dab106d2 --- /dev/null +++ b/app/helpers/closet_pages_helper.rb @@ -0,0 +1,2 @@ +module ClosetPagesHelper +end diff --git a/app/models/closet_page.rb b/app/models/closet_page.rb index d9de7430..b9e25f8b 100644 --- a/app/models/closet_page.rb +++ b/app/models/closet_page.rb @@ -1,6 +1,9 @@ require 'yaml' class ClosetPage + include ActiveModel::Conversion + extend ActiveModel::Naming + SELECTORS = { :items => "form[action=\"process_closet.phtml\"] tr[bgcolor!=silver][bgcolor!=\"#E4E4E4\"]", :item_thumbnail => "img", @@ -11,18 +14,39 @@ class ClosetPage :selected => "option[selected]" } - attr_reader :hangers, :index, :total_pages, :unknown_item_names + attr_reader :hangers, :index, :source, :total_pages, :unknown_item_names, :user def initialize(user) raise ArgumentError, "Expected #{user.inspect} to be a User", caller unless user.is_a?(User) @user = user end + def last? + @index == @total_pages + end + + def persisted? + false + end + def save_hangers! - @hangers.each(&:save!) + counts = {:created => 0, :updated => 0} + ClosetHanger.transaction do + @hangers.each do |hanger| + if hanger.new_record? + counts[:created] += 1 + hanger.save! + elsif hanger.changed? + counts[:updated] += 1 + hanger.save! + end + end + end + counts end def source=(source) + @source = source parse_source!(source) end @@ -42,7 +66,7 @@ class ClosetPage page_selector = element(:page_select, doc) @total_pages = page_selector.children.size - @index = element(:selected, page_selector)['value'] + @index = element(:selected, page_selector)['value'].to_i items_data = { :id => {}, @@ -89,8 +113,7 @@ class ClosetPage @hangers = items.map do |item| data = items_data[:id].delete(item.id) || items_data[:thumbnail_url].delete(item.thumbnail_url) - hanger = @user.closet_hangers.build - hanger.item = item + hanger = @user.closet_hangers.find_or_initialize_by_item_id(item.id) hanger.quantity = data[:quantity] hanger end diff --git a/app/views/closet_pages/new.html.haml b/app/views/closet_pages/new.html.haml new file mode 100644 index 00000000..e141128a --- /dev/null +++ b/app/views/closet_pages/new.html.haml @@ -0,0 +1,5 @@ += form_for(@closet_page) do |f| + = f.label :source + = f.text_area :source + = f.submit 'Add items to closet' + diff --git a/config/routes.rb b/config/routes.rb index cd3e06ff..6ad714b7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -24,6 +24,8 @@ OpenneoImpressItems::Application.routes.draw do |map| resources :pet_attributes, :only => [:index] resources :swf_assets, :only => [:index, :show] + resources :closet_pages, :only => [:new, :create], :path => 'closet/pages' + match '/users/current-user/outfits' => 'outfits#index', :as => :current_user_outfits match '/pets/load' => 'pets#load', :method => :post, :as => :load_pet @@ -37,6 +39,7 @@ OpenneoImpressItems::Application.routes.draw do |map| resources :contributions, :only => [:index] resources :closet_hangers, :only => [:index], :path => 'closet' end + match 'users/top-contributors' => 'users#top_contributors', :as => :top_contributors match 'users/top_contributors' => redirect('/users/top-contributors') diff --git a/spec/controllers/closet_pages_controller_spec.rb b/spec/controllers/closet_pages_controller_spec.rb new file mode 100644 index 00000000..9f7b67ac --- /dev/null +++ b/spec/controllers/closet_pages_controller_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe ClosetPagesController do + +end diff --git a/spec/helpers/closet_pages_helper_spec.rb b/spec/helpers/closet_pages_helper_spec.rb new file mode 100644 index 00000000..9483444d --- /dev/null +++ b/spec/helpers/closet_pages_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the ClosetPagesHelper. For example: +# +# describe ClosetPagesHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe ClosetPagesHelper do + pending "add some examples to (or delete) #{__FILE__}" +end From a33898a3937e818a214a25d7f7ae987e14724439 Mon Sep 17 00:00:00 2001 From: Matchu Date: Wed, 13 Jul 2011 00:25:14 -0400 Subject: [PATCH 04/69] import closet page --- app/controllers/application_controller.rb | 4 + app/controllers/closet_pages_controller.rb | 10 +- app/models/closet_page.rb | 7 +- app/stylesheets/closet_hangers/_index.sass | 15 +++ app/stylesheets/closet_hangers/index.sass | 4 - app/stylesheets/closet_pages/_new.sass | 42 ++++++++ app/stylesheets/screen.sass | 1 + app/views/closet_hangers/index.html.haml | 1 + app/views/closet_pages/new.html.haml | 50 +++++++++- .../compiled/closet_hangers/index.css | 4 - public/stylesheets/compiled/screen.css | 99 ++++++++++++++++++- 11 files changed, 221 insertions(+), 16 deletions(-) create mode 100644 app/stylesheets/closet_hangers/_index.sass delete mode 100644 app/stylesheets/closet_hangers/index.sass create mode 100644 app/stylesheets/closet_pages/_new.sass delete mode 100644 public/stylesheets/compiled/closet_hangers/index.css diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 903f64ec..4543f7c7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,6 +3,10 @@ class ApplicationController < ActionController::Base helper_method :can_use_image_mode? + def authenticate_user! # too lazy to change references to login_path + redirect_to(login_path) unless user_signed_in? + end + def can_use_image_mode? user_signed_in? && current_user.image_mode_tester? end diff --git a/app/controllers/closet_pages_controller.rb b/app/controllers/closet_pages_controller.rb index 02a9624e..9e1a1860 100644 --- a/app/controllers/closet_pages_controller.rb +++ b/app/controllers/closet_pages_controller.rb @@ -8,6 +8,8 @@ class ClosetPagesController < ApplicationController def create if params[:closet_page] && params[:closet_page][:source] @closet_page.source = params[:closet_page][:source] + @index = @closet_page.index + saved_counts = @closet_page.save_hangers! any_created = saved_counts[:created] > 0 @@ -35,8 +37,8 @@ class ClosetPagesController < ApplicationController message << "That was the last page of your Neopets closet." destination = user_closet_hangers_path(current_user) else - message << "Let's move onto the next page!" - destination = {:action => :new, :page => (@closet_page.index + 1)} + message << "Now the frame should contain page #{@closet_page.index + 1}. Paste that source code over, too." + destination = {:action => :new, :index => (@closet_page.index + 1)} end flash[:success] = message @@ -47,16 +49,18 @@ class ClosetPagesController < ApplicationController end def new + @closet_page.index ||= 1 end protected def build_closet_page @closet_page = ClosetPage.new(current_user) + @closet_page.index = params[:index] end def on_parse_error - flash[:alert] = "We had trouble reading your source code. Is it a valid HTML document? Make sure you pasted the computery-looking result of right-click > View Source, and not the pretty page itself." + flash[:alert] = "We had trouble reading your source code. Is it a valid HTML document? Make sure you pasted the computery-looking result of clicking View Frame Source, and not the pretty page itself." render :action => :new end end diff --git a/app/models/closet_page.rb b/app/models/closet_page.rb index b9e25f8b..9ac91838 100644 --- a/app/models/closet_page.rb +++ b/app/models/closet_page.rb @@ -14,7 +14,8 @@ class ClosetPage :selected => "option[selected]" } - attr_reader :hangers, :index, :source, :total_pages, :unknown_item_names, :user + attr_accessor :index + attr_reader :hangers, :source, :total_pages, :unknown_item_names, :user def initialize(user) raise ArgumentError, "Expected #{user.inspect} to be a User", caller unless user.is_a?(User) @@ -50,6 +51,10 @@ class ClosetPage parse_source!(source) end + def url + "http://www.neopets.com/closet.phtml?per_page=50&page=#{@index}" + end + protected def element(selector_name, parent) diff --git a/app/stylesheets/closet_hangers/_index.sass b/app/stylesheets/closet_hangers/_index.sass new file mode 100644 index 00000000..c9b0d0f6 --- /dev/null +++ b/app/stylesheets/closet_hangers/_index.sass @@ -0,0 +1,15 @@ +body.closet_hangers-index + #title + float: left + + #import-link + +awesome-button + +loud-awesome-button-color + margin: + left: 2em + top: .75em + + #closet-hangers + clear: both + text-align: center + diff --git a/app/stylesheets/closet_hangers/index.sass b/app/stylesheets/closet_hangers/index.sass deleted file mode 100644 index ad242282..00000000 --- a/app/stylesheets/closet_hangers/index.sass +++ /dev/null @@ -1,4 +0,0 @@ -body.closet_hangers-index - #closet-hangers - text-align: center - diff --git a/app/stylesheets/closet_pages/_new.sass b/app/stylesheets/closet_pages/_new.sass new file mode 100644 index 00000000..90357610 --- /dev/null +++ b/app/stylesheets/closet_pages/_new.sass @@ -0,0 +1,42 @@ +body.closet_pages-new, body.closet_pages-create + + #closet-page-form + +clearfix + margin-bottom: 1em + + #closet-page-frame-wrapper + float: left + margin-right: 2% + width: 48% + + #closet-page-frame + height: 19em + width: 100% + + #closet-page-source + float: left + width: 50% + + label + font-weight: bold + + textarea + height: 19em + + + ol + padding-left: 1em + + > li + margin-bottom: 1em + + ul + font-size: 85% + margin: + bottom: 1em + top: 0 + padding-left: 1em + + p + margin: 0 + diff --git a/app/stylesheets/screen.sass b/app/stylesheets/screen.sass index 73b7ca23..a7ebbc88 100644 --- a/app/stylesheets/screen.sass +++ b/app/stylesheets/screen.sass @@ -7,6 +7,7 @@ @import partials/jquery.jgrowl @import closet_hangers/index +@import closet_pages/new @import contributions/index @import items @import items/index diff --git a/app/views/closet_hangers/index.html.haml b/app/views/closet_hangers/index.html.haml index 1c30b833..25d9b459 100644 --- a/app/views/closet_hangers/index.html.haml +++ b/app/views/closet_hangers/index.html.haml @@ -1,5 +1,6 @@ - if user_is?(@user) - title 'Your Closet' + = link_to "Import closet from Neopets", new_closet_page_path, :id => 'import-link' - else - title "#{@user.name}'s Closet" #closet-hangers diff --git a/app/views/closet_pages/new.html.haml b/app/views/closet_pages/new.html.haml index e141128a..fd7aec84 100644 --- a/app/views/closet_pages/new.html.haml +++ b/app/views/closet_pages/new.html.haml @@ -1,5 +1,49 @@ -= form_for(@closet_page) do |f| - = f.label :source - = f.text_area :source +- title "Closet Importer, Page #{@closet_page.index}" + += form_for @closet_page, :html => {:id => 'closet-page-form'} do |f| + #closet-page-frame-wrapper + %span + %strong Page #{@closet_page.index} + of your closet + %iframe#closet-page-frame{:src => @closet_page.url} + #closet-page-source + = f.label :source, "Paste source code below" + = f.text_area :source = f.submit 'Add items to closet' +:markdown + **Welcome to the bulk closet importer!** We're going to make it as + easy as possible to import your Neopets.com closet data into your Dress to + Impress closet. Here's how it works. + + 1. Check the framed Neopets.com window on the left, pointing to + [page #{@closet_page.index} of your closet][cp]. + * **Log in if you haven't already.** If you're logged into + Neopets, but not in this frame, enable "third-party cookies" in your + browser. (Most have that on by default.) + * **Confirm that the page is, in fact, your closet.** Don't just trust a + website when they tell you to copy-paste the source code of another site. + Instead, check that the page is what it is supposed to be and does not + contain any information you didn't mean to give out. + + 2. View the frame's source code. + * **In Google Chrome,** right-click the frame and choose **View Frame Source**. + * **In Firefox,** right-click the frame, choose **This Frame**, then **View Frame Source**. + * In other browsers, right-click, and look for something similar. If you're + still having trouble, try + #{link_to "viewing the page in a new window", @closet_page.url, :target => "_blank"}, + right-clicking, and choosing View Source. + + 3. Highlight the entire source code, and copy-paste it into the box on the right. + * Some nifty shortcuts: Ctrl-A to select all the text, Ctrl-C to copy it, + Ctrl-V to paste it in. + + 4. Submit! + * We'll analyze the code you sent us, grab exclusively the identity and + quantity of items in your closet, and add that to your Dress to Impress + closet. I promise it's all safe, but, if you're concerned, find a + programmer buddy and [check out the source code to be sure][source]. + + [cp]: #{@closet_page.url} + [source]: http://github.com/matchu/openneo-impress-rails + diff --git a/public/stylesheets/compiled/closet_hangers/index.css b/public/stylesheets/compiled/closet_hangers/index.css deleted file mode 100644 index f8ef829f..00000000 --- a/public/stylesheets/compiled/closet_hangers/index.css +++ /dev/null @@ -1,4 +0,0 @@ -/* line 2, ../../../../app/stylesheets/closet_hangers/index.sass */ -body.closet_hangers-index #closet-hangers { - text-align: center; -} diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index d7ae053a..47b6d943 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -538,11 +538,108 @@ div.jGrowl div.jGrowl-closer { } } -/* line 2, ../../../app/stylesheets/closet_hangers/index.sass */ +/* line 2, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #title { + float: left; +} +/* line 5, ../../../app/stylesheets/closet_hangers/_index.sass */ +body.closet_hangers-index #import-link { + /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + background: #006400 url('/images/alert-overlay.png?1296599919') repeat-x; + border: 0; + display: inline-block; + padding: 0.5em 0.75em 0.45em; + color: white; + text-decoration: none; + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5); + text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.25); + border-bottom: 1px solid rgba(0, 0, 0, 0.25); + position: relative; + font-weight: bold; + line-height: 1; + background: #ff5c00 url('/images/alert-overlay.png?1296599919') repeat-x; + margin-left: 2em; + margin-top: 0.75em; +} +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #import-link:hover { + background-color: #005300; +} +/* line 53, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #import-link:hover { + color: white; +} +/* line 55, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #import-link:active { + top: 1px; +} +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_hangers-index #import-link:hover { + background-color: #ee4b00; +} +/* line 12, ../../../app/stylesheets/closet_hangers/_index.sass */ body.closet_hangers-index #closet-hangers { + clear: both; text-align: center; } +/* line 3, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new #closet-page-form, body.closet_pages-create #closet-page-form { + overflow: hidden; + display: inline-block; + margin-bottom: 1em; +} +/* line 8, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.closet_pages-new #closet-page-form, body.closet_pages-create #closet-page-form { + display: block; +} +/* line 7, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new #closet-page-frame-wrapper, body.closet_pages-create #closet-page-frame-wrapper { + float: left; + margin-right: 2%; + width: 48%; +} +/* line 12, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new #closet-page-frame, body.closet_pages-create #closet-page-frame { + height: 19em; + width: 100%; +} +/* line 16, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new #closet-page-source, body.closet_pages-create #closet-page-source { + float: left; + width: 50%; +} +/* line 20, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new #closet-page-source label, body.closet_pages-create #closet-page-source label { + font-weight: bold; +} +/* line 23, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new #closet-page-source textarea, body.closet_pages-create #closet-page-source textarea { + height: 19em; +} +/* line 27, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new ol, body.closet_pages-create ol { + padding-left: 1em; +} +/* line 30, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new ol > li, body.closet_pages-create ol > li { + margin-bottom: 1em; +} +/* line 33, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new ol ul, body.closet_pages-create ol ul { + font-size: 85%; + margin-bottom: 1em; + margin-top: 0; + padding-left: 1em; +} +/* line 40, ../../../app/stylesheets/closet_pages/_new.sass */ +body.closet_pages-new ol p, body.closet_pages-create ol p { + margin: 0; +} + /* line 1, ../../../app/stylesheets/contributions/_index.sass */ body.contributions-index { text-align: center; From 3a193d534d70775918dd8b87414d882a50bd79f8 Mon Sep 17 00:00:00 2001 From: Matchu Date: Wed, 13 Jul 2011 01:21:48 -0400 Subject: [PATCH 05/69] closeted icon, all over the place --- app/controllers/items_controller.rb | 9 +++- app/helpers/items_helper.rb | 11 ++++ app/models/item.rb | 9 ++-- app/models/user.rb | 11 ++++ app/stylesheets/_layout.sass | 27 ++++++---- app/views/items/_item_link.html.haml | 1 + public/images/closeted.png | Bin 0 -> 537 bytes public/images/nc.png | Bin 738 -> 732 bytes public/javascripts/outfits/edit.js | 3 ++ public/stylesheets/compiled/screen.css | 71 +++++++++++++++---------- 10 files changed, 100 insertions(+), 42 deletions(-) create mode 100644 public/images/closeted.png diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 961dd770..db12323e 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -11,6 +11,7 @@ class ItemsController < ApplicationController per_page = nil end @items = Item.search(@query).alphabetize.paginate :page => params[:page], :per_page => per_page + assign_closeted! respond_to do |format| format.html { render } format.json { render :json => {:items => @items, :total_pages => @items.total_pages} } @@ -24,6 +25,7 @@ class ItemsController < ApplicationController end elsif params.has_key?(:ids) && params[:ids].is_a?(Array) @items = Item.find(params[:ids]) + assign_closeted! respond_to do |format| format.json { render :json => @items } end @@ -50,11 +52,16 @@ class ItemsController < ApplicationController raise ActiveRecord::RecordNotFound, 'Pet type not found' end @items = @pet_type.needed_items.alphabetize + assign_closeted! @pet_name = params[:name] render :layout => 'application' end - private + protected + + def assign_closeted! + current_user.assign_closeted_to_items!(@items) if user_signed_in? + end def set_query @query = params[:q] diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb index cf586268..b2868693 100644 --- a/app/helpers/items_helper.rb +++ b/app/helpers/items_helper.rb @@ -48,6 +48,17 @@ module ItemsHelper end end + def closeted_icon_for(item) + if item.closeted? + image_tag( + 'closeted.png', + :title => 'You own this', + :alt => 'Closet', + :class => 'closeted-icon' + ) + end + end + def list_zones(zones, method=:label) zones.sort { |x,y| x.label <=> y.label }.map(&method).join(', ') end diff --git a/app/models/item.rb b/app/models/item.rb index 91386315..7c426deb 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -10,7 +10,7 @@ class Item < ActiveRecord::Base has_many :swf_assets, :through => :parent_swf_asset_relationships, :source => :object_asset, :conditions => {:type => SwfAssetType} - attr_writer :current_body_id + attr_writer :closeted, :current_body_id NCRarities = [0, 500] PAINTBRUSH_SET_DESCRIPTION = 'This item is part of a deluxe paint brush set!' @@ -43,7 +43,9 @@ class Item < ActiveRecord::Base scope :sitemap, select([:id, :name]).order(:id).limit(49999) - # Not defining validations, since this app is currently read-only + def closeted? + !!@closeted + end def nc? NCRarities.include?(rarity_index) @@ -155,7 +157,8 @@ class Item < ActiveRecord::Base :name => name, :thumbnail_url => thumbnail_url, :zones_restrict => zones_restrict, - :rarity_index => rarity_index + :rarity_index => rarity_index, + :closeted => closeted? } end diff --git a/app/models/user.rb b/app/models/user.rb index fe8f6820..1bdad3ab 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,6 +3,7 @@ class User < ActiveRecord::Base PreviewTopContributorsCount = 3 has_many :closet_hangers + has_many :closeted_items, :through => :closet_hangers, :source => :item has_many :contributions has_many :outfits @@ -40,6 +41,16 @@ class User < ActiveRecord::Base new_points end + def assign_closeted_to_items!(items) + # Assigning these items to a hash by ID means that we don't have to go + # N^2 searching the items list for items that match the given IDs or vice + # versa, and everything stays a lovely O(n) + items_by_id = {} + items.each { |item| items_by_id[item.id] = item } + closeted_item_ids = closeted_items.where(:id => items_by_id.keys).map(&:id) + closeted_item_ids.each { |id| items_by_id[id].closeted = true } + end + def self.find_or_create_from_remote_auth_data(user_data) user = find_or_initialize_by_remote_id_and_auth_server_id( user_data['id'], diff --git a/app/stylesheets/_layout.sass b/app/stylesheets/_layout.sass index a4b5722a..58bfc903 100644 --- a/app/stylesheets/_layout.sass +++ b/app/stylesheets/_layout.sass @@ -157,7 +157,8 @@ ul.buttons .object +inline-block - padding: .5em + margin: .5em 0 + padding: 0 .5em position: relative text-align: center vertical-align: top @@ -174,6 +175,21 @@ ul.buttons margin: 0 auto width: $object-img-size + .nc-icon, .closeted-icon + +opacity(1) + height: $nc-icon-size + position: absolute + top: $object-img-size - $nc-icon-size + width: $nc-icon-size + &:hover + +opacity(0.5) + + .nc-icon + right: ($object-width - $object-img-size) / 2 + $object-padding + + .closeted-icon + left: ($object-width - $object-img-size) / 2 + $object-padding + dt font-weight: bold @@ -202,15 +218,6 @@ dd .current font-weight: bold -.object .nc-icon - height: 16px - position: absolute - right: ($object-width - $object-img-size) / 2 + $object-padding - top: $object-img-size - $nc-icon-size - width: 16px - &:hover - +opacity(0.5) - /* Fonts /* A font by Jos Buivenga (exljbris) -> www.exljbris.nl diff --git a/app/views/items/_item_link.html.haml b/app/views/items/_item_link.html.haml index 11a3a979..107b7ed9 100644 --- a/app/views/items/_item_link.html.haml +++ b/app/views/items/_item_link.html.haml @@ -2,4 +2,5 @@ = image_tag item.thumbnail_url, :alt => item.description, :title => item.description = item.name = nc_icon_for(item) + = closeted_icon_for(item) diff --git a/public/images/closeted.png b/public/images/closeted.png new file mode 100644 index 0000000000000000000000000000000000000000..a9925a06ab02db30c1e7ead9c701c15bc63145cb GIT binary patch literal 537 zcmV+!0_OdRP)Hs{AQG2a)rMyf zFQK~pm1x3+7!nu%-M`k}``c>^00{o_1pjWJUTfl8mg=3qGEl8H@}^@w`VUx0_$uy4 z2FhRqKX}xI*?Tv1DJd8z#F#0c%*~rM30HE1@2o5m~}ZyoWhqv>ql{V z1ZGE0lgcoK^lx+eqc*rAX1Ky;Xx3U%u#zG!m-;eD1Qsn@kf3|F9qz~|95=&g3(7!X zB}JAT>RU;a%vaNOGnJ%e1=K6eAh43c(QN8RQ6~GP%O}Jju$~Ld*%`mO1p6OYS$}RxL_t(I%Z-rBYg~00hM#lGnW;%kGHI+WUeXI_OA3Ne>e?>c zxb#ox##34*$mpa_E5sId)1CE9?!PCJ=NX3jY?=ls5lYm*Ut;oH4D zyw4Z8JIB-9d;OxDfA7v2H%r{8-Fz2g{e|lfzy4R*-A~+j`+wC@cyiml+Ho(o+>bUr zbZ`6chqHek@1{(NtIehhZ^Ps<$N<8CIG@ABE*$Sp1(<@>4~fDd_yisALmi`XQujX= zI6C~9(ESFh3#>XK>s-SG{^tTC&d-s}zlqmRvFsG)hKij8)Z4GkyZNr0opB>^^*Zth z8U2RzckoGpR(~Vf=dVszFttz8m5w0WI@T{zdi2I_>3m@YYk3d;l(JU>d+b zPFLOo8G;T$3)1!qp*$dock%HEEk|V03L2&;r~p>tQh+yD{T!MxBF4;%7xC6JH1Ctl zE}+w%Xkuu&haUcdHC?=ZKr(+GZJfIQJ6@GU%>XYSaesO#=IE#We5WpKO&kup|x;{rtu501~$gMZL+z`q;r?amab79+$YJG z&{Jn=y?^m8mcLB(;12E+96{ue(f$Ta?Hj2C+p7C_KZs9XA;}WLxS;6oQ62WaEr0xS z!Nu2RW}D%PDHLkV1m9@NId`m delta 661 zcmV;G0&4x-1>yyeS$}j%L_t(I%axPePts8s$GNCmwl2GMYpu&#|3FO_P3IfSvU1Ui zoY|y>X^IH)BF)zT|q5^yC6t()>C0c&mDb<=+4()xCOKUbT}sa-s0 zXXotmeZJ3gp2Gvc+b`PVt&DC~#oz62U$`x%VXP?=v=JqmLw^nY{}Ol@RWp659t1x5 zU|ukyDNv7E`Y!)K0>m<7NwP2v=jt&0YZEZM?10o;gX-~H{5=I)U$ijhq!EFSUOfFU z49Aic^^;OeWrmwsRl>e#!Qi49kCz8QXI*Fs z%W>6yY5gAo^?ywBy6Lr^*!3d)Z5bO|-!b-f1e)3AZ8+nCGAzU8!LrRAB^VQ3$5hYd zKYA07xLVs{S`MaSy~ut|Ll;xQn;C~d{p(*$PrItbsC%{@V&UayoG=FGpWr(YF;5`L3v8{`$Fp(aI zJk)?n_YDr7`y54NEd*g-5zZU(j_@=y3Ofnd-caympP|+#LH|1whL`#Y?Buf5P2VGM z98)VaYJyc8sYjH!{kit5`kWFLqFG!VyYli z&?C?b^nbZIJDS+&zi+jtY>?6t7+!V4v+9J*Uxy3U63B>%u&+2>WXeCAZ#;Km*HNye zCC6LBO1opG voc%uA-_6ZY(aCF$D@pQH`3L#pf8sYdyv!R*(+)jz00000NkvXXu0mjfKSMxC diff --git a/public/javascripts/outfits/edit.js b/public/javascripts/outfits/edit.js index bdb8e2d2..239bfbe5 100644 --- a/public/javascripts/outfits/edit.js +++ b/public/javascripts/outfits/edit.js @@ -102,6 +102,9 @@ Partial.ItemSet = function ItemSet(wardrobe, selector) { ) { $('