Sharing now fully supports saved outfits, not just shared ones

This commit is contained in:
Emi Matchu 2012-07-26 23:47:22 -04:00
parent b02c95c2d9
commit 374c7e6147
9 changed files with 456 additions and 317 deletions

View file

@ -75,7 +75,7 @@ class OutfitsController < ApplicationController
def update def update
if @outfit.update_attributes(params[:outfit]) if @outfit.update_attributes(params[:outfit])
render :json => true render :json => @outfit
else else
render_outfit_errors render_outfit_errors
end end

View file

@ -15,12 +15,13 @@ class Outfit < ActiveRecord::Base
mount_uploader :image, OutfitImageUploader mount_uploader :image, OutfitImageUploader
before_save :update_enqueued_image
after_commit :enqueue_image! after_commit :enqueue_image!
def as_json(more_options={}) def as_json(more_options={})
serializable_hash :only => [:id, :name, :pet_state_id, :starred], 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_versions, :image_enqueued, :image_layers_hash]
end end
def image_versions def image_versions
@ -94,6 +95,7 @@ class Outfit < ActiveRecord::Base
create_image! image create_image! image
self.image_layers_hash = generate_image_layers_hash self.image_layers_hash = generate_image_layers_hash
self.image = image self.image = image
self.image_enqueued = false
save! save!
end end
end end
@ -104,7 +106,12 @@ class Outfit < ActiveRecord::Base
# Enqueue an image write iff the new image would be different than the # Enqueue an image write iff the new image would be different than the
# current one. # current one.
def enqueue_image! def enqueue_image!
Resque.enqueue(OutfitImageUpdate, id) if image_layers_dirty? Resque.enqueue(OutfitImageUpdate, id)
end
def update_enqueued_image
self.image_enqueued = (image_layers_dirty?)
true
end end
def s3_key(size) def s3_key(size)

View file

@ -573,11 +573,14 @@ body.outfits-edit
display: block display: block
height: 150px height: 150px
margin: 1em auto 0 margin: 1em auto 0
position: relative
width: 150px width: 150px
#preview-sharing-thumbnail-loading #preview-sharing-thumbnail-loading
height: 100% height: 100%
position: relative left: 0
position: absolute
top: 0
width: 100% width: 100%
span span
@ -605,6 +608,13 @@ body.outfits-edit
#preview-sharing-thumbnail #preview-sharing-thumbnail
display: block display: block
&.urls-loaded.thumbnail-available
#preview-sharing-thumbnail-loading
+opacity(0.85)
#preview-sharing-thumbnail
display: block
.preview-sidebar-nav .preview-sidebar-nav
float: right float: right

View file

@ -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

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20120716193946) do ActiveRecord::Schema.define(:version => 20120725232903) do
create_table "auth_servers", :force => true do |t| create_table "auth_servers", :force => true do |t|
t.string "short_name", :limit => 10, :null => false t.string "short_name", :limit => 10, :null => false
@ -119,6 +119,7 @@ ActiveRecord::Schema.define(:version => 20120716193946) do
t.boolean "starred", :default => false, :null => false t.boolean "starred", :default => false, :null => false
t.string "image" t.string "image"
t.string "image_layers_hash" t.string "image_layers_hash"
t.boolean "image_enqueued", :default => false, :null => false
end end
add_index "outfits", ["pet_state_id"], :name => "index_outfits_on_pet_state_id" add_index "outfits", ["pet_state_id"], :name => "index_outfits_on_pet_state_id"

View file

