Skip to content
This repository has been archived by the owner on Jul 19, 2021. It is now read-only.

Update to sections and variant js #24

Merged
merged 7 commits into from
Oct 20, 2016
Merged

Conversation

stevebosworth
Copy link
Contributor

@Shopify/themes-fed

  • Updates Slate to use variants.js instead of option_selection.js
  • Adds sections.js
  • Switched product template to a section

@stevebosworth stevebosworth self-assigned this Oct 17, 2016
var $container = this.$container = $(container);

this.settings = {
enableHistoryState: $container.data('enable-history-state'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default to true if data attribute not set

this.variants = new slate.Variants(options);

this.$container.on('variantChange' + this.settings.eventNamespace, this.updateVariantSelection.bind(this));

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whitespace 👮

*/
updateVariantSelection: function(evt) {
var variant = evt.variant;
console.log(variant);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔥

* @param {boolean} enabeled - Decides whether cart is enabled or disabled
* @param {string} text - Updates the text notification content of the cart
*/
updateAddToCartState: function(enabeled, text) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spelling: "enabled"

console.log(variant);
// Update cart button and text status
if (!variant) {
this.updateAddToCartState(false, theme.strings.unavailable);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sending true/false here is confusing because you have to go find the function to see what it is. I'd recommend this.updateAddToCartState(theme.strings.unavailable, 'disabled'); — if the second param is not set it can stay as the default enabled/true

*
* @param {object} product - Product object
*/
simplifyVariantLabels: function(product) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be done in Liquid now

* @param {string} src - Image src URL
*/
updateProductImage: function(src) {
var sizedImgUrl = slate.Image.getSizedImageUrl(src, this.settings.imageSize);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set the main image's size as part of this.settings so that if we want to preload images we already know what size to load

var currentOptions = this._getCurrentOptions();
this.currentVariant = this._getVariantFromOptions(currentOptions);

$(this.selectors.singleOptionSelector).on('change', this._onSelectChange.bind(this));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit strange that this required selector is merely a part of this.settings rather than it's own option. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya, i was thinking about that. might make more sense to pass in the two required selectors explicitly. I don't see the number of selectors ballooning down the road

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just the one required selector, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

originalSelectorId and singleOptionSelector

@@ -0,0 +1,100 @@
<div id="ProductSection-{{ section.id }}" data-section-id="{{ section.id }}" data-section-type="product" itemscope itemtype="http://schema.org/Product">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id not needed for anything

eventNamespace: '.product'
};

this.selectors = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably add sectionId to these selectors, knowing we're likely to have a "Featured product" home page section eventually

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about that, I think we'd want to build that out as part of slate or just leave it as is... let's discuss during our planning session

@@ -20,12 +20,14 @@ slate.Variants = (function() {
this.$container = options.$container;
this.product = options.product;
this.selectors = options.selectors;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this.selectors with the latest update

@@ -20,12 +20,14 @@ slate.Variants = (function() {
this.$container = options.$container;
this.product = options.product;
this.selectors = options.selectors;
this.singleOptionSelector = options.singleOptionSelector;
this.originalSelectorId = options.originalSelectorId;
this.settings = options.settings;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can remove this.settings in favour of this.enableHistoryState since that's the only one we actually use

eventNamespace: '.product'
};

this.selectors = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been bugging me - why are we placing the selectors inside the constructor? It bloats it so much 😢

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case it's not needed, but it will be if we add sectionId to the selectors like in Debut to support multiple product sections on the page.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You really shouldn't need to add sectionId to every selector - just the container, no? Reduces the complexity of both our JS and Liquid.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switch them to classes and that would work yea 👍


// Stop parsing if we don't have the product json script tag when loading
// section in the Theme Editor
if (!$('#ProductJson').html()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why aren't we using a selector here

initVariants: function() {
var options = {
$container: this.$container,
settings: this.settings,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is settings a standard object? i.e. Do we always know what's inside of it? Kind of vague passing an object like this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, I updated to use named options instead of passing in objects from the product

};

// eslint-disable-next-line no-new
this.variants = new slate.Variants(options);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is options used anywhere else? Why not inline it and drop the variable declaration?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly have no preference between these two approaches and can think of arguments supporting both. 👍 for inline object, 🎉 for separate var?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slight preference to options var, but not much. This is how I always did it in WordPress land with args passed to helpers

// eslint-disable-next-line no-new
this.variants = new slate.Variants(options);

this.$container.on('variantChange' + this.settings.eventNamespace, this.updateAddToCartState.bind(this));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Realized we don't have to be as careful with event handlers as I originally thought. Only with event handlers that are tied to document. Event handlers are cleaned up by the garbage collector when the object it is bound too is removed from the DOM. Source

I think we no longer need the namespacing (in most cases).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh that's interesting! 🤔 I do like being able to call off(this.settings.eventNamespace) for TE events though. I wonder if the TE always rebuilds the DOM or not though... we might not need to remove any events that aren't attached to document in the onUnload event...

this.$container = options.$container;
this.product = options.product;
this.selectors = options.selectors;
this.singleOptionSelector = options.singleOptionSelector;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still feel like we should have defaults set for these options so that you don't need to include them when initializing unless they are different from the default values. How often do you use a different selector across themes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to avoid hardcoding things like that into variant.js since you may want different selectors depending on how you build the DOM. It think these values should be set in the themes product.js instead. One example would be radio buttons vs non-radio button. Also if you decide not to use BEM it's one more place to track down a class name.

this.settings = options.settings;

var currentOptions = this._getCurrentOptions();
this.currentVariant = this._getVariantFromOptions(currentOptions);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We never got to combining these two functions? _getCurrentOptions() and _getVariantFromOptions()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's a good idea to combine them now that _getCurrentOptions is a little more complicated, but i think you're right about them being tied together so I moved _getCurrentOptions() callsite inside _getVariantFromOptions

}
});

options = _.filter(options);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this doing? It has no truth test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's removing unchecked values (if you're using a radio button), looking through lodash again, _.compact is a better choice. The values returned in the array are a string or false so this works too but is maybe a bit confusing.

* @return {k} [description]
*/
_updateHistoryState: function(variant) {
if (!history.pushState || !variant) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably also be checking for replaceState()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one doesn't really exist without the other but I can switch this to replaceState since that's what we're using

@stevebosworth stevebosworth force-pushed the update-variant-js branch 2 times, most recently from 06b783a to 704ccd7 Compare October 19, 2016 18:30
@cshold
Copy link
Contributor

cshold commented Oct 19, 2016

error Unexpected template string expression no-template-curly-in-string

In currency.js. Warnings can be fixed in another PR. 👍

@bertiful
Copy link
Contributor

There's a few other warnings as well.

🚢

t-kelly pushed a commit that referenced this pull request Jul 31, 2017
* suggested updates for CLI help content

* updates based on PR feedback

* adding back missing aliases
t-kelly pushed a commit that referenced this pull request Jul 31, 2017
* suggested updates for CLI help content

* updates based on PR feedback

* adding back missing aliases
t-kelly pushed a commit that referenced this pull request Jul 31, 2017
* suggested updates for CLI help content

* updates based on PR feedback

* adding back missing aliases
@lock
Copy link

lock bot commented Oct 26, 2018

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Oct 26, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants