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