@ -57,7 +57,7 @@ Partial.ItemSet = function ItemSet(wardrobe, selector) {
var item, no_assets, li, no_assets_message; var item, no_assets, li, no_assets_message;
for(var i = 0, l = specific_items.length; i < l; i++) { for(var i = 0, l = specific_items.length; i < l; i++) {
item = specific_items[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); li = $('li.object-' + item.id).toggleClass('no-assets', no_assets);
(function (li) { (function (li) {
no_assets_message = li.find('span.no-assets-message'); 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); li.append(img).append(controls).append(info_link).append(item.name).appendTo(ul);
} }
setClosetItems(wardrobe.outfit.getClosetItems()); setClosetItems(wardrobe.outfits.getClosetItems());
setOutfitItems(wardrobe.outfit.getWornItems()); setOutfitItems(wardrobe.outfits.getWornItems());
} }
$('span.no-assets-message').live('mouseover', function () { $('span.no-assets-message').live('mouseover', function () {
@ -117,9 +117,9 @@ Partial.ItemSet = function ItemSet(wardrobe, selector) {
no_assets_full_message.removeAttr('style'); no_assets_full_message.removeAttr('style');
}); });
wardrobe.outfit.bind('updateItemAssets', function () { setHasAssets(wardrobe.outfit.getWornItems()) }); wardrobe.outfits.bind('updateItemAssets', function () { setHasAssets(wardrobe.outfits.getWornItems()) });
wardrobe.outfit.bind('updateWornItems', setOutfitItems); wardrobe.outfits.bind('updateWornItems', setOutfitItems);
wardrobe.outfit.bind('updateClosetItems', setClosetItems); wardrobe.outfits.bind('updateClosetItems', setClosetItems);
} }
Partial.ItemSet.CONTROL_SETS = {}; Partial.ItemSet.CONTROL_SETS = {};
@ -151,12 +151,12 @@ Partial.ItemSet.setWardrobe = function (wardrobe) {
} }
toggle_fn.closeted = {}; toggle_fn.closeted = {};
toggle_fn.closeted[true] = $.proxy(wardrobe.outfit, 'closetItem'); toggle_fn.closeted[true] = $.proxy(wardrobe.outfits, 'closetItem');
toggle_fn.closeted[false] = $.proxy(wardrobe.outfit, 'unclosetItem'); toggle_fn.closeted[false] = $.proxy(wardrobe.outfits, 'unclosetItem');
toggle_fn.worn = {}; toggle_fn.worn = {};
toggle_fn.worn[true] = $.proxy(wardrobe.outfit, 'wearItem'); toggle_fn.worn[true] = $.proxy(wardrobe.outfits, 'wearItem');
toggle_fn.worn[false] = $.proxy(wardrobe.outfit, 'unwearItem'); toggle_fn.worn[false] = $.proxy(wardrobe.outfits, 'unwearItem');
Partial.ItemSet.setWardrobe = $.noop; Partial.ItemSet.setWardrobe = $.noop;
} }
@ -164,7 +164,7 @@ Partial.ItemSet.setWardrobe = function (wardrobe) {
View.Closet = function (wardrobe) { View.Closet = function (wardrobe) {
var item_set = new Partial.ItemSet(wardrobe, '#preview-closet ul'); 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) { View.Fullscreen = function (wardrobe) {
@ -281,32 +281,32 @@ View.Hash = function (wardrobe) {
} }
if(new_data.color !== data.color || new_data.species !== data.species) { 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(new_data.closet) {
if(!arraysMatch(new_data.closet, 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)) { } 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 { } else {
wardrobe.outfit.setClosetItemsByIds([]); wardrobe.outfits.setClosetItemsByIds([]);
} }
if(new_data.objects) { if(new_data.objects) {
if(!arraysMatch(new_data.objects, 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 { } else {
wardrobe.outfit.setWornItemsByIds([]); wardrobe.outfits.setWornItemsByIds([]);
} }
if(new_data.name != data.name && new_data.name) { if(new_data.name != data.name && new_data.name) {
wardrobe.base_pet.setName(new_data.name); wardrobe.base_pet.setName(new_data.name);
} }
if(new_data.state != data.state) { if(new_data.state != data.state) {
wardrobe.outfit.setPetStateById(new_data.state); wardrobe.outfits.setPetStateById(new_data.state);
} }
if(new_data.outfit != data.outfit) { 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) { if(new_data.search != data.search || new_data.search_offset != data.search_offset) {
wardrobe.search.setItemsByQuery(new_data.search, {offset: new_data.search_offset}); wardrobe.search.setItemsByQuery(new_data.search, {offset: new_data.search_offset});
@ -358,8 +358,8 @@ View.Hash = function (wardrobe) {
} }
function singleOutfitResponse(event_name, response) { function singleOutfitResponse(event_name, response) {
wardrobe.outfit.bind(event_name, function () { wardrobe.outfits.bind(event_name, function () {
if(!wardrobe.outfit.in_transaction) response.apply(this, arguments); if(!wardrobe.outfits.in_transaction) response.apply(this, arguments);
}); });
} }
@ -378,7 +378,7 @@ View.Hash = function (wardrobe) {
if(arraysMatch(item_ids, data.closet) || arraysMatch(item_ids, data.objects)) { if(arraysMatch(item_ids, data.closet) || arraysMatch(item_ids, data.objects)) {
changes.closet = undefined; changes.closet = undefined;
} else { } else {
changes.closet = wardrobe.outfit.getClosetItems().mapProperty('id'); changes.closet = wardrobe.outfits.getClosetItems().mapProperty('id');
} }
if(changes.objects || changes.closet) changeQuery(changes); if(changes.objects || changes.closet) changeQuery(changes);
}); });
@ -398,7 +398,7 @@ View.Hash = function (wardrobe) {
}); });
singleOutfitResponse('updatePetState', function (pet_state) { 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])) { if(pet_state.id != data.state && pet_type && (data.state || pet_state.id != pet_type.pet_state_ids[0])) {
changeQuery({state: pet_state.id}); changeQuery({state: pet_state.id});
} }
@ -410,7 +410,7 @@ View.Hash = function (wardrobe) {
} }
}); });
wardrobe.outfit.bind('loadOutfit', function (outfit) { wardrobe.outfits.bind('loadOutfit', function (outfit) {
changeQuery({ changeQuery({
closet: outfit.getClosetItemIds(), closet: outfit.getClosetItemIds(),
color: outfit.pet_type.color_id, color: outfit.pet_type.color_id,
@ -421,7 +421,7 @@ View.Hash = function (wardrobe) {
}); });
}); });
wardrobe.outfit.bind('outfitNotFound', function (outfit) { wardrobe.outfits.bind('outfitNotFound', function (outfit) {
var new_id = outfit ? outfit.id : undefined; var new_id = outfit ? outfit.id : undefined;
changeQuery({outfit: new_id}); changeQuery({outfit: new_id});
}); });
@ -475,15 +475,18 @@ View.Outfits = function (wardrobe) {
/* Nav */ /* Nav */
function showCloset() { function showCloset() {
sharing.onHide();
navigateTo(''); navigateTo('');
} }
function showOutfits() { function showOutfits() {
wardrobe.user.loadOutfits(); sharing.onHide();
wardrobe.outfits.loadOutfits();
navigateTo('viewing-outfits'); navigateTo('viewing-outfits');
} }
function showSharing() { function showSharing() {
sharing.onShow();
navigateTo('sharing'); navigateTo('sharing');
} }
@ -501,7 +504,7 @@ View.Outfits = function (wardrobe) {
$('#preview-sidebar-navbar-closet').click(showCloset); $('#preview-sidebar-navbar-closet').click(showCloset);
$('#preview-sidebar-navbar-sharing').click(function () { $('#preview-sidebar-navbar-sharing').click(function () {
sharing.startLoading(); sharing.startLoading();
wardrobe.outfit.share(); wardrobe.outfits.share();
showSharing(); showSharing();
}); });
$('#preview-sidebar-navbar-outfits').click(showOutfits); $('#preview-sidebar-navbar-outfits').click(showOutfits);
@ -518,13 +521,13 @@ View.Outfits = function (wardrobe) {
$('#outfit-template').template('outfitTemplate'); $('#outfit-template').template('outfitTemplate');
wardrobe.user.bind('outfitsLoaded', function (outfits) { wardrobe.outfits.bind('outfitsLoaded', function (outfits) {
var outfit_els = $.tmpl('outfitTemplate', outfits); var outfit_els = $.tmpl('outfitTemplate', outfits);
outfits_list_el.html('').append(outfit_els).addClass('loaded'); outfits_list_el.html('').append(outfit_els).addClass('loaded');
updateActiveOutfit(); updateActiveOutfit();
}); });
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), var next_child = outfits_list_el.children().not('.hiding').eq(i),
outfit_el = $.tmpl('outfitTemplate', outfit); outfit_el = $.tmpl('outfitTemplate', outfit);
if(next_child.length) { if(next_child.length) {
@ -536,13 +539,13 @@ View.Outfits = function (wardrobe) {
outfit_el.hide().show('normal'); outfit_el.hide().show('normal');
}); });
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); 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).hide('normal', function () { outfit_el.remove() });
}); });
$('#preview-outfits h4').live('click', function () { $('#preview-outfits h4').live('click', function () {
wardrobe.outfit.load($(this).tmplItem().data.id); wardrobe.outfits.load($(this).tmplItem().data.id);
}); });
$('a.outfit-rename-button').live('click', function (e) { $('a.outfit-rename-button').live('click', function (e) {
@ -557,7 +560,7 @@ View.Outfits = function (wardrobe) {
li = el.closest('li').removeClass('renaming'); li = el.closest('li').removeClass('renaming');
if(new_name != outfit.name) { if(new_name != outfit.name) {
li.startLoading(); li.startLoading();
wardrobe.user.renameOutfit(outfit, new_name); wardrobe.outfits.renameOutfit(outfit, new_name);
} }
} }
@ -583,9 +586,9 @@ View.Outfits = function (wardrobe) {
$('a.outfit-delete-confirmation-yes').live('click', function (e) { $('a.outfit-delete-confirmation-yes').live('click', function (e) {
var outfit = $(this).tmplItem().data; var outfit = $(this).tmplItem().data;
e.preventDefault(); e.preventDefault();
wardrobe.user.destroyOutfit(outfit); wardrobe.outfits.destroyOutfit(outfit);
if(wardrobe.outfit.getOutfit().id == outfit.id) { if(wardrobe.outfits.getOutfit().id == outfit.id) {
wardrobe.outfit.setId(null); wardrobe.outfits.setId(null);
} }
}); });
@ -597,7 +600,7 @@ View.Outfits = function (wardrobe) {
stars.live('click', function () { stars.live('click', function () {
var el = $(this); var el = $(this);
el.closest('li').startLoading(); el.closest('li').startLoading();
wardrobe.user.toggleOutfitStar(el.tmplItem().data); wardrobe.outfits.toggleOutfitStar(el.tmplItem().data);
}); });
function pathToUrl(path) { function pathToUrl(path) {
@ -631,14 +634,14 @@ View.Outfits = function (wardrobe) {
} }
function updateActiveOutfit() { function updateActiveOutfit() {
setActiveOutfit(wardrobe.outfit.getOutfit()); setActiveOutfit(wardrobe.outfits.getOutfit());
} }
wardrobe.outfit.bind('setOutfit', setActiveOutfit); wardrobe.outfits.bind('setOutfit', setActiveOutfit);
wardrobe.outfit.bind('outfitNotFound', setActiveOutfit); wardrobe.outfits.bind('outfitNotFound', setActiveOutfit);
wardrobe.user.bind('outfitRenamed', function (outfit) { wardrobe.outfits.bind('outfitRenamed', function (outfit) {
if(outfit.id == wardrobe.outfit.getId()) { if(outfit.id == wardrobe.outfits.getId()) {
save_current_outfit_name_el.text(outfit.name); save_current_outfit_name_el.text(outfit.name);
} }
}); });
@ -654,6 +657,7 @@ View.Outfits = function (wardrobe) {
small_image: $('#preview-sharing-small-image-url'), small_image: $('#preview-sharing-small-image-url'),
}; };
var format_selector_els = $('#preview-sharing-url-formats li'); var format_selector_els = $('#preview-sharing-url-formats li');
var thumbnail_el = $('#preview-sharing-thumbnail');
var formats = { var formats = {
plain: { plain: {
@ -691,13 +695,51 @@ View.Outfits = function (wardrobe) {
formatUrls(); formatUrls();
}); });
var image_subscription = null;
function unsubscribeFromImage() {
if(image_subscription !== null) {
wardrobe.image_subscriptions.unsubscribe(image_subscription);
image_subscription = null;
}
}
function subscribeToImage(outfit) {
image_subscription = wardrobe.image_subscriptions.subscribe(outfit);
}
function subscribeToImageIfVisible() {
if(current_shared_outfit && sidebar_el.hasClass('sharing')) {
subscribeToImage(current_shared_outfit);
}
}
var current_shared_outfit = {id: null};
this.setOutfit = function (outfit) { this.setOutfit = function (outfit) {
urls.permalink = generateOutfitPermalink(outfit); // If outfit has no ID but we're already on the Sharing tab (e.g. user is
urls.small_image = pathToUrl(outfit.image_versions.small); // on Sharing but goes back in history to a no-ID outfit), we can't
urls.medium_image = pathToUrl(outfit.image_versions.medium); // exactly do anything with it but submit it for sharing.
urls.large_image = pathToUrl(outfit.image_versions.large); if(!outfit.id) {
thumbnail.setUrl(urls.small_image); sharing.startLoading();
formatUrls(); 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();
}
WRAPPER.addClass('urls-loaded'); WRAPPER.addClass('urls-loaded');
} }
@ -705,6 +747,14 @@ View.Outfits = function (wardrobe) {
WRAPPER.removeClass('urls-loaded'); WRAPPER.removeClass('urls-loaded');
} }
this.onHide = function () {
unsubscribeFromImage();
}
this.onShow = function () {
subscribeToImageIfVisible();
}
function formatUrls() { function formatUrls() {
formatImageUrl('small_image'); formatImageUrl('small_image');
formatImageUrl('medium_image'); formatImageUrl('medium_image');
@ -723,69 +773,45 @@ View.Outfits = function (wardrobe) {
function formatUrl(key, url) { function formatUrl(key, url) {
sharing_url_els[key].val(url); sharing_url_els[key].val(url);
} }
var thumbnail = new function SharingThumbnail() { wardrobe.image_subscriptions.bind('imageEnqueued', function (outfit) {
var IMAGE = $('#preview-sharing-thumbnail'); log("Sharing thumbnail enqueued for outfit", outfit);
var RETRY_DELAY = 2000; // 2 seconds
var url = null;
var xhr = null;
function abort() { WRAPPER.removeClass('thumbnail-loaded');
if(xhr && xhr.readystate != 4) { });
log("Aborting sharing thumbnail XHR");
xhr.abort(); wardrobe.image_subscriptions.bind('imageReady', function (outfit) {
} log("Sharing thumbnail ready for outfit", outfit);
}
function hide() { var src = outfit.image_versions.small + '?' + outfit.image_layers_hash;
WRAPPER.removeClass('thumbnail-loaded'); thumbnail_el.attr('src', src);
WRAPPER.addClass('thumbnail-loaded');
WRAPPER.addClass('thumbnail-available');
image_subscription = null;
});
wardrobe.outfits.bind('updateSuccess', function (outfit) {
if(sidebar_el.hasClass('sharing')) {
subscribeToImage(outfit);
} }
});
function load() {
log("Loading sharing thumbnail", url); wardrobe.outfits.bind('setOutfit', function (outfit) {
xhr = $.ajax({ log("Sharing sees the setOutfit signal, and will set", outfit);
type: 'HEAD', sharing.setOutfit(outfit);
cache: false, // in case some browser tries to cache a 404 });
url: url,
success: show,
error: retry
});
}
function retry() {
log("Sharing thumbnail not found, retry in", RETRY_DELAY);
setTimeout(load, RETRY_DELAY);
}
function show() {
log("Sharing thumbnail found");
IMAGE.attr('src', url);
WRAPPER.addClass('thumbnail-loaded');
}
this.setUrl = function (newUrl) {
if(newUrl != url) {
abort();
hide();
url = newUrl;
load();
} else {
log("Sharing thumbnail URLs are identical; no change.");
}
}
}
} }
/* Saving */ /* Saving */
save_current_outfit_el.click(function () { save_current_outfit_el.click(function () {
wardrobe.outfit.update(); wardrobe.outfits.update();
}); });
new_outfit_form_el.submit(function (e) { new_outfit_form_el.submit(function (e) {
e.preventDefault(); e.preventDefault();
new_outfit_form_el.startLoading(); new_outfit_form_el.startLoading();
wardrobe.outfit.create({starred: new_outfit_form_el.hasClass('starred'), name: new_outfit_name_el.val()}); 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 () { new_outfit_form_el.find('div.outfit-star').click(function () {
@ -803,20 +829,14 @@ View.Outfits = function (wardrobe) {
save_error_el.text(text).notify(); save_error_el.text(text).notify();
} }
wardrobe.outfit.bind('saveSuccess', function (outfit) { wardrobe.outfits.bind('saveSuccess', function (outfit) {
save_success_el.notify(); save_success_el.notify();
sharing.setOutfit(outfit);
}); });
wardrobe.outfit.bind('createSuccess', function (outfit) { wardrobe.outfits.bind('createSuccess', function (outfit) {
wardrobe.user.addOutfit(outfit);
showOutfits(); showOutfits();
hideNewOutfitForm(); hideNewOutfitForm();
}); });
wardrobe.outfit.bind('updateSuccess', function (outfit) {
wardrobe.user.updateOutfit(outfit);
});
function shareComplete(outfit) { function shareComplete(outfit) {
save_outfit_wrapper_el.stopLoading().addClass('shared-outfit'); save_outfit_wrapper_el.stopLoading().addClass('shared-outfit');
@ -824,16 +844,16 @@ View.Outfits = function (wardrobe) {
showSharing(); showSharing();
} }
wardrobe.outfit.bind('shareSuccess', shareComplete); wardrobe.outfits.bind('shareSuccess', shareComplete);
wardrobe.outfit.bind('shareSkipped', shareComplete); wardrobe.outfits.bind('shareSkipped', shareComplete);
function clearSharedOutfit() { function clearSharedOutfit() {
save_outfit_wrapper_el.removeClass('shared-outfit'); save_outfit_wrapper_el.removeClass('shared-outfit');
} }
wardrobe.outfit.bind('updateClosetItems', clearSharedOutfit); wardrobe.outfits.bind('updateClosetItems', clearSharedOutfit);
wardrobe.outfit.bind('updateWornItems', clearSharedOutfit); wardrobe.outfits.bind('updateWornItems', clearSharedOutfit);
wardrobe.outfit.bind('updatePetState', clearSharedOutfit); wardrobe.outfits.bind('updatePetState', clearSharedOutfit);
function saveFailure(outfit, response) { function saveFailure(outfit, response) {
var errors = response.errors; var errors = response.errors;
@ -856,16 +876,16 @@ View.Outfits = function (wardrobe) {
liForOutfit(outfit).stopLoading(); liForOutfit(outfit).stopLoading();
} }
wardrobe.outfit.bind('saveFailure', saveFailure); wardrobe.outfits.bind('saveFailure', saveFailure);
wardrobe.user.bind('saveFailure', saveFailure) wardrobe.outfits.bind('saveFailure', saveFailure)
wardrobe.outfit.bind('shareFailure', function (outfit, response) { wardrobe.outfits.bind('shareFailure', function (outfit, response) {
save_outfit_wrapper_el.stopLoading(); save_outfit_wrapper_el.stopLoading();
saveFailure(outfit, response); saveFailure(outfit, response);
}); });
/* Error */ /* Error */
wardrobe.outfit.bind('outfitNotFound', function () { wardrobe.outfits.bind('outfitNotFound', function () {
outfit_not_found_el.notify(); outfit_not_found_el.notify();
}); });
} }
@ -877,7 +897,7 @@ View.PetStateForm = function (wardrobe) {
button_query = form_query + ' button'; button_query = form_query + ' button';
$(button_query).live('click', function (e) { $(button_query).live('click', function (e) {
e.preventDefault(); e.preventDefault();
wardrobe.outfit.setPetStateById(+$(this).data('value')); wardrobe.outfits.setPetStateById(+$(this).data('value'));
}); });
function updatePetState(pet_state) { function updatePetState(pet_state) {
@ -887,7 +907,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; var ids = pet_type.pet_state_ids, i, id, li, button, label;
ul.children().remove(); ul.children().remove();
if(ids.length == 1) { if(ids.length == 1) {
@ -905,18 +925,18 @@ View.PetStateForm = function (wardrobe) {
button.appendTo(li); button.appendTo(li);
li.appendTo(ul); 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) { View.PetTypeForm = function (wardrobe) {
var form = $('#pet-type-form'), dropdowns = {}, loaded = false; var form = $('#pet-type-form'), dropdowns = {}, loaded = false;
form.submit(function (e) { form.submit(function (e) {
e.preventDefault(); e.preventDefault();
wardrobe.outfit.setPetTypeByColorAndSpecies( wardrobe.outfits.setPetTypeByColorAndSpecies(
+dropdowns.color.val(), +dropdowns.species.val() +dropdowns.color.val(), +dropdowns.species.val()
); );
}).children('select').each(function () { }).children('select').each(function () {
@ -947,12 +967,12 @@ View.PetTypeForm = function (wardrobe) {
}); });
}); });
loaded = true; 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'); $('#pet-type-not-found').show('normal').delay(3000).hide('fast');
}); });
} }
@ -1009,7 +1029,7 @@ View.ReportBrokenImage = function (wardrobe) {
var baseURL = link.attr('data-base-url'); var baseURL = link.attr('data-base-url');
function updateLink() { function updateLink() {
var assets = wardrobe.outfit.getVisibleAssets(); var assets = wardrobe.outfits.getVisibleAssets();
var url = baseURL + "?"; var url = baseURL + "?";
for(var i = 0; i < assets.length; i++) { for(var i = 0; i < assets.length; i++) {
@ -1020,9 +1040,9 @@ View.ReportBrokenImage = function (wardrobe) {
link.attr('href', url); link.attr('href', url);
} }
wardrobe.outfit.bind('updateWornItems', updateLink); wardrobe.outfits.bind('updateWornItems', updateLink);
wardrobe.outfit.bind('updateItemAssets', updateLink); wardrobe.outfits.bind('updateItemAssets', updateLink);
wardrobe.outfit.bind('updatePetState', updateLink); wardrobe.outfits.bind('updatePetState', updateLink);
} }
View.Search = function (wardrobe) { View.Search = function (wardrobe) {

View file

@ -7,4 +7,4 @@ var main_wardrobe = new Wardrobe(), View = Wardrobe.getStandardView({
}); });
main_wardrobe.registerViews(View); main_wardrobe.registerViews(View);
main_wardrobe.initialize(); main_wardrobe.initialize();
main_wardrobe.outfit.loadData(INITIAL_OUTFIT_DATA); main_wardrobe.outfits.loadData(INITIAL_OUTFIT_DATA);

View file

@ -275,17 +275,23 @@ function Wardrobe() {
worn_item_ids = new_ids.worn; worn_item_ids = new_ids.worn;
closet_item_ids = new_ids.unworn.concat(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') { if(typeof data != 'undefined') {
this.color_id = data.color_id; loadAttributes(data);
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.image_versions = data.image_versions;
this.setWornAndUnwornItemIds(data.worn_and_unworn_item_ids);
new_record = false;
} }
this.closet_items = []; this.closet_items = [];
@ -378,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) { this.closetItem = function (item, updateClosetItemsCallback) {
if(!hasItemInCloset(item)) { if(!hasItemInCloset(item)) {
this.closet_items.push(item); this.closet_items.push(item);
@ -539,6 +528,9 @@ function Wardrobe() {
new_outfit.id = outfit.id; new_outfit.id = outfit.id;
new_outfit.name = outfit.name; new_outfit.name = outfit.name;
new_outfit.starred = outfit.starred; 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; return new_outfit;
} }
@ -556,6 +548,13 @@ function Wardrobe() {
new_ids.unworn = base_ids.unworn.slice(0); new_ids.unworn = base_ids.unworn.slice(0);
outfit.setWornAndUnwornItemIds(new_ids); 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) { this.destroy = function (success) {
$.ajax({ $.ajax({
@ -574,8 +573,7 @@ function Wardrobe() {
dataType: 'json', dataType: 'json',
success: function (data) { success: function (data) {
new_record = false; new_record = false;
outfit.id = data.id; updateFromSaveResponse(data);
outfit.image_versions = data.image_versions;
Outfit.cache[outfit.id] = outfit; Outfit.cache[outfit.id] = outfit;
success(outfit); success(outfit);
}, },
@ -584,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) { this.updateAttributes = function (attributes, success, failure) {
var outfit_data = {}; var outfit_data = {};
@ -602,19 +626,23 @@ function Wardrobe() {
if(typeof Outfit.cache[id] !== 'undefined') { if(typeof Outfit.cache[id] !== 'undefined') {
callback(Outfit.cache[id]); callback(Outfit.cache[id]);
} else { } else {
$.ajax({ Outfit.load(id, callback);
url: '/outfits/' + id + '.json',
success: function (data) {
var outfit = new Outfit(data);
Outfit.cache[id] = outfit;
callback(outfit);
},
error: function () {
callback(null);
}
});
} }
} }
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) { Outfit.loadForCurrentUser = function (success) {
var outfits = []; var outfits = [];
@ -807,7 +835,12 @@ function Wardrobe() {
Controller.all = {}; Controller.all = {};
Controller.all.Outfit = function OutfitController() { 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; var controller = this, outfit = new Outfit, last_shared_outfit = null;
this.in_transaction = false; this.in_transaction = false;
@ -881,6 +914,7 @@ function Wardrobe() {
} }
outfit.create( outfit.create(
function (outfit) { function (outfit) {
insertOutfit(outfit);
controller.events.trigger('saveSuccess', outfit); controller.events.trigger('saveSuccess', outfit);
controller.events.trigger('createSuccess', outfit); controller.events.trigger('createSuccess', outfit);
controller.events.trigger('setOutfit', outfit); controller.events.trigger('setOutfit', outfit);
@ -974,6 +1008,7 @@ function Wardrobe() {
this.update = function () { this.update = function () {
outfit.update( outfit.update(
function (outfit) { function (outfit) {
updateUserOutfit(outfit);
controller.events.trigger('saveSuccess', outfit), controller.events.trigger('saveSuccess', outfit),
controller.events.trigger('updateSuccess', outfit) controller.events.trigger('updateSuccess', outfit)
}, },
@ -989,6 +1024,139 @@ function Wardrobe() {
controller.event('updateItemAssets') 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) {
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) }, DELAY);
} else {
controller.unsubscribe(outfit);
controller.events.trigger('imageReady', outfit);
}
} else {
log("Outfit was unsubscribed", outfit);
delete outfitSubscriptionTotals[outfit.id];
}
});
}
this.subscribe = function (outfit) {
if(!(outfit.id in outfitSubscriptionTotals)) {
outfitSubscriptionTotals[outfit.id] = 0;
}
outfitSubscriptionTotals[outfit.id] += 1;
if(outfit.image_enqueued) {
// If the image is enqueued, trigger that event and start checking.
controller.events.trigger('imageEnqueued', outfit);
checkSubscription(outfit);
return outfit;
} else {
// Otherwise, never bother checking: skip straight to the ready phase.
controller.events.trigger('imageReady', outfit);
return null;
}
}
this.unsubscribe = function (outfit) {
outfitSubscriptionTotals[outfit.id] -= 1;
}
} }
Controller.all.BasePet = function BasePetController() { Controller.all.BasePet = function BasePetController() {
@ -1059,96 +1227,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; var underscored_name;
for(var name in Controller.all) { for(var name in Controller.all) {
@ -1227,13 +1305,13 @@ Wardrobe.getStandardView = function (options) {
var outfit_events = ['updateWornItems', 'updateClosetItems', 'updateItemAssets', 'updatePetType', 'updatePetState']; var outfit_events = ['updateWornItems', 'updateClosetItems', 'updateItemAssets', 'updatePetType', 'updatePetState'];
for(var i = 0; i < outfit_events.length; i++) { for(var i = 0; i < outfit_events.length; i++) {
(function (event) { (function (event) {
wardrobe.outfit.bind(event, function (obj) { wardrobe.outfits.bind(event, function (obj) {
log(event, obj); log(event, obj);
}); });
})(outfit_events[i]); })(outfit_events[i]);
} }
wardrobe.outfit.bind('petTypeNotFound', function (pet_type) { wardrobe.outfits.bind('petTypeNotFound', function (pet_type) {
log(pet_type.toString() + ' not found'); log(pet_type.toString() + ' not found');
}); });
} }
@ -1277,7 +1355,7 @@ Wardrobe.getStandardView = function (options) {
var assets, assets_for_swf; var assets, assets_for_swf;
if(update_pending_flash) return false; if(update_pending_flash) return false;
if(preview_swf && preview_swf.setAssets) { if(preview_swf && preview_swf.setAssets) {
assets = wardrobe.outfit.getVisibleAssets(); assets = wardrobe.outfits.getVisibleAssets();
preview_swf.setAssets(assets); preview_swf.setAssets(assets);
} else { } else {
update_pending_flash = true; update_pending_flash = true;
@ -1334,7 +1412,7 @@ Wardrobe.getStandardView = function (options) {
// Get a copy of the visible assets, then sort them in ascending zone // Get a copy of the visible assets, then sort them in ascending zone
// order. // order.
var assets = wardrobe.outfit.getVisibleAssets().slice(0); var assets = wardrobe.outfits.getVisibleAssets().slice(0);
assets.sort(function (a, b) { assets.sort(function (a, b) {
return a.depth - b.depth; return a.depth - b.depth;
}); });
@ -1348,7 +1426,7 @@ Wardrobe.getStandardView = function (options) {
} }
this.updateAssets = function () { this.updateAssets = function () {
var assets = wardrobe.outfit.getVisibleAssets(), asset, var assets = wardrobe.outfits.getVisibleAssets(), asset,
availableAssets = []; availableAssets = [];
pendingAssets = {}; pendingAssets = {};
pendingAssetsCount = 0; pendingAssetsCount = 0;
@ -1507,9 +1585,9 @@ Wardrobe.getStandardView = function (options) {
preview.adapter.updateAssets(); preview.adapter.updateAssets();
} }
wardrobe.outfit.bind('updateWornItems', updateAssets); wardrobe.outfits.bind('updateWornItems', updateAssets);
wardrobe.outfit.bind('updateItemAssets', updateAssets); wardrobe.outfits.bind('updateItemAssets', updateAssets);
wardrobe.outfit.bind('updatePetState', updateAssets); wardrobe.outfits.bind('updatePetState', updateAssets);
function useAdapter(name) { function useAdapter(name) {
preview.adapter = new Adapter[name](); preview.adapter = new Adapter[name]();

View file

@ -3085,15 +3085,18 @@ body.outfits-edit #preview-sharing #preview-sharing-thumbnail-wrapper {
display: block; display: block;
height: 150px; height: 150px;
margin: 1em auto 0; margin: 1em auto 0;
position: relative;
width: 150px; width: 150px;
} }
/* line 578, ../../../app/stylesheets/outfits/_edit.sass */ /* line 579, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sharing #preview-sharing-thumbnail-loading { body.outfits-edit #preview-sharing #preview-sharing-thumbnail-loading {
height: 100%; height: 100%;
position: relative; left: 0;
position: absolute;
top: 0;
width: 100%; width: 100%;
} }
/* line 583, ../../../app/stylesheets/outfits/_edit.sass */ /* line 586, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sharing #preview-sharing-thumbnail-loading span { body.outfits-edit #preview-sharing #preview-sharing-thumbnail-loading span {
color: #448844; color: #448844;
font-size: 85%; font-size: 85%;
@ -3103,52 +3106,63 @@ body.outfits-edit #preview-sharing #preview-sharing-thumbnail-loading span {
top: 50%; top: 50%;
width: 100%; width: 100%;
} }
/* line 592, ../../../app/stylesheets/outfits/_edit.sass */ /* line 595, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sharing #preview-sharing-thumbnail, body.outfits-edit #preview-sharing #preview-sharing-thumbnail-generating { body.outfits-edit #preview-sharing #preview-sharing-thumbnail, body.outfits-edit #preview-sharing #preview-sharing-thumbnail-generating {
display: none; display: none;
} }
/* line 596, ../../../app/stylesheets/outfits/_edit.sass */ /* line 599, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sharing.urls-loaded #preview-sharing-thumbnail-saving { body.outfits-edit #preview-sharing.urls-loaded #preview-sharing-thumbnail-saving {
display: none; display: none;
} }
/* line 599, ../../../app/stylesheets/outfits/_edit.sass */ /* line 602, ../../../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 { 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; display: block;
} }
/* line 603, ../../../app/stylesheets/outfits/_edit.sass */ /* line 606, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sharing.urls-loaded.thumbnail-loaded #preview-sharing-thumbnail-loading { body.outfits-edit #preview-sharing.urls-loaded.thumbnail-loaded #preview-sharing-thumbnail-loading {
display: none; display: none;
} }
/* line 606, ../../../app/stylesheets/outfits/_edit.sass */ /* line 609, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sharing.urls-loaded.thumbnail-loaded #preview-sharing-thumbnail { body.outfits-edit #preview-sharing.urls-loaded.thumbnail-loaded #preview-sharing-thumbnail {
display: block; display: block;
} }
/* line 609, ../../../app/stylesheets/outfits/_edit.sass */ /* line 613, ../../../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 616, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sharing.urls-loaded.thumbnail-available #preview-sharing-thumbnail {
display: block;
}
/* line 619, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit .preview-sidebar-nav { body.outfits-edit .preview-sidebar-nav {
float: right; float: right;
font-size: 85%; font-size: 85%;
margin-right: 24px; margin-right: 24px;
margin-top: 1em; margin-top: 1em;
} }
/* line 621, ../../../app/stylesheets/outfits/_edit.sass */ /* line 631, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sidebar #preview-sidebar-navbar-closet { body.outfits-edit #preview-sidebar #preview-sidebar-navbar-closet {
background: white; background: white;
border-bottom-color: white; border-bottom-color: white;
font-weight: bold; font-weight: bold;
} }
/* line 625, ../../../app/stylesheets/outfits/_edit.sass */ /* line 635, ../../../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 { body.outfits-edit #preview-sidebar.viewing-outfits #preview-sidebar-navbar-closet, body.outfits-edit #preview-sidebar.sharing #preview-sidebar-navbar-closet {
background: transparent; background: transparent;
border-bottom: 1px solid #aaddaa; border-bottom: 1px solid #aaddaa;
font-weight: normal; font-weight: normal;
} }
/* line 628, ../../../app/stylesheets/outfits/_edit.sass */ /* line 638, ../../../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 { body.outfits-edit #preview-sidebar.viewing-outfits #preview-sidebar-navbar-outfits, body.outfits-edit #preview-sidebar.sharing #preview-sidebar-navbar-sharing {
background: white; background: white;
border-bottom-color: white; border-bottom-color: white;
font-weight: bold; font-weight: bold;
} }
/* line 631, ../../../app/stylesheets/outfits/_edit.sass */ /* line 641, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sidebar-navbar { body.outfits-edit #preview-sidebar-navbar {
-moz-border-radius: 10px 10px 0 0; -moz-border-radius: 10px 10px 0 0;
-webkit-border-radius: 10px 10px 0 0; -webkit-border-radius: 10px 10px 0 0;
@ -3168,7 +3182,7 @@ body.outfits-edit #preview-sidebar-navbar {
body.outfits-edit #preview-sidebar-navbar { body.outfits-edit #preview-sidebar-navbar {
display: block; display: block;
} }
/* line 640, ../../../app/stylesheets/outfits/_edit.sass */ /* line 650, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sidebar-navbar > div { body.outfits-edit #preview-sidebar-navbar > div {
background: transparent; background: transparent;
border-bottom: 1px solid #aaddaa; border-bottom: 1px solid #aaddaa;
@ -3180,11 +3194,11 @@ body.outfits-edit #preview-sidebar-navbar > div {
text-align: center; text-align: center;
width: 132px; width: 132px;
} }
/* line 649, ../../../app/stylesheets/outfits/_edit.sass */ /* line 659, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sidebar-navbar > div:first-child { body.outfits-edit #preview-sidebar-navbar > div:first-child {
border-left: 0; border-left: 0;
} }
/* line 652, ../../../app/stylesheets/outfits/_edit.sass */ /* line 662, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sidebar-content { body.outfits-edit #preview-sidebar-content {
-moz-border-radius: 0 0 10px 10px; -moz-border-radius: 0 0 10px 10px;
-webkit-border-radius: 0 0 10px 10px; -webkit-border-radius: 0 0 10px 10px;
@ -3196,7 +3210,7 @@ body.outfits-edit #preview-sidebar-content {
border-top: 0; border-top: 0;
overflow: auto; overflow: auto;
} }
/* line 658, ../../../app/stylesheets/outfits/_edit.sass */ /* line 668, ../../../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 { 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-left: 24px;
margin-right: 24px; margin-right: 24px;
@ -3204,7 +3218,7 @@ body.outfits-edit #save-success, body.outfits-edit #save-error, body.outfits-edi
margin-top: 1em; margin-top: 1em;
text-align: center; text-align: center;
} }
/* line 665, ../../../app/stylesheets/outfits/_edit.sass */ /* line 675, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sidebar-donation-request { body.outfits-edit #preview-sidebar-donation-request {
background: #e6efc2; background: #e6efc2;
border: 1px solid #c6d880; border: 1px solid #c6d880;
@ -3212,23 +3226,23 @@ body.outfits-edit #preview-sidebar-donation-request {
font-size: 85%; font-size: 85%;
padding: 1em; padding: 1em;
} }
/* line 670, ../../../app/stylesheets/outfits/_edit.sass */ /* line 680, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sidebar-donation-request-no-thanks { body.outfits-edit #preview-sidebar-donation-request-no-thanks {
margin-left: 1em; margin-left: 1em;
} }
/* line 673, ../../../app/stylesheets/outfits/_edit.sass */ /* line 683, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #save-success { body.outfits-edit #save-success {
background: #e6efc2; background: #e6efc2;
border: 1px solid #c6d880; border: 1px solid #c6d880;
color: #264409; color: #264409;
} }
/* line 676, ../../../app/stylesheets/outfits/_edit.sass */ /* line 686, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #save-error, body.outfits-edit #outfit-not-found { body.outfits-edit #save-error, body.outfits-edit #outfit-not-found {
background: #fbe3e4; background: #fbe3e4;
border: 1px solid #fbc2c4; border: 1px solid #fbc2c4;
color: #8a1f11; color: #8a1f11;
} }
/* line 679, ../../../app/stylesheets/outfits/_edit.sass */ /* line 689, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #userbar-message { body.outfits-edit #userbar-message {
-moz-opacity: 0.5; -moz-opacity: 0.5;
-webkit-opacity: 0.5; -webkit-opacity: 0.5;
@ -3236,7 +3250,7 @@ body.outfits-edit #userbar-message {
-khtml-opacity: 0.5; -khtml-opacity: 0.5;
display: none; display: none;
} }
/* line 683, ../../../app/stylesheets/outfits/_edit.sass */ /* line 693, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #new-outfit { body.outfits-edit #new-outfit {
padding: 0.25em 0; padding: 0.25em 0;
margin-left: 24px; margin-left: 24px;
@ -3422,28 +3436,28 @@ body.outfits-edit #new-outfit.renaming:hover .outfit-rename-button {
body.outfits-edit #new-outfit:hover .outfit-rename-button { body.outfits-edit #new-outfit:hover .outfit-rename-button {
display: inline; display: inline;
} }
/* line 687, ../../../app/stylesheets/outfits/_edit.sass */ /* line 697, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #new-outfit h4 { body.outfits-edit #new-outfit h4 {
display: inline; display: inline;
} }
/* line 689, ../../../app/stylesheets/outfits/_edit.sass */ /* line 699, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #new-outfit h4:hover { body.outfits-edit #new-outfit h4:hover {
text-decoration: none; text-decoration: none;
} }
/* line 691, ../../../app/stylesheets/outfits/_edit.sass */ /* line 701, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #new-outfit .outfit-star { body.outfits-edit #new-outfit .outfit-star {
margin-top: 0.5em; margin-top: 0.5em;
} }
/* line 694, ../../../app/stylesheets/outfits/_edit.sass */ /* line 704, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #new-outfit-name { body.outfits-edit #new-outfit-name {
font: inherit; font: inherit;
line-height: 1; line-height: 1;
} }
/* line 698, ../../../app/stylesheets/outfits/_edit.sass */ /* line 708, ../../../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 { 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; position: relative;
} }
/* line 701, ../../../app/stylesheets/outfits/_edit.sass */ /* line 711, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit .control-overlay { body.outfits-edit .control-overlay {
height: 100%; height: 100%;
left: 0; left: 0;
@ -3452,11 +3466,11 @@ body.outfits-edit .control-overlay {
width: 100%; width: 100%;
z-index: 5; z-index: 5;
} }
/* line 709, ../../../app/stylesheets/outfits/_edit.sass */ /* line 719, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-sidebar-nav-outfits, body.outfits-edit #save-outfit-signed-in { body.outfits-edit #preview-sidebar-nav-outfits, body.outfits-edit #save-outfit-signed-in {
display: none; display: none;
} }
/* line 712, ../../../app/stylesheets/outfits/_edit.sass */ /* line 722, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit form#save-outfit-form { body.outfits-edit form#save-outfit-form {
padding: 0.25em 0; padding: 0.25em 0;
display: none; display: none;
@ -3642,7 +3656,7 @@ body.outfits-edit form#save-outfit-form.renaming:hover .outfit-rename-button {
body.outfits-edit form#save-outfit-form:hover .outfit-rename-button { body.outfits-edit form#save-outfit-form:hover .outfit-rename-button {
display: inline; display: inline;
} }
/* line 718, ../../../app/stylesheets/outfits/_edit.sass */ /* line 728, ../../../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 { 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; display: -moz-inline-box;
-moz-box-orient: vertical; -moz-box-orient: vertical;
@ -3656,46 +3670,46 @@ body.outfits-edit form#save-outfit-form .outfit-star, body.outfits-edit form#sav
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 { 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; *display: inline;
} }
/* line 723, ../../../app/stylesheets/outfits/_edit.sass */ /* line 733, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit form#save-outfit-form .outfit-star { body.outfits-edit form#save-outfit-form .outfit-star {
margin-top: 0.25em; margin-top: 0.25em;
} }
/* line 726, ../../../app/stylesheets/outfits/_edit.sass */ /* line 736, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit .outfit-url { body.outfits-edit .outfit-url {
font-size: 75%; font-size: 75%;
} }
/* line 729, ../../../app/stylesheets/outfits/_edit.sass */ /* line 739, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #preview-search-form-error { body.outfits-edit #preview-search-form-error {
background: #fbe3e4; background: #fbe3e4;
border: 1px solid #fbc2c4; border: 1px solid #fbc2c4;
color: #8a1f11; color: #8a1f11;
padding: 0.25em 0.5em; padding: 0.25em 0.5em;
} }
/* line 734, ../../../app/stylesheets/outfits/_edit.sass */ /* line 744, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit.user-signed-in #preview-sidebar-nav-outfits { body.outfits-edit.user-signed-in #preview-sidebar-nav-outfits {
display: block; display: block;
} }
/* line 736, ../../../app/stylesheets/outfits/_edit.sass */ /* line 746, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit.user-signed-in #save-outfit { body.outfits-edit.user-signed-in #save-outfit {
display: inline-block; display: inline-block;
} }
/* line 740, ../../../app/stylesheets/outfits/_edit.sass */ /* line 750, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-outfit { body.outfits-edit.user-signed-in #save-outfit-wrapper.active-outfit #save-outfit {
display: none; display: none;
} }
/* line 742, ../../../app/stylesheets/outfits/_edit.sass */ /* line 752, ../../../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 { 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; display: inline-block;
} }
/* line 750, ../../../app/stylesheets/outfits/_edit.sass */ /* line 760, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit-form { body.outfits-edit.user-signed-in #save-outfit-wrapper.saving-outfit #save-outfit-form {
display: block; display: block;
} }
/* line 752, ../../../app/stylesheets/outfits/_edit.sass */ /* line 762, ../../../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 { 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; display: none;
} }
/* line 754, ../../../app/stylesheets/outfits/_edit.sass */ /* line 764, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit.user-signed-in .preview-search-form-your-items { body.outfits-edit.user-signed-in .preview-search-form-your-items {
display: -moz-inline-box; display: -moz-inline-box;
-moz-box-orient: vertical; -moz-box-orient: vertical;
@ -3707,23 +3721,23 @@ body.outfits-edit.user-signed-in .preview-search-form-your-items {
body.outfits-edit.user-signed-in .preview-search-form-your-items { body.outfits-edit.user-signed-in .preview-search-form-your-items {
*display: inline; *display: inline;
} }
/* line 756, ../../../app/stylesheets/outfits/_edit.sass */ /* line 766, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit.user-signed-in #preview-outfits-not-logged-in { body.outfits-edit.user-signed-in #preview-outfits-not-logged-in {
display: none; display: none;
} }
/* line 758, ../../../app/stylesheets/outfits/_edit.sass */ /* line 768, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit.user-signed-in #preview-outfits-list { body.outfits-edit.user-signed-in #preview-outfits-list {
display: block; display: block;
} }
/* line 762, ../../../app/stylesheets/outfits/_edit.sass */ /* line 772, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit.user-not-signed-in #save-outfit-not-signed-in { body.outfits-edit.user-not-signed-in #save-outfit-not-signed-in {
display: inline-block; display: inline-block;
} }
/* line 766, ../../../app/stylesheets/outfits/_edit.sass */ /* line 776, ../../../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 { 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; display: inline-block;
} }
/* line 768, ../../../app/stylesheets/outfits/_edit.sass */ /* line 778, ../../../app/stylesheets/outfits/_edit.sass */
body.outfits-edit #save-outfit-wrapper.shared-outfit #current-outfit-permalink { body.outfits-edit #save-outfit-wrapper.shared-outfit #current-outfit-permalink {
display: none !important; display: none !important;
} }