Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions components/block-cart-note/assets/block-cart-note.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,27 @@
export class CartNote extends HTMLElement {
import { HTMLSectionElement } from '@archetype-themes/custom-elements/section'

export class CartNote extends HTMLSectionElement {
connectedCallback() {
super.connectedCallback()
this.addEventListener('change', this.handleChange.bind(this))
}

onBlockSelect() {
this.style.outline = '2px solid coral'
}

onBlockDeselect() {
this.style.outline = 'none'
}

async handleChange({ target }) {
if (target.getAttribute('name') !== 'note') return

await this.updateCart({ note: target.value })
}

async updateCart(body) {
const response = await fetch(`${window.Shopify.routes.root}cart/update.js`, {
const response = await fetch(`${Shopify.routes.root}cart/update.js`, {
method: 'POST',
headers: { 'Content-type': 'application/json' },
body: JSON.stringify(body),
Expand Down
84 changes: 84 additions & 0 deletions scripts/custom-elements/section.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const ThemeEditorEventHandlerMixin = (Base) =>
class extends Base {
connectedCallback() {
if (Shopify.designMode) {
this.boundEventMap = this.createThemeEditorEventMap()

Object.entries(this.boundEventMap).forEach(([event, boundHandler]) => {
const target = event.includes('section') ? document : this
target.addEventListener(event, boundHandler)
})

if (typeof this.onSectionLoad === 'function') {
this.onSectionLoad()
}
}
}

disconnectedCallback() {
if (Shopify.designMode) {
Object.entries(this.boundEventMap).forEach(([event, boundHandler]) => {
if (event.includes('section')) {
document.removeEventListener(event, boundHandler)
}
})

if (typeof this.onSectionUnload === 'function') {
this.onSectionUnload()
}
}
}

createThemeEditorEventMap() {
const events = [
'shopify:section:select',
'shopify:section:deselect',
'shopify:section:reorder',
'shopify:block:select',
'shopify:block:deselect'
]

return events.reduce((acc, eventName) => {
const methodName = this.convertEventToMethodName(eventName)

if (typeof this[methodName] === 'function') {
acc[eventName] = this.createEventBoundHandler(this[methodName])
}

return acc
}, {})
}

convertEventToMethodName(eventName) {
const capitalize = (str) => {
return str.charAt(0).toUpperCase() + str.slice(1)
}

return `on${eventName.split(':').slice(1).map(capitalize).join('')}`
}

createEventBoundHandler(handler) {
return (event) => {
if (event.detail && event.detail.sectionId === this.sectionId) {
handler.call(this, event)
}
}
}
}

class Section extends HTMLElement {
get sectionId() {
if (!this._sectionId) {
this._sectionId = this.getAttribute('section-id') || this.extractSectionId(this)
}

return this._sectionId
}

extractSectionId(element) {
element = element.classList.contains('shopify-section') ? element : element.closest('.shopify-section')
return element.id.replace('shopify-section-', '')
}
}

export class HTMLSectionElement extends ThemeEditorEventHandlerMixin(Section) {}