diff --git a/Gemfile b/Gemfile index 36ea87d4..fcd8ddf4 100644 --- a/Gemfile +++ b/Gemfile @@ -41,6 +41,13 @@ gem 'newrelic_rpm' gem 'neopets', :git => 'git://github.com/matchu/neopets.git' +gem "mini_magick", "~> 3.4" + +gem "fog", "~> 1.1.2" +gem "carrierwave", "~> 0.5.8" + +gem "parallel", "~> 0.5.17" + group :development_async do # async wrappers gem 'eventmachine', :git => 'git://github.com/eventmachine/eventmachine.git' diff --git a/Gemfile.lock b/Gemfile.lock index 9803cf92..f0891775 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -86,6 +86,8 @@ GEM arel (2.0.10) bcrypt-ruby (2.1.4) builder (2.1.2) + carrierwave (0.5.8) + activesupport (~> 3.0) character-encodings (0.4.1) chronic (0.6.7) closure-compiler (1.1.4) @@ -100,11 +102,23 @@ GEM eventmachine erubis (2.6.6) abstract (>= 1.0.0) + excon (0.9.6) factory_girl (2.3.2) activesupport factory_girl_rails (1.4.0) factory_girl (~> 2.3.0) railties (>= 3.0.0) + fog (1.1.2) + builder + excon (~> 0.9.0) + formatador (~> 0.2.0) + mime-types + multi_json (~> 1.0.3) + net-scp (~> 1.0.4) + net-ssh (>= 2.1.3) + nokogiri (~> 1.5.0) + ruby-hmac + formatador (0.2.1) haml (3.0.25) hoptoad_notifier (2.4.11) activesupport @@ -122,13 +136,20 @@ GEM treetop (~> 1.4.8) memcache-client (1.8.5) mime-types (1.17.2) + mini_magick (3.4) + subexec (~> 0.2.1) msgpack (0.4.6) + multi_json (1.0.4) mysql2 (0.2.6) + net-scp (1.0.4) + net-ssh (>= 1.99.1) + net-ssh (2.3.0) newrelic_rpm (3.3.3) nokogiri (1.5.3) open4 (1.3.0) openneo-auth-signatory (0.1.0) ruby-hmac + parallel (0.5.17) polyglot (0.3.3) rack (1.2.5) rack-fiber_pool (0.9.2) @@ -189,6 +210,7 @@ GEM sinatra (1.2.8) rack (~> 1.1) tilt (>= 1.2.2, < 2.0) + subexec (0.2.1) swf_converter (0.0.3) thor (0.14.6) tilt (1.3.3) @@ -213,6 +235,7 @@ PLATFORMS DEPENDENCIES RocketAMF! addressable + carrierwave (~> 0.5.8) character-encodings (~> 0.4.1) compass (~> 0.10.1) devise (~> 1.1.5) @@ -221,10 +244,12 @@ DEPENDENCIES em-synchrony! eventmachine! factory_girl_rails (~> 1.0) + fog (~> 1.1.2) haml (~> 3.0.18) hoptoad_notifier jammit (~> 0.5.3) memcache-client (~> 1.8.5) + mini_magick (~> 3.4) msgpack (~> 0.4.3) mysql2 (< 0.3) mysqlplus! @@ -232,6 +257,7 @@ DEPENDENCIES newrelic_rpm nokogiri (~> 1.5.2) openneo-auth-signatory (~> 0.1.0) + parallel (~> 0.5.17) rack-fiber_pool rails (= 3.0.5) rdiscount (~> 1.6.5) diff --git a/app/controllers/outfits_controller.rb b/app/controllers/outfits_controller.rb index 7a4685df..bc7a5e69 100644 --- a/app/controllers/outfits_controller.rb +++ b/app/controllers/outfits_controller.rb @@ -2,18 +2,11 @@ class OutfitsController < ApplicationController before_filter :find_authorized_outfit, :only => [:update, :destroy] def create - Rails.logger.debug "Signed in?: #{user_signed_in?}" - Rails.logger.debug "User 1: #{current_user.inspect}" @outfit = Outfit.build_for_user(current_user, params[:outfit]) - Rails.logger.debug "User 2: #{current_user.inspect}" if @outfit.save - Rails.logger.debug "User 3: #{current_user.inspect}" - render :json => @outfit.id - Rails.logger.debug "User 4: #{current_user.inspect}" + render :json => @outfit else - Rails.logger.debug "User 5: #{current_user.inspect}" render_outfit_errors - Rails.logger.debug "User 6: #{current_user.inspect}" end end @@ -82,7 +75,7 @@ class OutfitsController < ApplicationController def update if @outfit.update_attributes(params[:outfit]) - render :json => true + render :json => @outfit else render_outfit_errors end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index d6bb8c3c..63d4af2f 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,4 +1,12 @@ module ApplicationHelper + def absolute_url(path_or_url) + if path_or_url.include?('://') # already an absolute URL + path_or_url + else # a relative path + request.protocol + request.host_with_port + path_or_url + end + end + def add_body_class(class_name) @body_class ||= '' @body_class << " #{class_name}" @@ -100,6 +108,23 @@ module ApplicationHelper def origin_tag(value) hidden_field_tag 'origin', value, :id => nil end + + def open_graph(properties) + if @open_graph + @open_graph.merge! properties + else + @open_graph = properties + end + end + + def open_graph_tags + if @open_graph + @open_graph.inject('') do |output, property| + key, value = property + output + tag(:meta, :property => "og:#{key}", :content => value) + end.html_safe + end + end def return_to_field_tag hidden_field_tag :return_to, request.fullpath diff --git a/app/models/outfit.rb b/app/models/outfit.rb index 7b314f08..f26a034d 100644 --- a/app/models/outfit.rb +++ b/app/models/outfit.rb @@ -12,10 +12,23 @@ class Outfit < ActiveRecord::Base attr_accessible :name, :pet_state_id, :starred, :worn_and_unworn_item_ids scope :wardrobe_order, order('starred DESC', :name) + + mount_uploader :image, OutfitImageUploader + + before_save :update_enqueued_image + after_commit :enqueue_image! def as_json(more_options={}) serializable_hash :only => [:id, :name, :pet_state_id, :starred], - :methods => [:color_id, :species_id, :worn_and_unworn_item_ids] + :methods => [:color_id, :species_id, :worn_and_unworn_item_ids, + :image_versions, :image_enqueued, :image_layers_hash] + end + + def image_versions + {}.tap do |versions| + versions[:large] = image.url + image.versions.each { |name, version| versions[name] = version.url } + end end def closet_item_ids @@ -64,9 +77,45 @@ class Outfit < ActiveRecord::Base end self.item_outfit_relationships = new_rels end - - def worn_item_ids - worn_and_unworn_item_ids[:worn] + + # Returns the array of SwfAssets representing each layer of the output image, + # ordered from bottom to top. Careful: this method is memoized, so if the + # image layers change after its first call we'll get bad results. + def image_layers + @image_layers ||= visible_assets_with_images.sort { |a, b| a.zone.depth <=> b.zone.depth } + end + + # Creates and writes the thumbnail images for this outfit iff the new image + # would be different than the current one. (Writes to file in development, + # S3 in production.) If the image is updated, updates the image layers hash + # and runs #save! on the record, so any other changes will also be saved. + def write_image! + if image_layers_dirty? + Tempfile.open(['outfit_image', '.png']) do |image| + create_image! image + self.image_layers_hash = generate_image_layers_hash + self.image = image + self.image_enqueued = false + save! + end + end + + self.image + end + + # Enqueue an image write iff the new image would be different than the + # current one. + def enqueue_image! + Resque.enqueue(OutfitImageUpdate, id) + end + + def update_enqueued_image + self.image_enqueued = (image_layers_dirty?) + true + end + + def s3_key(size) + URI.encode("#{id}/#{size.join 'x'}.png") end def self.build_for_user(user, params) @@ -82,5 +131,87 @@ class Outfit < ActiveRecord::Base outfit.attributes = params end end + + protected + + # Creates a 600x600 PNG image of this outfit, writing to the given output + # file. + def create_image!(output) + unless image_layers.empty? + temp_image_files = Parallel.map(image_layers, :in_threads => 8) do |swf_asset| + image_file = Tempfile.open(['outfit_layer', '.png']) + write_temp_swf_asset_image!(swf_asset, image_file) + image_file.close + image_file + end + + # Here we do some awkwardness to get the exact ImageMagick command we + # want, though it's still less awkward than handling the command + # ourselves. Give all of the temporary images as input, flatten them and + # write them to the output path. + command = MiniMagick::CommandBuilder.new('convert') + temp_image_files.each { |image_file| command.push image_file.path } + command.layers 'flatten' + command.push output.path + + # Though the above command really is sufficient, we still need a dummy + # image to handle execution. + output_image = MiniMagick::Image.new(output.path) + output_image.run(command) + + temp_image_files.each(&:unlink) + else + output.close + end + end + + def visible_assets + biology_assets = pet_state.swf_assets + object_assets = SwfAsset.object_assets. + fitting_body_id(pet_state.pet_type.body_id).for_item_ids(worn_item_ids) + + # Now for fun with bitmasks! Rather than building a bunch of integer arrays + # here, we instead go low-level and use bit-level operations. Build the + # bitmask by parsing the binary string (reversing it to get the lower zone + # numbers on the right), then OR them all together to get the mask + # representing all the restricted zones. (Note to self: why not just store + # in this format in the first place?) + restrictors = biology_assets + worn_items + restricted_zones_mask = restrictors.inject(0) do |mask, restrictor| + mask | restrictor.zones_restrict.reverse.to_i(2) + end + + # Now, check each asset's zone is not restricted in the bitmask using + # bitwise operations: shift 1 to the zone_id position, then AND it with + # the restricted zones mask. If we get 0, then the bit for that zone ID was + # not turned on, so the zone is not restricted and this asset is visible. + all_assets = biology_assets + object_assets + all_assets.select { |a| (1 << (a.zone_id - 1)) & restricted_zones_mask == 0 } + end + + def visible_assets_with_images + visible_assets.select(&:has_image?) + end + + # Generate 8-char hex digest representing visible image layers for this outfit. + # Hash function should be decently collision-resistant. + def generate_image_layers_hash + @generated_image_layers_hash ||= + Digest::MD5.hexdigest(image_layers.map(&:id).join(',')).first(8) + end + + def image_layers_dirty? + generate_image_layers_hash != self.image_layers_hash + end + + IMAGE_BASE_SIZE = [600, 600] + def write_temp_swf_asset_image!(swf_asset, file) + key = swf_asset.s3_key(IMAGE_BASE_SIZE) + bucket = SwfAsset::IMAGE_BUCKET + data = bucket.get(key) + file.binmode # write in binary mode + file.truncate(0) # clear the file + file.write data # write the new data + end end diff --git a/app/models/outfit_image_update.rb b/app/models/outfit_image_update.rb new file mode 100644 index 00000000..59364fb4 --- /dev/null +++ b/app/models/outfit_image_update.rb @@ -0,0 +1,15 @@ +class OutfitImageUpdate + @queue = :outfit_image_updates + + def self.perform(id) + Outfit.find(id).write_image! + end + + # Represents an outfit image update for an outfit that existed before this + # feature was built. Its queue has a lower priority, so new outfits will + # be updated before retroactively converted outfits. + class Retroactive < OutfitImageUpdate + @queue = :retroactive_outfit_image_updates + end +end + diff --git a/app/models/outfit_image_uploader.rb b/app/models/outfit_image_uploader.rb new file mode 100644 index 00000000..6bbf26c4 --- /dev/null +++ b/app/models/outfit_image_uploader.rb @@ -0,0 +1,39 @@ +require 'carrierwave/processing/mime_types' + +class OutfitImageUploader < CarrierWave::Uploader::Base + include CarrierWave::MimeTypes + include CarrierWave::MiniMagick + + # Settings for S3 storage. Will only be used on production. + fog_directory 'impress-outfit-images' + fog_attributes 'Cache-Control' => "max-age=#{15.minutes}", + 'Content-Type' => 'image/png' + + process :set_content_type + + version :medium do + process :resize_to_fill => [300, 300] + end + + version :small, :from_version => :medium do + process :resize_to_fill => [150, 150] + end + + def filename + "preview.png" + end + + def store_dir + "outfits/#{partition_dir}" + end + + # 123006789 => "123/006/789" + def partition_dir + partitions.map { |partition| "%03d" % partition }.join('/') + end + + # 123006789 => [123, 6, 789] + def partitions + [6, 3, 0].map { |n| model.id / 10**n % 1000 } + end +end diff --git a/app/models/swf_asset.rb b/app/models/swf_asset.rb index 25cff6e1..4faf040b 100644 --- a/app/models/swf_asset.rb +++ b/app/models/swf_asset.rb @@ -15,8 +15,14 @@ class SwfAsset < ActiveRecord::Base set_inheritance_column 'inheritance_type' + IMAGE_SIZES = { + :small => [150, 150], + :medium => [300, 300], + :large => [600, 600] + } + include SwfConverter - converts_swfs :size => [600, 600], :output_sizes => [[150, 150], [300, 300], [600, 600]] + converts_swfs :size => IMAGE_SIZES[:large], :output_sizes => IMAGE_SIZES.values def local_swf_path LOCAL_ASSET_DIR.join(local_path_within_outfit_swfs) @@ -74,6 +80,21 @@ class SwfAsset < ActiveRecord::Base end end end + + def image_version + converted_at.to_i + end + + def image_url(size=IMAGE_SIZES[:large]) + host = ASSET_HOSTS[:swf_asset_images] + size_key = size.join('x') + + "http://#{host}/#{s3_path}/#{size_key}.png?#{image_version}" + end + + def images + IMAGE_SIZES.values.map { |size| {:size => size, :url => image_url(size)} } + end def convert_swf_if_not_converted! if needs_conversion? @@ -161,7 +182,7 @@ class SwfAsset < ActiveRecord::Base :zones_restrict => zones_restrict, :is_body_specific => body_specific?, :has_image => has_image?, - :s3_path => s3_path + :images => images } if options[:for] == 'wardrobe' json[:local_path] = local_url diff --git a/app/stylesheets/outfits/_edit.sass b/app/stylesheets/outfits/_edit.sass index fef2a109..ad6bc564 100644 --- a/app/stylesheets/outfits/_edit.sass +++ b/app/stylesheets/outfits/_edit.sass @@ -3,12 +3,13 @@ @import "partials/context_button" @import "partials/icon" +@import "partials/outfit" @import star $object-padding: 6px $nc-icon-size: 16px -$preview-dimension: 400px +$preview-dimension: 380px $sidebar-margin: 20px $sidebar-width: 400px $sidebar-unit-horizontal-padding: 24px @@ -21,88 +22,23 @@ $outfit-header-padding: 24px $outfit-content-width: $sidebar-unit-inner-width - $outfit-thumbnail-size - $outfit-thumbnail-margin - 32px $outfit-content-inner-width: $outfit-content-width - $outfit-header-padding +=user-select($select) + select: unquote($select) + +experimental(user-select, $select, -moz, -webkit, not -o, not -ms, -khtml, official) + =active-mode color: $text-color font-weight: bold -=outfit - +outfit-star-shifted - padding: .25em 0 - //.outfit-thumbnail - float: left - height: $outfit-thumbnail-size - margin-right: $outfit-thumbnail-margin - overflow: hidden - position: relative - width: $outfit-thumbnail-size - img - height: $outfit-thumbnail-original-size - left: -$outfit-thumbnail-original-size / 4 - position: absolute - top: -$outfit-thumbnail-original-size / 4 - width: $outfit-thumbnail-original-size - .outfit-delete - +reset-awesome-button - +opacity(.5) - font-size: 150% - float: right - line-height: 1 - margin-top: -.125em - padding: .125em .25em - &:hover - +opacity(1) - background: $module-bg-color - header - display: block - padding-left: $outfit-header-padding - h4 - cursor: pointer - display: inline - &:hover - text-decoration: underline - h4, .outfit-rename-field - font-size: 115% - .outfit-rename-button, .outfit-rename-form - display: none - .outfit-rename-button - +opacity(.75) - font-size: 75% - margin-left: 1em - .outfit-url - +opacity(.5) - background: transparent - border-width: 0 - width: $outfit-content-inner-width - &:hover - +opacity(1) - border-width: 1px - .outfit-delete-confirmation - display: none - font-size: 75% - span - color: red - a - margin: 0 .25em - &.active - background: $module-bg-color - &.confirming-deletion - .outfit-delete - visibility: hidden - .outfit-url - display: none - .outfit-delete-confirmation - display: block - &.renaming - h4 - display: none - .outfit-rename-form - display: inline - &:hover - .outfit-rename-button - display: none - &:hover - .outfit-rename-button - display: inline +=sidebar-navbar-unselected + background: transparent + border-bottom: 1px solid $soft-border-color + font-weight: normal + +=sidebar-navbar-selected + background: white + border-bottom-color: white + font-weight: bold =sidebar-view-child margin: @@ -144,7 +80,7 @@ body.outfits-edit position: left center repeat: no-repeat padding-left: 20px - #save-outfit, #save-outfit-not-signed-in, #save-current-outfit, #save-outfit-copy, #save-outfit-finish + #save-outfit, #save-outfit-not-signed-in, #save-current-outfit, #save-outfit-finish +loud-awesome-button-color #current-outfit-permalink, #shared-outfit-permalink display: none @@ -207,11 +143,14 @@ body.outfits-edit &.image-active #preview-mode-image +active-mode - #report-broken-image + #preview-mode-note, #report-broken-image display: block - &.can-download - #preview-download-image - display: inline-block + // Phasing out the image download section. Not confident enough yet to + // *remove* it, depending on user feedback, but that's a TODO for down + // the road if hiding goes well. + // &.can-download + // #preview-download-image + // display: inline-block #preview-mode-toggle +border-radius(.5em) border: 1px solid $module-border-color @@ -249,34 +188,27 @@ body.outfits-edit em font-style: normal text-decoration: underline - #report-broken-image + #preview-mode-note, #report-broken-image display: none + #preview-sidebar - +border-radius(10px) - border: 1px solid $soft-border-color float: left height: $preview-dimension margin-left: $sidebar-margin margin-bottom: 1em - overflow: auto - width: $container_width - $preview-dimension - $sidebar-margin - 2px + width: $container_width - $preview-dimension - $sidebar-margin &.viewing-outfits #preview-closet display: none #preview-outfits display: block - &.viewing-saving-outfit - height: auto - max-height: 100% + &.sharing #preview-closet display: none - #preview-saving-outfit + #preview-sharing display: block .sidebar-view - h2 - margin: - bottom: .25em - left: $sidebar-unit-horizontal-padding + margin: 1.5em 0 #preview-closet h2 margin-bottom: 0 @@ -378,7 +310,6 @@ body.outfits-edit width: 100% #preview-sidebar float: right - height: 100% margin: 0 position: relative width: $sidebar-width @@ -461,19 +392,283 @@ body.outfits-edit #preview-outfits display: none text-align: left + + $outfit-inner-size: 110px + $outfit-margin: 1px + $outfit-outer-size: $outfit-inner-size + ($outfit-margin * 2) > ul + +outfits-list +sidebar-view-child background: image-url("loading.gif") no-repeat center top - display: block + display: none font-family: $main-font - list-style: none - margin: - bottom: 1em + margin: 0 auto 1em min-height: 16px - > li - +outfit + width: $outfit-outer-size * 3 + &.loaded background: transparent + + > li + height: $outfit-inner-size + margin: $outfit-margin + width: $outfit-inner-size + + $outfit-header-h-padding: 4px + $outfit-header-v-padding: 2px + $outfit-header-inner-width: $outfit-inner-size - (2 * $outfit-header-h-padding) + $outfit-header-inner-height: 12px + $outfit-header-outer-height: $outfit-header-inner-height + (2 * $outfit-header-v-padding) + header, footer, .outfit-delete-confirmation + font-size: $outfit-header-inner-height + padding: $outfit-header-v-padding $outfit-header-h-padding + width: $outfit-header-inner-width + + header + +opacity(0.75) + bottom: 0 + cursor: pointer + + footer, .outfit-delete-confirmation + display: none + + .outfit-delete-confirmation + +outfit-banner + +outfit-banner-background(rgb(255, 50, 50)) + text-align: center + top: 0 + + span + font-weight: bold + + $outfit-thumbnail-size: 150px + $outfit-thumbnail-h-offset: ($outfit-inner-size - $outfit-thumbnail-size) / 2 + $outfit-thumbnail-v-offset: $outfit-thumbnail-h-offset - ($outfit-header-outer-height / 4) + .outfit-thumbnail-wrapper + +opacity(.5) + background: + image: url(/images/outfits/small_default.png) + position: center center + size: $outfit-inner-size $outfit-inner-size + cursor: pointer + height: $outfit-thumbnail-size + left: $outfit-thumbnail-h-offset + position: absolute + top: $outfit-thumbnail-v-offset + width: $outfit-thumbnail-size + z-index: 1 + + .outfit-thumbnail + display: none + + .outfit-star + bottom: 0 + margin-right: 4px + + .outfit-delete + float: right + + .outfit-rename-button + float: left + + .outfit-rename-button, .outfit-delete + font-size: 85% + text-decoration: none + + &:hover + text-decoration: underline + + .outfit-rename-form + display: none + + input + background: transparent + border: 1px solid white + width: 6em + + &:hover + header + +opacity(1) + + .outfit-thumbnail + +opacity(0.75) + + footer + display: block + + &.active + header + +opacity(1) + font-weight: bold + + .outfit-thumbnail + +opacity(1) + + &.confirming-deletion + footer + display: none + + .outfit-delete-confirmation + display: block + + &.renaming + .outfit-name + display: none + + .outfit-rename-form + display: inline + + &.thumbnail-available + background: transparent + + .outfit-thumbnail-wrapper + background-image: none + + .outfit-thumbnail + display: block + + &.loading + .outfit-star + background-image: image-url("loading_outfit_pane.gif") + + #preview-outfits-not-logged-in + text-align: center + overflow-x: hidden + + img + border: + color: $module-border-color + style: solid + width: 1px 0 + + figure + display: block + margin: 0 0 1em 0 + padding: 0 + + figcaption + display: block + font-weight: bold + + p + +sidebar-view-child + font-size: 85% + + #preview-outfits-log-in + +awesome-button + +loud-awesome-button-color + + #preview-sharing + display: none + + #preview-sharing-urls + +sidebar-view-child + display: none + margin: + bottom: 1em + top: 1em + + li + display: block + padding: .25em 0 + width: 100% + + label + display: block + font-weight: bold + + input + display: block + width: 100% + + #preview-sharing-url-formats + +sidebar-view-child + +user-select(none) + // remove whitespace between inline-block elements + display: none + font-size: 0 + text-align: center + + li + +inline-block + + border: 1px solid $module-border-color + border-left-width: 0 + border-right-color: $soft-border-color + color: $soft-text-color + cursor: pointer + font-size: 12px + padding: 0 2em + + &.active + background: $module-bg-color + color: inherit + font-weight: bold + + &:first-child + +border-top-left-radius(5px) + +border-bottom-left-radius(5px) + border-left-width: 1px + + &:last-child + +border-top-right-radius(5px) + +border-bottom-right-radius(5px) + border-right-color: $module-border-color + + #preview-sharing-thumbnail-wrapper + border: 1px solid $soft-border-color + display: block + height: 150px + margin: 1em auto 0 + position: relative + width: 150px + + #preview-sharing-thumbnail-loading + height: 100% + left: 0 + position: absolute + top: 0 + width: 100% + + span + color: $soft-text-color + font-size: 85% + margin-top: -0.75em + position: absolute + text-align: center + top: 50% + width: 100% + + #preview-sharing-thumbnail, #preview-sharing-thumbnail-generating + display: none + + #preview-sharing-beta-note + +sidebar-view-child + +warning + font-size: 85% + margin-top: 1em + text-align: center + + &.urls-loaded + #preview-sharing-thumbnail-saving + display: none + + #preview-sharing-urls, #preview-sharing-url-formats, #preview-sharing-thumbnail-generating + display: block + + &.urls-loaded.thumbnail-loaded + #preview-sharing-thumbnail-loading + display: none + + #preview-sharing-thumbnail + display: block + + &.urls-loaded.thumbnail-available + #preview-sharing-thumbnail-loading + +opacity(0.85) + + #preview-sharing-thumbnail + display: block .preview-sidebar-nav float: right @@ -481,6 +676,49 @@ body.outfits-edit margin: right: $sidebar-unit-horizontal-padding top: 1em + + $sidebar-border-radius: 10px + $sidebar-navbar-inner-width: $sidebar-width - 2px + $sidebar-navbar-child-outer-width: floor($sidebar-navbar-inner-width / 3) + + #preview-sidebar + #preview-sidebar-navbar-closet + +sidebar-navbar-selected + + &.viewing-outfits, &.sharing + #preview-sidebar-navbar-closet + +sidebar-navbar-unselected + + &.viewing-outfits #preview-sidebar-navbar-outfits, &.sharing #preview-sidebar-navbar-sharing + +sidebar-navbar-selected + + #preview-sidebar-navbar + +border-radius($sidebar-border-radius $sidebar-border-radius 0 0) + +clearfix + +header-text + background: $module-bg-color + border: 1px solid $soft-border-color + border-bottom: 0 + font-size: 150% + + > div + +sidebar-navbar-unselected + cursor: pointer + float: left + border-left: 1px solid $soft-border-color + padding: .5em 0 + text-align: center + width: $sidebar-navbar-child-outer-width + + &:first-child + border-left: 0 + + #preview-sidebar-content + +border-radius(0 0 $sidebar-border-radius $sidebar-border-radius) + border: 1px solid $soft-border-color + border-top: 0 + height: 300px + overflow: auto #save-success, #save-error, #outfit-not-found, #preview-sidebar-donation-request +sidebar-view-child @@ -507,25 +745,10 @@ body.outfits-edit +opacity(.5) display: none - #new-outfit - +outfit - +sidebar-view-child - display: none - h4 - display: inline - &:hover - text-decoration: none - .outfit-star - margin-top: .5em - #new-outfit-name font: inherit line-height: 1 - #preview-saving-outfit - display: none - padding-bottom: 1em - #pet-type-form, #pet-state-form, #preview-swf, #preview-search-form position: relative @@ -541,10 +764,10 @@ body.outfits-edit display: none form#save-outfit-form - +outfit + +outfit-star-shifted display: none margin-right: 0 - padding: 0 + padding: 0 .outfit-star, input, button +inline-block @@ -572,8 +795,11 @@ body.outfits-edit display: none #save-current-outfit, #save-outfit-copy display: inline-block - #current-outfit-permalink - display: inline-block + // Phasing out permalink. Shared outfit links have been straight-up + // removed, but this may stay depending on user feedback. Otherwise, + // removing it is TODO down the road. + // #current-outfit-permalink + // display: inline-block &.saving-outfit #save-outfit-form display: block @@ -581,6 +807,10 @@ body.outfits-edit display: none .preview-search-form-your-items +inline-block + #preview-outfits-not-logged-in + display: none + #preview-outfits-list + display: block &.user-not-signed-in #save-outfit-not-signed-in diff --git a/app/stylesheets/outfits/_index.sass b/app/stylesheets/outfits/_index.sass index fd40a952..9dc5f94b 100644 --- a/app/stylesheets/outfits/_index.sass +++ b/app/stylesheets/outfits/_index.sass @@ -1,27 +1,55 @@ +@import "partials/outfit" @import star +$outfit-inner-height: 150px +$outfit-inner-width: 150px +$outfit-banner-h-padding: 4px +$outfit-banner-v-padding: 2px +$outfit-banner-inner-width: $outfit-inner-width - (2 * $outfit-banner-h-padding) + body.outfits-index #outfits - list-style: none - - li - +outfit-star - clear: left - float: left - margin-bottom: .5em - - h4 - float: left - width: 12em - - .outfit-edit-link, form - float: left - font-size: 85% - margin-left: 1em - - .outfit-edit-link - +awesome-button - + +outfits-list + + > li + height: $outfit-inner-height + margin: 2px + width: $outfit-inner-width + + header, footer + padding: $outfit-banner-v-padding $outfit-banner-h-padding + width: $outfit-banner-inner-width + + footer + display: none + + .outfit-edit-link + float: left + text-decoration: none + + form + float: right + + .outfit-delete-button + margin: 0 + padding: 0 + + .outfit-edit-link, .outfit-delete-button + &:hover + text-decoration: underline + + .outfit-star + cursor: auto + + .outfit-name + text-decoration: none + + &:hover + text-decoration: underline + + &:hover + footer + display: block + .outfit-delete-button - margin: 0 - + +reset-awesome-button diff --git a/app/stylesheets/outfits/_star.sass b/app/stylesheets/outfits/_star.sass index ec6ce0b8..056ee3af 100644 --- a/app/stylesheets/outfits/_star.sass +++ b/app/stylesheets/outfits/_star.sass @@ -15,8 +15,6 @@ background-image: image-url("star.png") &.loading .outfit-star background-image: image-url("loading.gif") - &.loading.active .outfit-star - background-image: image-url("loading_current_outfit.gif") =outfit-star-shifted +outfit-star diff --git a/app/stylesheets/partials/_outfit.sass b/app/stylesheets/partials/_outfit.sass new file mode 100644 index 00000000..adce069e --- /dev/null +++ b/app/stylesheets/partials/_outfit.sass @@ -0,0 +1,37 @@ +=outfit + +inline-block + +outfit-star + overflow: hidden + position: relative + + header, footer + +outfit-banner + +outfit-banner-background(black) + + header + bottom: 0 + + footer + top: 0 + + a + color: white + +=outfits-list + // remove whitespace between inline-block elements + font-size: 0 + list-style: none + + > li + +outfit + font-size: 14px + +=outfit-banner + color: white + left: 0 + position: absolute + z-index: 2 + +=outfit-banner-background($color) + background: $color + background: rgba($color, 0.75) diff --git a/app/views/broken_image_reports/new.html.haml b/app/views/broken_image_reports/new.html.haml index cd20f855..42205509 100644 --- a/app/views/broken_image_reports/new.html.haml +++ b/app/views/broken_image_reports/new.html.haml @@ -12,7 +12,7 @@ %ul#report-assets - @swf_assets.each do |swf_asset| %li - = link_to image_tag(swf_asset.s3_url([150, 150])), swf_asset.url + = link_to image_tag(swf_asset.image_url([150, 150])), swf_asset.url - unless swf_asset.image_pending_repair? = form_tag(:action => :create) do = hidden_field_tag 'swf_asset_remote_id', swf_asset.remote_id diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 0736bedf..2c5437c3 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -14,6 +14,7 @@ = yield :stylesheets = stylesheet_link_tag "compiled/screen" = yield :meta + = open_graph_tags = csrf_meta_tag = signed_in_meta_tag %body{:class => body_class} diff --git a/app/views/outfits/_outfit.html.haml b/app/views/outfits/_outfit.html.haml index ebf3c9a0..181ff8d9 100644 --- a/app/views/outfits/_outfit.html.haml +++ b/app/views/outfits/_outfit.html.haml @@ -1,6 +1,14 @@ = outfit_li_for(outfit) do - .outfit-star - %h4= link_to outfit.name, outfit - = link_to_edit_outfit 'Edit', outfit, :class => 'outfit-edit-link' - = button_to('Delete', outfit, :method => 'delete', :class => 'outfit-delete-button', :confirm => "Are you sure you want to delete the outfit #{outfit.name}?") + - if outfit.image? + = link_to image_tag(outfit.image.small.url), outfit + + %header + .outfit-star + = link_to outfit.name, outfit, :class => 'outfit-name' + + %footer + = link_to_edit_outfit 'edit', outfit, :class => 'outfit-edit-link' + = button_to 'delete', outfit, :method => 'delete', :class => 'outfit-delete-button', :confirm => "Are you sure you want to delete the outfit #{outfit.name}?" + + diff --git a/app/views/outfits/edit.html.haml b/app/views/outfits/edit.html.haml index 64105861..11345a0e 100644 --- a/app/views/outfits/edit.html.haml +++ b/app/views/outfits/edit.html.haml @@ -17,14 +17,10 @@ #save-outfit-wrapper %a#current-outfit-permalink{:target => '_blank'} = image_tag 'link_go.png', :alt => 'Permalink', :title => 'Permalink to current outfit' - %a#shared-outfit-permalink{:target => '_blank'} - = image_tag 'link_go.png', :alt => 'Permalink', :title => 'Permalink to shared outfit' - %input#shared-outfit-url.outfit-url{:type => 'text'} - %button#share-outfit Share outfit %button#save-outfit Save outfit %button#save-outfit-not-signed-in Log in to save + %button#save-outfit-copy Save as… %button#save-current-outfit Save "current outfit" - %button#save-outfit-copy Save a copy %form#save-outfit-form .outfit-star %input#save-outfit-name{:type => 'text', :placeholder => 'Outfit name'} @@ -62,30 +58,67 @@ %em donate at least $5 to help upgrade the server. Thanks! #preview-sidebar - #outfit-not-found Outfit not found - #save-success Outfit successfully saved - #save-error - #preview-closet.sidebar-view - %a#preview-sidebar-nav-outfits.preview-sidebar-nav{:href => '#'} Your outfits - %h2 Closet - %ul - %p#fullscreen-copyright - Images © 2000-2010 Neopets, Inc. All Rights Reserved. - Used With Permission - #preview-outfits.sidebar-view - %a#preview-sidebar-nav-closet.preview-sidebar-nav{:href => "#"} ← Back to Closet - %h2 Your outfits - %ul - #preview-saving-outfit.sidebar-view - %a#preview-sidebar-nav-cancel-save.preview-sidebar-nav{:href => '#'} ← Cancel - %h2 Saving new outfit - #new-outfit - %form#new-outfit-form - %header - .outfit-star - %h4 - %input#new-outfit-name{:type => 'text', :placeholder => 'Outfit name'} - %button{:type => 'submit'} Save + %nav#preview-sidebar-navbar + #preview-sidebar-navbar-closet Closet + #preview-sidebar-navbar-sharing Sharing + #preview-sidebar-navbar-outfits Outfits + #preview-sidebar-content + #outfit-not-found Outfit not found + #save-success Outfit successfully saved + #save-error + #preview-closet.sidebar-view + %ul + %p#fullscreen-copyright + Images © 2000-2010 Neopets, Inc. All Rights Reserved. + Used With Permission + #preview-outfits.sidebar-view + %ul#preview-outfits-list + #preview-outfits-not-logged-in + %figure + = image_tag 'outfits_welcome.png' + %figcaption Ready to become a pro designer? + :markdown + We know how hard it can be to keep track of your ideas, + especially if you end up having a lot of them. + **But Dress to Impress makes it easy.** + + Once you have an idea for an outfit, you can **build it, + save it, and view it again later**, either to update your + design or finally make your dream a reality. + + **Thousands of users have already saved tens of thousands of + outfits — will you be next?** + + = link_to 'Log in to save this outfit', login_path_with_return_to, :id => 'preview-outfits-log-in' + #preview-sharing.sidebar-view + #preview-sharing-thumbnail-wrapper + #preview-sharing-thumbnail-loading + = image_tag 'outfits/small_loading.gif' + %span#preview-sharing-thumbnail-saving Saving… + %span#preview-sharing-thumbnail-generating Generating… + %img#preview-sharing-thumbnail + %p#preview-sharing-beta-note + We're currently beta testing outfit image generation. It might be + slow or not work at all, and we might have to take it down. + Still, we're really excited about this feature, and we hope you + are, too! + %ul#preview-sharing-urls + %li + %label{:for => 'preview-sharing-permalink-url'} Outfit page + %input#preview-sharing-permalink-url.outfit-url{:type => 'text'} + %li + %label{:for => 'preview-sharing-large-image-url'} Large image + %input#preview-sharing-large-image-url.outfit-url{:type => 'text'} + %li + %label{:for => 'preview-sharing-medium-image-url'} Medium image + %input#preview-sharing-medium-image-url.outfit-url{:type => 'text'} + %li + %label{:for => 'preview-sharing-small-image-url'} Small image + %input#preview-sharing-small-image-url.outfit-url{:type => 'text'} + %ul#preview-sharing-url-formats + %li.active{'data-format' => 'plain'} Plain + %li{'data-format' => 'html'} HTML + %li{'data-format' => 'bbcode'} BBCode %form#preview-search-form %header %h2 Add an item @@ -132,18 +165,20 @@ %script#outfit-template{:type => 'text/x-jquery-tmpl'}
  • %header - %button.outfit-delete × .outfit-star - %h4 ${name} - %a.outfit-rename-button{:href => '#'} rename + %span.outfit-name ${name} %form.outfit-rename-form %input.outfit-rename-field{:type => 'text'} - %input.outfit-url{:type => 'text', :value => "http://#{request.host}/outfits/${id}"} + %footer + %a.outfit-rename-button{:href => '#'} rename + %a.outfit-delete{:href => '#'} delete + .outfit-thumbnail-wrapper + %img.outfit-thumbnail .outfit-delete-confirmation - %span Delete forever? + %span Delete? %a.outfit-delete-confirmation-yes{:href => '#'} yes \/ - %a.outfit-delete-confirmation-no{:href => '#'} no, thanks + %a.outfit-delete-confirmation-no{:href => '#'} no
  • - content_for :javascripts do = include_javascript_libraries :jquery, :swfobject, :jquery_tmpl diff --git a/app/views/outfits/show.html.haml b/app/views/outfits/show.html.haml index 880925b4..0a769542 100644 --- a/app/views/outfits/show.html.haml +++ b/app/views/outfits/show.html.haml @@ -1,6 +1,11 @@ - title(@outfit.name || "Shared outfit") - content_for :before_title, campaign_progress +- open_graph :type => 'openneo-impress:outfit', :title => yield(:title), + :url => outfit_url(@outfit) +- if @outfit.image? + - open_graph :image => absolute_url(@outfit.image.url) + = link_to_edit_outfit(@outfit, :class => 'button', :id => 'outfit-wardrobe-link') do Edit - unless user_signed_in? && @outfit.user == current_user diff --git a/config/initializers/asset_hosts.rb b/config/initializers/asset_hosts.rb new file mode 100644 index 00000000..304208b8 --- /dev/null +++ b/config/initializers/asset_hosts.rb @@ -0,0 +1,3 @@ +ASSET_HOSTS = { + :swf_asset_images => 'd1i4vx4g4uxw7j.cloudfront.net' +} diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb new file mode 100644 index 00000000..264719dc --- /dev/null +++ b/config/initializers/carrierwave.rb @@ -0,0 +1,20 @@ +# By default, we'll have CarrierWave use S3 only on production. (Since each +# asset image has only One True Image no matter the environment, we'll override +# this to use S3 on all environments for those images only.) + +CarrierWave.configure do |config| + if Rails.env.production? + s3_config = YAML.load_file Rails.root.join('config', 'aws_s3.yml') + access_key_id = s3_config['access_key_id'] + secret_access_key = s3_config['secret_access_key'] + + config.storage = :fog + config.fog_credentials = { + :provider => 'AWS', + :aws_access_key_id => access_key_id, + :aws_secret_access_key => secret_access_key + } + else + config.storage = :file + end +end diff --git a/db/migrate/20120308205324_add_image_to_outfits.rb b/db/migrate/20120308205324_add_image_to_outfits.rb new file mode 100644 index 00000000..b493e62d --- /dev/null +++ b/db/migrate/20120308205324_add_image_to_outfits.rb @@ -0,0 +1,9 @@ +class AddImageToOutfits < ActiveRecord::Migration + def self.up + add_column :outfits, :image, :string + end + + def self.down + remove_column :outfits, :image + end +end diff --git a/db/migrate/20120716193946_add_image_layers_hash_to_outfit.rb b/db/migrate/20120716193946_add_image_layers_hash_to_outfit.rb new file mode 100644 index 00000000..d5e04cef --- /dev/null +++ b/db/migrate/20120716193946_add_image_layers_hash_to_outfit.rb @@ -0,0 +1,9 @@ +class AddImageLayersHashToOutfit < ActiveRecord::Migration + def self.up + add_column :outfits, :image_layers_hash, :string, :length => 8 + end + + def self.down + remove_column :outfits, :image_layers_hash + end +end diff --git a/db/migrate/20120725232903_add_image_enqueued_to_outfits.rb b/db/migrate/20120725232903_add_image_enqueued_to_outfits.rb new file mode 100644 index 00000000..e7d3b59f --- /dev/null +++ b/db/migrate/20120725232903_add_image_enqueued_to_outfits.rb @@ -0,0 +1,9 @@ +class AddImageEnqueuedToOutfits < ActiveRecord::Migration + def self.up + add_column :outfits, :image_enqueued, :boolean, :null => false, :default => false + end + + def self.down + remove_column :outfits, :image_enqueued + end +end diff --git a/db/schema.rb b/db/schema.rb index 5d866571..38a662ba 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 => 20120521164652) do +ActiveRecord::Schema.define(:version => 20120725232903) do create_table "auth_servers", :force => true do |t| t.string "short_name", :limit => 10, :null => false @@ -116,8 +116,10 @@ ActiveRecord::Schema.define(:version => 20120521164652) do t.datetime "created_at" t.datetime "updated_at" t.string "name" - t.boolean "starred", :default => false, :null => false + t.boolean "starred", :default => false, :null => false t.string "image" + t.string "image_layers_hash" + t.boolean "image_enqueued", :default => false, :null => false end add_index "outfits", ["pet_state_id"], :name => "index_outfits_on_pet_state_id" diff --git a/lib/tasks/outfits.rake b/lib/tasks/outfits.rake new file mode 100644 index 00000000..93a03dd3 --- /dev/null +++ b/lib/tasks/outfits.rake @@ -0,0 +1,11 @@ +namespace :outfits do + desc 'Retroactively enqueue image updates for outfits saved to user accounts' + task :retroactively_enqueue => :environment do + outfits = Outfit.select([:id]).where('image IS NULL AND user_id IS NOT NULL') + puts "Enqueuing #{outfits.count} outfits" + outfits.find_each do |outfit| + Resque.enqueue(OutfitImageUpdate::Retroactive, outfit.id) + end + puts "Successfully enqueued." + end +end diff --git a/public/images/loading_outfit_pane.gif b/public/images/loading_outfit_pane.gif new file mode 100644 index 00000000..1ab02d52 Binary files /dev/null and b/public/images/loading_outfit_pane.gif differ diff --git a/public/images/outfits/default.png b/public/images/outfits/default.png new file mode 100644 index 00000000..59b6b6a2 Binary files /dev/null and b/public/images/outfits/default.png differ diff --git a/public/images/outfits/medium_default.png b/public/images/outfits/medium_default.png new file mode 100644 index 00000000..75c39309 Binary files /dev/null and b/public/images/outfits/medium_default.png differ diff --git a/public/images/outfits/small_default.png b/public/images/outfits/small_default.png new file mode 100644 index 00000000..50e992bb Binary files /dev/null and b/public/images/outfits/small_default.png differ diff --git a/public/images/outfits/small_loading.gif b/public/images/outfits/small_loading.gif new file mode 100644 index 00000000..89f4b504 Binary files /dev/null and b/public/images/outfits/small_loading.gif differ diff --git a/public/images/outfits_welcome.png b/public/images/outfits_welcome.png new file mode 100644 index 00000000..325ac388 Binary files /dev/null and b/public/images/outfits_welcome.png differ diff --git a/public/javascripts/outfits/edit.js b/public/javascripts/outfits/edit.js index b6d8009c..60a899f4 100644 --- a/public/javascripts/outfits/edit.js +++ b/public/javascripts/outfits/edit.js @@ -57,7 +57,7 @@ Partial.ItemSet = function ItemSet(wardrobe, selector) { var item, no_assets, li, no_assets_message; for(var i = 0, l = specific_items.length; i < l; i++) { item = specific_items[i]; - no_assets = item.couldNotLoadAssetsFitting(wardrobe.outfit.getPetType()); + no_assets = item.couldNotLoadAssetsFitting(wardrobe.outfits.getPetType()); li = $('li.object-' + item.id).toggleClass('no-assets', no_assets); (function (li) { no_assets_message = li.find('span.no-assets-message'); @@ -103,8 +103,8 @@ Partial.ItemSet = function ItemSet(wardrobe, selector) { } li.append(img).append(controls).append(info_link).append(item.name).appendTo(ul); } - setClosetItems(wardrobe.outfit.getClosetItems()); - setOutfitItems(wardrobe.outfit.getWornItems()); + setClosetItems(wardrobe.outfits.getClosetItems()); + setOutfitItems(wardrobe.outfits.getWornItems()); } $('span.no-assets-message').live('mouseover', function () { @@ -117,9 +117,9 @@ Partial.ItemSet = function ItemSet(wardrobe, selector) { no_assets_full_message.removeAttr('style'); }); - wardrobe.outfit.bind('updateItemAssets', function () { setHasAssets(wardrobe.outfit.getWornItems()) }); - wardrobe.outfit.bind('updateWornItems', setOutfitItems); - wardrobe.outfit.bind('updateClosetItems', setClosetItems); + wardrobe.outfits.bind('updateItemAssets', function () { setHasAssets(wardrobe.outfits.getWornItems()) }); + wardrobe.outfits.bind('updateWornItems', setOutfitItems); + wardrobe.outfits.bind('updateClosetItems', setClosetItems); } Partial.ItemSet.CONTROL_SETS = {}; @@ -151,12 +151,12 @@ Partial.ItemSet.setWardrobe = function (wardrobe) { } toggle_fn.closeted = {}; - toggle_fn.closeted[true] = $.proxy(wardrobe.outfit, 'closetItem'); - toggle_fn.closeted[false] = $.proxy(wardrobe.outfit, 'unclosetItem'); + toggle_fn.closeted[true] = $.proxy(wardrobe.outfits, 'closetItem'); + toggle_fn.closeted[false] = $.proxy(wardrobe.outfits, 'unclosetItem'); toggle_fn.worn = {}; - toggle_fn.worn[true] = $.proxy(wardrobe.outfit, 'wearItem'); - toggle_fn.worn[false] = $.proxy(wardrobe.outfit, 'unwearItem'); + toggle_fn.worn[true] = $.proxy(wardrobe.outfits, 'wearItem'); + toggle_fn.worn[false] = $.proxy(wardrobe.outfits, 'unwearItem'); Partial.ItemSet.setWardrobe = $.noop; } @@ -164,14 +164,16 @@ Partial.ItemSet.setWardrobe = function (wardrobe) { View.Closet = function (wardrobe) { var item_set = new Partial.ItemSet(wardrobe, '#preview-closet ul'); - wardrobe.outfit.bind('updateClosetItems', $.proxy(item_set, 'setItems')); + wardrobe.outfits.bind('updateClosetItems', $.proxy(item_set, 'setItems')); } View.Fullscreen = function (wardrobe) { var full = $(document.body).hasClass('fullscreen'), win = $(window), preview_el = $('#preview'), search_el = $('#preview-search-form'), preview_swf = $('#preview-swf'), sidebar_el = $('#preview-sidebar'), - footer = $('#footer'), jwindow = $(window), overrideFull = false; + sidebar_content_el = $('#preview-sidebar-content'), + sidebar_navbar_el = $('#preview-sidebar-navbar'), footer = $('#footer'), + jwindow = $(window), overrideFull = false; function fit() { if(!overrideFull) { @@ -182,6 +184,7 @@ View.Fullscreen = function (wardrobe) { if(!full) { preview_swf.removeAttr('style').css('visibility', 'visible'); preview_el.removeAttr('style'); + sidebar_content_el.removeAttr('style'); } } } @@ -213,6 +216,12 @@ View.Fullscreen = function (wardrobe) { preview_swf.css(size.next); preview_el.height(available.height); + + // Now that preview is fit, we fit the sidebar's content element, which + // also has to deal with the constraint of its navbar's height. + var sidebar_content_height = available.height - + sidebar_navbar_el.outerHeight() - 1; // 1px bottom border + sidebar_content_el.height(sidebar_content_height); } } $('#preview').data('fit', fit); @@ -273,32 +282,32 @@ View.Hash = function (wardrobe) { } if(new_data.color !== data.color || new_data.species !== data.species) { - wardrobe.outfit.setPetTypeByColorAndSpecies(new_data.color, new_data.species); + wardrobe.outfits.setPetTypeByColorAndSpecies(new_data.color, new_data.species); } if(new_data.closet) { if(!arraysMatch(new_data.closet, data.closet)) { - wardrobe.outfit.setClosetItemsByIds(new_data.closet.slice(0)); + wardrobe.outfits.setClosetItemsByIds(new_data.closet.slice(0)); } } else if(new_data.objects && !arraysMatch(new_data.objects, data.closet)) { - wardrobe.outfit.setClosetItemsByIds(new_data.objects.slice(0)); + wardrobe.outfits.setClosetItemsByIds(new_data.objects.slice(0)); } else { - wardrobe.outfit.setClosetItemsByIds([]); + wardrobe.outfits.setClosetItemsByIds([]); } if(new_data.objects) { if(!arraysMatch(new_data.objects, data.objects)) { - wardrobe.outfit.setWornItemsByIds(new_data.objects.slice(0)); + wardrobe.outfits.setWornItemsByIds(new_data.objects.slice(0)); } } else { - wardrobe.outfit.setWornItemsByIds([]); + wardrobe.outfits.setWornItemsByIds([]); } if(new_data.name != data.name && new_data.name) { wardrobe.base_pet.setName(new_data.name); } if(new_data.state != data.state) { - wardrobe.outfit.setPetStateById(new_data.state); + wardrobe.outfits.setPetStateById(new_data.state); } if(new_data.outfit != data.outfit) { - wardrobe.outfit.setId(new_data.outfit); + wardrobe.outfits.setId(new_data.outfit); } if(new_data.search != data.search || new_data.search_offset != data.search_offset) { wardrobe.search.setItemsByQuery(new_data.search, {offset: new_data.search_offset}); @@ -350,27 +359,27 @@ View.Hash = function (wardrobe) { } function singleOutfitResponse(event_name, response) { - wardrobe.outfit.bind(event_name, function () { - if(!wardrobe.outfit.in_transaction) response.apply(this, arguments); + wardrobe.outfits.bind(event_name, function () { + if(!wardrobe.outfits.in_transaction) response.apply(this, arguments); }); } singleOutfitResponse('updateClosetItems', function (items) { - var item_ids = items.map('id'); + var item_ids = items.mapProperty('id'); if(!arraysMatch(item_ids, data.closet)) { changeQuery({closet: item_ids}); } }); singleOutfitResponse('updateWornItems', function (items) { - var item_ids = items.map('id'), changes = {}; + var item_ids = items.mapProperty('id'), changes = {}; if(!arraysMatch(item_ids, data.objects)) { changes.objects = item_ids; } if(arraysMatch(item_ids, data.closet) || arraysMatch(item_ids, data.objects)) { changes.closet = undefined; } else { - changes.closet = wardrobe.outfit.getClosetItems().map('id'); + changes.closet = wardrobe.outfits.getClosetItems().mapProperty('id'); } if(changes.objects || changes.closet) changeQuery(changes); }); @@ -390,7 +399,7 @@ View.Hash = function (wardrobe) { }); singleOutfitResponse('updatePetState', function (pet_state) { - var pet_type = wardrobe.outfit.getPetType(); + var pet_type = wardrobe.outfits.getPetType(); if(pet_state.id != data.state && pet_type && (data.state || pet_state.id != pet_type.pet_state_ids[0])) { changeQuery({state: pet_state.id}); } @@ -402,7 +411,7 @@ View.Hash = function (wardrobe) { } }); - wardrobe.outfit.bind('loadOutfit', function (outfit) { + wardrobe.outfits.bind('loadOutfit', function (outfit) { changeQuery({ closet: outfit.getClosetItemIds(), color: outfit.pet_type.color_id, @@ -413,7 +422,7 @@ View.Hash = function (wardrobe) { }); }); - wardrobe.outfit.bind('outfitNotFound', function (outfit) { + wardrobe.outfits.bind('outfitNotFound', function (outfit) { var new_id = outfit ? outfit.id : undefined; changeQuery({outfit: new_id}); }); @@ -430,8 +439,6 @@ View.Hash = function (wardrobe) { View.Outfits = function (wardrobe) { var current_outfit_permalink_el = $('#current-outfit-permalink'), - shared_outfit_permalink_el = $('#shared-outfit-permalink'), - shared_outfit_url_el = $('#shared-outfit-url'), new_outfit_form_el = $('#save-outfit-form'), new_outfit_name_el = $('#save-outfit-name'), outfits_el = $('#preview-outfits'), @@ -451,13 +458,6 @@ View.Outfits = function (wardrobe) { return $('li.outfit-' + outfit.id); } - function navLinkTo(callback) { - return function (e) { - e.preventDefault(); - callback(); - } - } - function navigateTo(will_be_viewing) { var currently_viewing = sidebar_el.attr('class'); if(currently_viewing != will_be_viewing) previously_viewing = currently_viewing; @@ -476,13 +476,20 @@ View.Outfits = function (wardrobe) { /* Nav */ function showCloset() { + sharing.onHide(); navigateTo(''); } function showOutfits() { - wardrobe.user.loadOutfits(); + sharing.onHide(); + wardrobe.outfits.loadOutfits(); navigateTo('viewing-outfits'); } + + function showSharing() { + sharing.onShow(); + navigateTo('sharing'); + } function showNewOutfitForm() { new_outfit_name_el.val(''); @@ -495,9 +502,13 @@ View.Outfits = function (wardrobe) { save_outfit_wrapper_el.removeClass('saving-outfit'); } - $('#preview-sidebar-nav-outfits').click(navLinkTo(showOutfits)); - - $('#preview-sidebar-nav-closet').click(navLinkTo(showCloset)); + $('#preview-sidebar-navbar-closet').click(showCloset); + $('#preview-sidebar-navbar-sharing').click(function () { + sharing.startLoading(); + wardrobe.outfits.share(); + showSharing(); + }); + $('#preview-sidebar-navbar-outfits').click(showOutfits); $('#save-outfit, #save-outfit-copy').click(showNewOutfitForm); @@ -508,40 +519,65 @@ View.Outfits = function (wardrobe) { }); /* Outfits list */ + + var list_image_subscriptions = {}; + + function listSubscribeToImage(outfit) { + list_image_subscriptions[outfit.id] = wardrobe.image_subscriptions.subscribe(outfit); + } + + function listUnsubscribeFromImage(outfit) { + if(outfit.id in list_image_subscriptions) { + if(list_image_subscriptions[outfit.id] !== null) { + wardrobe.image_subscriptions.unsubscribe(list_image_subscriptions[outfit.id]); + } + + delete list_image_subscriptions[outfit.id]; + } + } $('#outfit-template').template('outfitTemplate'); - wardrobe.user.bind('outfitsLoaded', function (outfits) { + wardrobe.outfits.bind('outfitsLoaded', function (outfits) { var outfit_els = $.tmpl('outfitTemplate', outfits); outfits_list_el.html('').append(outfit_els).addClass('loaded'); updateActiveOutfit(); + + for(var i = 0; i < outfits.length; i++) { + listSubscribeToImage(outfits[i]); + } }); - wardrobe.user.bind('addOutfit', function (outfit, i) { + wardrobe.outfits.bind('addOutfit', function (outfit, i) { var next_child = outfits_list_el.children().not('.hiding').eq(i), - outfit_el = $.tmpl('outfitTemplate', outfit); + outfit_el = $.tmpl('outfitTemplate', outfit.clone()); if(next_child.length) { outfit_el.insertBefore(next_child); } else { outfit_el.appendTo(outfits_list_el); } updateActiveOutfit(); - outfit_el.hide().show('normal'); + + var naturalWidth = outfit_el.css('width'); + log("Natural width is", naturalWidth, outfit_el.width()); + outfit_el.width(0).animate({width: naturalWidth}, 'normal'); + listSubscribeToImage(outfit); }); - wardrobe.user.bind('removeOutfit', function (outfit, i) { + wardrobe.outfits.bind('removeOutfit', function (outfit, i) { var outfit_el = outfits_list_el.children().not('.hiding').eq(i); - outfit_el.addClass('hiding').stop(true).hide('normal', function () { outfit_el.remove() }); + outfit_el.addClass('hiding').stop(true).animate({width: 0}, 'normal', function () { outfit_el.remove() }); + listUnsubscribeFromImage(outfit); }); - $('#preview-outfits h4').live('click', function () { - wardrobe.outfit.load($(this).tmplItem().data.id); + $('#preview-outfits li header, #preview-outfits li .outfit-thumbnail-wrapper').live('click', function () { + wardrobe.outfits.load($(this).tmplItem().data.id); }); $('a.outfit-rename-button').live('click', function (e) { e.preventDefault(); var li = $(this).closest('li').addClass('renaming'), - name = li.find('h4').text(); + name = li.find('span.outfit-name').text(); li.find('input.outfit-rename-field').val(name).focus(); }); @@ -550,7 +586,7 @@ View.Outfits = function (wardrobe) { li = el.closest('li').removeClass('renaming'); if(new_name != outfit.name) { li.startLoading(); - wardrobe.user.renameOutfit(outfit, new_name); + wardrobe.outfits.renameOutfit(outfit, new_name); } } @@ -568,7 +604,8 @@ View.Outfits = function (wardrobe) { this.blur(); }); - $('button.outfit-delete').live('click', function (e) { + $('a.outfit-delete').live('click', function (e) { + e.stopPropagation(); e.preventDefault(); $(this).closest('li').addClass('confirming-deletion'); }); @@ -576,9 +613,9 @@ View.Outfits = function (wardrobe) { $('a.outfit-delete-confirmation-yes').live('click', function (e) { var outfit = $(this).tmplItem().data; e.preventDefault(); - wardrobe.user.destroyOutfit(outfit); - if(wardrobe.outfit.getOutfit().id == outfit.id) { - wardrobe.outfit.setId(null); + wardrobe.outfits.destroyOutfit(outfit); + if(wardrobe.outfits.getOutfit().id == outfit.id) { + wardrobe.outfits.setId(null); } }); @@ -587,16 +624,25 @@ View.Outfits = function (wardrobe) { $(this).closest('li').removeClass('confirming-deletion'); }); - stars.live('click', function () { + stars.live('click', function (e) { + e.stopPropagation(); var el = $(this); el.closest('li').startLoading(); - wardrobe.user.toggleOutfitStar(el.tmplItem().data); + wardrobe.outfits.toggleOutfitStar(el.tmplItem().data); }); + + function pathToUrl(path) { + var host = document.location.protocol + "//" + document.location.host; + if(document.location.port) host += ":" + document.location.port; + return host + path; + } + + function generateOutfitPermalink(outfit) { + return pathToUrl("/outfits/" + outfit.id); + } function setOutfitPermalink(outfit, outfit_permalink_el, outfit_url_el) { - var url = document.location.protocol + "//" + document.location.host; - if(document.location.port) url += ":" + document.location.port; - url += "/outfits/" + outfit.id; + var url = generateOutfitPermalink(outfit); outfit_permalink_el.attr('href', url); if(outfit_url_el) outfit_url_el.val(url); } @@ -605,10 +651,6 @@ View.Outfits = function (wardrobe) { setOutfitPermalink(outfit, current_outfit_permalink_el); } - function setSharedOutfitPermalink(outfit) { - setOutfitPermalink(outfit, shared_outfit_permalink_el, shared_outfit_url_el); - } - function setActiveOutfit(outfit) { outfits_list_el.find('li.active').removeClass('active'); if(outfit.id) { @@ -620,33 +662,210 @@ View.Outfits = function (wardrobe) { } function updateActiveOutfit() { - setActiveOutfit(wardrobe.outfit.getOutfit()); + setActiveOutfit(wardrobe.outfits.getOutfit()); } - wardrobe.outfit.bind('setOutfit', setActiveOutfit); - wardrobe.outfit.bind('outfitNotFound', setActiveOutfit); + wardrobe.outfits.bind('setOutfit', setActiveOutfit); + wardrobe.outfits.bind('outfitNotFound', setActiveOutfit); - wardrobe.user.bind('outfitRenamed', function (outfit) { - if(outfit.id == wardrobe.outfit.getId()) { + wardrobe.outfits.bind('outfitRenamed', function (outfit) { + if(outfit.id == wardrobe.outfits.getId()) { save_current_outfit_name_el.text(outfit.name); } }); + + function outfitElement(outfit) { + return outfits_el.find('li.outfit-' + outfit.id); + } + + wardrobe.outfits.bind('saveSuccess', function (outfit) { + listSubscribeToImage(outfit); + }); + + wardrobe.image_subscriptions.bind('imageEnqueued', function (outfit) { + if(outfit.id in list_image_subscriptions) { + log("List sees imageEnqueued for", outfit); + outfitElement(outfit).removeClass('thumbnail-loaded'); + } + }); + + wardrobe.image_subscriptions.bind('imageReady', function (outfit) { + if(outfit.id in list_image_subscriptions) { + log("List sees imageReady for", outfit); + listUnsubscribeFromImage(outfit); + + var src = outfit.image_versions.small + '?' + (new Date()).getTime(); + outfitElement(outfit).addClass('thumbnail-loaded').addClass('thumbnail-available'). + find('img.outfit-thumbnail').attr('src', src); + } + }); + + /* Sharing */ + + var sharing = new function Sharing() { + var WRAPPER = $('#preview-sharing'); + var sharing_url_els = { + permalink: $('#preview-sharing-permalink-url'), + large_image: $('#preview-sharing-large-image-url'), + medium_image: $('#preview-sharing-medium-image-url'), + small_image: $('#preview-sharing-small-image-url'), + }; + var format_selector_els = $('#preview-sharing-url-formats li'); + var thumbnail_el = $('#preview-sharing-thumbnail'); + + var formats = { + plain: { + image: function (url) { return url }, + text: function (url) { return url } + }, + html: { + image: function (url, permalink) { + return ''; + }, + text: function (url) { + return 'Dress to Impress'; + } + }, + bbcode: { + image: function (url, permalink) { + return '[URL=' + permalink + '][IMG]' + url + '[/IMG][/URL]'; + }, + text: function (url) { + return '[URL=' + url + ']Dress to Impress[/URL]'; + } + } + }; + + var format = formats.plain; + var urls = {permalink: null, small_image: null, medium_image: null, + large_image: null}; + + format_selector_els.click(function () { + var selector_el = $(this); + format_selector_els.removeClass('active'); + selector_el.addClass('active'); + log("Setting sharing URL format:", selector_el.attr('data-format')); + format = formats[selector_el.attr('data-format')]; + formatUrls(); + }); + + var image_subscription = null; + function unsubscribeFromImage() { + wardrobe.image_subscriptions.unsubscribe(image_subscription); + image_subscription = null; + } + + function subscribeToImage(outfit) { + image_subscription = wardrobe.image_subscriptions.subscribe(outfit); + } + + function subscribeToImageIfVisible(outfit) { + if(outfit && sidebar_el.hasClass('sharing')) { + subscribeToImage(outfit); + } + } + + var current_shared_outfit = {id: null}; + this.setOutfit = function (outfit) { + // If outfit has no ID but we're already on the Sharing tab (e.g. user is + // on Sharing but goes back in history to a no-ID outfit), we can't + // exactly do anything with it but submit it for sharing. + if(!outfit.id) { + sharing.startLoading(); + wardrobe.outfits.share(outfit); + return false; + } + + // But if the outfit does have a valid ID, we're good to go. If it's the + // same as the currently shared outfit ID, then don't even change + // anything. If it's new, then change everything. + if(outfit.id != current_shared_outfit.id) { + // The current shared outfit needs to be a clone, or else modifications + // to the active outfit will show up here, too, and then our comparison + // to discover if this is a new outfit ID or not fails. + current_shared_outfit = outfit.clone(); + urls.permalink = generateOutfitPermalink(outfit); + urls.small_image = pathToUrl(outfit.image_versions.small); + urls.medium_image = pathToUrl(outfit.image_versions.medium); + urls.large_image = pathToUrl(outfit.image_versions.large); + formatUrls(); + WRAPPER.removeClass('thumbnail-available'); + subscribeToImageIfVisible(current_shared_outfit); + } + WRAPPER.addClass('urls-loaded'); + } + + this.startLoading = function () { + WRAPPER.removeClass('urls-loaded'); + } + + this.onHide = function () { + unsubscribeFromImage(); + } + + this.onShow = function () { + subscribeToImageIfVisible(wardrobe.outfits.getOutfit()); + } + + function formatUrls() { + formatImageUrl('small_image'); + formatImageUrl('medium_image'); + formatImageUrl('large_image'); + formatTextUrl('permalink'); + } + + function formatTextUrl(key) { + formatUrl(key, format.text(urls[key])); + } + + function formatImageUrl(key) { + formatUrl(key, format.image(urls[key], urls.permalink)); + } + + function formatUrl(key, url) { + sharing_url_els[key].val(url); + } + + wardrobe.image_subscriptions.bind('imageEnqueued', function (outfit) { + if(outfit.id == current_shared_outfit.id) { + log("Sharing thumbnail enqueued for outfit", outfit); + WRAPPER.removeClass('thumbnail-loaded'); + } + }); + + wardrobe.image_subscriptions.bind('imageReady', function (outfit) { + if(outfit.id == current_shared_outfit.id) { + log("Sharing thumbnail ready for outfit", outfit); + var src = outfit.image_versions.small + '?' + outfit.image_layers_hash; + thumbnail_el.attr('src', src); + WRAPPER.addClass('thumbnail-loaded'); + WRAPPER.addClass('thumbnail-available'); + unsubscribeFromImage(outfit); + } + }); + + wardrobe.outfits.bind('updateSuccess', function (outfit) { + if(sidebar_el.hasClass('sharing')) { + subscribeToImage(outfit); + } + }); + + wardrobe.outfits.bind('setOutfit', function (outfit) { + log("Sharing sees the setOutfit signal, and will set", outfit); + sharing.setOutfit(outfit); + }); + } /* Saving */ save_current_outfit_el.click(function () { - wardrobe.outfit.update(); + wardrobe.outfits.update(); }); new_outfit_form_el.submit(function (e) { e.preventDefault(); new_outfit_form_el.startLoading(); - wardrobe.outfit.create({starred: new_outfit_form_el.hasClass('starred'), name: new_outfit_name_el.val()}); - }); - - $('#share-outfit').click(function () { - save_outfit_wrapper_el.startLoading(); - wardrobe.outfit.share(); + wardrobe.outfits.create({starred: new_outfit_form_el.hasClass('starred'), name: new_outfit_name_el.val()}); }); new_outfit_form_el.find('div.outfit-star').click(function () { @@ -664,32 +883,31 @@ View.Outfits = function (wardrobe) { save_error_el.text(text).notify(); } - wardrobe.outfit.bind('saveSuccess', function (outfit) { + wardrobe.outfits.bind('saveSuccess', function (outfit) { save_success_el.notify(); }); - wardrobe.outfit.bind('createSuccess', function (outfit) { - wardrobe.user.addOutfit(outfit); + wardrobe.outfits.bind('createSuccess', function (outfit) { showOutfits(); hideNewOutfitForm(); }); - - wardrobe.outfit.bind('updateSuccess', function (outfit) { - wardrobe.user.updateOutfit(outfit); - }); - - wardrobe.outfit.bind('shareSuccess', function (outfit) { + + function shareComplete(outfit) { save_outfit_wrapper_el.stopLoading().addClass('shared-outfit'); - setSharedOutfitPermalink(outfit); - }); + sharing.setOutfit(outfit); + showSharing(); + } + + wardrobe.outfits.bind('shareSuccess', shareComplete); + wardrobe.outfits.bind('shareSkipped', shareComplete); function clearSharedOutfit() { save_outfit_wrapper_el.removeClass('shared-outfit'); } - wardrobe.outfit.bind('updateClosetItems', clearSharedOutfit); - wardrobe.outfit.bind('updateWornItems', clearSharedOutfit); - wardrobe.outfit.bind('updatePetState', clearSharedOutfit); + wardrobe.outfits.bind('updateClosetItems', clearSharedOutfit); + wardrobe.outfits.bind('updateWornItems', clearSharedOutfit); + wardrobe.outfits.bind('updatePetState', clearSharedOutfit); function saveFailure(outfit, response) { var errors = response.errors; @@ -712,16 +930,16 @@ View.Outfits = function (wardrobe) { liForOutfit(outfit).stopLoading(); } - wardrobe.outfit.bind('saveFailure', saveFailure); - wardrobe.user.bind('saveFailure', saveFailure) - wardrobe.outfit.bind('shareFailure', function (outfit, response) { + wardrobe.outfits.bind('saveFailure', saveFailure); + wardrobe.outfits.bind('saveFailure', saveFailure) + wardrobe.outfits.bind('shareFailure', function (outfit, response) { save_outfit_wrapper_el.stopLoading(); saveFailure(outfit, response); }); /* Error */ - wardrobe.outfit.bind('outfitNotFound', function () { + wardrobe.outfits.bind('outfitNotFound', function () { outfit_not_found_el.notify(); }); } @@ -733,7 +951,7 @@ View.PetStateForm = function (wardrobe) { button_query = form_query + ' button'; $(button_query).live('click', function (e) { e.preventDefault(); - wardrobe.outfit.setPetStateById(+$(this).data('value')); + wardrobe.outfits.setPetStateById(+$(this).data('value')); }); function updatePetState(pet_state) { @@ -743,7 +961,7 @@ View.PetStateForm = function (wardrobe) { } } - wardrobe.outfit.bind('petTypeLoaded', function (pet_type) { + wardrobe.outfits.bind('petTypeLoaded', function (pet_type) { var ids = pet_type.pet_state_ids, i, id, li, button, label; ul.children().remove(); if(ids.length == 1) { @@ -761,18 +979,18 @@ View.PetStateForm = function (wardrobe) { button.appendTo(li); li.appendTo(ul); } - updatePetState(wardrobe.outfit.getPetState()); + updatePetState(wardrobe.outfits.getPetState()); } }); - wardrobe.outfit.bind('updatePetState', updatePetState); + wardrobe.outfits.bind('updatePetState', updatePetState); } View.PetTypeForm = function (wardrobe) { var form = $('#pet-type-form'), dropdowns = {}, loaded = false; form.submit(function (e) { e.preventDefault(); - wardrobe.outfit.setPetTypeByColorAndSpecies( + wardrobe.outfits.setPetTypeByColorAndSpecies( +dropdowns.color.val(), +dropdowns.species.val() ); }).children('select').each(function () { @@ -803,12 +1021,12 @@ View.PetTypeForm = function (wardrobe) { }); }); loaded = true; - updatePetType(wardrobe.outfit.getPetType()); + updatePetType(wardrobe.outfits.getPetType()); }); - wardrobe.outfit.bind('updatePetType', updatePetType); + wardrobe.outfits.bind('updatePetType', updatePetType); - wardrobe.outfit.bind('petTypeNotFound', function () { + wardrobe.outfits.bind('petTypeNotFound', function () { $('#pet-type-not-found').show('normal').delay(3000).hide('fast'); }); } @@ -865,7 +1083,7 @@ View.ReportBrokenImage = function (wardrobe) { var baseURL = link.attr('data-base-url'); function updateLink() { - var assets = wardrobe.outfit.getVisibleAssets(); + var assets = wardrobe.outfits.getVisibleAssets(); var url = baseURL + "?"; for(var i = 0; i < assets.length; i++) { @@ -876,9 +1094,9 @@ View.ReportBrokenImage = function (wardrobe) { link.attr('href', url); } - wardrobe.outfit.bind('updateWornItems', updateLink); - wardrobe.outfit.bind('updateItemAssets', updateLink); - wardrobe.outfit.bind('updatePetState', updateLink); + wardrobe.outfits.bind('updateWornItems', updateLink); + wardrobe.outfits.bind('updateItemAssets', updateLink); + wardrobe.outfits.bind('updatePetState', updateLink); } View.Search = function (wardrobe) { diff --git a/public/javascripts/outfits/show.js b/public/javascripts/outfits/show.js index 99e081e7..16b0e728 100644 --- a/public/javascripts/outfits/show.js +++ b/public/javascripts/outfits/show.js @@ -7,4 +7,4 @@ var main_wardrobe = new Wardrobe(), View = Wardrobe.getStandardView({ }); main_wardrobe.registerViews(View); main_wardrobe.initialize(); -main_wardrobe.outfit.loadData(INITIAL_OUTFIT_DATA); +main_wardrobe.outfits.loadData(INITIAL_OUTFIT_DATA); diff --git a/public/javascripts/wardrobe.js b/public/javascripts/wardrobe.js index 9013170b..74991ae0 100644 --- a/public/javascripts/wardrobe.js +++ b/public/javascripts/wardrobe.js @@ -7,9 +7,6 @@ function arraysMatch(array1, array2) { return array1 == array2; } temp = []; - if ( (!array1[0]) || (!array2[0]) ) { - return false; - } if (array1.length != array2.length) { return false; } @@ -28,7 +25,7 @@ function arraysMatch(array1, array2) { return true; } -Array.prototype.map = function (property) { +Array.prototype.mapProperty = function (property) { return $.map(this, function (element) { return element[property]; }); @@ -78,9 +75,20 @@ function Wardrobe() { function Asset(newData) { var asset = this; + + function size_key(size) { + return size[0] + 'x' + size[1]; + } + + this.image_urls_by_size_key = {}; + var image; + for(var i = 0; i < newData.images.length; i++) { + image = newData.images[i]; + this.image_urls_by_size_key[size_key(image.size)] = image.url; + } this.imageURL = function (size) { - return Wardrobe.IMAGE_CONFIG.base_url + this.s3_path + "/" + size[0] + "x" + size[1] + ".png"; + return this.image_urls_by_size_key[size_key(size)]; } this.update = function (data) { @@ -267,16 +275,23 @@ function Wardrobe() { worn_item_ids = new_ids.worn; closet_item_ids = new_ids.unworn.concat(new_ids.worn); } + + function loadAttributes(data) { + outfit.color_id = data.color_id; + outfit.id = data.id; + outfit.name = data.name; + outfit.pet_state_id = data.pet_state_id; + outfit.starred = data.starred; + outfit.species_id = data.species_id; + outfit.image_versions = data.image_versions; + outfit.image_enqueued = data.image_enqueued; + outfit.image_layers_hash = data.image_layers_hash; + outfit.setWornAndUnwornItemIds(data.worn_and_unworn_item_ids); + new_record = false; + } if(typeof data != 'undefined') { - this.color_id = data.color_id; - this.id = data.id; - this.name = data.name; - this.pet_state_id = data.pet_state_id; - this.starred = data.starred; - this.species_id = data.species_id; - this.setWornAndUnwornItemIds(data.worn_and_unworn_item_ids); - new_record = false; + loadAttributes(data); } this.closet_items = []; @@ -327,11 +342,11 @@ function Wardrobe() { new_items = [], new_worn_item_ids = []; if(added_item) { // now that we've loaded, check for conflicts on the added item - item_zones = added_item.getAssetsFitting(outfit.pet_type).map('zone_id'); + item_zones = added_item.getAssetsFitting(outfit.pet_type).mapProperty('zone_id'); item_zones_length = item_zones.length; for(var i = 0; i < outfit.worn_items.length; i++) { existing_item = outfit.worn_items[i]; - existing_item_zones = existing_item.getAssetsFitting(outfit.pet_type).map('zone_id'); + existing_item_zones = existing_item.getAssetsFitting(outfit.pet_type).mapProperty('zone_id'); passed = true; if(existing_item != added_item) { for(var j = 0; j < item_zones_length; j++) { @@ -369,23 +384,6 @@ function Wardrobe() { } } - function sendUpdate(outfit_data, success, failure) { - $.ajax({ - url: '/outfits/' + outfit.id, - type: 'post', - data: {'_method': 'put', outfit: outfit_data}, - success: function () { - Outfit.cache[outfit.id] = outfit; - success(outfit); - }, - error: function (xhr) { - if(typeof failure !== 'undefined') { - failure(outfit, $.parseJSON(xhr.responseText)); - } - } - }); - } - this.closetItem = function (item, updateClosetItemsCallback) { if(!hasItemInCloset(item)) { this.closet_items.push(item); @@ -415,6 +413,14 @@ function Wardrobe() { }); return visible_assets; } + + this.isIdenticalTo = function (other) { + return other && // other exists + this.constructor == other.constructor && // other is an outfit + this.getPetStateId() == other.getPetStateId() && + arraysMatch(this.getWornItemIds(), other.getWornItemIds()) && + arraysMatch(this.getClosetItemIds(), other.getClosetItemIds()); + } this.rename = function (new_name, success, failure) { this.updateAttributes({name: new_name}, success, failure); @@ -522,6 +528,9 @@ function Wardrobe() { new_outfit.id = outfit.id; new_outfit.name = outfit.name; new_outfit.starred = outfit.starred; + new_outfit.image_enqueued = outfit.image_enqueued; + new_outfit.image_versions = outfit.image_versions; + new_outfit.image_layers_hash = outfit.image_layers_hash; return new_outfit; } @@ -539,6 +548,13 @@ function Wardrobe() { new_ids.unworn = base_ids.unworn.slice(0); outfit.setWornAndUnwornItemIds(new_ids); } + + function updateFromSaveResponse(data) { + outfit.id = data.id; + outfit.image_versions = data.image_versions; + outfit.image_enqueued = data.image_enqueued; + outfit.image_layers_hash = data.image_layers_hash; + } this.destroy = function (success) { $.ajax({ @@ -554,10 +570,11 @@ function Wardrobe() { url: '/outfits', type: 'post', data: {outfit: getAttributes()}, + dataType: 'json', success: function (data) { new_record = false; - outfit.id = data; - Outfit.cache[data] = outfit; + updateFromSaveResponse(data); + Outfit.cache[outfit.id] = outfit; success(outfit); }, error: function (xhr) { @@ -565,6 +582,32 @@ function Wardrobe() { } }); } + + this.reload = function (success) { + Outfit.load(this.id, function (new_outfit) { + loadAttributes(new_outfit); + success(outfit); + }); + } + + function sendUpdate(outfit_data, success, failure) { + $.ajax({ + url: '/outfits/' + outfit.id, + type: 'post', + data: {'_method': 'put', outfit: outfit_data}, + dataType: 'json', + success: function (data) { + updateFromSaveResponse(data); + Outfit.cache[outfit.id] = outfit; + success(outfit); + }, + error: function (xhr) { + if(typeof failure !== 'undefined') { + failure(outfit, $.parseJSON(xhr.responseText)); + } + } + }); + } this.updateAttributes = function (attributes, success, failure) { var outfit_data = {}; @@ -583,19 +626,23 @@ function Wardrobe() { if(typeof Outfit.cache[id] !== 'undefined') { callback(Outfit.cache[id]); } else { - $.ajax({ - url: '/outfits/' + id + '.json', - success: function (data) { - var outfit = new Outfit(data); - Outfit.cache[id] = outfit; - callback(outfit); - }, - error: function () { - callback(null); - } - }); + Outfit.load(id, callback); } } + + Outfit.load = function (id, callback) { + $.ajax({ + url: '/outfits/' + id + '.json', + success: function (data) { + var outfit = new Outfit(data); + Outfit.cache[id] = outfit; + callback(outfit); + }, + error: function () { + callback(null); + } + }); + } Outfit.loadForCurrentUser = function (success) { var outfits = []; @@ -788,8 +835,13 @@ function Wardrobe() { Controller.all = {}; - Controller.all.Outfit = function OutfitController() { - var controller = this, outfit = new Outfit; + Controller.all.Outfits = function OutfitsController() { + // TODO: clean up the merge of outfits and user controller. Some is already + // done, but I'm sure there's tons of redundant code still lying around. + + /* Current outfit management */ + + var controller = this, outfit = new Outfit, last_shared_outfit = null; this.in_transaction = false; @@ -862,6 +914,7 @@ function Wardrobe() { } outfit.create( function (outfit) { + insertOutfit(outfit); controller.events.trigger('saveSuccess', outfit); controller.events.trigger('createSuccess', outfit); controller.events.trigger('setOutfit', outfit); @@ -920,12 +973,24 @@ function Wardrobe() { } this.share = function () { - var sharedOutfit = outfit.clone(); - sharedOutfit.anonymous = true; - sharedOutfit.create( - controller.event('shareSuccess'), - controller.event('shareFailure') - ); + if(outfit.id) { + // If this is a user-saved outfit (user is logged in), no need to + // re-share it. Skip to using the current outfit. + controller.events.trigger('shareSkipped', outfit); + } else if(outfit.isIdenticalTo(last_shared_outfit)) { + // If the outfit hasn't changed since last time we shared it, no need to + // re-share it. Skip to using the last shared outfit. + controller.events.trigger('shareSkipped', last_shared_outfit); + } else { + // Otherwise, this is a fresh outfit that needs to be shared. Try, and + // report success or failure. + last_shared_outfit = outfit.clone(); + last_shared_outfit.anonymous = true; + last_shared_outfit.create( + controller.event('shareSuccess'), + controller.event('shareFailure') + ); + } } this.unclosetItem = function (item) { @@ -943,6 +1008,7 @@ function Wardrobe() { this.update = function () { outfit.update( function (outfit) { + updateUserOutfit(outfit); controller.events.trigger('saveSuccess', outfit), controller.events.trigger('updateSuccess', outfit) }, @@ -958,6 +1024,159 @@ function Wardrobe() { controller.event('updateItemAssets') ); } + + /* User outfits management */ + + var outfits = [], outfits_loaded = false; + + function compareOutfits(a, b) { + if(a.starred) { + if(!b.starred) return -1; + } else if(b.starred) { + return 1; + } + if(a.name < b.name) return -1; + else if(a.name == b.name) return 0; + else return 1; + } + + function insertOutfit(outfit) { + for(var i = 0; i < outfits.length; i++) { + if(compareOutfits(outfit, outfits[i]) < 0) { + outfits.splice(i, 0, outfit); + controller.events.trigger('addOutfit', outfit, i); + return; + } + } + controller.events.trigger('addOutfit', outfit, outfits.length); + outfits.push(outfit); + } + + function sortOutfits(outfits) { + outfits.sort(compareOutfits); + } + + function yankOutfit(outfit) { + var i; + for(i = 0; i < outfits.length; i++) { + if(outfit.id == outfits[i].id) { + outfits.splice(i, 1); + break; + } + } + controller.events.trigger('removeOutfit', outfit, i); + } + + this.destroyOutfit = function (outfit) { + outfit.destroy(function () { + yankOutfit(outfit); + }); + } + + this.loadOutfits = function () { + if(!outfits_loaded) { + Outfit.loadForCurrentUser(function (new_outfits) { + outfits = new_outfits; + outfits_loaded = true; + sortOutfits(outfits); + controller.events.trigger('outfitsLoaded', outfits); + }); + } + } + + this.renameOutfit = function (outfit, new_name) { + var old_name = outfit.name; + outfit.rename(new_name, function () { + yankOutfit(outfit); + insertOutfit(outfit); + controller.events.trigger('outfitRenamed', outfit); + }, function (outfit_copy, response) { + outfit.name = old_name; + controller.events.trigger('saveFailure', outfit_copy, response); + }); + } + + this.toggleOutfitStar = function (outfit) { + outfit.toggleStar(function () { + yankOutfit(outfit); + insertOutfit(outfit); + controller.events.trigger('outfitStarToggled', outfit); + }); + } + + function updateUserOutfit(outfit) { + for(var i = 0; i < outfits.length; i++) { + if(outfits[i].id == outfit.id) { + outfits[i] = outfit.clone(); + break; + } + } + } + } + + Controller.all.ImageSubscriptions = function ImagesSubscriptionsController() { + var outfitSubscriptionTotals = {}; + var DELAY = 5000; + var controller = this; + + function checkSubscription(outfit_id) { + Outfit.find(outfit_id, function (outfit) { + log("Checking image for", outfit); + outfit.reload(function () { + if(outfitSubscriptionTotals[outfit_id] > 0) { + if(outfit.image_enqueued) { + log("Outfit image still enqueued; will try again soon", outfit); + setTimeout(function () { checkSubscription(outfit_id) }, DELAY); + } else { + // Unsubscribe everyone from this outfit and fire ready events + delete outfitSubscriptionTotals[outfit_id]; + controller.events.trigger('imageReady', outfit); + } + } else { + log("Outfit was unsubscribed", outfit); + delete outfitSubscriptionTotals[outfit_id]; + } + }); + }); + } + + this.subscribe = function (outfit) { + if(outfit.image_enqueued) { + if(outfit.id in outfitSubscriptionTotals) { + // The subscription is already running. Just mark that one more + // consumer is interested in it, and they'll all get a response soon. + outfitSubscriptionTotals[outfit.id] += 1; + } else { + // This is a new subscription! Let's start checking it. + outfitSubscriptionTotals[outfit.id] = 1; + checkSubscription(outfit.id); + } + + // Regardless, trigger the enqueued event for the new consumer's sake. + controller.events.trigger('imageEnqueued', outfit); + } else { + // Otherwise, never bother checking: skip straight to the ready phase. + // Give it an instant timeout so that we're sure the consumer is ready + // for the event. (It can be tricky when the consumer assigns this + // return value somewhere to know if it cares about the event, so the + // event can't fire before the return.) + setTimeout(function () { + controller.events.trigger('imageReady', outfit) + }, 0); + } + + return outfit; + } + + this.unsubscribe = function (outfit) { + if(outfit && outfit.id in outfitSubscriptionTotals) { + if(outfitSubscriptionTotals[outfit.id] > 1) { + outfitSubscriptionTotals[outfit.id] -= 1; + } else { + delete outfitSubscriptionTotals[outfit.id]; + } + } + } } Controller.all.BasePet = function BasePetController() { @@ -1028,96 +1247,6 @@ function Wardrobe() { } } - Controller.all.User = function UserController() { - var controller = this, outfits = [], outfits_loaded = false; - - function compareOutfits(a, b) { - if(a.starred) { - if(!b.starred) return -1; - } else if(b.starred) { - return 1; - } - if(a.name < b.name) return -1; - else if(a.name == b.name) return 0; - else return 1; - } - - function insertOutfit(outfit) { - for(var i = 0; i < outfits.length; i++) { - if(compareOutfits(outfit, outfits[i]) < 0) { - outfits.splice(i, 0, outfit); - controller.events.trigger('addOutfit', outfit, i); - return; - } - } - controller.events.trigger('addOutfit', outfit, outfits.length); - outfits.push(outfit); - } - - function sortOutfits(outfits) { - outfits.sort(compareOutfits); - } - - function yankOutfit(outfit) { - var i; - for(i = 0; i < outfits.length; i++) { - if(outfit.id == outfits[i].id) { - outfits.splice(i, 1); - break; - } - } - controller.events.trigger('removeOutfit', outfit, i); - } - - this.addOutfit = insertOutfit; - - this.destroyOutfit = function (outfit) { - outfit.destroy(function () { - yankOutfit(outfit); - }); - } - - this.loadOutfits = function () { - if(!outfits_loaded) { - Outfit.loadForCurrentUser(function (new_outfits) { - outfits = new_outfits; - outfits_loaded = true; - sortOutfits(outfits); - controller.events.trigger('outfitsLoaded', outfits); - }); - } - } - - this.renameOutfit = function (outfit, new_name) { - var old_name = outfit.name; - outfit.rename(new_name, function () { - yankOutfit(outfit); - insertOutfit(outfit); - controller.events.trigger('outfitRenamed', outfit); - }, function (outfit_copy, response) { - outfit.name = old_name; - controller.events.trigger('saveFailure', outfit_copy, response); - }); - } - - this.toggleOutfitStar = function (outfit) { - outfit.toggleStar(function () { - yankOutfit(outfit); - insertOutfit(outfit); - controller.events.trigger('outfitStarToggled', outfit); - }); - } - - this.updateOutfit = function (outfit) { - for(var i = 0; i < outfits.length; i++) { - if(outfits[i].id == outfit.id) { - outfits[i] = outfit.clone(); - break; - } - } - } - } - var underscored_name; for(var name in Controller.all) { @@ -1196,13 +1325,13 @@ Wardrobe.getStandardView = function (options) { var outfit_events = ['updateWornItems', 'updateClosetItems', 'updateItemAssets', 'updatePetType', 'updatePetState']; for(var i = 0; i < outfit_events.length; i++) { (function (event) { - wardrobe.outfit.bind(event, function (obj) { + wardrobe.outfits.bind(event, function (obj) { log(event, obj); }); })(outfit_events[i]); } - wardrobe.outfit.bind('petTypeNotFound', function (pet_type) { + wardrobe.outfits.bind('petTypeNotFound', function (pet_type) { log(pet_type.toString() + ' not found'); }); } @@ -1246,7 +1375,7 @@ Wardrobe.getStandardView = function (options) { var assets, assets_for_swf; if(update_pending_flash) return false; if(preview_swf && preview_swf.setAssets) { - assets = wardrobe.outfit.getVisibleAssets(); + assets = wardrobe.outfits.getVisibleAssets(); preview_swf.setAssets(assets); } else { update_pending_flash = true; @@ -1303,10 +1432,11 @@ Wardrobe.getStandardView = function (options) { // Get a copy of the visible assets, then sort them in ascending zone // order. - var assets = wardrobe.outfit.getVisibleAssets().slice(0); + var assets = wardrobe.outfits.getVisibleAssets().slice(0); assets.sort(function (a, b) { return a.depth - b.depth; }); + console.log(assets.mapProperty('id'));return; for(var i = 0; i < assets.length; i++) { url += "," + encodeURIComponent(assets[i].imageURL(size)); @@ -1316,7 +1446,7 @@ Wardrobe.getStandardView = function (options) { } this.updateAssets = function () { - var assets = wardrobe.outfit.getVisibleAssets(), asset, + var assets = wardrobe.outfits.getVisibleAssets(), asset, availableAssets = []; pendingAssets = {}; pendingAssetsCount = 0; @@ -1375,10 +1505,9 @@ Wardrobe.getStandardView = function (options) { for(var i in sizes) { if(!sizes.hasOwnProperty(i)) continue; size = sizes[i]; - size[2] = size[0] * size[1]; inserted = false; for(var i in SIZES_SMALL_TO_LARGE) { - if(SIZES_SMALL_TO_LARGE[i][2] > size[2]) { + if(SIZES_SMALL_TO_LARGE[i][0] * SIZES_SMALL_TO_LARGE[i][1] > size[0] * size[1]) { SIZES_SMALL_TO_LARGE.splice(i, 0, size); inserted = true; break; @@ -1476,9 +1605,9 @@ Wardrobe.getStandardView = function (options) { preview.adapter.updateAssets(); } - wardrobe.outfit.bind('updateWornItems', updateAssets); - wardrobe.outfit.bind('updateItemAssets', updateAssets); - wardrobe.outfit.bind('updatePetState', updateAssets); + wardrobe.outfits.bind('updateWornItems', updateAssets); + wardrobe.outfits.bind('updateItemAssets', updateAssets); + wardrobe.outfits.bind('updatePetState', updateAssets); function useAdapter(name) { preview.adapter = new Adapter[name](); diff --git a/public/images/outfit/.gitignore b/public/outfits/.gitignore similarity index 100% rename from public/images/outfit/.gitignore rename to public/outfits/.gitignore diff --git a/public/outfits/000/19/medium_thumb.png b/public/outfits/000/19/medium_thumb.png new file mode 100644 index 00000000..bc78be54 Binary files /dev/null and b/public/outfits/000/19/medium_thumb.png differ diff --git a/public/outfits/000/19/small_thumb.png b/public/outfits/000/19/small_thumb.png new file mode 100644 index 00000000..9acc38bd Binary files /dev/null and b/public/outfits/000/19/small_thumb.png differ diff --git a/public/outfits/000/19/thumb.png b/public/outfits/000/19/thumb.png new file mode 100644 index 00000000..97788429 Binary files /dev/null and b/public/outfits/000/19/thumb.png differ diff --git a/public/stylesheets/compiled/screen.css b/public/stylesheets/compiled/screen.css index a090de48..b8072c63 100644 --- a/public/stylesheets/compiled/screen.css +++ b/public/stylesheets/compiled/screen.css @@ -2046,12 +2046,12 @@ body.items-show.js #trade-hangers p.showing-more { } @import url(../shared/jquery.jgrowl.css); -/* line 113, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 49, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-toolbar { margin-bottom: 0.5em; text-align: left; } -/* line 116, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 52, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-toolbar form { display: -moz-inline-box; -moz-box-orient: vertical; @@ -2064,23 +2064,23 @@ body.outfits-edit #preview-toolbar form { body.outfits-edit #preview-toolbar form { *display: inline; } -/* line 119, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 55, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-info form { display: inline; } -/* line 122, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 58, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-state-form ul { list-style: none; } -/* line 124, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 60, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-state-form ul, body.outfits-edit #pet-state-form ul li { display: inline; } -/* line 126, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 62, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-state-form input { display: none; } -/* line 128, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 64, ../../../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; @@ -2116,7 +2116,7 @@ body.outfits-edit #pet-state-form label:hover { body.outfits-edit #pet-state-form label:active { top: 1px; } -/* line 131, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 67, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-state-form li.selected button { background: #0b61a4 url('/images/alert-overlay.png?1315327995') repeat-x; } @@ -2124,75 +2124,75 @@ body.outfits-edit #pet-state-form li.selected button { body.outfits-edit #pet-state-form li.selected button:hover { background-color: #005093; } -/* line 133, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 69, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #pet-state-form.hidden { visibility: hidden; } -/* line 135, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 71, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper { float: right; } -/* line 137, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 73, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper button { display: none; } -/* line 139, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 75, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper #share-outfit { display: inline-block; } -/* line 141, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 77, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-outfit-wrapper.loading { background-image: url('/images/loading.gif?1315327995'); background-position: left center; background-repeat: no-repeat; padding-left: 20px; } -/* 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 { +/* line 83, ../../../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-finish { background: #ff5c00 url('/images/alert-overlay.png?1315327995') repeat-x; } /* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ -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 { +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-finish:hover { background-color: #ee4b00; } -/* line 149, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 85, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #current-outfit-permalink, body.outfits-edit #shared-outfit-permalink { display: none; margin-right: 0.25em; } -/* line 152, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 88, ../../../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 154, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 90, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #shared-outfit-url { display: none; width: 15em; } -/* line 157, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 93, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview { clear: both; } -/* line 159, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 95, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-swf { float: left; - height: 400px; + height: 380px; margin-bottom: 1em; position: relative; - width: 400px; + width: 380px; } -/* line 166, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 102, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-swf.swf-adapter #preview-image-container { display: none; } -/* line 169, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 105, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-swf.image-adapter #preview-swf-container { display: none; } -/* line 171, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 107, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-image-container { position: relative; } @@ -2202,12 +2202,12 @@ body.outfits-edit #preview-image-container img { position: absolute; top: 0; } -/* line 174, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 110, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-image-container, body.outfits-edit #preview-image-container img { height: 100%; width: 100%; } -/* line 177, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 113, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-swf-overlay { -moz-opacity: 0; -webkit-opacity: 0; @@ -2220,7 +2220,7 @@ body.outfits-edit #preview-swf-overlay { top: 0; width: 100%; } -/* line 185, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 121, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-images-pending { background: black; background: rgba(0, 0, 0, 0.75); @@ -2232,11 +2232,11 @@ body.outfits-edit #preview-images-pending { right: 0; z-index: 1000; } -/* line 195, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 131, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-images-pending.waiting-on-0 { display: none; } -/* line 197, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 133, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode { margin-right: 1em; position: absolute; @@ -2245,25 +2245,21 @@ body.outfits-edit #preview-mode { top: 0; width: 7em; } -/* line 205, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 141, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode.flash-active #preview-mode-flash { color: #004400; font-weight: bold; } -/* line 208, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 144, ../../../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 */ -body.outfits-edit #preview-mode.image-active #report-broken-image { +/* line 146, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-mode.image-active #preview-mode-note, body.outfits-edit #preview-mode.image-active #report-broken-image { display: block; } -/* line 213, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-mode.image-active.can-download #preview-download-image { - display: inline-block; -} -/* line 215, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 154, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode-toggle { -moz-border-radius: 0.5em; -webkit-border-radius: 0.5em; @@ -2279,37 +2275,37 @@ body.outfits-edit #preview-mode-toggle { text-align: center; width: 5em; } -/* line 224, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 163, ../../../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 229, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 168, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode-toggle li:first-child { border-top: 0; } -/* line 231, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 170, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-download-image { display: none; margin: 1em auto; } -/* line 234, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 173, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-download-image h3 { font-size: 125%; margin-bottom: 0.5em; } -/* line 237, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 176, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-download-image ul { list-style: none; } -/* line 239, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 178, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-download-image button { font-size: 75%; width: 100%; } -/* line 242, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 181, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode-note, body.outfits-edit #report-broken-image { display: block; font-size: 75%; @@ -2318,98 +2314,84 @@ body.outfits-edit #preview-mode-note, body.outfits-edit #report-broken-image { text-decoration: none; width: 100%; } -/* line 249, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 188, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-mode-note em, body.outfits-edit #report-broken-image em { font-style: normal; text-decoration: underline; } -/* line 252, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #report-broken-image { +/* line 191, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-mode-note, body.outfits-edit #report-broken-image { display: none; } -/* line 254, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 194, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar { - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - -o-border-radius: 10px; - -ms-border-radius: 10px; - -khtml-border-radius: 10px; - border-radius: 10px; - border: 1px solid #aaddaa; float: left; - height: 400px; + height: 380px; margin-left: 20px; margin-bottom: 1em; - overflow: auto; - width: 378px; + width: 400px; } -/* line 264, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 201, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar.viewing-outfits #preview-closet { display: none; } -/* line 266, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 203, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar.viewing-outfits #preview-outfits { display: block; } -/* line 268, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-sidebar.viewing-saving-outfit { - height: auto; - max-height: 100%; -} -/* line 271, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-sidebar.viewing-saving-outfit #preview-closet { +/* line 206, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sidebar.sharing #preview-closet { display: none; } -/* line 273, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-sidebar.viewing-saving-outfit #preview-saving-outfit { +/* line 208, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sidebar.sharing #preview-sharing { display: block; } -/* line 276, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-sidebar .sidebar-view h2 { - margin-bottom: 0.25em; - margin-left: 24px; +/* line 210, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sidebar .sidebar-view { + margin: 1.5em 0; } -/* line 281, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 213, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet h2 { margin-bottom: 0; } -/* line 283, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 215, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet ul { text-align: center; } -/* line 285, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 217, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object { background: #eeffee; } -/* line 287, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 219, ../../../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 289, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 221, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object.worn { background: transparent; } -/* line 291, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 223, ../../../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 293, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 225, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object.no-assets { background: #fbe3e4; color: #8a1f11; padding-bottom: 1.25em; } -/* line 297, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 229, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-closet .object.no-assets .no-assets-message { display: block; } -/* line 299, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 231, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .no-assets-message { background: #f3dbdc; bottom: 0; @@ -2421,7 +2403,7 @@ body.outfits-edit .no-assets-message { position: absolute; width: 100%; } -/* line 309, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 241, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #no-assets-full-message { -moz-border-radius: 5px; -webkit-border-radius: 5px; @@ -2439,12 +2421,12 @@ body.outfits-edit #no-assets-full-message { top: -9999px; width: 30em; } -/* line 320, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 252, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form { clear: both; text-align: left; } -/* line 323, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 255, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form h2 { display: -moz-inline-box; -moz-box-orient: vertical; @@ -2457,7 +2439,7 @@ body.outfits-edit #preview-search-form h2 { body.outfits-edit #preview-search-form h2 { *display: inline; } -/* line 326, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 258, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form input { display: -moz-inline-box; -moz-box-orient: vertical; @@ -2469,17 +2451,17 @@ body.outfits-edit #preview-search-form input { body.outfits-edit #preview-search-form input { *display: inline; } -/* line 328, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 260, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form input[type=submit] { margin-right: 2em; } -/* line 330, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 262, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .preview-search-form-your-items { display: none; font-size: 85%; margin-right: 1em; } -/* line 334, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 266, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-pagination { display: -moz-inline-box; -moz-box-orient: vertical; @@ -2491,53 +2473,53 @@ body.outfits-edit #preview-search-form-pagination { body.outfits-edit #preview-search-form-pagination { *display: inline; } -/* line 336, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 268, ../../../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 338, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 270, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-pagination .current { font-weight: bold; } -/* line 340, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 272, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-clear { display: none; font-size: 87.5%; margin-left: 2em; } -/* line 344, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 276, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-loading { display: none; font-size: 75%; font-style: italic; margin-left: 2em; } -/* line 350, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 282, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-no-results { display: none; } -/* line 352, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 284, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-search-form-help { font-size: 87.5%; margin-left: 2em; } -/* line 355, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 287, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .search-helper { font-family: inherit; } -/* line 357, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 289, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .possible-error { display: none; } -/* line 360, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 292, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #fullscreen-copyright { display: none; } -/* line 362, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 294, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen { height: 100%; } -/* line 365, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 297, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #container { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; @@ -2550,32 +2532,31 @@ body.outfits-edit.fullscreen #container { position: relative; width: 80%; } -/* line 373, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 305, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen h1 { display: none; } -/* line 375, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 307, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #short-url-response { position: static; } -/* line 377, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 309, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview { width: 100%; } -/* line 379, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 311, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-sidebar { float: right; - height: 100%; margin: 0; position: relative; width: 400px; } -/* line 385, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 316, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-sidebar.viewing-saving-outfit { height: auto; max-height: 100%; } -/* line 388, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 319, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-search-form { bottom: 1.5em; left: 0; @@ -2584,7 +2565,7 @@ body.outfits-edit.fullscreen #preview-search-form { position: absolute; width: 100%; } -/* line 396, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 327, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #preview-search-form-help div { display: -moz-inline-box; -moz-box-orient: vertical; @@ -2597,27 +2578,27 @@ body.outfits-edit.fullscreen #preview-search-form-help div { body.outfits-edit.fullscreen #preview-search-form-help div { *display: inline; } -/* line 399, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 330, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #footer { bottom: 0; left: 0; position: absolute; width: 100%; } -/* line 404, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 335, ../../../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 406, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 337, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit.fullscreen #footer ul { margin-right: 2em; } -/* line 409, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 340, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object { padding: 6px; position: relative; } -/* line 412, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 343, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object ul { display: none; left: 0; @@ -2625,11 +2606,11 @@ body.outfits-edit .object ul { position: absolute; top: 0; } -/* line 418, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 349, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object ul li { margin-bottom: 0.25em; } -/* line 420, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 351, ../../../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; @@ -2674,11 +2655,11 @@ body.outfits-edit .object ul li a:active { body.outfits-edit .object ul li a:hover { background-color: #999999; } -/* line 423, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 354, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object:hover ul, body.outfits-edit .object:hover .object-info { display: block; } -/* line 430, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 361, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .nc-icon { background: url('/images/nc.png?1315327995') no-repeat; height: 16px; @@ -2688,14 +2669,14 @@ body.outfits-edit .nc-icon { top: 64px; width: 16px; } -/* line 438, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 369, ../../../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 441, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 372, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object-info { -moz-border-radius: 12px; -webkit-border-radius: 12px; @@ -2716,39 +2697,52 @@ body.outfits-edit .object-info { top: 0; width: 16px; } -/* line 452, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 383, ../../../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 458, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 389, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .object-info:hover { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; } -/* line 461, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 392, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits { display: none; text-align: left; } -/* line 464, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 399, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul { + font-size: 0; + list-style: none; margin-left: 24px; margin-right: 24px; background: url('/images/loading.gif?1315327995') no-repeat center top; - display: block; + display: none; font-family: "Droid Sans", Helvetica, Arial, Verdana, sans-serif; - list-style: none; - margin-bottom: 1em; + margin: 0 auto 1em; min-height: 16px; + width: 336px; } -/* line 473, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 25, ../../../app/stylesheets/partials/_outfit.sass */ body.outfits-edit #preview-outfits > ul > li { - padding: 0.25em 0; + display: -moz-inline-box; + -moz-box-orient: vertical; + display: inline-block; + vertical-align: middle; + *vertical-align: auto; + overflow: hidden; + position: relative; + font-size: 14px; +} +/* line 7, ../../../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/css3/_inline-block.scss */ +body.outfits-edit #preview-outfits > ul > li { + *display: inline; } /* line 4, ../../../app/stylesheets/outfits/_star.sass */ body.outfits-edit #preview-outfits > ul > li .outfit-star { @@ -2772,175 +2766,499 @@ body.outfits-edit #preview-outfits > ul > li.starred .outfit-star { body.outfits-edit #preview-outfits > ul > li.loading .outfit-star { background-image: url('/images/loading.gif?1315327995'); } -/* line 18, ../../../app/stylesheets/outfits/_star.sass */ -body.outfits-edit #preview-outfits > ul > li.loading.active .outfit-star { - background-image: url('/images/loading_current_outfit.gif?1315327995'); -} -/* line 24, ../../../app/stylesheets/outfits/_star.sass */ -body.outfits-edit #preview-outfits > ul > li .outfit-star { - margin-left: -24px; - margin-right: 0; -} -/* line 38, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li img { - height: 100px; - left: -25px; +/* line 7, ../../../app/stylesheets/partials/_outfit.sass */ +body.outfits-edit #preview-outfits > ul > li header, body.outfits-edit #preview-outfits > ul > li footer { + color: white; + left: 0; position: absolute; - top: -25px; - width: 100px; + z-index: 2; + background: black; + background: rgba(0, 0, 0, 0.75); } -/* line 44, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li .outfit-delete { - -moz-border-radius: 0; - -webkit-border-radius: 0; - -o-border-radius: 0; - -ms-border-radius: 0; - -khtml-border-radius: 0; - border-radius: 0; - background: transparent; - display: inline; - padding: 0; - color: inherit; - -moz-box-shadow: none; - -webkit-box-shadow: none; - text-shadow: none; - border-bottom: 0; - position: static; - font-weight: normal; - line-height: inherit; - -moz-opacity: 0.5; - -webkit-opacity: 0.5; - -o-opacity: 0.5; - -khtml-opacity: 0.5; - font-size: 150%; - float: right; - line-height: 1; - margin-top: -0.125em; - padding: 0.125em 0.25em; -} -/* line 72, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.outfits-edit #preview-outfits > ul > li .outfit-delete:hover { - background: transparent; - color: inherit; -} -/* line 75, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.outfits-edit #preview-outfits > ul > li .outfit-delete:active { - top: auto; -} -/* line 52, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li .outfit-delete:hover { - -moz-opacity: 1; - -webkit-opacity: 1; - -o-opacity: 1; - -khtml-opacity: 1; - background: #eeffee; -} -/* line 55, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 11, ../../../app/stylesheets/partials/_outfit.sass */ body.outfits-edit #preview-outfits > ul > li header { - display: block; - padding-left: 24px; + bottom: 0; } -/* line 58, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li h4 { - cursor: pointer; - display: inline; +/* line 14, ../../../app/stylesheets/partials/_outfit.sass */ +body.outfits-edit #preview-outfits > ul > li footer { + top: 0; } -/* line 61, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li h4:hover { - text-decoration: underline; +/* line 17, ../../../app/stylesheets/partials/_outfit.sass */ +body.outfits-edit #preview-outfits > ul > li a { + color: white; } -/* 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 409, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul.loaded { + background: transparent; } -/* 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 412, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li { + height: 110px; + margin: 1px; + width: 110px; } -/* line 67, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li .outfit-rename-button { +/* line 422, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li header, body.outfits-edit #preview-outfits > ul > li footer, body.outfits-edit #preview-outfits > ul > li .outfit-delete-confirmation { + font-size: 12px; + padding: 2px 4px; + width: 102px; +} +/* line 427, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li header { -moz-opacity: 0.75; -webkit-opacity: 0.75; -o-opacity: 0.75; -khtml-opacity: 0.75; - font-size: 75%; - margin-left: 1em; + bottom: 0; + cursor: pointer; } -/* line 71, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li .outfit-url { +/* line 432, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li footer, body.outfits-edit #preview-outfits > ul > li .outfit-delete-confirmation { + display: none; +} +/* line 435, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li .outfit-delete-confirmation { + color: white; + left: 0; + position: absolute; + z-index: 2; + background: #ff3232; + background: rgba(255, 50, 50, 0.75); + text-align: center; + top: 0; +} +/* line 441, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li .outfit-delete-confirmation span { + font-weight: bold; +} +/* line 447, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li .outfit-thumbnail-wrapper { -moz-opacity: 0.5; -webkit-opacity: 0.5; -o-opacity: 0.5; -khtml-opacity: 0.5; - background: transparent; - border-width: 0; - width: 284px; + background-image: url(/images/outfits/small_default.png); + background-position: center center; + background-size: 110px 110px; + cursor: pointer; + height: 150px; + left: -20px; + position: absolute; + top: -24px; + width: 150px; + z-index: 1; } -/* line 76, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li .outfit-url:hover { +/* line 461, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li .outfit-thumbnail { + display: none; +} +/* line 464, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li .outfit-star { + bottom: 0; + margin-right: 4px; +} +/* line 468, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li .outfit-delete { + float: right; +} +/* line 471, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li .outfit-rename-button { + float: left; +} +/* line 474, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li .outfit-rename-button, body.outfits-edit #preview-outfits > ul > li .outfit-delete { + font-size: 85%; + text-decoration: none; +} +/* line 478, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li .outfit-rename-button:hover, body.outfits-edit #preview-outfits > ul > li .outfit-delete:hover { + text-decoration: underline; +} +/* line 481, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li .outfit-rename-form { + display: none; +} +/* line 484, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li .outfit-rename-form input { + background: transparent; + border: 1px solid white; + width: 6em; +} +/* line 490, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li:hover header { -moz-opacity: 1; -webkit-opacity: 1; -o-opacity: 1; -khtml-opacity: 1; - border-width: 1px; } -/* line 79, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li .outfit-delete-confirmation { - display: none; - font-size: 75%; +/* line 493, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li:hover .outfit-thumbnail { + -moz-opacity: 0.75; + -webkit-opacity: 0.75; + -o-opacity: 0.75; + -khtml-opacity: 0.75; } -/* line 82, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li .outfit-delete-confirmation span { - color: red; +/* line 496, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li:hover footer { + display: block; } -/* line 84, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li .outfit-delete-confirmation a { - margin: 0 0.25em; +/* line 500, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li.active header { + -moz-opacity: 1; + -webkit-opacity: 1; + -o-opacity: 1; + -khtml-opacity: 1; + font-weight: bold; } -/* line 86, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li.active { - background: #eeffee; +/* line 504, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li.active .outfit-thumbnail { + -moz-opacity: 1; + -webkit-opacity: 1; + -o-opacity: 1; + -khtml-opacity: 1; } -/* line 89, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li.confirming-deletion .outfit-delete { - visibility: hidden; -} -/* line 91, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li.confirming-deletion .outfit-url { +/* line 508, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li.confirming-deletion footer { display: none; } -/* line 93, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 511, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li.confirming-deletion .outfit-delete-confirmation { display: block; } -/* line 96, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li.renaming h4 { +/* line 515, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li.renaming .outfit-name { display: none; } -/* line 98, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 518, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-outfits > ul > li.renaming .outfit-rename-form { display: inline; } -/* line 101, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li.renaming:hover .outfit-rename-button { - display: none; -} -/* line 104, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul > li:hover .outfit-rename-button { - display: inline; -} -/* line 475, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-outfits > ul.loaded { +/* line 521, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li.thumbnail-available { background: transparent; } -/* line 478, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 524, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li.thumbnail-available .outfit-thumbnail-wrapper { + background-image: none; +} +/* line 527, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li.thumbnail-available .outfit-thumbnail { + display: block; +} +/* line 531, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits > ul > li.loading .outfit-star { + background-image: url('/images/loading_outfit_pane.gif?1343373151'); +} +/* line 534, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits #preview-outfits-not-logged-in { + text-align: center; + overflow-x: hidden; +} +/* line 538, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits #preview-outfits-not-logged-in img { + border-color: #006600; + border-style: solid; + border-width: 1px 0; +} +/* line 544, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits #preview-outfits-not-logged-in figure { + display: block; + margin: 0 0 1em 0; + padding: 0; +} +/* line 549, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits #preview-outfits-not-logged-in figcaption { + display: block; + font-weight: bold; +} +/* line 553, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits #preview-outfits-not-logged-in p { + margin-left: 24px; + margin-right: 24px; + font-size: 85%; +} +/* line 557, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-outfits #preview-outfits-not-logged-in #preview-outfits-log-in { + /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -o-border-radius: 5px; + -ms-border-radius: 5px; + -khtml-border-radius: 5px; + border-radius: 5px; + background: #006400 url('/images/alert-overlay.png?1315327995') 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?1315327995') repeat-x; +} +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.outfits-edit #preview-outfits #preview-outfits-not-logged-in #preview-outfits-log-in:hover { + background-color: #005300; +} +/* line 53, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.outfits-edit #preview-outfits #preview-outfits-not-logged-in #preview-outfits-log-in:hover { + color: white; +} +/* line 55, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.outfits-edit #preview-outfits #preview-outfits-not-logged-in #preview-outfits-log-in:active { + top: 1px; +} +/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.outfits-edit #preview-outfits #preview-outfits-not-logged-in #preview-outfits-log-in:hover { + background-color: #ee4b00; +} +/* line 561, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing { + display: none; +} +/* line 564, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-urls { + margin-left: 24px; + margin-right: 24px; + display: none; + margin-bottom: 1em; + margin-top: 1em; +} +/* line 571, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-urls li { + display: block; + padding: 0.25em 0; + width: 100%; +} +/* line 576, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-urls li label { + display: block; + font-weight: bold; +} +/* line 580, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-urls li input { + display: block; + width: 100%; +} +/* line 584, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-url-formats { + margin-left: 24px; + margin-right: 24px; + select: none; + -moz-user-select: none; + -webkit-user-select: none; + -khtml-user-select: none; + user-select: none; + display: none; + font-size: 0; + text-align: center; +} +/* line 592, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-url-formats li { + display: -moz-inline-box; + -moz-box-orient: vertical; + display: inline-block; + vertical-align: middle; + *vertical-align: auto; + border: 1px solid #006600; + border-left-width: 0; + border-right-color: #aaddaa; + color: #448844; + cursor: pointer; + font-size: 12px; + padding: 0 2em; +} +/* line 7, ../../../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/css3/_inline-block.scss */ +body.outfits-edit #preview-sharing #preview-sharing-url-formats li { + *display: inline; +} +/* line 603, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-url-formats li.active { + background: #eeffee; + color: inherit; + font-weight: bold; +} +/* line 608, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-url-formats li:first-child { + -moz-border-radius-topleft: 5px; + -webkit-border-top-left-radius: 5px; + -o-border-top-left-radius: 5px; + -ms-border-top-left-radius: 5px; + -khtml-border-top-left-radius: 5px; + border-top-left-radius: 5px; + -moz-border-radius-bottomleft: 5px; + -webkit-border-bottom-left-radius: 5px; + -o-border-bottom-left-radius: 5px; + -ms-border-bottom-left-radius: 5px; + -khtml-border-bottom-left-radius: 5px; + border-bottom-left-radius: 5px; + border-left-width: 1px; +} +/* line 613, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-url-formats li:last-child { + -moz-border-radius-topright: 5px; + -webkit-border-top-right-radius: 5px; + -o-border-top-right-radius: 5px; + -ms-border-top-right-radius: 5px; + -khtml-border-top-right-radius: 5px; + border-top-right-radius: 5px; + -moz-border-radius-bottomright: 5px; + -webkit-border-bottom-right-radius: 5px; + -o-border-bottom-right-radius: 5px; + -ms-border-bottom-right-radius: 5px; + -khtml-border-bottom-right-radius: 5px; + border-bottom-right-radius: 5px; + border-right-color: #006600; +} +/* line 618, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-thumbnail-wrapper { + border: 1px solid #aaddaa; + display: block; + height: 150px; + margin: 1em auto 0; + position: relative; + width: 150px; +} +/* line 626, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-thumbnail-loading { + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; +} +/* line 633, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-thumbnail-loading span { + color: #448844; + font-size: 85%; + margin-top: -0.75em; + position: absolute; + text-align: center; + top: 50%; + width: 100%; +} +/* line 642, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-thumbnail, body.outfits-edit #preview-sharing #preview-sharing-thumbnail-generating { + display: none; +} +/* line 645, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing #preview-sharing-beta-note { + margin-left: 24px; + margin-right: 24px; + background: #fff6bf; + border: 1px solid #ffd324; + color: #514721; + font-size: 85%; + margin-top: 1em; + text-align: center; +} +/* line 653, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing.urls-loaded #preview-sharing-thumbnail-saving { + display: none; +} +/* line 656, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing.urls-loaded #preview-sharing-urls, body.outfits-edit #preview-sharing.urls-loaded #preview-sharing-url-formats, body.outfits-edit #preview-sharing.urls-loaded #preview-sharing-thumbnail-generating { + display: block; +} +/* line 660, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing.urls-loaded.thumbnail-loaded #preview-sharing-thumbnail-loading { + display: none; +} +/* line 663, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing.urls-loaded.thumbnail-loaded #preview-sharing-thumbnail { + display: block; +} +/* line 667, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing.urls-loaded.thumbnail-available #preview-sharing-thumbnail-loading { + -moz-opacity: 0.85; + -webkit-opacity: 0.85; + -o-opacity: 0.85; + -khtml-opacity: 0.85; +} +/* line 670, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sharing.urls-loaded.thumbnail-available #preview-sharing-thumbnail { + display: block; +} +/* line 673, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .preview-sidebar-nav { float: right; font-size: 85%; margin-right: 24px; margin-top: 1em; } -/* line 485, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 685, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sidebar #preview-sidebar-navbar-closet { + background: white; + border-bottom-color: white; + font-weight: bold; +} +/* line 689, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sidebar.viewing-outfits #preview-sidebar-navbar-closet, body.outfits-edit #preview-sidebar.sharing #preview-sidebar-navbar-closet { + background: transparent; + border-bottom: 1px solid #aaddaa; + font-weight: normal; +} +/* line 692, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sidebar.viewing-outfits #preview-sidebar-navbar-outfits, body.outfits-edit #preview-sidebar.sharing #preview-sidebar-navbar-sharing { + background: white; + border-bottom-color: white; + font-weight: bold; +} +/* line 695, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sidebar-navbar { + -moz-border-radius: 10px 10px 0 0; + -webkit-border-radius: 10px 10px 0 0; + -o-border-radius: 10px 10px 0 0; + -ms-border-radius: 10px 10px 0 0; + -khtml-border-radius: 10px 10px 0 0; + border-radius: 10px 10px 0 0; + overflow: hidden; + display: inline-block; + font-family: Delicious, Helvetica, Arial, Verdana, sans-serif; + background: #eeffee; + border: 1px solid #aaddaa; + border-bottom: 0; + font-size: 150%; +} +/* line 8, ../../../app/stylesheets/partials/clean/_mixins.sass */ +body.outfits-edit #preview-sidebar-navbar { + display: block; +} +/* line 704, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sidebar-navbar > div { + background: transparent; + border-bottom: 1px solid #aaddaa; + font-weight: normal; + cursor: pointer; + float: left; + border-left: 1px solid #aaddaa; + padding: 0.5em 0; + text-align: center; + width: 132px; +} +/* line 713, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sidebar-navbar > div:first-child { + border-left: 0; +} +/* line 716, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-sidebar-content { + -moz-border-radius: 0 0 10px 10px; + -webkit-border-radius: 0 0 10px 10px; + -o-border-radius: 0 0 10px 10px; + -ms-border-radius: 0 0 10px 10px; + -khtml-border-radius: 0 0 10px 10px; + border-radius: 0 0 10px 10px; + border: 1px solid #aaddaa; + border-top: 0; + height: 300px; + overflow: auto; +} +/* line 723, ../../../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; @@ -2948,7 +3266,7 @@ body.outfits-edit #save-success, body.outfits-edit #save-error, body.outfits-edi margin-top: 1em; text-align: center; } -/* line 492, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 730, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar-donation-request { background: #e6efc2; border: 1px solid #c6d880; @@ -2956,23 +3274,23 @@ body.outfits-edit #preview-sidebar-donation-request { font-size: 85%; padding: 1em; } -/* line 497, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 735, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar-donation-request-no-thanks { margin-left: 1em; } -/* line 500, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 738, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #save-success { background: #e6efc2; border: 1px solid #c6d880; color: #264409; } -/* line 503, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 741, ../../../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 506, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 744, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #userbar-message { -moz-opacity: 0.5; -webkit-opacity: 0.5; @@ -2980,219 +3298,16 @@ body.outfits-edit #userbar-message { -khtml-opacity: 0.5; display: none; } -/* line 510, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit { - padding: 0.25em 0; - margin-left: 24px; - margin-right: 24px; - display: none; -} -/* line 4, ../../../app/stylesheets/outfits/_star.sass */ -body.outfits-edit #new-outfit .outfit-star { - bottom: -2px; - height: 16px; - position: relative; - width: 16px; - background-image: url('/images/unstarred.png?1315327995'); - background-position: left top; - background-repeat: no-repeat; - cursor: pointer; - display: block; - float: left; - margin-right: 8px; -} -/* line 14, ../../../app/stylesheets/outfits/_star.sass */ -body.outfits-edit #new-outfit.starred .outfit-star { - background-image: url('/images/star.png?1315327995'); -} -/* line 16, ../../../app/stylesheets/outfits/_star.sass */ -body.outfits-edit #new-outfit.loading .outfit-star { - background-image: url('/images/loading.gif?1315327995'); -} -/* line 18, ../../../app/stylesheets/outfits/_star.sass */ -body.outfits-edit #new-outfit.loading.active .outfit-star { - background-image: url('/images/loading_current_outfit.gif?1315327995'); -} -/* line 24, ../../../app/stylesheets/outfits/_star.sass */ -body.outfits-edit #new-outfit .outfit-star { - margin-left: -24px; - margin-right: 0; -} -/* line 38, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit img { - height: 100px; - left: -25px; - position: absolute; - top: -25px; - width: 100px; -} -/* line 44, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit .outfit-delete { - -moz-border-radius: 0; - -webkit-border-radius: 0; - -o-border-radius: 0; - -ms-border-radius: 0; - -khtml-border-radius: 0; - border-radius: 0; - background: transparent; - display: inline; - padding: 0; - color: inherit; - -moz-box-shadow: none; - -webkit-box-shadow: none; - text-shadow: none; - border-bottom: 0; - position: static; - font-weight: normal; - line-height: inherit; - -moz-opacity: 0.5; - -webkit-opacity: 0.5; - -o-opacity: 0.5; - -khtml-opacity: 0.5; - font-size: 150%; - float: right; - line-height: 1; - margin-top: -0.125em; - padding: 0.125em 0.25em; -} -/* line 72, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.outfits-edit #new-outfit .outfit-delete:hover { - background: transparent; - color: inherit; -} -/* line 75, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.outfits-edit #new-outfit .outfit-delete:active { - top: auto; -} -/* line 52, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit .outfit-delete:hover { - -moz-opacity: 1; - -webkit-opacity: 1; - -o-opacity: 1; - -khtml-opacity: 1; - background: #eeffee; -} -/* line 55, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit header { - display: block; - padding-left: 24px; -} -/* line 58, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit h4 { - cursor: pointer; - display: inline; -} -/* line 61, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit h4:hover { - text-decoration: underline; -} -/* 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 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 67, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit .outfit-rename-button { - -moz-opacity: 0.75; - -webkit-opacity: 0.75; - -o-opacity: 0.75; - -khtml-opacity: 0.75; - font-size: 75%; - margin-left: 1em; -} -/* line 71, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit .outfit-url { - -moz-opacity: 0.5; - -webkit-opacity: 0.5; - -o-opacity: 0.5; - -khtml-opacity: 0.5; - background: transparent; - border-width: 0; - width: 284px; -} -/* line 76, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit .outfit-url:hover { - -moz-opacity: 1; - -webkit-opacity: 1; - -o-opacity: 1; - -khtml-opacity: 1; - border-width: 1px; -} -/* line 79, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit .outfit-delete-confirmation { - display: none; - font-size: 75%; -} -/* line 82, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit .outfit-delete-confirmation span { - color: red; -} -/* line 84, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit .outfit-delete-confirmation a { - margin: 0 0.25em; -} -/* line 86, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit.active { - background: #eeffee; -} -/* line 89, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit.confirming-deletion .outfit-delete { - visibility: hidden; -} -/* line 91, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit.confirming-deletion .outfit-url { - display: none; -} -/* line 93, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit.confirming-deletion .outfit-delete-confirmation { - display: block; -} -/* line 96, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit.renaming h4 { - display: none; -} -/* line 98, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit.renaming .outfit-rename-form { - display: inline; -} -/* line 101, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit.renaming:hover .outfit-rename-button { - display: none; -} -/* line 104, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit:hover .outfit-rename-button { - display: inline; -} -/* line 514, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit h4 { - display: inline; -} -/* line 516, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit h4:hover { - text-decoration: none; -} -/* line 518, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #new-outfit .outfit-star { - margin-top: 0.5em; -} -/* line 521, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 748, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #new-outfit-name { font: inherit; line-height: 1; } -/* line 525, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-saving-outfit { - display: none; - padding-bottom: 1em; -} -/* line 529, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 752, ../../../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 532, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 755, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit .control-overlay { height: 100%; left: 0; @@ -3201,13 +3316,12 @@ body.outfits-edit .control-overlay { width: 100%; z-index: 5; } -/* line 540, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 763, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit #preview-sidebar-nav-outfits, body.outfits-edit #save-outfit-signed-in { display: none; } -/* line 543, ../../../app/stylesheets/outfits/_edit.sass */ +/* line 766, ../../../app/stylesheets/outfits/_edit.sass */ body.outfits-edit form#save-outfit-form { - padding: 0.25em 0; display: none; margin-right: 0; padding: 0; @@ -3234,25 +3348,211 @@ body.outfits-edit form#save-outfit-form.starred .outfit-star { body.outfits-edit form#save-outfit-form.loading .outfit-star { background-image: url('/images/loading.gif?1315327995'); } -/* line 18, ../../../app/stylesheets/outfits/_star.sass */ -body.outfits-edit form#save-outfit-form.loading.active .outfit-star { - background-image: url('/images/loading_current_outfit.gif?1315327995'); -} -/* line 24, ../../../app/stylesheets/outfits/_star.sass */ +/* line 22, ../../../app/stylesheets/outfits/_star.sass */ body.outfits-edit form#save-outfit-form .outfit-star { margin-left: -24px; margin-right: 0; } -/* line 38, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form img { - height: 100px; - left: -25px; - position: absolute; - top: -25px; - width: 100px; +/* line 772, ../../../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; + display: inline-block; + vertical-align: middle; + *vertical-align: auto; + float: none; + vertical-align: top; } -/* line 44, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form .outfit-delete { +/* line 7, ../../../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/css3/_inline-block.scss */ +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: inline; +} +/* line 777, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit form#save-outfit-form .outfit-star { + margin-top: 0.25em; +} +/* line 780, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit .outfit-url { + font-size: 75%; +} +/* line 783, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #preview-search-form-error { + background: #fbe3e4; + border: 1px solid #fbc2c4; + color: #8a1f11; + padding: 0.25em 0.5em; +} +/* line 788, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit.user-signed-in #preview-sidebar-nav-outfits { + display: block; +} +/* line 790, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit.user-signed-in #save-outfit { + display: inline-block; +} +/* line 794, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-outfit { + display: none; +} +/* line 796, ../../../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 804, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit-form { + display: block; +} +/* line 806, ../../../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 808, ../../../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; + *vertical-align: auto; +} +/* line 7, ../../../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/css3/_inline-block.scss */ +body.outfits-edit.user-signed-in .preview-search-form-your-items { + *display: inline; +} +/* line 810, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit.user-signed-in #preview-outfits-not-logged-in { + display: none; +} +/* line 812, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit.user-signed-in #preview-outfits-list { + display: block; +} +/* line 816, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit.user-not-signed-in #save-outfit-not-signed-in { + display: inline-block; +} +/* line 820, ../../../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 822, ../../../app/stylesheets/outfits/_edit.sass */ +body.outfits-edit #save-outfit-wrapper.shared-outfit #current-outfit-permalink { + display: none !important; +} + +/* line 11, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits { + font-size: 0; + list-style: none; +} +/* line 25, ../../../app/stylesheets/partials/_outfit.sass */ +body.outfits-index #outfits > li { + display: -moz-inline-box; + -moz-box-orient: vertical; + display: inline-block; + vertical-align: middle; + *vertical-align: auto; + overflow: hidden; + position: relative; + font-size: 14px; +} +/* line 7, ../../../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/css3/_inline-block.scss */ +body.outfits-index #outfits > li { + *display: inline; +} +/* line 4, ../../../app/stylesheets/outfits/_star.sass */ +body.outfits-index #outfits > li .outfit-star { + bottom: -2px; + height: 16px; + position: relative; + width: 16px; + background-image: url('/images/unstarred.png?1315327995'); + background-position: left top; + background-repeat: no-repeat; + cursor: pointer; + display: block; + float: left; + margin-right: 8px; +} +/* line 14, ../../../app/stylesheets/outfits/_star.sass */ +body.outfits-index #outfits > li.starred .outfit-star { + background-image: url('/images/star.png?1315327995'); +} +/* line 16, ../../../app/stylesheets/outfits/_star.sass */ +body.outfits-index #outfits > li.loading .outfit-star { + background-image: url('/images/loading.gif?1315327995'); +} +/* line 7, ../../../app/stylesheets/partials/_outfit.sass */ +body.outfits-index #outfits > li header, body.outfits-index #outfits > li footer { + color: white; + left: 0; + position: absolute; + z-index: 2; + background: black; + background: rgba(0, 0, 0, 0.75); +} +/* line 11, ../../../app/stylesheets/partials/_outfit.sass */ +body.outfits-index #outfits > li header { + bottom: 0; +} +/* line 14, ../../../app/stylesheets/partials/_outfit.sass */ +body.outfits-index #outfits > li footer { + top: 0; +} +/* line 17, ../../../app/stylesheets/partials/_outfit.sass */ +body.outfits-index #outfits > li a { + color: white; +} +/* line 14, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits > li { + height: 150px; + margin: 2px; + width: 150px; +} +/* line 19, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits > li header, body.outfits-index #outfits > li footer { + padding: 2px 4px; + width: 142px; +} +/* line 23, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits > li footer { + display: none; +} +/* line 26, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits > li footer .outfit-edit-link { + float: left; + text-decoration: none; +} +/* line 30, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits > li footer form { + float: right; +} +/* line 33, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits > li footer form .outfit-delete-button { + margin: 0; + padding: 0; +} +/* line 38, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits > li footer .outfit-edit-link:hover, body.outfits-index #outfits > li footer .outfit-delete-button:hover { + text-decoration: underline; +} +/* line 41, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits > li .outfit-star { + cursor: auto; +} +/* line 44, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits > li .outfit-name { + text-decoration: none; +} +/* line 47, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits > li .outfit-name:hover { + text-decoration: underline; +} +/* line 51, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits > li:hover footer { + display: block; +} +/* line 54, ../../../app/stylesheets/outfits/_index.sass */ +body.outfits-index #outfits .outfit-delete-button { -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; @@ -3270,295 +3570,16 @@ body.outfits-edit form#save-outfit-form .outfit-delete { position: static; font-weight: normal; line-height: inherit; - -moz-opacity: 0.5; - -webkit-opacity: 0.5; - -o-opacity: 0.5; - -khtml-opacity: 0.5; - font-size: 150%; - float: right; - line-height: 1; - margin-top: -0.125em; - padding: 0.125em 0.25em; } /* line 72, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.outfits-edit form#save-outfit-form .outfit-delete:hover { +body.outfits-index #outfits .outfit-delete-button:hover { background: transparent; color: inherit; } /* line 75, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.outfits-edit form#save-outfit-form .outfit-delete:active { +body.outfits-index #outfits .outfit-delete-button:active { top: auto; } -/* line 52, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form .outfit-delete:hover { - -moz-opacity: 1; - -webkit-opacity: 1; - -o-opacity: 1; - -khtml-opacity: 1; - background: #eeffee; -} -/* line 55, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form header { - display: block; - padding-left: 24px; -} -/* line 58, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form h4 { - cursor: pointer; - display: inline; -} -/* line 61, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form h4:hover { - text-decoration: underline; -} -/* 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 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 67, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form .outfit-rename-button { - -moz-opacity: 0.75; - -webkit-opacity: 0.75; - -o-opacity: 0.75; - -khtml-opacity: 0.75; - font-size: 75%; - margin-left: 1em; -} -/* line 71, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form .outfit-url { - -moz-opacity: 0.5; - -webkit-opacity: 0.5; - -o-opacity: 0.5; - -khtml-opacity: 0.5; - background: transparent; - border-width: 0; - width: 284px; -} -/* line 76, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form .outfit-url:hover { - -moz-opacity: 1; - -webkit-opacity: 1; - -o-opacity: 1; - -khtml-opacity: 1; - border-width: 1px; -} -/* line 79, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form .outfit-delete-confirmation { - display: none; - font-size: 75%; -} -/* line 82, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form .outfit-delete-confirmation span { - color: red; -} -/* line 84, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form .outfit-delete-confirmation a { - margin: 0 0.25em; -} -/* line 86, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form.active { - background: #eeffee; -} -/* line 89, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form.confirming-deletion .outfit-delete { - visibility: hidden; -} -/* line 91, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form.confirming-deletion .outfit-url { - display: none; -} -/* line 93, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form.confirming-deletion .outfit-delete-confirmation { - display: block; -} -/* line 96, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form.renaming h4 { - display: none; -} -/* line 98, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form.renaming .outfit-rename-form { - display: inline; -} -/* line 101, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form.renaming:hover .outfit-rename-button { - display: none; -} -/* line 104, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form:hover .outfit-rename-button { - display: inline; -} -/* line 549, ../../../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; - display: inline-block; - vertical-align: middle; - *vertical-align: auto; - float: none; - vertical-align: top; -} -/* line 7, ../../../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/css3/_inline-block.scss */ -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: inline; -} -/* line 554, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit form#save-outfit-form .outfit-star { - margin-top: 0.25em; -} -/* line 557, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit .outfit-url { - font-size: 75%; -} -/* line 560, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #preview-search-form-error { - background: #fbe3e4; - border: 1px solid #fbc2c4; - color: #8a1f11; - padding: 0.25em 0.5em; -} -/* line 565, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit.user-signed-in #preview-sidebar-nav-outfits { - display: block; -} -/* line 567, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit.user-signed-in #save-outfit { - display: inline-block; -} -/* line 571, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-outfit { - display: none; -} -/* line 573, ../../../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 575, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #current-outfit-permalink { - display: inline-block; -} -/* line 578, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit-form { - display: block; -} -/* line 580, ../../../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 582, ../../../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; - *vertical-align: auto; -} -/* line 7, ../../../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/css3/_inline-block.scss */ -body.outfits-edit.user-signed-in .preview-search-form-your-items { - *display: inline; -} -/* line 586, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit.user-not-signed-in #save-outfit-not-signed-in { - display: inline-block; -} -/* line 590, ../../../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 592, ../../../app/stylesheets/outfits/_edit.sass */ -body.outfits-edit #save-outfit-wrapper.shared-outfit #current-outfit-permalink { - display: none !important; -} - -/* line 4, ../../../app/stylesheets/outfits/_index.sass */ -body.outfits-index #outfits { - list-style: none; -} -/* line 7, ../../../app/stylesheets/outfits/_index.sass */ -body.outfits-index #outfits li { - clear: left; - float: left; - margin-bottom: 0.5em; -} -/* line 4, ../../../app/stylesheets/outfits/_star.sass */ -body.outfits-index #outfits li .outfit-star { - bottom: -2px; - height: 16px; - position: relative; - width: 16px; - background-image: url('/images/unstarred.png?1315327995'); - background-position: left top; - background-repeat: no-repeat; - cursor: pointer; - display: block; - float: left; - margin-right: 8px; -} -/* line 14, ../../../app/stylesheets/outfits/_star.sass */ -body.outfits-index #outfits li.starred .outfit-star { - background-image: url('/images/star.png?1315327995'); -} -/* line 16, ../../../app/stylesheets/outfits/_star.sass */ -body.outfits-index #outfits li.loading .outfit-star { - background-image: url('/images/loading.gif?1315327995'); -} -/* line 18, ../../../app/stylesheets/outfits/_star.sass */ -body.outfits-index #outfits li.loading.active .outfit-star { - background-image: url('/images/loading_current_outfit.gif?1315327995'); -} -/* line 13, ../../../app/stylesheets/outfits/_index.sass */ -body.outfits-index #outfits h4 { - float: left; - width: 12em; -} -/* line 17, ../../../app/stylesheets/outfits/_index.sass */ -body.outfits-index #outfits .outfit-edit-link, body.outfits-index #outfits form { - float: left; - font-size: 85%; - margin-left: 1em; -} -/* line 22, ../../../app/stylesheets/outfits/_index.sass */ -body.outfits-index #outfits .outfit-edit-link { - /* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */ - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -o-border-radius: 5px; - -ms-border-radius: 5px; - -khtml-border-radius: 5px; - border-radius: 5px; - background: #006400 url('/images/alert-overlay.png?1315327995') 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; -} -/* line 34, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.outfits-index #outfits .outfit-edit-link:hover { - background-color: #005300; -} -/* line 53, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.outfits-index #outfits .outfit-edit-link:hover { - color: white; -} -/* line 55, ../../../app/stylesheets/partials/clean/_mixins.sass */ -body.outfits-index #outfits .outfit-edit-link:active { - top: 1px; -} -/* line 25, ../../../app/stylesheets/outfits/_index.sass */ -body.outfits-index #outfits .outfit-delete-button { - margin: 0; -} /* line 2, ../../../app/stylesheets/partials/_campaign-progress.sass */ body.outfits-new .campaign-progress-wrapper { diff --git a/vendor/cache/carrierwave-0.5.8.gem b/vendor/cache/carrierwave-0.5.8.gem new file mode 100644 index 00000000..4c4791b1 Binary files /dev/null and b/vendor/cache/carrierwave-0.5.8.gem differ diff --git a/vendor/cache/excon-0.9.6.gem b/vendor/cache/excon-0.9.6.gem new file mode 100644 index 00000000..721a7c3e Binary files /dev/null and b/vendor/cache/excon-0.9.6.gem differ diff --git a/vendor/cache/fog-1.1.2.gem b/vendor/cache/fog-1.1.2.gem new file mode 100644 index 00000000..494ec94c Binary files /dev/null and b/vendor/cache/fog-1.1.2.gem differ diff --git a/vendor/cache/formatador-0.2.1.gem b/vendor/cache/formatador-0.2.1.gem new file mode 100644 index 00000000..54dc8467 Binary files /dev/null and b/vendor/cache/formatador-0.2.1.gem differ diff --git a/vendor/cache/mini_magick-3.4.gem b/vendor/cache/mini_magick-3.4.gem new file mode 100644 index 00000000..0c0e384f Binary files /dev/null and b/vendor/cache/mini_magick-3.4.gem differ diff --git a/vendor/cache/multi_json-1.0.4.gem b/vendor/cache/multi_json-1.0.4.gem new file mode 100644 index 00000000..2c862408 Binary files /dev/null and b/vendor/cache/multi_json-1.0.4.gem differ diff --git a/vendor/cache/net-scp-1.0.4.gem b/vendor/cache/net-scp-1.0.4.gem new file mode 100644 index 00000000..a81ac2cd Binary files /dev/null and b/vendor/cache/net-scp-1.0.4.gem differ diff --git a/vendor/cache/net-ssh-2.3.0.gem b/vendor/cache/net-ssh-2.3.0.gem new file mode 100644 index 00000000..11d064e5 Binary files /dev/null and b/vendor/cache/net-ssh-2.3.0.gem differ diff --git a/vendor/cache/parallel-0.5.17.gem b/vendor/cache/parallel-0.5.17.gem new file mode 100644 index 00000000..6b2fec49 Binary files /dev/null and b/vendor/cache/parallel-0.5.17.gem differ diff --git a/vendor/cache/subexec-0.2.1.gem b/vendor/cache/subexec-0.2.1.gem new file mode 100644 index 00000000..a8fd7513 Binary files /dev/null and b/vendor/cache/subexec-0.2.1.gem differ