Skip to content
This repository has been archived by the owner on Oct 24, 2023. It is now read-only.

Commit

Permalink
Merge pull request #19 from sbounmy/default_to_master_variant
Browse files Browse the repository at this point in the history
display master price if variants are all out-of-stock - thanks @sbounmy
  • Loading branch information
citrus committed Mar 8, 2012
2 parents cfa0831 + e68df07 commit fb79382
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 63 deletions.
70 changes: 37 additions & 33 deletions app/assets/javascripts/store/variant_options.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,58 +31,58 @@ if (!Array.find_matches) Array.find_matches = function(a) {
}

function VariantOptions(options, allow_backorders) {

var options = options;
var allow_backorders = allow_backorders;
var variant, divs, parent, index = 0;
var selection = [];

function init() {
divs = $('#product-variants .variant-options');
divs = $('#product-variants .variant-options');
disable(divs.find('a.option-value').addClass('locked'));
update();
enable(parent.find('a.option-value'));
toggle();
$('.clear-option a.clear-button').hide().click(handle_clear);
}

function get_index(parent) {
return parseInt($(parent).attr('class').replace(/[^\d]/g, ''));
}

function update(i) {
index = isNaN(i) ? index : i;
parent = $(divs.get(index));
buttons = parent.find('a.option-value');
parent.find('a.clear-button').hide();
}

function disable(btns) {
return btns.removeClass('selected');
}

function enable(btns) {
return btns.not('.unavailable').removeClass('locked').unbind('click').filter('.in-stock').click(handle_click).filter('.auto-click').removeClass('auto-click').click();
}

function advance() {
index++
update();
update();
inventory(buttons.removeClass('locked'));
enable(buttons.filter('.in-stock'));
}

function inventory(btns) {
var keys, variants, count = 0, selected = {};
var sels = $.map(divs.find('a.selected'), function(i) { return i.rel });
var sels = $.map(divs.find('a.selected'), function(i) { return i.rel });
$.each(sels, function(key, value) {
key = value.split('-');
var v = options[key[0]][key[1]];
keys = $.keys(v);
var m = Array.find_matches(selection.concat(keys));
if (selection.length == 0) {
selection = keys;
} else if (m) {
} else if (m) {
selection = m;
}
});
Expand All @@ -98,11 +98,11 @@ function VariantOptions(options, allow_backorders) {
$(element).addClass('in-stock');
} else {
$.each(variants, function(key, value) { count += value.count });
$(element).addClass(count ? 'in-stock' : 'out-of-stock');
$(element).addClass(count ? 'in-stock' : 'out-of-stock');
}
});
}

function get_variant_objects(rels) {
var i, ids, obj, variants = {};
if (typeof(rels) == 'string') { rels = [rels]; }
Expand Down Expand Up @@ -130,14 +130,14 @@ function VariantOptions(options, allow_backorders) {
}
} catch(error) {
//console.log(error);
}
}
return variants;
}

function to_f(string) {
return parseFloat(string.replace(/[^\d\.]/g, ''));
}

function find_variant() {
var selected = divs.find('a.selected');
var variants = get_variant_objects(selected.get(0).rel);
Expand All @@ -150,31 +150,35 @@ function VariantOptions(options, allow_backorders) {
return to_f(a) < to_f(b) ? -1 : 1;
});
if (prices.length == 1) {
$('#product-price .price').html('<span class="price assumed">' + prices[0] + '</span>');
} else {
$('#product-price .price').html('<span class="price assumed">' + prices[0] + '</span>');
} else {
$('#product-price .price').html('<span class="price from">' + prices[0] + '</span> - <span class="price to">' + prices[prices.length - 1] + '</span>');
}
return false;
}
}

