Skip to content

Commit

Permalink
Add featured product section (Shopify#261)
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasLacerdaUX authored Aug 19, 2021
1 parent 9789ae1 commit 7a2f34f
Show file tree
Hide file tree
Showing 65 changed files with 3,019 additions and 238 deletions.
5 changes: 3 additions & 2 deletions assets/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,6 @@ deferred-media {
.share-button {
display: block;
position: relative;
max-width: 31rem;
}

.share-button details {
Expand All @@ -1218,7 +1217,8 @@ deferred-media {
.share-button__button {
font-size: 1.4rem;
display: flex;
align-items: baseline;
min-height: 2.4rem;
align-items: center;
color: rgba(var(--color-link), var(--alpha-link));
margin-left: 0;
padding-left: 0;
Expand Down Expand Up @@ -1257,6 +1257,7 @@ details[open] > .share-button__fallback {
left: 0.1rem;
z-index: 3;
width: 100%;
min-width: 31rem;
box-shadow: 0 0 0 0.1rem rgba(var(--color-foreground), 0.55);
}

Expand Down
1 change: 1 addition & 0 deletions assets/component-pickup-availability.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pickup-availability[available] {
color: rgba(var(--color-foreground), 0.75);
letter-spacing: 0.06rem;
padding: 0 0 0.2rem;
text-align: left;
text-decoration: underline;
}

Expand Down
2 changes: 1 addition & 1 deletion assets/component-product-model.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
}

@media screen and (min-width: 750px) {
.product__media-wrapper > .button.product__xr-button {
slider-component + .button.product__xr-button {
display: none;
}

Expand Down
2 changes: 1 addition & 1 deletion assets/global.js
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ class VariantSelects extends HTMLElement {
}

updateURL() {
if (!this.currentVariant) return;
if (!this.currentVariant || this.dataset.updateUrl === 'false') return;
window.history.replaceState({ }, '', `${this.dataset.url}?variant=${this.currentVariant.id}`);
}

Expand Down
174 changes: 87 additions & 87 deletions assets/pickup-availability.js
Original file line number Diff line number Diff line change
@@ -1,100 +1,100 @@
class PickupAvailability extends HTMLElement {
constructor() {
super();

if(!this.hasAttribute('available')) return;

this.errorHtml = this.querySelector('template').content.firstElementChild.cloneNode(true);
this.onClickRefreshList = this.onClickRefreshList.bind(this);
this.fetchAvailability(this.dataset.variantId);
}

fetchAvailability(variantId) {
const variantSectionUrl = `${this.dataset.baseUrl}variants/${variantId}/?section_id=pickup-availability`;

fetch(variantSectionUrl)
.then(response => response.text())
.then(text => {
const sectionInnerHTML = new DOMParser()
.parseFromString(text, 'text/html')
.querySelector('.shopify-section');
this.renderPreview(sectionInnerHTML);
})
.catch(e => {
this.querySelector('button')?.removeEventListener('click', this.onClickRefreshList);
this.renderError();
});
}

onClickRefreshList(evt) {
this.fetchAvailability(this.dataset.variantId);
}

renderError() {
this.innerHTML = '';
this.appendChild(this.errorHtml);

this.querySelector('button').addEventListener('click', this.onClickRefreshList);
}

renderPreview(sectionInnerHTML) {
const drawer = document.querySelector('pickup-availability-drawer');
if (drawer) drawer.remove();
if (!sectionInnerHTML.querySelector('pickup-availability-preview')) {
this.innerHTML = "";
this.removeAttribute('available');
return;
if (!customElements.get('pickup-availability')) {
customElements.define('pickup-availability', class PickupAvailability extends HTMLElement {
constructor() {
super();

if(!this.hasAttribute('available')) return;

this.errorHtml = this.querySelector('template').content.firstElementChild.cloneNode(true);
this.onClickRefreshList = this.onClickRefreshList.bind(this);
this.fetchAvailability(this.dataset.variantId);
}

fetchAvailability(variantId) {
const variantSectionUrl = `${this.dataset.baseUrl}variants/${variantId}/?section_id=pickup-availability`;

fetch(variantSectionUrl)
.then(response => response.text())
.then(text => {
const sectionInnerHTML = new DOMParser()
.parseFromString(text, 'text/html')
.querySelector('.shopify-section');
this.renderPreview(sectionInnerHTML);
})
.catch(e => {
this.querySelector('button')?.removeEventListener('click', this.onClickRefreshList);
this.renderError();
});
}

onClickRefreshList(evt) {
this.fetchAvailability(this.dataset.variantId);
}

renderError() {
this.innerHTML = '';
this.appendChild(this.errorHtml);

this.querySelector('button').addEventListener('click', this.onClickRefreshList);
}

this.innerHTML = sectionInnerHTML.querySelector('pickup-availability-preview').outerHTML;
this.setAttribute('available', '');
renderPreview(sectionInnerHTML) {
const drawer = document.querySelector('pickup-availability-drawer');
if (drawer) drawer.remove();
if (!sectionInnerHTML.querySelector('pickup-availability-preview')) {
this.innerHTML = "";
this.removeAttribute('available');
return;
}

document.body.appendChild(sectionInnerHTML.querySelector('pickup-availability-drawer'));
this.innerHTML = sectionInnerHTML.querySelector('pickup-availability-preview').outerHTML;
this.setAttribute('available', '');

this.querySelector('button').addEventListener('click', (evt) => {
document.querySelector('pickup-availability-drawer').show(evt.target);
});
}
document.body.appendChild(sectionInnerHTML.querySelector('pickup-availability-drawer'));

this.querySelector('button').addEventListener('click', (evt) => {
document.querySelector('pickup-availability-drawer').show(evt.target);
});
}
});
}

customElements.define('pickup-availability', PickupAvailability);
if (!customElements.get('pickup-availability-drawer')) {
customElements.define('pickup-availability-drawer', class PickupAvailabilityDrawer extends HTMLElement {
constructor() {
super();

class PickupAvailabilityDrawer extends HTMLElement {
constructor() {
super();
this.onBodyClick = this.handleBodyClick.bind(this);

this.querySelector('button').addEventListener('click', () => {
this.hide();
});

this.onBodyClick = this.handleBodyClick.bind(this);
this.addEventListener('keyup', () => {
if(event.code.toUpperCase() === 'ESCAPE') this.hide();
});
}

this.querySelector('button').addEventListener('click', () => {
this.hide();
});
handleBodyClick(evt) {
const target = evt.target;
if (target != this && !target.closest('pickup-availability-drawer') && target.id != 'ShowPickupAvailabilityDrawer') {
this.hide();
}
}

this.addEventListener('keyup', () => {
if(event.code.toUpperCase() === 'ESCAPE') this.hide();
});
}
hide() {
this.removeAttribute('open');
document.body.removeEventListener('click', this.onBodyClick);
document.body.classList.remove('overflow-hidden');
removeTrapFocus(this.focusElement);
}

handleBodyClick(evt) {
const target = evt.target;
if (target != this && !target.closest('pickup-availability-drawer') && target.id != 'ShowPickupAvailabilityDrawer') {
this.hide();
show(focusElement) {
this.focusElement = focusElement;
this.setAttribute('open', '');
document.body.addEventListener('click', this.onBodyClick);
document.body.classList.add('overflow-hidden');
trapFocus(this);
}
}

hide() {
this.removeAttribute('open');
document.body.removeEventListener('click', this.onBodyClick);
document.body.classList.remove('overflow-hidden');
removeTrapFocus(this.focusElement);
}

show(focusElement) {
this.focusElement = focusElement;
this.setAttribute('open', '');
document.body.addEventListener('click', this.onBodyClick);
document.body.classList.add('overflow-hidden');
trapFocus(this);
}
});
}

customElements.define('pickup-availability-drawer', PickupAvailabilityDrawer);
66 changes: 33 additions & 33 deletions assets/product-form.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
class ProductForm extends HTMLElement {
constructor() {
super();
if (!customElements.get('product-form')) {
customElements.define('product-form', class ProductForm extends HTMLElement {
constructor() {
super();

this.form = this.querySelector('form');
this.form.addEventListener('submit', this.onSubmitHandler.bind(this));
this.cartNotification = document.querySelector('cart-notification');
}
this.form = this.querySelector('form');
this.form.addEventListener('submit', this.onSubmitHandler.bind(this));
this.cartNotification = document.querySelector('cart-notification');
}

onSubmitHandler(evt) {
evt.preventDefault();
this.cartNotification.setActiveElement(document.activeElement);

const submitButton = this.querySelector('[type="submit"]');
onSubmitHandler(evt) {
evt.preventDefault();
this.cartNotification.setActiveElement(document.activeElement);

submitButton.setAttribute('disabled', true);
submitButton.classList.add('loading');
const submitButton = this.querySelector('[type="submit"]');

const body = JSON.stringify({
...JSON.parse(serializeForm(this.form)),
sections: this.cartNotification.getSectionsToRender().map((section) => section.id),
sections_url: window.location.pathname
});
submitButton.setAttribute('disabled', true);
submitButton.classList.add('loading');

fetch(`${routes.cart_add_url}`, { ...fetchConfig('javascript'), body })
.then((response) => response.json())
.then((parsedState) => {
this.cartNotification.renderContents(parsedState);
})
.catch((e) => {
console.error(e);
})
.finally(() => {
submitButton.classList.remove('loading');
submitButton.removeAttribute('disabled');
const body = JSON.stringify({
...JSON.parse(serializeForm(this.form)),
sections: this.cartNotification.getSectionsToRender().map((section) => section.id),
sections_url: window.location.pathname
});
}
}

customElements.define('product-form', ProductForm);
fetch(`${routes.cart_add_url}`, { ...fetchConfig('javascript'), body })
.then((response) => response.json())
.then((parsedState) => {
this.cartNotification.renderContents(parsedState);
})
.catch((e) => {
console.error(e);
})
.finally(() => {
submitButton.classList.remove('loading');
submitButton.removeAttribute('disabled');
});
}
});
}
39 changes: 20 additions & 19 deletions assets/product-model.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
class ProductModel extends DeferredMedia {
constructor() {
super();
}
if (!customElements.get('product-model')) {
customElements.define('product-model', class ProductModel extends DeferredMedia {
constructor() {
super();
}

loadContent() {
super.loadContent();
loadContent() {
super.loadContent();

Shopify.loadFeatures([
{
name: 'model-viewer-ui',
version: '1.0',
onLoad: this.setupModelViewerUI.bind(this),
},
]);
}
Shopify.loadFeatures([
{
name: 'model-viewer-ui',
version: '1.0',
onLoad: this.setupModelViewerUI.bind(this),
},
]);
}

setupModelViewerUI(errors) {
if (errors) return;
setupModelViewerUI(errors) {
if (errors) return;

this.modelViewerUI = new Shopify.ModelViewerUI(this.querySelector('model-viewer'));
}
this.modelViewerUI = new Shopify.ModelViewerUI(this.querySelector('model-viewer'));
}
});
}
customElements.define('product-model', ProductModel);

window.ProductModel = {
loadShopifyXR() {
Expand Down
Loading

0 comments on commit 7a2f34f

Please sign in to comment.