function toggle() {
if (variant) {
$('#variant_id').val(variant.id);
$('#product-price .price').removeClass('unselected').text(variant.price);
$('button[type=submit]').attr('disabled', false).fadeTo(100, 1);
$('#product-price .price').removeClass('unselected').text(variant.price);
$('#cart-form button[type=submit]').attr('disabled', false).fadeTo(100, 1);
try {
show_variant_images(variant.id);
} catch(error) {
// depends on modified version of product.js
// depends on modified version of product.js
}
} else {
$('#variant_id').val('');
$('button[type=submit]').attr('disabled', true).fadeTo(0, 0.5);
$('#product-price .price').addClass('unselected').text('(select)');
}
$('#cart-form button[type=submit]').attr('disabled', true).fadeTo(0, 0.5);
price = $('#product-price .price').addClass('unselected')
// Replace product price by "(select)" only when there are at least 1 variant not out-of-stock
variants = $("div.variant-options.index-0")
if (variants.find("a.option-value.out-of-stock").length != variants.find("a.option-value").length)
price.text('(select)');
}
}

function clear(i) {
variant = null;
update(i);
Expand All @@ -186,20 +190,20 @@ function VariantOptions(options, allow_backorders) {
});
show_all_variant_images();
}


function handle_clear(evt) {
evt.preventDefault();
clear(get_index(this));
}

function handle_click(evt) {
evt.preventDefault();
variant = null;
selection = [];
var a = $(this);
if (!parent.has(a).length) {
clear(divs.index(a.parents('.variant-options:first')));
clear(divs.index(a.parents('.variant-options:first')));
}
disable(buttons);
var a = enable(a.addClass('selected'));
Expand All @@ -209,7 +213,7 @@ function VariantOptions(options, allow_backorders) {
toggle();
}
}

$(document).ready(init);

};
47 changes: 28 additions & 19 deletions features/spree/variant_options.feature
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
@javascript
Feature: Products should have variant options

In order to purchase a product
As a customer
I want to select a variant

Scenario: Display options when visiting a product
Given I have a product with variants
And I'm on the product page for the first product
Expand All @@ -13,13 +13,13 @@ Feature: Products should have variant options
And I should see disabled links for the second option type
And I should have a hidden input for the selected variant
And the add to cart button should be disabled

Scenario: Display option images when visiting a product
Given I have a product with variants
And the first option type has an option value with image "1.jpg"
And I'm on the product page for the first product
Then I should see image "1.jpg" within the first option value

Scenario: Interact with options for a product
Given I have a product with variants
And I'm on the product page for the first product
Expand All @@ -33,7 +33,7 @@ Feature: Products should have variant options
And the add to cart button should be disabled
When I follow "Red" within the second set of options
And the add to cart button should be enabled

Scenario: Should show out of stock for appropriate variants
Given I don't allow backorders
And I have a product with variants
Expand All @@ -42,7 +42,7 @@ Feature: Products should have variant options
When I follow "Small" within the first set of options
Then I should see an out-of-stock link for "Green"
And I should see an in-stock link for "Red, Blue, Black, White, Gray"

Scenario: Should allow backorders of in stock variants
Given I allow backorders
And I have a product with variants
Expand All @@ -51,16 +51,16 @@ Feature: Products should have variant options
When I follow "Small" within the first set of options
Then I should see an in-stock link for "Green"
And I should see an in-stock link for "Red, Blue, Black, White, Gray"

Scenario: Should clear current selection
Given I have a product with variants
And I'm on the product page for the first product
When I follow "Small" within the first set of options
And I click the current clear button
Then I should see disabled links for the second option type
And I should see enabled links for the first option type
Scenario: Should clear current selection and maintain parent selection

Scenario: Should clear current selection and maintain parent selection
Given I have a product with variants
And I'm on the product page for the first product
When I follow "Small" within the first set of options
Expand All @@ -70,8 +70,8 @@ Feature: Products should have variant options
Then I should see "Small" selected within the first set of options
And I should see enabled links for the second option type
And the add to cart button should be disabled
Scenario: Should clear current selection and parent selection

Scenario: Should clear current selection and parent selection
Given I have a product with variants
And I'm on the product page for the first product
When I follow "Small" within the first set of options
Expand All @@ -82,7 +82,7 @@ Feature: Products should have variant options
And I should see disabled links for the second option type
And I should see enabled links for the first option type
And the add to cart button should be disabled

Scenario: Should add proper variant to cart
Given I have a product with variants
And I'm on the product page for the first product
Expand All @@ -92,17 +92,17 @@ Feature: Products should have variant options
And I press "Add To Cart"
Then I should be on the cart page
And I should see "Size: Small, Color: Green"

Scenario: Should auto-select variant if its the only option
Given I have a product with variants
And I have an "XXL Turquoise" variant
And I'm on the product page for the first product
When I follow "XXL" within the first set of options
Then I should see "Turquoise" selected within the second set of options
And the add to cart button should be enabled
When I follow "Small" within the first set of options
When I follow "Small" within the first set of options
Then the add to cart button should be disabled

Scenario: Should adjust price according to variant
Given I have a product with variants
And I have an "XXS Turquoise" variant for $29.99
Expand All @@ -116,14 +116,23 @@ Feature: Products should have variant options
When I follow "Pink" within the second set of options
Then I should see "$24.99" in the price
And the add to cart button should be enabled


Scenario: Should show the master price when all variants are out of stock
Given I don't allow backorders
And I have a product with variants
And all the variants are out of stock
And I have a "master" variant for $20.99
When I'm on the product page for the first product
And I should see an out-of-stock link for "Small, Medium, Large, X-Large"
And I should see disabled links for the second option type
Then I should see "$20.99" in the price

#Scenario: Should show variant images when a selection is made
# Given I have a product with variants and images
# And I'm on the product page for the first product
# When I follow "Small" within the first set of options
# And I follow "Green" within the second set of options
# Then the add to cart button should be enabled
# And I should see "Small Green" in the variant images label
# And I should see "Small Green" in the variant images label
# When I follow "Red" within the second set of options
# Then I should see "Small Red" in the variant images label

# Then I should see "Small Red" in the variant images label
30 changes: 19 additions & 11 deletions features/step_definitions/variant_options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def random_image
@product.variants.each do |v|
v.images.create(:attachment => random_image, :alt => v.sku)
end
end
end
end
end

Expand All @@ -57,18 +57,26 @@ def random_image
@variant.update_attributes(:count_on_hand => 0)
end

Given /^all the variants are out of stock$/ do
@product.variants.update_all(:count_on_hand => 0)
end

Given /^I have an? "([^"]*)" variant( for .*)?$/ do |descriptor, price|
price = price ? price.gsub(/[^\d\.]/, '').to_f : 10.00
values = descriptor.split(" ")
flunk unless @product && values.length == @product.option_types.length
@variant = variant_by_descriptor(descriptor)
return @variant if @variant
@product.option_type_ids.each_with_index do |otid, index|
word = values[index]
val = Spree::OptionValue.find_by_presentation(word) || Factory.create(:option_value, :option_type_id => otid, :presentation => word, :name => word.downcase)
values[index] = val
if descriptor == "master"
@product.master.update_attributes(:price => price)
else
values = descriptor.split(" ")
flunk unless @product && values.length == @product.option_types.length
@variant = variant_by_descriptor(descriptor)
return @variant if @variant
@product.option_type_ids.each_with_index do |otid, index|
word = values[index]
val = Spree::OptionValue.find_by_presentation(word) || Factory.create(:option_value, :option_type_id => otid, :presentation => word, :name => word.downcase)
values[index] = val
end
@variant = Factory.create(:variant, :product => @product, :option_values => values, :price => price)
end
@variant = Factory.create(:variant, :product => @product, :option_values => values, :price => price)
@product.reload
end

Expand Down Expand Up @@ -109,7 +117,7 @@ def random_image
assert_equal "#", link.native.attribute('href').last
assert_equal "option-value #{enabled ? 'in-stock' : 'locked'}", link.native.attribute('class')
assert_equal rel, link.native.attribute('rel') # obviously!
end
end
end

Then /^I should have a hidden input for the selected variant$/ do
Expand Down

0 comments on commit fb79382

Please sign in to comment.