├── docs ├── CNAME ├── _includes │ ├── head │ │ ├── content-post.html │ │ ├── content-pre.html │ │ ├── stylesheets-post.html │ │ ├── stylesheets-pre.html │ │ ├── stylesheets.html │ │ ├── base.html │ │ ├── full.html │ │ └── content.html │ ├── sidebar │ │ ├── content-post.html │ │ ├── content-pre.html │ │ └── content.html │ ├── svg-icon.html │ ├── v2 │ │ ├── content │ │ │ ├── lifecycle-reference.html │ │ │ ├── lifecycle-events-reference.html │ │ │ ├── links-to-request-methods.html │ │ │ ├── sections-event-code-example.html │ │ │ ├── event-request-start-example.html │ │ │ ├── queue-end-use-cases.html │ │ │ ├── init-event-example.html │ │ │ ├── cart-loading-state-css-example.html │ │ │ ├── cart-state-json-example.html │ │ │ ├── add-to-cart-class-example.html │ │ │ ├── form-loading-state-block.html │ │ │ ├── request-options-object.html │ │ │ └── request-end-use-cases.html │ │ ├── codeblock.html │ │ ├── styles │ │ │ ├── footer.scss │ │ │ ├── quote.scss │ │ │ ├── tabs.scss │ │ │ ├── side-menu.scss │ │ │ ├── cards.scss │ │ │ ├── critical.scss │ │ │ └── codeblock.scss │ │ ├── last-release-file-name.html │ │ └── footer.html │ ├── footer │ │ ├── content-post.html │ │ ├── content-pre.html │ │ ├── scripts-post.html │ │ ├── scripts-pre.html │ │ ├── full.html │ │ └── scripts.html │ ├── code │ │ ├── data-ajax-cart-form-error.html │ │ ├── js-ajax-cart-form-in-progress.html │ │ ├── state.html │ │ ├── data-ajax-cart-bind-state.html │ │ ├── last-release-file-name.html │ │ └── request-options-object.html │ ├── fa-icon.html │ ├── facebook.html │ ├── svg │ │ └── download.svg │ ├── twitter.html │ ├── google-analytics.html │ ├── masthead.html │ ├── disqus.html │ ├── styles │ │ ├── containers.scss │ │ ├── masthead.scss │ │ └── sidebar.scss │ ├── internal │ │ └── variables.html │ ├── jekyll-docs-theme │ │ ├── anchor_headings.html │ │ └── toc.html │ ├── home │ │ └── youtube-link.css │ └── navigation.html ├── _sass │ ├── base │ │ ├── _horizontal-rule.scss │ │ ├── _blockquote.scss │ │ └── _anchor.scss │ ├── abstracts │ │ ├── _variables.scss │ │ └── _themer.scss │ └── components │ │ ├── _mobile-toc.scss │ │ ├── _footer.scss │ │ └── _highlight.scss ├── v2 │ ├── index.md │ ├── docs │ │ ├── index.md │ │ ├── releases.md │ │ ├── cart-section.md │ │ ├── event-init.md │ │ ├── installation.md │ │ ├── js-snippets.md │ │ ├── product-forms.md │ │ ├── request-event.md │ │ ├── request-state.md │ │ ├── binder-formatters.md │ │ ├── event-queue-end.md │ │ ├── event-queue-start.md │ │ ├── event-request-end.md │ │ ├── js-ajax-cart-init.md │ │ ├── liquid-ajax-cart.md │ │ ├── queue-of-requests.md │ │ ├── ajax-cart-quantity.md │ │ ├── data-ajax-cart-bind.md │ │ ├── differences-from-v1.md │ │ ├── event-request-start.md │ │ ├── js-ajax-cart-empty.md │ │ ├── request-error-text.md │ │ ├── ajax-cart-product-form.md │ │ ├── cart-totals-in-header.md │ │ ├── data-ajax-cart-errors.md │ │ ├── data-ajax-cart-section.md │ │ ├── js-ajax-cart-not-empty.md │ │ ├── lifecycle-events-api.md │ │ ├── liquid-ajax-cart-add.md │ │ ├── liquid-ajax-cart-cart.md │ │ ├── liquid-ajax-cart-clear.md │ │ ├── liquid-ajax-cart-conf.md │ │ ├── liquid-ajax-cart-get.md │ │ ├── liquid-ajax-cart-init.md │ │ ├── update-on-window-focus.md │ │ ├── data-ajax-cart-quantity-minus.md │ │ ├── data-ajax-cart-quantity-plus.md │ │ ├── js-ajax-cart-processing.md │ │ ├── liquid-ajax-cart-change.md │ │ ├── liquid-ajax-cart-update.md │ │ ├── liquid-ajax-cart-processing.md │ │ ├── data-ajax-cart-initial-state.md │ │ ├── data-ajax-cart-property-input.md │ │ ├── data-ajax-cart-quantity-input.md │ │ ├── data-ajax-cart-request-button.md │ │ ├── data-ajax-cart-section-scroll.md │ │ └── data-ajax-cart-static-element.md │ ├── releases │ │ └── index.md │ ├── event-init.md │ ├── liquid-ajax-cart-init.md │ ├── liquid-ajax-cart-get.md │ ├── quantity-tag-debounce.md │ ├── js-ajax-cart-empty.md │ ├── request-error-text.md │ ├── js-ajax-cart-not-empty.md │ ├── js-ajax-cart-processing.md │ ├── quantity-tag-allow-zero.md │ ├── liquid-ajax-cart-clear.md │ ├── liquid-ajax-cart-conf.md │ ├── liquid-ajax-cart-update.md │ ├── data-ajax-cart-initial-state.md │ ├── liquid-ajax-cart-add.md │ ├── liquid-ajax-cart-change.md │ ├── event-queue-start.md │ ├── js-snippets.md │ ├── ajax-cart-product-form.md │ ├── liquid-ajax-cart-processing.md │ ├── js-ajax-cart-init.md │ ├── update-on-window-focus.md │ ├── binder-formatters.md │ ├── liquid-ajax-cart-cart.md │ ├── liquid-ajax-cart.md │ ├── data-ajax-cart-quantity-plus.md │ ├── data-ajax-cart-quantity-minus.md │ ├── extra-request-on-error.md │ └── event-queue-end.md ├── guide.md ├── examples.md ├── .gitignore ├── googlec36874fccad31125.html ├── releases │ └── index.md ├── v1 │ ├── reference │ │ ├── index.md │ │ ├── getCartState.md │ │ ├── js-ajax-cart-empty.md │ │ ├── js-ajax-cart-set.md │ │ ├── js-ajax-cart-not-empty.md │ │ ├── cartRequestGet.md │ │ ├── cartRequestClear.md │ │ ├── js-ajax-cart-form-in-progress.md │ │ ├── js-ajax-cart-not-compatible.md │ │ ├── product-forms.md │ │ ├── js-ajax-cart-request-in-progress.md │ │ ├── body-css-classes.md │ │ ├── cartRequestUpdate.md │ │ ├── cartRequestChange.md │ │ ├── cartRequestAdd.md │ │ ├── productFormsFilter.md │ │ ├── data-ajax-cart-bind-state.md │ │ ├── data-ajax-cart-initial-state.md │ │ ├── requestErrorText.md │ │ ├── subscribeToCartStateUpdate.md │ │ ├── requests.md │ │ ├── configure.md │ │ ├── subscribeToCartSectionsUpdate.md │ │ ├── stateBinderFormatters.md │ │ ├── data-ajax-cart-quantity-input.md │ │ ├── data-ajax-cart-section-scroll.md │ │ ├── data-ajax-cart-toggle-class-button.md │ │ ├── updateOnWindowFocus.md │ │ ├── addToCartCssClass.md │ │ └── sections.md │ └── index.md ├── reference │ ├── index.md │ ├── queues.md │ ├── state.md │ ├── controls.md │ ├── requests.md │ ├── sections.md │ ├── configure.md │ ├── getCartState.md │ ├── product-forms.md │ ├── requestState.md │ ├── body-css-classes.md │ ├── cartRequestAdd.md │ ├── cartRequestClear.md │ ├── cartRequestGet.md │ ├── js-ajax-cart-set.md │ ├── messageBuilder.md │ ├── requestErrorText.md │ ├── addToCartCssClass.md │ ├── cartRequestChange.md │ ├── cartRequestUpdate.md │ ├── js-ajax-cart-empty.md │ ├── productFormsFilter.md │ ├── stateBinderFormatters.md │ ├── updateOnWindowFocus.md │ ├── data-ajax-cart-messages.md │ ├── data-ajax-cart-section.md │ ├── js-ajax-cart-not-empty.md │ ├── data-ajax-cart-bind-state.md │ ├── subscribeToCartStateUpdate.md │ ├── data-ajax-cart-initial-state.md │ ├── js-ajax-cart-not-compatible.md │ ├── subscribeToCartAjaxRequests.md │ ├── data-ajax-cart-property-input.md │ ├── data-ajax-cart-quantity-input.md │ ├── data-ajax-cart-request-button.md │ ├── data-ajax-cart-section-scroll.md │ ├── data-ajax-cart-static-element.md │ ├── js-ajax-cart-form-in-progress.md │ ├── subscribeToCartSectionsUpdate.md │ ├── js-ajax-cart-request-in-progress.md │ └── data-ajax-cart-toggle-class-button.md ├── robots.txt ├── Gemfile ├── assets │ ├── screens │ │ ├── bks.jpg │ │ ├── ce.jpg │ │ ├── beau.jpg │ │ ├── getalt.jpg │ │ ├── khaite.jpg │ │ ├── mahsa.jpg │ │ ├── novus.jpg │ │ ├── quip.jpg │ │ ├── rubynz.jpg │ │ ├── sadi.jpg │ │ ├── talia.jpg │ │ ├── acmecups.jpg │ │ ├── alastin.jpg │ │ ├── arizona.jpg │ │ ├── becuming.jpg │ │ ├── edikted.jpg │ │ ├── nestera.jpg │ │ ├── alephbeauty.jpg │ │ ├── drinknatz.jpg │ │ ├── eigenhain.jpg │ │ ├── goodcounsel.jpg │ │ ├── kitandace.jpg │ │ ├── lafavorita.jpg │ │ ├── lovemypulse.jpg │ │ ├── middlehurst.jpg │ │ ├── seatosummit.jpg │ │ ├── starforge.jpg │ │ ├── twoislands.jpg │ │ ├── deadlyponies.jpg │ │ ├── emmalewisham.jpg │ │ ├── jonopandolfi.jpg │ │ ├── nakedcashmere.jpg │ │ ├── acornfurniture.jpg │ │ ├── bluntumbrellas.jpg │ │ ├── brandonblackwood.jpg │ │ ├── lytteltonlights.jpg │ │ ├── nightworksstudio.jpg │ │ └── lucasbauerjewellery.jpg │ ├── images │ │ ├── readme.gif │ │ └── roberto-aresena.jpg │ ├── js │ │ └── docs.js │ └── css │ │ └── styles.scss ├── index.md ├── _layouts │ └── full.html ├── sitemap.xml └── jekyll-docs-theme.gemspec ├── templates ├── index.liquid ├── 404.liquid ├── page.full-width-no-heading.liquid ├── blog.liquid ├── cart.liquid ├── article.liquid ├── product.liquid ├── password.liquid ├── page.no-heading.liquid ├── list-collections.liquid ├── page.full-width.liquid ├── page.liquid ├── collection.liquid └── customers │ ├── reset_password.liquid │ ├── activate_account.liquid │ ├── register.liquid │ └── account.liquid ├── assets ├── icons.eot ├── icons.ttf ├── icons.woff ├── password-page-background.jpg └── ico-select.svg.liquid ├── snippets ├── css-variables.liquid ├── mobile-nav-icons.liquid ├── collection-sorting.liquid ├── tags-article.liquid ├── comment.liquid ├── blog-sidebar.liquid ├── image-style.liquid ├── featured-blog.liquid ├── product-properties.liquid ├── product-unit-price.liquid ├── pagination-custom.liquid ├── onboarding-featured-blog.liquid ├── newsletter-form.liquid ├── collection-tags.liquid └── search-bar.liquid ├── sections └── dynamic-cart.liquid ├── tsconfig.json ├── _src ├── const.ts ├── controls.ts ├── helpers.ts ├── global-classes.ts ├── settings.ts ├── controls │ └── product-form-element.ts └── state.ts ├── .gitignore ├── .github └── FUNDING.yml ├── webpack.config.js ├── package.json └── screenshot.js /docs/CNAME: -------------------------------------------------------------------------------- 1 | liquid-ajax-cart.js.org -------------------------------------------------------------------------------- /docs/_includes/head/content-post.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/_includes/head/content-pre.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/_includes/head/stylesheets-post.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/_includes/head/stylesheets-pre.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/_includes/sidebar/content-post.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/_includes/sidebar/content-pre.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/_sass/base/_horizontal-rule.scss: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /templates/index.liquid: -------------------------------------------------------------------------------- 1 | {{ content_for_index }} 2 | -------------------------------------------------------------------------------- /docs/v2/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: / 4 | --- -------------------------------------------------------------------------------- /docs/guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/guide/ 4 | --- -------------------------------------------------------------------------------- /docs/examples.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/examples/ 4 | --- -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle 3 | .idea 4 | .sass-cache 5 | _site 6 | Gemfile.lock -------------------------------------------------------------------------------- /docs/googlec36874fccad31125.html: -------------------------------------------------------------------------------- 1 | google-site-verification: googlec36874fccad31125.html -------------------------------------------------------------------------------- /docs/releases/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/releases 4 | --- -------------------------------------------------------------------------------- /docs/v1/reference/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Reference 3 | layout: reference-content 4 | --- -------------------------------------------------------------------------------- /docs/reference/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/installation/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/releases.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/releases/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/releases/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/releases/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/queues.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/queues/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/state.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/state/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/cart-section.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/cart-section/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/event-init.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/event-init/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/installation/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/js-snippets.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/js-snippets/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/controls.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/controls/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/requests.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/requests/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/sections.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/sections/ 4 | --- -------------------------------------------------------------------------------- /docs/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow: / 3 | 4 | Sitemap: https://liquid-ajax-cart.js.org/sitemap.xml -------------------------------------------------------------------------------- /docs/v2/docs/product-forms.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/product-forms/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/request-event.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/event-request/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/request-state.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/request-state/ 4 | --- -------------------------------------------------------------------------------- /assets/icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/assets/icons.eot -------------------------------------------------------------------------------- /assets/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/assets/icons.ttf -------------------------------------------------------------------------------- /assets/icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/assets/icons.woff -------------------------------------------------------------------------------- /docs/reference/configure.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/configure/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/binder-formatters.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/binder-formatters/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/event-queue-end.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/event-queue-end/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/event-queue-start.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/event-queue-start/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/event-request-end.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/event-request-end/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/js-ajax-cart-init.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/js-ajax-cart-init/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/liquid-ajax-cart.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/liquid-ajax-cart/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/queue-of-requests.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/queue-of-requests/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/getCartState.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/getCartState/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/product-forms.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/product-forms/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/requestState.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/requestState/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/ajax-cart-quantity.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/ajax-cart-quantity/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/data-ajax-cart-bind.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/data-ajax-cart-bind/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/differences-from-v1.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/differences-from-v1/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/event-request-start.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/event-request-start/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/js-ajax-cart-empty.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/js-ajax-cart-empty/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/request-error-text.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/request-error-text/ 4 | --- -------------------------------------------------------------------------------- /docs/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | gemspec 3 | gem "kramdown-parser-gfm" 4 | gem "webrick", "~> 1.8" 5 | -------------------------------------------------------------------------------- /docs/reference/body-css-classes.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/body-css-classes/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/cartRequestAdd.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/cartRequestAdd/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/cartRequestClear.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/cartRequestClear/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/cartRequestGet.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/cartRequestGet/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/js-ajax-cart-set.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/js-ajax-cart-set/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/messageBuilder.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/messageBuilder/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/requestErrorText.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/requestErrorText/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/ajax-cart-product-form.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/ajax-cart-product-form/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/cart-totals-in-header.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/cart-totals-in-header/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/data-ajax-cart-errors.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/data-ajax-cart-errors/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/data-ajax-cart-section.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/data-ajax-cart-section/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/js-ajax-cart-not-empty.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/js-ajax-cart-not-empty/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/lifecycle-events-api.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/lifecycle-events-api/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/liquid-ajax-cart-add.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/liquid-ajax-cart-add/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/liquid-ajax-cart-cart.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/liquid-ajax-cart-cart/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/liquid-ajax-cart-clear.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/liquid-ajax-cart-clear/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/liquid-ajax-cart-conf.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/liquid-ajax-cart-conf/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/liquid-ajax-cart-get.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/liquid-ajax-cart-get/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/liquid-ajax-cart-init.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/liquid-ajax-cart-init/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/update-on-window-focus.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/update-on-window-focus/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/addToCartCssClass.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/addToCartCssClass/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/cartRequestChange.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/cartRequestChange/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/cartRequestUpdate.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/cartRequestUpdate/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/js-ajax-cart-empty.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/js-ajax-cart-empty/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/productFormsFilter.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/productFormsFilter/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/data-ajax-cart-quantity-minus.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/data-ajax-cart-minus/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/data-ajax-cart-quantity-plus.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/data-ajax-cart-plus/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/js-ajax-cart-processing.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/js-ajax-cart-processing/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/liquid-ajax-cart-change.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/liquid-ajax-cart-change/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/liquid-ajax-cart-update.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/liquid-ajax-cart-update/ 4 | --- -------------------------------------------------------------------------------- /docs/assets/screens/bks.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/bks.jpg -------------------------------------------------------------------------------- /docs/assets/screens/ce.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/ce.jpg -------------------------------------------------------------------------------- /docs/reference/stateBinderFormatters.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/stateBinderFormatters/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/updateOnWindowFocus.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/updateOnWindowFocus/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/liquid-ajax-cart-processing.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/liquid-ajax-cart-processing/ 4 | --- -------------------------------------------------------------------------------- /docs/assets/images/readme.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/images/readme.gif -------------------------------------------------------------------------------- /docs/assets/screens/beau.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/beau.jpg -------------------------------------------------------------------------------- /docs/assets/screens/getalt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/getalt.jpg -------------------------------------------------------------------------------- /docs/assets/screens/khaite.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/khaite.jpg -------------------------------------------------------------------------------- /docs/assets/screens/mahsa.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/mahsa.jpg -------------------------------------------------------------------------------- /docs/assets/screens/novus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/novus.jpg -------------------------------------------------------------------------------- /docs/assets/screens/quip.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/quip.jpg -------------------------------------------------------------------------------- /docs/assets/screens/rubynz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/rubynz.jpg -------------------------------------------------------------------------------- /docs/assets/screens/sadi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/sadi.jpg -------------------------------------------------------------------------------- /docs/assets/screens/talia.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/talia.jpg -------------------------------------------------------------------------------- /docs/reference/data-ajax-cart-messages.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/data-ajax-cart-messages/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/data-ajax-cart-section.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/data-ajax-cart-section/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/js-ajax-cart-not-empty.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/js-ajax-cart-not-empty/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/data-ajax-cart-initial-state.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/data-ajax-cart-initial-state/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/data-ajax-cart-property-input.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/data-ajax-cart-property-input/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/data-ajax-cart-quantity-input.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/data-ajax-cart-quantity-input/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/data-ajax-cart-request-button.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/data-ajax-cart-request-button/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/data-ajax-cart-section-scroll.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/data-ajax-cart-section-scroll/ 4 | --- -------------------------------------------------------------------------------- /docs/v2/docs/data-ajax-cart-static-element.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v2/data-ajax-cart-static-element/ 4 | --- -------------------------------------------------------------------------------- /docs/_includes/head/stylesheets.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/assets/screens/acmecups.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/acmecups.jpg -------------------------------------------------------------------------------- /docs/assets/screens/alastin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/alastin.jpg -------------------------------------------------------------------------------- /docs/assets/screens/arizona.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/arizona.jpg -------------------------------------------------------------------------------- /docs/assets/screens/becuming.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/becuming.jpg -------------------------------------------------------------------------------- /docs/assets/screens/edikted.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/edikted.jpg -------------------------------------------------------------------------------- /docs/assets/screens/nestera.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/nestera.jpg -------------------------------------------------------------------------------- /docs/reference/data-ajax-cart-bind-state.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/data-ajax-cart-bind-state/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/subscribeToCartStateUpdate.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/subscribeToCartStateUpdate/ 4 | --- -------------------------------------------------------------------------------- /assets/password-page-background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/assets/password-page-background.jpg -------------------------------------------------------------------------------- /docs/assets/screens/alephbeauty.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/alephbeauty.jpg -------------------------------------------------------------------------------- /docs/assets/screens/drinknatz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/drinknatz.jpg -------------------------------------------------------------------------------- /docs/assets/screens/eigenhain.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/eigenhain.jpg -------------------------------------------------------------------------------- /docs/assets/screens/goodcounsel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/goodcounsel.jpg -------------------------------------------------------------------------------- /docs/assets/screens/kitandace.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/kitandace.jpg -------------------------------------------------------------------------------- /docs/assets/screens/lafavorita.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/lafavorita.jpg -------------------------------------------------------------------------------- /docs/assets/screens/lovemypulse.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/lovemypulse.jpg -------------------------------------------------------------------------------- /docs/assets/screens/middlehurst.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/middlehurst.jpg -------------------------------------------------------------------------------- /docs/assets/screens/seatosummit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/seatosummit.jpg -------------------------------------------------------------------------------- /docs/assets/screens/starforge.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/starforge.jpg -------------------------------------------------------------------------------- /docs/assets/screens/twoislands.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/twoislands.jpg -------------------------------------------------------------------------------- /docs/reference/data-ajax-cart-initial-state.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/data-ajax-cart-initial-state/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/js-ajax-cart-not-compatible.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/js-ajax-cart-not-compatible/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/subscribeToCartAjaxRequests.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/subscribeToCartAjaxRequests/ 4 | --- -------------------------------------------------------------------------------- /docs/assets/screens/deadlyponies.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/deadlyponies.jpg -------------------------------------------------------------------------------- /docs/assets/screens/emmalewisham.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/emmalewisham.jpg -------------------------------------------------------------------------------- /docs/assets/screens/jonopandolfi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/jonopandolfi.jpg -------------------------------------------------------------------------------- /docs/assets/screens/nakedcashmere.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/nakedcashmere.jpg -------------------------------------------------------------------------------- /docs/reference/data-ajax-cart-property-input.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/data-ajax-cart-property-input/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/data-ajax-cart-quantity-input.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/data-ajax-cart-quantity-input/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/data-ajax-cart-request-button.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/data-ajax-cart-request-button/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/data-ajax-cart-section-scroll.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/data-ajax-cart-section-scroll/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/data-ajax-cart-static-element.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/data-ajax-cart-static-element/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/js-ajax-cart-form-in-progress.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/js-ajax-cart-form-in-progress/ 4 | --- -------------------------------------------------------------------------------- /docs/reference/subscribeToCartSectionsUpdate.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/subscribeToCartSectionsUpdate/ 4 | --- -------------------------------------------------------------------------------- /docs/assets/images/roberto-aresena.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/images/roberto-aresena.jpg -------------------------------------------------------------------------------- /docs/assets/screens/acornfurniture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/acornfurniture.jpg -------------------------------------------------------------------------------- /docs/assets/screens/bluntumbrellas.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/bluntumbrellas.jpg -------------------------------------------------------------------------------- /docs/assets/screens/brandonblackwood.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/brandonblackwood.jpg -------------------------------------------------------------------------------- /docs/assets/screens/lytteltonlights.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/lytteltonlights.jpg -------------------------------------------------------------------------------- /docs/assets/screens/nightworksstudio.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/nightworksstudio.jpg -------------------------------------------------------------------------------- /docs/reference/js-ajax-cart-request-in-progress.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/js-ajax-cart-request-in-progress/ 4 | --- -------------------------------------------------------------------------------- /templates/404.liquid: -------------------------------------------------------------------------------- 1 |

{{ 'general.404.title' | t }}

2 |

{{ 'general.404.subtext_html' | t: link: routes.all_products_collection_url }}

3 | -------------------------------------------------------------------------------- /docs/reference/data-ajax-cart-toggle-class-button.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default-v2 3 | redirect_url: /v1/reference/data-ajax-cart-toggle-class-button/ 4 | --- -------------------------------------------------------------------------------- /docs/assets/screens/lucasbauerjewellery.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EvgeniyMukhamedjanov/liquid-ajax-cart/HEAD/docs/assets/screens/lucasbauerjewellery.jpg -------------------------------------------------------------------------------- /docs/_includes/svg-icon.html: -------------------------------------------------------------------------------- 1 | 2 | {% assign icon_path = "svg/" | append: include.icon | append: ".svg" %} 3 | {% include {{ icon_path }} %} 4 | -------------------------------------------------------------------------------- /templates/page.full-width-no-heading.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Regular page content goes here. 3 | {% endcomment %} 4 |
5 | {{ page.content }} 6 |
7 | -------------------------------------------------------------------------------- /docs/_includes/head/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /templates/blog.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | The contents of the blog.liquid template can be found in /sections/blog-template.liquid 3 | {% endcomment %} 4 | 5 | {% section 'blog-template' %} 6 | -------------------------------------------------------------------------------- /templates/cart.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | The contents of the cart.liquid template can be found in /sections/cart-template.liquid 3 | {% endcomment %} 4 | 5 | {% section 'cart-template' %} 6 | -------------------------------------------------------------------------------- /snippets/css-variables.liquid: -------------------------------------------------------------------------------- 1 | {% style %} 2 | :root { 3 | --color-body-text: {{ settings.color_body_text }}; 4 | --color-body: {{ settings.color_body_bg }}; 5 | } 6 | {% endstyle %} 7 | -------------------------------------------------------------------------------- /docs/_includes/v2/content/lifecycle-reference.html: -------------------------------------------------------------------------------- 1 | The detailed explanation on how to interact with Liquid Ajax Cart using JavaScript 2 | is in the "[Lifecycle, events, API](/v2/lifecycle-events-api/)" guide. -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home-v2 3 | homepage: true 4 | description: A Javascript library for building Shopify Ajax-carts using Liquid templates 5 | title: Liquid Ajax Cart — Ajax Cart for Shopify 6 | --- -------------------------------------------------------------------------------- /templates/article.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | The contents of the article.liquid template can be found in /sections/article-template.liquid 3 | {% endcomment %} 4 | 5 | {% section 'article-template' %} 6 | -------------------------------------------------------------------------------- /docs/_includes/sidebar/content.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /docs/_includes/v2/content/lifecycle-events-reference.html: -------------------------------------------------------------------------------- 1 | The detailed explanation on when each event is fired and what exactly happens before and after each event 2 | is in the "[Lifecycle, events, API](/v2/lifecycle-events-api/)" guide. -------------------------------------------------------------------------------- /docs/_includes/footer/content-post.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | This file was intentionally left blank so that it can be overriden by theme 3 | developers. This file is loaded AFTER the footer's main body is loaded. 4 | {% endcomment %} 5 | -------------------------------------------------------------------------------- /docs/_includes/footer/content-pre.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | This file was intentionally left blank so that it can be overriden by theme 3 | developers. This file is loaded BEFORE the footer's main body is loaded. 4 | {% endcomment %} 5 | -------------------------------------------------------------------------------- /docs/_sass/abstracts/_variables.scss: -------------------------------------------------------------------------------- 1 | $background-color-dark: #252525 !default; 2 | $background-color-light: #ffffff !default; 3 | $color-dark: #d8d8d8 !default; 4 | $color-light: #222222 !default; 5 | 6 | $sidebar-border-width: 2px !default; 7 | -------------------------------------------------------------------------------- /sections/dynamic-cart.liquid: -------------------------------------------------------------------------------- 1 |
2 | {{ cart.item_count }} 3 |
4 | 5 | {% schema %} 6 | { 7 | "name": "Dynamic cart", 8 | "presets": [{ 9 | "name": "Dynamic cart" 10 | }] 11 | } 12 | {% endschema %} -------------------------------------------------------------------------------- /templates/product.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | The contents of the product.liquid template can be found in /sections/product-template.liquid 3 | {% endcomment %} 4 | 5 | {% section 'product-template' %} 6 | {% section 'product-recommendations' %} -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitAny": true, 4 | "module": "es6", 5 | "target": "es6", 6 | "allowJs": false, 7 | "moduleResolution": "node", 8 | "experimentalDecorators": true 9 | } 10 | } -------------------------------------------------------------------------------- /docs/_includes/footer/scripts-post.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | This file was intentionally left blank so that it can be overriden by theme 3 | developers. This file is loaded AFTER the theme's JavaScript files are loaded. 4 | {% endcomment %} 5 | -------------------------------------------------------------------------------- /docs/_includes/footer/scripts-pre.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | This file was intentionally left blank so that it can be overriden by theme 3 | developers. This file is loaded BEFORE the theme's JavaScript files are loaded. 4 | {% endcomment %} 5 | -------------------------------------------------------------------------------- /templates/password.liquid: -------------------------------------------------------------------------------- 1 | {% layout 'password' %} 2 | 3 | {% comment %} 4 | The contents of the password.liquid templates can be found in /sections 5 | {% endcomment %} 6 | 7 | {% section 'password-header' %} 8 | {% section 'password-content' %} 9 | -------------------------------------------------------------------------------- /docs/v1/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | homepage: true 4 | description: A Javascript library for building Shopify Ajax-carts using Liquid templates 5 | disable_anchors: true 6 | title: Liquid Ajax Cart — Ajax Cart for Shopify 7 | --- 8 | 9 | 10 | -------------------------------------------------------------------------------- /templates/page.no-heading.liquid: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 | {{ page.content }} 7 |
8 | 9 |
10 | 11 |
12 | -------------------------------------------------------------------------------- /_src/const.ts: -------------------------------------------------------------------------------- 1 | export const EVENT_PREFIX = 'liquid-ajax-cart'; 2 | export const DATA_ATTR_PREFIX = 'data-ajax-cart'; 3 | export const CUSTOM_ELEMENT_PREFIX = 'ajax-cart'; 4 | export const CSS_CLASS_PREFIX = 'js-ajax-cart'; 5 | export const EVENT_INIT = `${EVENT_PREFIX}:init`; -------------------------------------------------------------------------------- /docs/_layouts/full.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 |
6 |
7 | {% include jekyll-docs-theme/anchor_headings.html %} 8 |
9 | 10 | {% include disqus.html %} 11 |
12 | -------------------------------------------------------------------------------- /templates/list-collections.liquid: -------------------------------------------------------------------------------- 1 | 2 | {% comment %} 3 | The contents of the lists-collections.liquid template can be found in /sections/lists-collections-template.liquid 4 | {% endcomment %} 5 | 6 | {% section 'list-collections-template' %} 7 | -------------------------------------------------------------------------------- /templates/page.full-width.liquid: -------------------------------------------------------------------------------- 1 |
2 |

{{ page.title }}

3 |
4 | 5 | {% comment %} 6 | Regular page content goes here. 7 | {% endcomment %} 8 |
9 | {{ page.content }} 10 |
11 | -------------------------------------------------------------------------------- /docs/_includes/head/full.html: -------------------------------------------------------------------------------- 1 | {% include head/base.html %} 2 | 3 | {% include head/content-pre.html %} 4 | {% include head/content.html %} 5 | {% include head/content-post.html %} 6 | 7 | {% include head/stylesheets-pre.html %} 8 | {% include head/stylesheets.html %} 9 | {% include head/stylesheets-post.html %} 10 | -------------------------------------------------------------------------------- /docs/_includes/v2/content/links-to-request-methods.html: -------------------------------------------------------------------------------- 1 | the methods 2 | [`get`](/v2/liquid-ajax-cart-get/), 3 | [`add`](/v2/liquid-ajax-cart-add/), 4 | [`change`](/v2/liquid-ajax-cart-change/), 5 | [`update`](/v2/liquid-ajax-cart-update/), 6 | [`clear`](/v2/liquid-ajax-cart-clear/) 7 | of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object -------------------------------------------------------------------------------- /docs/_includes/code/data-ajax-cart-form-error.html: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | ```html 3 | {% form 'product', product %} 4 | 5 | 6 | 7 |
8 | 9 |
10 | {% endform %} 11 | ``` 12 | {% endraw %} -------------------------------------------------------------------------------- /docs/_includes/code/js-ajax-cart-form-in-progress.html: -------------------------------------------------------------------------------- 1 | ```css 2 | /* Make the submit button visually disabled */ 3 | form.js-ajax-cart-form-in-progress [type="submit"] { 4 | opacity: .7; 5 | } 6 | 7 | /* Show a loading indicator */ 8 | form.js-ajax-cart-form-in-progress:after { 9 | content: 'Adding to cart…' 10 | display: block; 11 | } 12 | ``` -------------------------------------------------------------------------------- /templates/page.liquid: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |

{{ page.title }}

7 |
8 | 9 |
10 | {{ page.content }} 11 |
12 | 13 |
14 | 15 |
16 | -------------------------------------------------------------------------------- /docs/_includes/v2/content/sections-event-code-example.html: -------------------------------------------------------------------------------- 1 | {%- capture highlight_code -%} 2 | document.addEventListener("liquid-ajax-cart:request-end", function(event) { 3 | const {sections} = event.detail; 4 | console.log("Sections are re-rendered: ", sections); 5 | }); 6 | {%- endcapture -%} 7 | {% include v2/codeblock.html title="script.js" language="javascript" code=highlight_code %} -------------------------------------------------------------------------------- /docs/_includes/fa-icon.html: -------------------------------------------------------------------------------- 1 | {% if include.icon %} 2 | {% capture fa_prefix -%} 3 | {%- if include.brand -%} 4 | fab 5 | {%- else -%} 6 | fas 7 | {%- endif -%} 8 | {%- endcapture -%} 9 | 13 | {% endif %} 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore all files starting with . or ~ 2 | .* 3 | ~* 4 | 5 | /node_modules 6 | /_npm 7 | /config.yml 8 | /notes.txt 9 | /liquid-ajax-cart.js 10 | 11 | # ignore packaged files 12 | *.7z 13 | *.dmg 14 | *.gz 15 | *.iso 16 | *.jar 17 | *.rar 18 | *.tar 19 | *.zip 20 | 21 | # track these files, if they exist 22 | !.gitignore 23 | !.editorconfig 24 | !README.md 25 | !CHANGELOG.md 26 | !composer.json -------------------------------------------------------------------------------- /docs/_includes/v2/content/event-request-start-example.html: -------------------------------------------------------------------------------- 1 | {%- capture highlight_code -%} 2 | document.addEventListener("liquid-ajax-cart:request-start", function(event) { 3 | const {requestState} = event.detail; 4 | 5 | // Print the requestState before the request is performed 6 | console.log(requestState); 7 | }); 8 | {%- endcapture -%} 9 | {% include v2/codeblock.html language="javascript" code=highlight_code %} -------------------------------------------------------------------------------- /snippets/mobile-nav-icons.liquid: -------------------------------------------------------------------------------- 1 | 5 | 9 | -------------------------------------------------------------------------------- /docs/_includes/facebook.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /docs/v1/reference/getCartState.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: getCartState() 3 | layout: page 4 | --- 5 | 6 | # getCartState() 7 | The `getCartState` function returns the current [State object](/v1/reference/state/). 8 | 9 | ```html 10 | 16 | ``` 17 | -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | --- 2 | layout: null 3 | --- 4 | 5 | 6 | {% for page in site.pages %} 7 | {% if page.name contains '.md' %} 8 | {% unless page.redirect_url %} 9 | 10 | {{ page.url | replace: 'index.html', '' | absolute_url }} 11 | 12 | {% endunless %} 13 | {% endif %} 14 | {% endfor %} 15 | -------------------------------------------------------------------------------- /docs/_includes/svg/download.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/_includes/footer/full.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | {% include footer/scripts-pre.html %} 8 | {% include footer/scripts.html %} 9 | {% include footer/scripts-post.html %} 10 | 11 | {% if site.analytics.google %} 12 | {% include google-analytics.html %} 13 | {% endif %} 14 | -------------------------------------------------------------------------------- /docs/_includes/twitter.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /snippets/collection-sorting.liquid: -------------------------------------------------------------------------------- 1 |
2 | 3 | 8 |
9 | -------------------------------------------------------------------------------- /docs/_includes/google-analytics.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/collection.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | The contents of the collection.liquid template can be found in /sections/collection-template.liquid 3 | {% endcomment %} 4 | 5 | {% section 'collection-template' %} 6 | 7 | 15 | -------------------------------------------------------------------------------- /docs/_includes/v2/content/queue-end-use-cases.html: -------------------------------------------------------------------------------- 1 | Use this event when you want to: 2 | * modify the page content when Liquid Ajax Cart has executed all the Shopify Cart API Ajax requests and switching back to the "idle" mode; 3 | * modify the cart state by performing an additional Shopify Cart API Ajax request based on a particular rule. 4 | 5 | Code examples with this event: 6 | * [Add a gift to the cart if the total price is $100 or higher](/v2/js-snippets/#add-a-gift-to-the-cart-if-the-total-price-is-100-or-higher); -------------------------------------------------------------------------------- /docs/v2/event-init.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: liquid-ajax-cart:init 3 | layout: docs-v2 4 | --- 5 | 6 | # liquid-ajax-cart:init 7 | 8 |

9 | An event which is fired at the `document` when Liquid Ajax Cart is initialized. 10 |

11 | 12 | ## Use case 13 | 14 | Use this event along with the [`liquidAjaxCart.init`](/v2/liquid-ajax-cart-init/) property 15 | when you want to run your JavaScript once Liquid Ajax Cart is initialized. 16 | 17 | {% include v2/content/init-event-example.html %} -------------------------------------------------------------------------------- /docs/_sass/base/_blockquote.scss: -------------------------------------------------------------------------------- 1 | blockquote { 2 | @include themer(border-bottom-color, ( 3 | 'dark': $site-ui-border-color-dark, 4 | 'light': $site-ui-border-color-light, 5 | )); 6 | 7 | @include themer(color, ( 8 | 'dark': rgba($color-dark, 60%), 9 | 'light': rgba($color-light, 60%), 10 | )); 11 | 12 | border-left-style: solid; 13 | border-left-width: 4px; 14 | padding: 0.5rem 1.25rem; 15 | 16 | *:last-child { 17 | margin-bottom: 0; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/v1/reference/js-ajax-cart-empty.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: .js-ajax-cart-empty 3 | layout: page 4 | --- 5 | 6 | # .js-ajax-cart-empty 7 | 8 | Liquid Ajax Cart adds the `js-ajax-cart-not-empty` CSS class to the `body` tag if the user’s cart is empty. 9 | 10 | Under the hood Liquid Ajax Cart checks the `status.cartStateSet` and the `cart.item_count` properties of the [`State`](/v1/reference/state/) object and adds the CSS class if the `status.cartStateSet` is `true` and the `cart.item_count` is `0`. Otherwise — it removes the CSS class. 11 | -------------------------------------------------------------------------------- /docs/v1/reference/js-ajax-cart-set.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: .js-ajax-cart-set 3 | layout: page 4 | --- 5 | 6 | # .js-ajax-cart-set 7 | 8 | Liquid Ajax Cart adds the `js-ajax-cart-set` CSS class to the `body` tag if Liquid Ajax Cart has been loaded and got information about a user’s cart state. 9 | 10 | Under the hood Liquid Ajax Cart checks the `status.cartStateSet` property of the [`State`](/v1/reference/state/) object and adds the CSS class if the `status.cartStateSet` value is `true` and removes the CSS class if the value is `false`. 11 | -------------------------------------------------------------------------------- /docs/_includes/v2/codeblock.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | {% if include.title %} 5 |
{{ include.title | escape }}
6 | {% endif %} 7 |
{{ include.code | strip | escape }}
8 | 9 |
10 | -------------------------------------------------------------------------------- /docs/v1/reference/js-ajax-cart-not-empty.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: .js-ajax-cart-not-empty 3 | layout: page 4 | --- 5 | 6 | # .js-ajax-cart-not-empty 7 | 8 | Liquid Ajax Cart adds the `js-ajax-cart-not-empty` CSS class to the `body` tag if the user’s cart is not empty. 9 | 10 | Under the hood Liquid Ajax Cart checks the `status.cartStateSet` and the `cart.item_count` properties of the [`State`](/v1/reference/state/) object and adds the CSS class if the `status.cartStateSet` is `true` and the `cart.item_count` is more than `0`. Otherwise — it removes the CSS class. 11 | -------------------------------------------------------------------------------- /docs/v1/reference/cartRequestGet.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: cartRequestGet() 3 | layout: page 4 | --- 5 | 6 | # cartRequestGet() 7 | 8 | Performs a request to the Shopify Cart API `GET /cart.js` endpoint. 9 | 10 | Takes the options object as the first parameter. 11 | 12 | ```html 13 | 20 | ``` 21 | 22 | {% include code/request-options-text.html %} -------------------------------------------------------------------------------- /docs/v2/liquid-ajax-cart-init.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: liquidAjaxCart.init 3 | layout: docs-v2 4 | --- 5 | 6 | # liquidAjaxCart.init 7 | 8 |

9 | A boolean read-only property of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object, 10 | which becomes `true` once Liquid Ajax Cart is initialized. 11 |

12 | 13 | ## Use case 14 | 15 | Use this property along with the [`liquid-ajax-cart:init`](/v2/event-init/) event 16 | when you want to run your JavaScript once Liquid Ajax Cart is initialized. 17 | 18 | {% include v2/content/init-event-example.html %} -------------------------------------------------------------------------------- /docs/_includes/v2/content/init-event-example.html: -------------------------------------------------------------------------------- 1 | {%- capture highlight_code -%} 2 | 3 | function runWhenInit() { 4 | console.log("The current cart state is: ", window.liquidAjaxCart.cart); 5 | } 6 | 7 | if (window.liquidAjaxCart?.init) { 8 | // if Liquid Ajax Cart is already initialized 9 | runWhenInit(); 10 | } else { 11 | // wait for Liquid Ajax Cart to be initialized 12 | document.addEventListener("liquid-ajax-cart:init", runWhenInit); 13 | } 14 | 15 | {%- endcapture -%} 16 | {% include v2/codeblock.html title="assets/script.js" language="javascript" code=highlight_code %} -------------------------------------------------------------------------------- /docs/_includes/v2/content/cart-loading-state-css-example.html: -------------------------------------------------------------------------------- 1 | {%- capture highlight_code -%} 2 | .my-cart__items { 3 | opacity: 1; 4 | transition: opacity .2s; 5 | } 6 | 7 | /* Make the cart content look visually disabled while updating */ 8 | html.js-ajax-cart-processing .my-cart__items { 9 | opacity: .7; 10 | } 11 | 12 | /* Show a loading indicator */ 13 | html.js-ajax-cart-processing .my-cart__items:before { 14 | content: 'Loading'; 15 | display: block; 16 | } 17 | 18 | {%- endcapture -%} 19 | {% include v2/codeblock.html title="assets/style.css" language="css" code=highlight_code %} -------------------------------------------------------------------------------- /docs/_sass/abstracts/_themer.scss: -------------------------------------------------------------------------------- 1 | @mixin themer($property, $values) { 2 | @if $site-ui-mode == 'auto' { 3 | @media (prefers-color-scheme: dark) { 4 | & { 5 | #{$property}: map-get($values, 'dark'); 6 | } 7 | } 8 | 9 | @media (prefers-color-scheme: light) { 10 | & { 11 | #{$property}: map-get($values, 'light'); 12 | } 13 | } 14 | } 15 | @else if $site-ui-mode == 'dark' or $site-ui-mode == 'light' { 16 | #{$property}: map-get($values, $site-ui-mode); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /_src/controls.ts: -------------------------------------------------------------------------------- 1 | import {cartProductFormElementInit} from './controls/product-form-element'; 2 | import {cartRequestButtonInit} from './controls/request-button'; 3 | import {cartQuantityInputInit} from './controls/quantity-input'; 4 | import {cartPropertyInputInit} from './controls/property-input'; 5 | import {cartQuantityElementInit} from './controls/quantity-element'; 6 | 7 | function cartControlsInit() { 8 | cartProductFormElementInit(); 9 | cartRequestButtonInit(); 10 | cartPropertyInputInit(); 11 | cartQuantityInputInit(); 12 | cartQuantityElementInit(); 13 | } 14 | 15 | export {cartControlsInit} -------------------------------------------------------------------------------- /docs/_includes/code/state.html: -------------------------------------------------------------------------------- 1 | ```json 2 | { 3 | "cart":{ 4 | "token":"b7d3743e2c398043f209c5a3a9014f9d", 5 | "note":null, 6 | "attributes":{}, 7 | "original_total_price":1000, 8 | "total_price":1000, 9 | "total_discount":0, 10 | "total_weight":0, 11 | "item_count":1, 12 | "items":[{…}], 13 | "requires_shipping":false, 14 | "currency":"USD", 15 | "items_subtotal_price":1000, 16 | "cart_level_discount_applications":[] 17 | }, 18 | "previousCart":{…}, 19 | "status":{ 20 | "requestInProgress":false, 21 | "cartStateSet":true 22 | } 23 | } 24 | ``` -------------------------------------------------------------------------------- /snippets/tags-article.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | 3 | This snippet renders a list item with all tags listed out. 4 | It is used in article.liquid and blog.liquid. 5 | 6 | More information: 7 | - index#article-tags 8 | - http://docs.shopify.com/themes/liquid-variables/article 9 | 10 | {% endcomment %} 11 | 12 | {% if article.tags.size > 0 %} 13 |
  • 14 | {{ 'blogs.article.tags' | t }}: 15 | {% for tag in article.tags %} 16 | {{ tag }}{% unless forloop.last %}, {% endunless %} 17 | {% endfor %} 18 |
  • 19 | {% endif %} 20 | -------------------------------------------------------------------------------- /docs/_includes/v2/styles/footer.scss: -------------------------------------------------------------------------------- 1 | .footer { 2 | padding: 2rem 0; 3 | border-top: 1px solid #bababa; 4 | margin-top: 4rem; 5 | color: #717171; 6 | font-size: .875rem; 7 | display: flex; 8 | justify-content: space-between; 9 | align-items: center; 10 | 11 | a { 12 | color: inherit; 13 | } 14 | 15 | .homepage & { 16 | border-top-color: #20344C; 17 | color: #8699af; 18 | 19 | svg * { 20 | fill: #8699af; 21 | } 22 | } 23 | } 24 | 25 | @media (max-width: 400px) { 26 | .footer { 27 | text-align: center; 28 | flex-direction: column-reverse; 29 | gap: 1rem; 30 | } 31 | } -------------------------------------------------------------------------------- /docs/v1/reference/cartRequestClear.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: cartRequestClear() 3 | layout: page 4 | --- 5 | 6 | # cartRequestClear() 7 | 8 | Performs a request to the Shopify Cart API `POST /cart/clear.js` endpoint. 9 | 10 | Takes the request's body as a first parameter, the options object as the second parameter. 11 | 12 | ```html 13 | 21 | ``` 22 | 23 | {% include code/request-options-text.html %} -------------------------------------------------------------------------------- /docs/_includes/masthead.html: -------------------------------------------------------------------------------- 1 | {% assign reference_url = '/v1/reference/' %} 2 | {% assign page_url_reference_slice = page.url | slice: 0, reference_url.size %} 3 | 4 | {% if page_url_reference_slice == reference_url and page.url.size > reference_url.size %} 5 |
    6 | {% else %} 7 | 8 |
    9 |
    10 |
    11 | {% include masthead/title.html %} 12 | {% include masthead/buttons.html %} 13 |
    14 |
    15 |
    16 | 17 | {% endif %} 18 | -------------------------------------------------------------------------------- /docs/v1/reference/js-ajax-cart-form-in-progress.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: .js-ajax-cart-form-in-progress 3 | layout: page 4 | --- 5 | 6 | # .js-ajax-cart-form-in-progress 7 | 8 | When a user submits a Shopify product form, Liquid Ajax Cart intercepts the submission and sends an Ajax "Add to Cart" request. The form remains inactive when the request is in progress to prevent accidental double submissions. 9 | 10 | Liquid Ajax Cart adds the `js-ajax-cart-form-in-progress` CSS class to the form if the request is in progress so you can show a loading indicator or make the submit button visually disabled. 11 | 12 | {% include code/js-ajax-cart-form-in-progress.html %} -------------------------------------------------------------------------------- /docs/_sass/components/_mobile-toc.scss: -------------------------------------------------------------------------------- 1 | .mobile-toc { 2 | h2 { 3 | font-size: 1rem; 4 | font-weight: bold; 5 | } 6 | 7 | ul { 8 | padding-left: 1.4rem; 9 | } 10 | 11 | .toggle-toc { 12 | @include themer(color, ( 13 | 'dark': $site-ui-brand-dark, 14 | 'light': $site-ui-brand-light, 15 | )); 16 | 17 | background-color: transparent; 18 | border: none; 19 | cursor: pointer; 20 | padding: 0; 21 | 22 | &::before { 23 | content: '['; 24 | } 25 | 26 | &::after { 27 | content: ']'; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /assets/ico-select.svg.liquid: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/v1/reference/js-ajax-cart-not-compatible.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: .js-ajax-cart-not-compatible 3 | layout: page 4 | --- 5 | 6 | # .js-ajax-cart-not-compatible 7 | 8 | Liquid Ajax Cart adds the `js-ajax-cart-not-compatible` CSS class to the `body` tag if the current browser doesn't support all the features needed for Liquid Ajax Cart. 9 | 10 | To run Liquid Ajax Cart a browser must support `fetch`, `Promise`, `FormData`, `WeakMap`, `DOMParser`, template strings, destructuring assignment. 11 | 12 | The function that checks browser compatibility is called `isCompatible` and it is located in the [index.ts](https://github.com/EvgeniyMukhamedjanov/liquid-ajax-cart/blob/main/_src/index.ts) file. -------------------------------------------------------------------------------- /docs/v1/reference/product-forms.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Product forms 3 | layout: page 4 | --- 5 | 6 | # Product forms 7 | 8 | Liquid Ajax Cart ajaxifies Shopify product forms once it is loaded. When a user submits a product form, Liquid Ajax Cart intercepts the submission and sends a Shopify Cart API "Add to cart" request. 9 | 10 | The form remains inactive when the "Add to cart" request is in progress and Liquid Ajax Cart adds the [`js-ajax-cart-form-in-progress`](/v1/reference/js-ajax-cart-form-in-progress/) CSS class to the form. 11 | 12 | Add a container with the [`data-ajax-cart-messages`](/v1/reference/data-ajax-cart-messages/) attribute with the `form` value within product forms to show error messages. 13 | -------------------------------------------------------------------------------- /docs/_includes/v2/content/cart-state-json-example.html: -------------------------------------------------------------------------------- 1 | {%- capture highlight_code -%} 2 | { 3 | "cart":{ 4 | "token":"b7d3743e2c398043f209c5a3a9014f9d", 5 | "note":null, 6 | "attributes":{}, 7 | "original_total_price":1000, 8 | "total_price":1000, 9 | "total_discount":0, 10 | "total_weight":0, 11 | "item_count":1, 12 | "items":[{…}], 13 | "requires_shipping":false, 14 | "currency":"USD", 15 | "items_subtotal_price":1000, 16 | "cart_level_discount_applications":[] 17 | }, 18 | "previousCart":{…}, 19 | "status":{ 20 | "requestInProgress":false, 21 | "cartStateSet":true 22 | } 23 | } 24 | {%- endcapture -%} 25 | {% include v2/codeblock.html language="json" code=highlight_code %} -------------------------------------------------------------------------------- /docs/_includes/head/content.html: -------------------------------------------------------------------------------- 1 | {% assign pageTitle = page.title | default: site.name ~ ' ' ~ site.project.version | escape %} 2 | 3 | {% if page.homepage != true %} 4 | {% assign pageTitle = pageTitle | append: ' — ' | append: site.name %} 5 | {% endif %} 6 | 7 | {% assign pageDescription = page.description | page.excerpt | default: site.description %} 8 | 9 | {{ pageTitle | strip_html | escape }} 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/_includes/code/data-ajax-cart-bind-state.html: -------------------------------------------------------------------------------- 1 | {% raw %} 2 | ```html 3 |
    4 | 5 |
    6 | 7 | 10 |
    11 | {{ cart.item_count }} 12 |
    13 | 14 | 16 |
    17 | {{ cart.total_price | money_with_currency }} 18 |
    19 | ``` 20 | {% endraw %} -------------------------------------------------------------------------------- /docs/v2/liquid-ajax-cart-get.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: liquidAjaxCart.get() 3 | layout: docs-v2 4 | --- 5 | 6 | # liquidAjaxCart.get() 7 | 8 |

    9 | A method of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object, 10 | which initiates an Ajax request to the Shopify Cart API `GET /cart.js` endpoint. 11 |

    12 | 13 | ## Structure 14 | 15 | The method takes an object with the request options as the first parameter: 16 | 17 | {%- capture highlight_code -%} 18 | {% include v2/content/request-options-object.html %} 19 | 20 | liquidAjaxCart.get(options); 21 | 22 | {%- endcapture -%} 23 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 24 | 25 | {% include v2/content/request-options-text.html %} 26 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: EvgeniyMukhamedjanov 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /snippets/comment.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | 3 | This snippet generates the structure of a comment. 4 | It is used to show not only recent comments, but also comments that were 5 | just published but not yet approved. 6 | 7 | More information: 8 | - http://docs.shopify.com/themes/liquid-variables/comment 9 | 10 | {% endcomment %} 11 | 12 |
    13 | {% capture author %}{{ comment.author }}{% endcapture %} 14 | {% capture date %}{% endcapture %} 15 | {{ 'blogs.article.comment_meta_html' | t: author: author, date: date }}
    16 |
    17 | {{ comment.content }} 18 |
    19 |
    20 | -------------------------------------------------------------------------------- /docs/_includes/v2/last-release-file-name.html: -------------------------------------------------------------------------------- 1 | {%- assign last_release_file = blank -%} 2 | {%- assign last_release_slice = '/v2/releases/last/liquid-ajax-cart-v' -%} 3 | {%- for file in site.static_files -%} 4 | {%- assign file_slice = file.path | slice: 0, last_release_slice.size -%} 5 | {%- if last_release_slice == file_slice -%} 6 | {%- assign last_release_file = file -%} 7 | {%- endif -%} 8 | {%- endfor -%} 9 | 10 | {%- if include.path -%} 11 | {{- last_release_file.path -}} 12 | {%- elsif include.version -%} 13 | {{- last_release_file.basename | split: '-v' | last -}} 14 | {%- else -%} 15 | {%- if include.asset_url -%}{% raw %}'{{ "{% endraw %}{%- endif -%} 16 | {{- last_release_file.name -}} 17 | {%- if include.asset_url -%}{% raw %}" | asset_url }}'{% endraw %}{%- endif -%} 18 | {%- endif -%} -------------------------------------------------------------------------------- /docs/_includes/code/last-release-file-name.html: -------------------------------------------------------------------------------- 1 | {%- assign last_release_file = blank -%} 2 | {%- assign last_release_slice = '/v1/releases/last/liquid-ajax-cart-v' -%} 3 | {%- for file in site.static_files -%} 4 | {%- assign file_slice = file.path | slice: 0, last_release_slice.size -%} 5 | {%- if last_release_slice == file_slice -%} 6 | {%- assign last_release_file = file -%} 7 | {%- endif -%} 8 | {%- endfor -%} 9 | 10 | {%- if include.path -%} 11 | {{- last_release_file.path -}} 12 | {%- elsif include.version -%} 13 | {{- last_release_file.basename | split: '-v' | last -}} 14 | {%- else -%} 15 | {%- if include.asset_url -%}{% raw %}'{{ "{% endraw %}{%- endif -%} 16 | {{- last_release_file.name -}} 17 | {%- if include.asset_url -%}{% raw %}" | asset_url }}'{% endraw %}{%- endif -%} 18 | {%- endif -%} -------------------------------------------------------------------------------- /docs/v1/reference/js-ajax-cart-request-in-progress.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: .js-ajax-cart-request-in-progress 3 | layout: page 4 | --- 5 | 6 | # .js-ajax-cart-request-in-progress 7 | 8 | Liquid Ajax Cart adds the `js-ajax-cart-request-in-progress` CSS class to the `body` if there are one or more Shopify Cart API requests in progress. 9 | 10 | Some [controls](/v1/reference/controls/) become inactive when Liquid Ajax Cart is sending an Ajax request so you can show a loading indicator or make the controls visually disabled using the `js-ajax-cart-request-in-progress` CSS class. 11 | 12 | Under the hood Liquid Ajax Cart checks the `status.requestInProgress` property of the [`State`](/v1/reference/state/) object and adds the CSS class if the `status.requestInProgress` value is `true` and removes the CSS class if the value is `false`. 13 | -------------------------------------------------------------------------------- /snippets/blog-sidebar.liquid: -------------------------------------------------------------------------------- 1 |

    {{ 'blogs.sidebar.recent_articles' | t }}

    2 | {% for article in blogs[blog.handle].articles limit:6 %} 3 |

    4 | {{ article.title }} 5 |
    6 | 9 |

    10 | {% endfor %} 11 | 12 | {% if blog.all_tags.size > 0 %} 13 |

    {{ 'blogs.sidebar.categories' | t }}

    14 | 23 | {% endif %} 24 | -------------------------------------------------------------------------------- /docs/_includes/code/request-options-object.html: -------------------------------------------------------------------------------- 1 | const options = { 2 | firstComplete: ( requestState ) => { 3 | // The first callback that will be called after the request is finished: 4 | // state object is not updated yet, 5 | // sections are not updated yet, 6 | // everything is not updated yet. 7 | }, 8 | lastComplete: ( requestState ) => { 9 | // The last callback that will be called after the request is finished: 10 | // state is updated, 11 | // sections are updated, 12 | // everything is updated. 13 | }, 14 | info: { 15 | // Any additional data you want to attach 16 | // Don't use the "initiator" and the "cancel" keys 17 | my_parameter: 'value' 18 | }, 19 | newQueue: true // whether the request should go to a new or the first queue 20 | } -------------------------------------------------------------------------------- /docs/_sass/components/_footer.scss: -------------------------------------------------------------------------------- 1 | .site-footer { 2 | padding: 24px 0; 3 | border-top: 1px solid rgba(0, 0, 0, .1); 4 | } 5 | 6 | .site-footer__links { 7 | padding-left: 0; 8 | list-style: none; 9 | margin-bottom: 0; 10 | 11 | .list-inline-item { 12 | display: inline-block; 13 | 14 | &:not(:last-child) { 15 | margin-right: 1rem; 16 | } 17 | } 18 | } 19 | 20 | .site-footer__summary { 21 | font-size: 0.8rem; 22 | margin-top: 8px; 23 | } 24 | 25 | @media (min-width: 768px) { 26 | .site-footer__body { 27 | display: flex; 28 | align-items: center; 29 | 30 | > * { 31 | flex: 0 0 50%; 32 | } 33 | } 34 | 35 | .site-footer__summary { 36 | text-align: right; 37 | margin-top: 0; 38 | } 39 | } -------------------------------------------------------------------------------- /docs/_includes/v2/content/add-to-cart-class-example.html: -------------------------------------------------------------------------------- 1 | {%- capture highlight_code -%} 2 | // Listen for the "liquid-ajax-cart:request-end" event which is fired 3 | // after a Shopify Cart API Ajax request is performed 4 | document.addEventListener('liquid-ajax-cart:request-end', event => { 5 | const {requestState} = event.detail; 6 | 7 | // If the "add to cart" request is successful 8 | if (requestState.requestType === 'add' && requestState.responseData?.ok) { 9 | 10 | // Add the CSS class to the "body" tag 11 | document.body.classList.add('js-show-ajax-cart'); 12 | } 13 | }); 14 | {%- endcapture -%} 15 | {% unless include.no_title %}{% assign code_title = "assets/script.js" %}{% endunless %} 16 | {% include v2/codeblock.html title=code_title language="javascript" code=highlight_code hide_line_numbers=include.hide_line_numbers %} -------------------------------------------------------------------------------- /docs/v1/reference/body-css-classes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Body CSS classes 3 | layout: page 4 | --- 5 | 6 | # Body CSS classes 7 | 8 | Liquid Ajax Cart adds CSS classes to the `body` tag depending on the [State](/v1/reference/state/) of a user's cart. 9 | 10 | - [`.js-ajax-cart-init`](/v1/reference/js-ajax-cart-init/) — if Liquid Ajax Cart has been loaded and initialized; 11 | - [`.js-ajax-cart-empty`](/v1/reference/js-ajax-cart-empty/) — if a user's cart is empty; 12 | - [`.js-ajax-cart-not-empty`](/v1/reference/js-ajax-cart-not-empty/) — if a user's cart is not empty; 13 | - [`.js-ajax-cart-request-in-progress`](/v1/reference/js-ajax-cart-request-in-progress/) — if Liquid Ajax Cart has one or more Ajax requests in progress. 14 | - [`.js-ajax-cart-not-compatible`](/v1/reference/js-ajax-cart-not-compatible/) — if Liquid Ajax Cart is not compatible with the browser. -------------------------------------------------------------------------------- /docs/v1/reference/cartRequestUpdate.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: cartRequestUpdate() 3 | layout: page 4 | --- 5 | 6 | # cartRequestUpdate() 7 | 8 | Performs a request to the Shopify Cart API `POST /cart/update.js` endpoint. 9 | 10 | Takes the request's body as a first parameter, the options object as the second parameter. 11 | 12 | See what parameters Shopify expects from the request's body in the [`/cart/update.js`](https://shopify.dev/api/ajax/reference/cart#post-cart-update-js) documentation. 13 | 14 | ```html 15 | 25 | ``` 26 | 27 | {% include code/request-options-text.html %} -------------------------------------------------------------------------------- /docs/_includes/disqus.html: -------------------------------------------------------------------------------- 1 | {% if site.disqus != false and page.comments != false and jekyll.environment == "production" %} 2 |
    3 | 15 | 16 | {% endif %} -------------------------------------------------------------------------------- /docs/jekyll-docs-theme.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # coding: utf-8 3 | 4 | Gem::Specification.new do |spec| 5 | spec.name = "jekyll-docs-theme" 6 | spec.version = "1.0.0" 7 | spec.authors = ["Vladimir 'allejo' Jimenez"] 8 | spec.email = ["me@allejo.io"] 9 | 10 | spec.summary = "A Jekyll Gem-based Theme for hosting documentation style websites" 11 | spec.homepage = "https://github.com/allejo/jekyll-docs-theme" 12 | spec.license = "MIT" 13 | 14 | spec.metadata["plugin_type"] = "theme" 15 | 16 | spec.files = `git ls-files -z`.split("\x0").select do |f| 17 | f.match(%r!^(assets|_(includes|layouts|sass)/|(LICENSE|README)((\.(md|markdown)|$)))!i) 18 | end 19 | 20 | spec.add_runtime_dependency "jekyll", "~> 3.9.3" 21 | 22 | spec.add_development_dependency "bundler", "~> 2.1" 23 | end 24 | -------------------------------------------------------------------------------- /docs/_includes/v2/content/form-loading-state-block.html: -------------------------------------------------------------------------------- 1 | ## Loading state 2 | 3 | When the `` element initiates an Ajax request, 4 | it adds the `processing` attribute to itself and freezes the "Add to cart" button. 5 | Use the attribute to signify that the product form is currently in the process of adding a product to the cart. 6 | 7 | {%- capture highlight_code -%} 8 | 9 | /* Show a loading indicator */ 10 | ajax-cart-product-form[processing]:before { 11 | content: 'Loading'; 12 | display: block; 13 | } 14 | 15 | /* Make the "Add to cart" button look visually disabled while loading */ 16 | ajax-cart-product-form[processing] [type="submit"] { 17 | opacity: .7; 18 | cursor: not-allowed; 19 | pointer-events: none; 20 | } 21 | 22 | {%- endcapture -%} 23 | {% include v2/codeblock.html title="assets/style.css" language="css" code=highlight_code %} -------------------------------------------------------------------------------- /_src/helpers.ts: -------------------------------------------------------------------------------- 1 | import {AppStateType, LineItemType} from './ts-types'; 2 | 3 | type CodeType = 'id' | 'line'; 4 | type LineItemByCodeType = [ 5 | LineItemType | null | undefined, 6 | CodeType | undefined 7 | ] 8 | 9 | export function findLineItemByCode(code: string, state: AppStateType): LineItemByCodeType { 10 | let lineItem: LineItemType | null | undefined; 11 | let codeType: CodeType | undefined; 12 | 13 | if (code.length > 3) { 14 | lineItem = state.cart.items.find((lineItem: LineItemType) => lineItem.key === code); 15 | codeType = 'id'; 16 | } else { 17 | lineItem = state.cart.items[Number(code) - 1]; 18 | codeType = 'line'; 19 | } 20 | 21 | if (lineItem === undefined) { 22 | lineItem = null; 23 | console.error(`Liquid Ajax Cart: line item with ${codeType}="${code}" not found`); 24 | } 25 | 26 | return [lineItem, codeType]; 27 | } -------------------------------------------------------------------------------- /snippets/image-style.liquid: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /docs/v1/reference/cartRequestChange.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: cartRequestChange() 3 | layout: page 4 | --- 5 | 6 | # cartRequestChange() 7 | 8 | Performs a request to the Shopify Cart API `POST /cart/change.js` endpoint. 9 | 10 | Takes the request's body as a first parameter, the options object as the second parameter. 11 | 12 | See what parameters Shopify expects from the request's body in the [`/cart/change.js`](https://shopify.dev/api/ajax/reference/cart#post-cart-change-js) documentation. 13 | 14 | ```html 15 | 26 | ``` 27 | 28 | {% include code/request-options-text.html %} -------------------------------------------------------------------------------- /docs/v1/reference/cartRequestAdd.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: cartRequestAdd 3 | layout: page 4 | --- 5 | 6 | # cartRequestAdd 7 | 8 | Performs a request to the Shopify Cart API `POST /cart/add.js` endpoint. 9 | 10 | Takes the request's body as a first parameter, the options object as the second parameter. 11 | 12 | See what parameters Shopify expects from the request's body in the [`/cart/add.js`](https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-add-js) documentation. 13 | 14 | ```html 15 | 29 | ``` 30 | 31 | {% include code/request-options-text.html %} -------------------------------------------------------------------------------- /docs/v1/reference/productFormsFilter.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: productFormsFilter 3 | layout: page 4 | --- 5 | 6 | # productFormsFilter 7 | 8 | Liquid Ajax Cart ajaxifies all Shopify product forms by default. 9 | 10 | But, for example, if you want to ajaxify only product forms with the `data-my-product-form` attribute then provide a function as the `productFormsFilter` parameter: 11 | {% raw %} 12 | ```html 13 | 20 | ``` 21 | {% endraw %} 22 | 23 | Liquid Ajax Cart will call your function and pass the *Element* object of the product form that is going to add a product to the cart, and proceed with an "Add to cart" Ajax request only if the function returns `true`. -------------------------------------------------------------------------------- /docs/v2/quantity-tag-debounce.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: quantityTagDebounce 3 | layout: docs-v2 4 | --- 5 | 6 | # quantityTagDebounce 7 | 8 |

    9 | A configuration parameter which sets the debounce time in milliseconds for 10 | the quantity controls built using the [``](/v2/ajax-cart-quantity/) custom tag. 11 |

    12 | 13 | ## Code example 14 | 15 | By default, the debounce time is 300 milliseconds. 16 | Use the [`conf`](/v2/liquid-ajax-cart-conf/) method of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object to set 17 | another value. 18 | 19 | For example if you want the [``](/v2/ajax-cart-quantity/) custom tag to start updating 20 | the quantity without any delay, set the value to 0: 21 | 22 | {%- capture highlight_code -%} 23 | liquidAjaxCart.conf("quantityTagDebounce", 0); 24 | {%- endcapture -%} 25 | {% include v2/codeblock.html language="javascript" code=highlight_code %} -------------------------------------------------------------------------------- /docs/v2/js-ajax-cart-empty.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: js-ajax-cart-empty 3 | layout: docs-v2 4 | --- 5 | 6 | # js-ajax-cart-empty 7 | 8 |

    9 | A CSS class which is appended to the `html` tag when the user cart is empty. 10 |

    11 | 12 | ## Example 13 | 14 | Hiding the cart quantity number in the header not to show "(0)": 15 | 16 | {%- capture highlight_code -%} 17 | {% raw %} 18 | 19 | ( 20 | 21 | {{ cart.item_count }} 22 | 23 | ) 24 | 25 | {% endraw %} 26 | {%- endcapture -%} 27 | {% include v2/codeblock.html title="sections/header.liquid" language="liquid" code=highlight_code %} 28 | 29 | {%- capture highlight_code -%} 30 | html.js-ajax-cart-empty .header__cart-quantity { 31 | display: none; 32 | } 33 | 34 | {%- endcapture -%} 35 | {% include v2/codeblock.html title="assets/style.css" language="css" code=highlight_code %} -------------------------------------------------------------------------------- /docs/v2/request-error-text.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: requestErrorText 3 | layout: docs-v2 4 | --- 5 | 6 | # requestErrorText 7 | 8 |

    9 | A configuration parameter which sets the error message text 10 | that appears in [`data-ajax-cart-errors`](/v2/data-ajax-cart-errors/) containers 11 | when a Shopify Cart API Ajax request is failed and doesn't have any error description, 12 | or when the request is not performed at all due to the Internet connection. 13 |

    14 | 15 | ## Code example 16 | 17 | By default, the text is "There was an error while updating your cart. Please try again.". 18 | 19 | Use the [`conf`](/v2/liquid-ajax-cart-conf/) method of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object to set your value: 20 | {%- capture highlight_code -%} 21 | liquidAjaxCart.conf("requestErrorText", "My request error message"); 22 | {%- endcapture -%} 23 | {% include v2/codeblock.html language="javascript" code=highlight_code %} -------------------------------------------------------------------------------- /docs/v2/js-ajax-cart-not-empty.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: js-ajax-cart-not-empty 3 | layout: docs-v2 4 | --- 5 | 6 | # js-ajax-cart-not-empty 7 | 8 |

    9 | A CSS class which is appended to the `html` tag when the user cart is not empty. 10 |

    11 | 12 | ## Example 13 | 14 | Showing the cart quantity number in the header: 15 | 16 | {%- capture highlight_code -%} 17 | {% raw %} 18 | 19 | ( 20 | 21 | {{ cart.item_count }} 22 | 23 | ) 24 | 25 | {% endraw %} 26 | {%- endcapture -%} 27 | {% include v2/codeblock.html title="sections/header.liquid" language="liquid" code=highlight_code %} 28 | 29 | {%- capture highlight_code -%} 30 | html.js-ajax-cart-not-empty .header__cart-quantity { 31 | display: inline-block; 32 | } 33 | 34 | {%- endcapture -%} 35 | {% include v2/codeblock.html title="assets/style.css" language="css" code=highlight_code %} -------------------------------------------------------------------------------- /docs/v2/js-ajax-cart-processing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: js-ajax-cart-processing 3 | layout: docs-v2 4 | --- 5 | 6 | # js-ajax-cart-processing 7 | 8 |

    9 | A CSS class which is appended to the `html` tag when there is a Shopify Cart API Ajax request in progress. 10 |

    11 | 12 | ## How it works 13 | 14 | Under the hood Liquid Ajax Cart is keeping the `js-ajax-cart-processing` CSS class appended to the `html` tag 15 | when the [Queue of requests](/v2/queue-of-requests/) is not empty, 16 | which means that Liquid Ajax Cart is currently executing Shopify Cart API Ajax requests 17 | until the [Queue of requests](/v2/queue-of-requests/) is empty. 18 | 19 | ## Use case 20 | 21 | Use this CSS class to show a loading indicator for an Ajax cart section or make the ajaxified elements, 22 | such as a cart item quantity input, or a remove cart item button, look visually disabled. 23 | 24 | {% include v2/content/cart-loading-state-css-example.html %} -------------------------------------------------------------------------------- /docs/_includes/footer/scripts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | -------------------------------------------------------------------------------- /docs/_includes/styles/containers.scss: -------------------------------------------------------------------------------- 1 | .wide-container { 2 | max-width: 1670px; 3 | padding: 0 15px; 4 | margin: 0 auto; 5 | } 6 | @media (min-width: 760px) { 7 | .wide-container { 8 | padding: 0 30px; 9 | } 10 | } 11 | @media (min-width: 1360px) { 12 | .wide-container { 13 | padding: 0 50px; 14 | } 15 | } 16 | 17 | .container { 18 | width: 100%; 19 | padding-right: 15px; 20 | padding-left: 15px; 21 | margin-right: auto; 22 | margin-left: auto; 23 | } 24 | 25 | @media (min-width: 576px) { 26 | .container { 27 | max-width: 680px; 28 | } 29 | } 30 | 31 | @media (min-width: 768px) { 32 | .container { 33 | max-width: 720px; 34 | } 35 | } 36 | 37 | @media (min-width: 992px) { 38 | .container { 39 | max-width: 960px; 40 | } 41 | } 42 | 43 | @media (min-width: 1200px) { 44 | .container { 45 | max-width: 1140px; 46 | } 47 | } -------------------------------------------------------------------------------- /snippets/featured-blog.liquid: -------------------------------------------------------------------------------- 1 |

    {{ article.title }} →

    2 | {% if section.settings.blog_show_date or section.settings.blog_show_author %} 3 | 16 | {% endif %} 17 | 18 | {% if section.settings.blog_show_excerpt %} 19 |
    20 | {{ article.excerpt_or_content | strip_html | truncatewords: 30 }} 21 |
    22 | {% endif %} 23 | -------------------------------------------------------------------------------- /docs/_includes/styles/masthead.scss: -------------------------------------------------------------------------------- 1 | .site-masthead { 2 | color: black; 3 | position: relative; 4 | padding: 64px 0 32px; 5 | } 6 | 7 | .site-masthead__title { 8 | font-family: 'Arial Black', 'Arial', sans-serif; 9 | font-weight: 900; 10 | font-size: 42px; 11 | line-height: 1; 12 | position: relative; 13 | z-index: 2; 14 | 15 | span { 16 | background: linear-gradient(104.39deg, #BAFF91 4.53%, #FFF6A4 73.74%); 17 | background-size: 100% 0.375em; 18 | background-repeat: repeat-x; 19 | background-position: left 0 bottom 0.15em; 20 | } 21 | 22 | @media (min-width: 410px) { 23 | font-size: 48px; 24 | } 25 | 26 | @media (min-width: 760px) { 27 | font-size: 56px; 28 | } 29 | 30 | @media (min-width: 1200px) { 31 | font-size: 60px; 32 | } 33 | } 34 | 35 | .site-masthead__npm { 36 | display: inline-block; 37 | border: none !important; 38 | vertical-align: 1em; 39 | font-size: 20px; 40 | line-height: 2; 41 | } -------------------------------------------------------------------------------- /docs/v2/quantity-tag-allow-zero.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: quantityTagAllowZero 3 | layout: docs-v2 4 | --- 5 | 6 | # quantityTagAllowZero 7 | 8 |

    9 | A configuration parameter which allows a user to remove a product from the cart by 10 | clicking the `data-ajax-cart-quantity-minus` button and reaching the "0" value in a 11 | quantity control built using the [``](/v2/ajax-cart-quantity/) custom tag. 12 |

    13 | 14 | ## Code example 15 | 16 | By default, the minimum value, that a user can reach by clicking a `data-ajax-cart-quantity-minus` button, 17 | is "1". Thus, a user can't remove an item from the cart by this way. 18 | 19 | Use the [`conf`](/v2/liquid-ajax-cart-conf/) method of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object to set 20 | the `quantityTagAllowZero` to `true` that lets a user reach the "0" value: 21 | {%- capture highlight_code -%} 22 | liquidAjaxCart.conf("quantityTagAllowZero", true); 23 | {%- endcapture -%} 24 | {% include v2/codeblock.html language="javascript" code=highlight_code %} -------------------------------------------------------------------------------- /docs/_includes/v2/content/request-options-object.html: -------------------------------------------------------------------------------- 1 | const options = { 2 | firstCallback: function(requestState) { 3 | /** 4 | * This callback function will be called first after the request is performed, 5 | * thus none of request subscribers knows the result of the request, 6 | * thus Cart state is not updated yet, sections are not updated yet, 7 | * everything is not updated yet. 8 | */ 9 | }, 10 | lastCallback: function(requestState) { 11 | /** 12 | * This callback-function will be called the latest 13 | * among request subscribers, 14 | * thus all the request subscribers are executed, 15 | * thus Cart state is updated, sections are updated, 16 | * everything is updated. 17 | */ 18 | }, 19 | info: { 20 | /** 21 | * Any additional data you want to attach to the Request state object. 22 | * Don't use the "initiator" and the "cancel" keys. 23 | */ 24 | myParameter: 'value' 25 | }, 26 | 27 | // whether the request should go to the beginning of the queue rather than to the end 28 | important: false 29 | } -------------------------------------------------------------------------------- /docs/_includes/v2/styles/quote.scss: -------------------------------------------------------------------------------- 1 | .quote { 2 | text-align: center; 3 | max-width: 33rem; 4 | margin: 8rem auto; 5 | position: relative; 6 | } 7 | 8 | .quote__reference { 9 | color: #b5bedd; 10 | margin-bottom: 1rem; 11 | 12 | a { 13 | font-weight: bold; 14 | } 15 | } 16 | 17 | .quote__text { 18 | font-size: 1.5rem; 19 | font-weight: bold; 20 | line-height: 1.3; 21 | 22 | &:before { 23 | content: "“"; 24 | display: inline; 25 | color: #8699af; 26 | } 27 | 28 | &:after { 29 | content: "”"; 30 | display: inline; 31 | color: #8699af; 32 | } 33 | 34 | @media (min-width: 600px) { 35 | font-size: 2.5rem; 36 | } 37 | } 38 | 39 | .quote__person { 40 | margin-top: 2rem; 41 | } 42 | 43 | .quote__person-image { 44 | width: 3rem; 45 | height: 3rem; 46 | margin: 0 auto; 47 | 48 | img { 49 | width: 100%; 50 | height: 100%; 51 | border-radius: 100%; 52 | object-fit: cover; 53 | } 54 | } 55 | 56 | .quote__person-name { 57 | margin-top: 1rem; 58 | } 59 | 60 | .quote__person-title { 61 | font-size: .875rem; 62 | color: #8699af; 63 | } -------------------------------------------------------------------------------- /snippets/product-properties.liquid: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
    5 | 6 |
    7 | 8 | 14 |
    15 | 16 |
    17 |
    Package
    18 | 19 | 20 | 21 |
    22 | 23 |
    24 | 25 | 26 |
    -------------------------------------------------------------------------------- /docs/v2/liquid-ajax-cart-clear.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: liquidAjaxCart.clear() 3 | layout: docs-v2 4 | --- 5 | 6 | # liquidAjaxCart.clear() 7 | 8 |

    9 | A method of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object, 10 | which initiates an Ajax request to the Shopify Cart API `POST /cart/clear.js` endpoint. 11 |

    12 | 13 | ## Structure 14 | 15 | The method takes a request body object as the first parameter, and an object with the request options as the second parameter. 16 | 17 | The request body object is passed to the Shopify Cart API endpoint as is, 18 | so read what data Shopify expects in the [`/cart/clear.js`](https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-clear-js) documentation. 19 | 20 | {%- capture highlight_code -%} 21 | 22 | // Request body data you want to send to Shopify 23 | const body = {} 24 | 25 | {% include v2/content/request-options-object.html %} 26 | 27 | liquidAjaxCart.clear(body, options); 28 | 29 | {%- endcapture -%} 30 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 31 | 32 | {% include v2/content/request-options-text.html %} 33 | -------------------------------------------------------------------------------- /docs/v2/liquid-ajax-cart-conf.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: liquidAjaxCart.conf() 3 | layout: docs-v2 4 | --- 5 | 6 | # liquidAjaxCart.conf() 7 | 8 |

    9 | A method of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object, which sets configuration parameter values. 10 |

    11 | 12 | ## Code example 13 | 14 | The `conf` method takes a configuration parameter name and its new value: 15 | 16 | {%- capture highlight_code -%} 17 | 18 | liquidAjaxCart.conf("updateOnWindowFocus", false); 19 | liquidAjaxCart.conf("requestErrorText", "My request error message"); 20 | 21 | {%- endcapture -%} 22 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 23 | 24 | ## Configuration parameters 25 | 26 | {% for docs_section in site.links_v2.docs -%} 27 | {%- for docs_subsection in docs_section.subsections -%} 28 | {%- if docs_subsection.id == 'configuration-subsection' -%} 29 | {%- for docs_link in docs_subsection.links %} 30 | * [`{{ docs_link.title | escape }}`](/v2/{{ docs_link.file }}/) 31 | {%- endfor -%} 32 | {%- break -%} 33 | {%- endif -%} 34 | {%- endfor -%} 35 | {%- endfor -%} -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | var PACKAGE = require('./package.json'); 3 | 4 | module.exports = (env, argv) => { 5 | let folder = 'assets'; 6 | let filename = 'liquid-ajax-cart.js'; 7 | 8 | if ( argv.mode === 'production' ) { 9 | folder = 'docs/v2/releases'; 10 | filename = `liquid-ajax-cart-v${PACKAGE.version}.js`; 11 | 12 | if ( env.last ) { 13 | folder = 'docs/v2/releases/last'; 14 | } 15 | 16 | if ( env.npm ) { 17 | folder = '.'; 18 | filename = 'liquid-ajax-cart.js' 19 | } 20 | } 21 | 22 | return { 23 | mode: argv.mode, 24 | entry: './_src/index.ts', 25 | module: { 26 | rules: [ 27 | { 28 | test: /\.tsx?$/, 29 | use: 'ts-loader', 30 | exclude: /node_modules/, 31 | }, 32 | ], 33 | }, 34 | resolve: { 35 | extensions: ['.tsx', '.ts', '.js'], 36 | }, 37 | output: { 38 | filename, 39 | path: path.resolve(__dirname, folder), 40 | library: { 41 | type: 'module', 42 | }, 43 | }, 44 | experiments: { 45 | outputModule: true 46 | } 47 | }; 48 | } -------------------------------------------------------------------------------- /docs/v2/liquid-ajax-cart-update.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: liquidAjaxCart.update() 3 | layout: docs-v2 4 | --- 5 | 6 | # liquidAjaxCart.update() 7 | 8 |

    9 | A method of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object, 10 | which initiates an Ajax request to the Shopify Cart API `POST /cart/update.js` endpoint. 11 |

    12 | 13 | ## Structure 14 | 15 | The method takes a request body object as the first parameter, and an object with the request options as the second parameter. 16 | 17 | The request body object is passed to the Shopify Cart API endpoint as is, 18 | so read what data Shopify expects in the [`/cart/update.js`](https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-update-js) documentation. 19 | 20 | {%- capture highlight_code -%} 21 | 22 | // Request body data you want to send to Shopify 23 | const body = { 24 | updates: [3, 2, 1] 25 | } 26 | 27 | {% include v2/content/request-options-object.html %} 28 | 29 | liquidAjaxCart.update(body, options); 30 | 31 | {%- endcapture -%} 32 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 33 | 34 | {% include v2/content/request-options-text.html %} 35 | -------------------------------------------------------------------------------- /docs/_sass/base/_anchor.scss: -------------------------------------------------------------------------------- 1 | a { 2 | /* 3 | @include themer(color, ( 4 | 'dark': $site-ui-brand-dark, 5 | 'light': $site-ui-brand-light, 6 | )); 7 | */ 8 | 9 | color: currentColor; 10 | border-bottom: 1px solid rgba(0, 0, 0, .2); 11 | text-decoration: none; 12 | 13 | transition: background-color .2s, border-color .2s; 14 | 15 | .scope-markdown &, 16 | .site-footer__summary & { 17 | background-color: rgba(#bfea52, .3); 18 | 19 | code { 20 | background-color: transparent; 21 | border: none; 22 | } 23 | } 24 | 25 | &:active, 26 | &:focus, 27 | &:hover { 28 | /* 29 | @include themer(color, ( 30 | 'dark': darken($site-ui-brand-dark, 10%), 31 | 'light': darken($site-ui-brand-light, 10%), 32 | )); 33 | */ 34 | 35 | color: currentColor; 36 | text-decoration: none; 37 | border-bottom-color: currentColor; 38 | 39 | .scope-markdown &, 40 | .site-footer__summary & { 41 | background-color: rgba(#bfea52, .4); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /docs/assets/js/docs.js: -------------------------------------------------------------------------------- 1 | //$(function() { 2 | // $('html').toggleClass('no-js js'); 3 | 4 | // Update sidebar highlighting based on Scrollspy 5 | /*$(window).on('activate.bs.scrollspy', function () { 6 | const spyTarget = $('[data-spy="scroll"]').data('target'); 7 | const $activeSpy = $(spyTarget).find('.nav-link.active'); 8 | const $tree = $activeSpy.parentsUntil('.bs-docs-sidenav', 'li'); 9 | 10 | $tree.find('> a').addClass('active'); 11 | });/ 12 | 13 | // Toggleable mobile table of contents button 14 | /*$('.toggle-toc').on('click', function () { 15 | const $this = $(this); 16 | const $toc = $("#mobileTOC"); 17 | 18 | $toc.toggle(); 19 | $this.attr('aria-expanded', $toc.is(':visible')); 20 | 21 | const $btn = $this.find('[data-role="toggle"]'); 22 | 23 | if ($btn.text() === 'Hide') { 24 | $btn.text('Show'); 25 | } else { 26 | $btn.text('Hide'); 27 | } 28 | });*/ 29 | //}); 30 | 31 | document.querySelector('[data-nav-toggle]').addEventListener('click', function() { 32 | document.querySelector('[data-nav]').classList.toggle('show'); 33 | }); 34 | -------------------------------------------------------------------------------- /docs/v1/reference/data-ajax-cart-bind-state.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: data-ajax-cart-bind-state 3 | layout: page 4 | --- 5 | 6 | # data-ajax-cart-bind-state 7 | 8 | Add the `data-ajax-cart-bind-state` attribute to an HTML element, pass a [State object](/v1/reference/state/) property as the attribute's value and Liquid Ajax Cart will display the state property's value within the HTML element and refresh it when the cart gets updated. 9 | 10 | {% include code/data-ajax-cart-bind-state.html %} 11 | 12 | The attribute supports formatters and there is the `money_with_currency` formatter out of the box. The `money_with_currency` uses the `Intl` JavaScript object and `Shopify.locale` value: 13 | 14 | ```javascript 15 | return Intl.NumberFormat(window.Shopify.locale, { 16 | style: 'currency', 17 | currency: state.cart.currency 18 | }).format(value / 100); 19 | ``` 20 | 21 | If the `Shopify.locale` or the `Intl` are not available, the formatter will return the following: 22 | ```javascript 23 | // 100.00 USD 24 | return `${ (value / 100).toFixed(2) } ${ state.cart.currency }`; 25 | ``` 26 | 27 | You can define your own formatters using the [`stateBinderFormatters`](/v1/reference/stateBinderFormatters/) configuration parameter. -------------------------------------------------------------------------------- /docs/v2/data-ajax-cart-initial-state.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: data-ajax-cart-initial-state 3 | layout: docs-v2 4 | --- 5 | 6 | # data-ajax-cart-initial-state 7 | 8 |

    9 | An attribute which helps Liquid Ajax Cart find the user cart data during initialization. 10 |

    11 | 12 | ## How it works 13 | 14 | Liquid Ajax Cart needs to know user cart state: what products are in the cart, what total price is, what discounts are applied etc. 15 | 16 | To provide this data, you should convert the Shopify [`cart`](https://shopify.dev/docs/api/liquid/objects/cart) object to JSON format 17 | and wrap it in the `script` tag with the `data-ajax-cart-initial-state` attribute. 18 | 19 | {%- capture highlight_code -%} 20 | {% raw %} 21 | {% comment %} Somewhere in layout/theme.liquid {% endcomment %} 22 | 23 | 26 | {% endraw %} 27 | {%- endcapture -%} 28 | {% include v2/codeblock.html title="layout/theme.liquid" language="liquid" code=highlight_code %} 29 | 30 | If Liquid Ajax Cart doesn't find the `data-ajax-cart-initial-state` script, 31 | it performs a Shopify Cart API Ajax request to get the cart state. 32 | 33 | -------------------------------------------------------------------------------- /docs/v2/liquid-ajax-cart-add.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: liquidAjaxCart.add() 3 | layout: docs-v2 4 | --- 5 | 6 | # liquidAjaxCart.add() 7 | 8 |

    9 | A method of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object, 10 | which initiates an Ajax request to the Shopify Cart API `POST /cart/add.js` endpoint. 11 |

    12 | 13 | ## Structure 14 | 15 | The method takes a request body object as the first parameter, and an object with the request options as the second parameter. 16 | 17 | The request body object is passed to the Shopify Cart API endpoint as is, 18 | so read what data Shopify expects in the [`/cart/add.js`](https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-add-js) documentation. 19 | 20 | {%- capture highlight_code -%} 21 | 22 | // Request body data you want to send to Shopify 23 | const body = { 24 | items: [ 25 | { 26 | id: 40934235668668, 27 | quantity: 1 28 | } 29 | ] 30 | } 31 | 32 | {% include v2/content/request-options-object.html %} 33 | 34 | liquidAjaxCart.add(body, options); 35 | 36 | {%- endcapture -%} 37 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 38 | 39 | {% include v2/content/request-options-text.html %} 40 | -------------------------------------------------------------------------------- /docs/v2/liquid-ajax-cart-change.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: liquidAjaxCart.change() 3 | layout: docs-v2 4 | --- 5 | 6 | # liquidAjaxCart.change() 7 | 8 |

    9 | A method of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object, 10 | which initiates an Ajax request to the Shopify Cart API `POST /cart/change.js` endpoint. 11 |

    12 | 13 | ## Structure 14 | 15 | The method takes a request body object as the first parameter, and an object with the request options as the second parameter. 16 | 17 | The request body object is passed to the Shopify Cart API endpoint as is, 18 | so read what data Shopify expects in the [`/cart/change.js`](https://shopify.dev/docs/api/ajax/reference/cart#post-locale-cart-change-js) documentation. 19 | 20 | {%- capture highlight_code -%} 21 | 22 | // Request body data you want to send to Shopify 23 | const body = { 24 | id: '40934235668668:719bc4cb60310cbc4dee2ae38d8bf04c', 25 | quantity: 0 26 | } 27 | 28 | {% include v2/content/request-options-object.html %} 29 | 30 | liquidAjaxCart.change(body, options); 31 | 32 | {%- endcapture -%} 33 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 34 | 35 | {% include v2/content/request-options-text.html %} 36 | -------------------------------------------------------------------------------- /docs/_includes/v2/styles/tabs.scss: -------------------------------------------------------------------------------- 1 | .tabs { 2 | display: flex; 3 | overflow: auto; 4 | flex-wrap: wrap; 5 | 6 | input { 7 | display: none; 8 | } 9 | 10 | label { 11 | flex: 0 0 auto; 12 | font-size: .875rem; 13 | padding: .75rem 0; 14 | order: 0; 15 | cursor: pointer; 16 | position: relative; 17 | white-space: nowrap; 18 | font-weight: 600; 19 | 20 | &:after { 21 | content: ''; 22 | position: absolute; 23 | left: 0; 24 | width: 100%; 25 | bottom: 0; 26 | background-color: transparent; 27 | transition: background-color .15s; 28 | height: 1px; 29 | } 30 | 31 | &:hover:after { 32 | background-color: #0A7307; 33 | } 34 | } 35 | 36 | input:not(:first-child) + label { 37 | margin-left: 1.5rem; 38 | } 39 | 40 | input:checked + label { 41 | color: #35812F; 42 | 43 | &:after { 44 | background-color: #0A7307; 45 | height: 2px; 46 | } 47 | } 48 | 49 | label + * { 50 | width: 100%; 51 | flex: 0 0 100%; 52 | display: none; 53 | order: 1; 54 | padding-top: 1rem; 55 | border-top: 1px solid #bababa; 56 | } 57 | 58 | input:checked + label + * { 59 | display: block; 60 | } 61 | } -------------------------------------------------------------------------------- /_src/global-classes.ts: -------------------------------------------------------------------------------- 1 | import {getCartState} from './state'; 2 | import {EVENT_QUEUE_END_INTERNAL, EVENT_QUEUE_START_INTERNAL, EVENT_REQUEST_END_INTERNAL, getProcessingStatus} from "./ajax-api"; 3 | import {CSS_CLASS_PREFIX} from "./const"; 4 | 5 | const CSS_CLASS_INIT = `${CSS_CLASS_PREFIX}-init`; 6 | const CSS_CLASS_IN_PROGRESS = `${CSS_CLASS_PREFIX}-processing`; 7 | const CSS_CLASS_EMPTY = `${CSS_CLASS_PREFIX}-empty`; 8 | const CSS_CLASS_NOT_EMPTY = `${CSS_CLASS_PREFIX}-not-empty`; 9 | 10 | function updateClasses(): void { 11 | const $element = document.querySelector('html'); 12 | const state = getCartState(); 13 | $element.classList.toggle(CSS_CLASS_INIT, state.cart !== null); 14 | $element.classList.toggle(CSS_CLASS_IN_PROGRESS, getProcessingStatus()); 15 | $element.classList.toggle(CSS_CLASS_EMPTY, state.cart.item_count === 0); 16 | $element.classList.toggle(CSS_CLASS_NOT_EMPTY, state.cart.item_count > 0); 17 | } 18 | 19 | const cartGlobalClassesInit = () => { 20 | document.addEventListener(EVENT_QUEUE_START_INTERNAL, updateClasses); 21 | document.addEventListener(EVENT_REQUEST_END_INTERNAL, updateClasses); 22 | document.addEventListener(EVENT_QUEUE_END_INTERNAL, updateClasses); 23 | updateClasses(); 24 | } 25 | 26 | export {cartGlobalClassesInit} -------------------------------------------------------------------------------- /docs/v1/reference/data-ajax-cart-initial-state.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: data-ajax-cart-initial-state 3 | layout: page 4 | --- 5 | 6 | # data-ajax-cart-initial-state 7 | 8 | To do its job Liquid Ajax Cart needs to know current Shopify cart state: what products are in the cart, what total price is, what discounts are applied etc. This information is stored in the [`cart`](https://shopify.dev/api/liquid/objects/cart) liquid object. 9 | 10 | The shortest way to make the cart state accessible for JavaScript code is to convert the Shopify `cart` object to JSON and include it to the page content within the `script` tag. 11 | 12 | In order Liquid Ajax Cart to find the `script` tag with the cart state, it should have the `data-ajax-cart-initial-state` attribute. 13 | 14 | {% raw %} 15 | ```html 16 | {% comment %} Somewhere in layout/theme.liquid {% endcomment %} 17 | 18 | 21 | ``` 22 | {% endraw %} 23 | 24 | It is highly recommended to add the mentioned code to the `layout/theme.liquid` file so that the initial cart state data is accessible on all pages. 25 | 26 | If Liquid Ajax Cart doesn't find the `data-ajax-cart-initial-state` script, it will make an extra Shopify Cart API request to get the cart state. -------------------------------------------------------------------------------- /docs/_includes/internal/variables.html: -------------------------------------------------------------------------------- 1 | {%- assign site_ui_mode = site.ui.mode | default: 'auto' -%} 2 | 3 | {%- assign site_ui_brand_dark = site.ui.brand.dark | default: '#00ceff' -%} 4 | {%- assign site_ui_brand_light = site.ui.brand.light | default: '#a20000' -%} 5 | 6 | {%- assign site_ui_border_color_dark = site.ui.border_color.dark | default: '#5f5f5f' -%} 7 | {%- assign site_ui_border_color_light = site.ui.border_color.light | default: '#dee2e6' -%} 8 | 9 | {%- if site.ui.header.trianglify == true or site.ui.header.trianglify == false -%} 10 | {%- assign site_ui_header_trianglify = site.ui.header.trianglify -%} 11 | {%- else -%} 12 | {%- assign site_ui_header_trianglify = true -%} 13 | {%- endif -%} 14 | 15 | {%- assign site_ui_header_dark_color1 = site.ui.header.dark.color1 | default: '#062a48' -%} 16 | {%- assign site_ui_header_dark_color2 = site.ui.header.dark.color2 | default: '#304e67' -%} 17 | {%- assign site_ui_header_light_color1 = site.ui.header.light.color1 | default: '#080331' -%} 18 | {%- assign site_ui_header_light_color2 = site.ui.header.light.color2 | default: '#673051' -%} 19 | 20 | {%- assign site_ui_masthead_color_dark = site.ui.masthead.color.dark | default: '#fff' -%} 21 | {%- assign site_ui_masthead_color_light = site.ui.masthead.color.light | default: '#fff' -%} 22 | -------------------------------------------------------------------------------- /templates/customers/reset_password.liquid: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | 4 | {% comment %} 5 | This form must use 'reset_customer_password' 6 | {% endcomment %} 7 | {% form 'reset_customer_password' %} 8 | 9 |
    10 |

    {{ 'customer.reset_password.title' | t }}

    11 |
    12 | 13 |

    {{ 'customer.reset_password.subtext' | t: email: email }}

    14 | 15 | {{ form.errors | default_errors }} 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |

    24 | 25 |

    26 | 27 | {% endform %} 28 | 29 |
    30 |
    31 | -------------------------------------------------------------------------------- /docs/assets/css/styles.scss: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | $site-ui-mode: {{ site.ui.mode | default: 'auto' }}; 5 | 6 | $site-ui-brand-dark: {{ site.ui.brand.dark | default: '#00ceff' }}; 7 | $site-ui-brand-light: {{ site.ui.brand.light | default: '#a20000' }}; 8 | 9 | $site-ui-border-color-dark: {{ site.ui.border_color.dark | default: '#5f5f5f' }}; 10 | $site-ui-border-color-light: {{ site.ui.border_color.light | default: '#dee2e6' }}; 11 | 12 | $site-ui-header-dark-color1: {{ site.ui.header.dark.color1 | default: '#062a48' }}; 13 | $site-ui-header-dark-color2: {{ site.ui.header.dark.color2 | default: '#304e67' }}; 14 | $site-ui-header-light-color1: {{ site.ui.header.light.color1 | default: '#080331' }}; 15 | $site-ui-header-light-color2: {{ site.ui.header.light.color2 | default: '#673051' }}; 16 | 17 | $site-ui-masthead-color-dark: {{ site.ui.masthead.color.dark | default: '#fff' }}; 18 | $site-ui-masthead-color-light: {{ site.ui.masthead.color.light | default: '#fff' }}; 19 | 20 | @import 'abstracts/themer'; 21 | @import 'abstracts/variables'; 22 | 23 | // Base Styles 24 | @import 'base/anchor'; 25 | @import 'base/body'; 26 | @import 'base/blockquote'; 27 | @import 'base/horizontal-rule'; 28 | @import 'base/scope-markdown'; 29 | 30 | // Components 31 | @import 'components/footer'; 32 | @import 'components/mobile-toc'; 33 | -------------------------------------------------------------------------------- /docs/v1/reference/requestErrorText.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: requestErrorText 3 | layout: page 4 | --- 5 | 6 | # requestErrorText 7 | 8 | The `requestErrorText` configuration parameter sets the error message text that will appear in [`data-ajax-cart-messages`](/v1/reference/data-ajax-cart-messages/) containers when a Shopify Cart API request is not successful and doesn't have any error description, or if the request is not performed at all due to internet connection, for example. 9 | 10 | By default the text is "*There was an error while updating your cart. Please try again.*". 11 | 12 | You can change the message if your store language is not English or the phrase doesn't fit to your store: 13 | {% raw %} 14 | ```html 15 | {% comment %} Somewhere in layout/theme.liquid {% endcomment %} 16 | 17 | 22 | ``` 23 | {% endraw %} 24 | 25 | You can also use the `configureCart` function: 26 | {% raw %} 27 | ```html 28 | 33 | ``` 34 | {% endraw %} -------------------------------------------------------------------------------- /docs/v1/reference/subscribeToCartStateUpdate.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: subscribeToCartStateUpdate() 3 | layout: page 4 | --- 5 | 6 | # subscribeToCartStateUpdate() 7 | 8 | The `subscribeToCartStateUpdate` function adds your callback function to the list of functions that will be called each time after the [State object](/v1/reference/state/) is changed. The callback should be passed as the only parameter. 9 | 10 | ```javascript 11 | subscribeToCartStateUpdate( myCallback ); 12 | ``` 13 | 14 | ```html 15 | 23 | ``` 24 | 25 | Your callback will be called with the [State object](/v1/reference/state/) and the `isCartUpdated` boolean parameter. 26 | 27 | If the `isCartUpdated` is `true`, it means that Liquid Ajax Cart has just received new cart JSON-data from Shopify from the last Shopify [Cart Ajax API request](/v1/reference/requests/) and the new cart state is available in the `cart` property. 28 | 29 | If the `isCartUpdated` is `false`, it means that only `status` State property is changed. -------------------------------------------------------------------------------- /snippets/product-unit-price.liquid: -------------------------------------------------------------------------------- 1 | {%- unless available -%} 2 | {%- if variant.title -%} 3 | {%- assign available = variant.available -%} 4 | {%- else -%} 5 | {%- assign available = true -%} 6 | {%- endif -%} 7 | {%- endunless -%} 8 | 9 | 10 | {%- capture unit_price_separator -%} 11 | {{ 'general.accessibility.unit_price_separator' | t }} 12 | {%- endcapture -%} 13 | {%- capture unit_price_base_unit -%} 14 | 15 | {%- if available and variant.unit_price_measurement -%} 16 | {%- if variant.unit_price_measurement.reference_value != 1 -%} 17 | {{- variant.unit_price_measurement.reference_value -}} 18 | {%- endif -%} 19 | {{ variant.unit_price_measurement.reference_unit }} 20 | {%- endif -%} 21 | 22 | {%- endcapture -%} 23 | {{ 'products.product.unit_price_label' | t }} 24 | {{ variant.unit_price | money }}{{- unit_price_separator -}}{{- unit_price_base_unit -}} 25 | 26 | -------------------------------------------------------------------------------- /docs/v2/event-queue-start.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: liquid-ajax-cart:queue-start 3 | layout: docs-v2 4 | --- 5 | 6 | # liquid-ajax-cart:queue-start 7 | 8 |

    9 | An event which is fired at the `document` when a Shopify Cart API Ajax request 10 | has been just added to the empty [Queue of requests](/v2/queue-of-requests/). 11 |

    12 | 13 | ## How it works 14 | 15 | Liquid Ajax Cart doesn't perform Shopify Cart API Ajax requests immediately, it adds them to the [Queue](/v2/queue-of-requests/). 16 | 17 | If there is no request performing at the moment (the [Queue](/v2/queue-of-requests/) is empty) 18 | and something initiates a new request (a user clicked an "Add to cart" button" 19 | or the request is made by a direct call of {% include v2/content/links-to-request-methods.html %}), 20 | the request will be added to the [Queue](/v2/queue-of-requests/), the Liquid Ajax Cart dispatches the 21 | `liquid-ajax-cart:queue-start` event and starts performing the request. 22 | 23 | {% include v2/content/lifecycle-events-reference.html %} 24 | 25 | {%- capture highlight_code -%} 26 | document.addEventListener("liquid-ajax-cart:queue-start", function() { 27 | console.log("A queue of requests is started"); 28 | }); 29 | {%- endcapture -%} 30 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 31 | 32 | -------------------------------------------------------------------------------- /docs/_includes/v2/content/request-end-use-cases.html: -------------------------------------------------------------------------------- 1 | {% assign queue_end_url = '/v2/event-queue-end/' %} 2 | {% if page.url contains 'lifecycle' %} 3 | {% assign queue_end_url = '#liquid-ajax-cart-queue-end' %} 4 | {% endif %} 5 | 6 | Use this event when you want to: 7 | * modify the page content depending on the request's result or when the cart state (which is stored in the [`liquidAjaxCart.cart`](/v2/liquid-ajax-cart-cart/) property) is updated; 8 | * modify the [`data-ajax-cart-section`](/v2/data-ajax-cart-section/) elements content or add event listeners to them when the elements are re-rendered; 9 | * track each successful cart-related user's action, such as adding a product to the cart, removing a product from the cart, etc. 10 | 11 | Code examples with this event: 12 | * [Open the Ajax-cart when a user adds a product to the cart](/v2/js-snippets/#open-the-ajax-cart-when-a-user-adds-a-product-to-the-cart); 13 | 14 | **Don't use** the event when you want to modify the cart state by performing an additional Shopify Cart API Ajax request 15 | based on a particular rule. 16 | There might be a few requests in the [Queue](/v2/queue-of-requests/), 17 | thus it is better to check the condition and initiate the additional request 18 | in a [`liquid-ajax-cart:queue-end`]({{ queue_end_url }}) event listener, 19 | when all the current requests are executed. -------------------------------------------------------------------------------- /docs/v2/js-snippets.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Ready snippets 3 | layout: docs-v2 4 | --- 5 | 6 | # Ready snippets 7 | 8 | ## Open the Ajax-cart when a user adds a product to the cart 9 | 10 | Usually the Ajax-cart isn't visible and opens when a user clicks the cart icon in the header. 11 | The click on the icon triggers a special CSS class to be added that makes the Ajax-cart show up. 12 | The simplified code looks like this: 13 | 14 | {%- capture highlight_code -%} 15 | // Add a special CSS class when the cart-icon is clicked 16 | document.querySelector("#cart-icon").addEventListener("click", function(){ 17 | document.body.classList.toggle("js-show-ajax-cart"); 18 | }); 19 | {%- endcapture -%} 20 | {% include v2/codeblock.html title="assets/script.js" language="javascript" code=highlight_code %} 21 | 22 | {%- capture highlight_code -%} 23 | // The Ajax-cart is hidden by default 24 | .my-ajax-cart { 25 | display: none; 26 | } 27 | 28 | // The Ajax-cart is visible if a special class is added 29 | body.js-show-ajax-cart .my-ajax-cart { 30 | display: block; 31 | } 32 | {%- endcapture -%} 33 | {% include v2/codeblock.html title="assets/style.css" language="css" code=highlight_code %} 34 | 35 | Our goal is to add the same CSS class to the `body` tag when a new product has been just added to the cart: 36 | {% include v2/content/add-to-cart-class-example.html %} -------------------------------------------------------------------------------- /templates/customers/activate_account.liquid: -------------------------------------------------------------------------------- 1 |
    2 |

    {{ 'customer.activate_account.title' | t }}

    3 |
    4 | 5 |

    {{ 'customer.activate_account.subtext' | t }}

    6 | 7 |
    8 |
    9 | 10 | {% comment %} 11 | This form must use 'activate_customer_password' 12 | {% endcomment %} 13 | {% form 'activate_customer_password' %} 14 | 15 | {{ form.errors | default_errors }} 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
    24 |

    25 | 26 |

    27 | 28 |
    29 | {% endform %} 30 | 31 |
    32 |
    33 | -------------------------------------------------------------------------------- /docs/v2/ajax-cart-product-form.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 3 | layout: docs-v2 4 | --- 5 | 6 | # ajax-cart-product-form 7 | 8 |

    9 | A custom tag which performs a Shopify Cart API `/cart/add.js` Ajax request once a user submits a product form. 10 |

    11 | 12 | ## How it works 13 | Once loaded, an `` element searches for 14 | a valid [Shopify product form](https://shopify.dev/docs/themes/architecture/templates/product#the-product-form) inside itself 15 | and subscribes to the form `submit` event. Once the event is fired, the `` element 16 | collects the form data and sends it as a Shopify Cart API `/cart/add.js` Ajax request in order to add the product to the cart. 17 | 18 | The `` element must contain only one Shopify product form inside: 19 | {%- capture highlight_code -%} 20 | {% raw %} 21 | 22 | {% form 'product', product %} 23 | 24 | 25 | 28 | {% endform %} 29 | 30 | {% endraw %} 31 | {%- endcapture -%} 32 | {% include v2/codeblock.html title="sections/main-product.liquid" language="liquid" code=highlight_code highlight_lines="1,9" %} 33 | 34 | {% include v2/content/form-loading-state-block.html %} -------------------------------------------------------------------------------- /docs/_includes/v2/styles/side-menu.scss: -------------------------------------------------------------------------------- 1 | .side-menu { 2 | line-height: 1.4; 3 | font-size: .875rem; 4 | } 5 | 6 | .side-menu__section + .side-menu__section { 7 | margin-top: 2rem; 8 | } 9 | 10 | .side-menu__section-title { 11 | font-weight: 700; 12 | } 13 | 14 | .side-menu__subsection { 15 | margin-top: 1.125rem; 16 | } 17 | 18 | .side-menu__subsection-title { 19 | font-size: .625rem; 20 | //font-weight: 500; 21 | letter-spacing: .1em; 22 | text-transform: uppercase; 23 | padding: 0 0 .56rem 1rem; 24 | color: #1C1C1C; 25 | } 26 | 27 | .side-menu__link { 28 | a { 29 | position: relative; 30 | color: inherit; 31 | display: block; 32 | text-decoration: none; 33 | padding: .10rem 1rem; 34 | border-left: 2px solid transparent; 35 | transition: border-color .15s; 36 | 37 | &:hover { 38 | border-color: #0A7307; 39 | } 40 | } 41 | 42 | & + &, 43 | ul { 44 | margin-top: .4rem; 45 | } 46 | 47 | &--active a { 48 | border-color: #0A7307; 49 | color: #35812F; 50 | font-weight: 700; 51 | } 52 | 53 | ul .side-menu__link a { 54 | padding-left: 2rem; 55 | } 56 | } 57 | 58 | .side-menu__subsection-content { 59 | position: relative; 60 | 61 | &:before { 62 | content: ''; 63 | position: absolute; 64 | left: 0; 65 | top: 0; 66 | height: 100%; 67 | border-left: 1px solid #bababa; 68 | } 69 | } -------------------------------------------------------------------------------- /docs/v1/reference/requests.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Cart Ajax API requests 3 | layout: page 4 | --- 5 | 6 | # Cart Ajax API requests 7 | 8 | It is highly recommended to use the following functions to make Shopify Cart Ajax API calls so Liquid Ajax Cart will keep the [State](/v1/reference/state/), [cart sections](/v1/reference/sections/), [body CSS classes](/v1/reference/body-css-classes/) and [`data-ajax-cart-bind-state`](/v1/reference/data-ajax-cart-bind-state/) content up to date: 9 | 10 | * [`cartRequestGet`](/v1/reference/cartRequestGet/) — sends a request to the `GET /cart.js` endpoint; 11 | * [`cartRequestAdd`](/v1/reference/cartRequestAdd/) — to the `POST /cart/add.js` endpoint; 12 | * [`cartRequestChange`](/v1/reference/cartRequestChange/) — to the `POST /cart/change.js` endpoint; 13 | * [`cartRequestUpdate`](/v1/reference/cartRequestUpdate/) — to the `POST /cart/update.js` endpoint; 14 | * [`cartRequestClear`](/v1/reference/cartRequestClear/) — to the `POST /cart/clear.js` endpoint. 15 | 16 | ### Subscribe to requests 17 | 18 | If you want to run your Javascript before or after a Shopify Cart Ajax API request, mutate or cancel a request before it is started — use the [`subscribeToCartAjaxRequests`](/v1/reference/subscribeToCartAjaxRequests/) function to add your callback. 19 | 20 | ### Queues of requests 21 | 22 | All Shopify Cart API requests don't get performed immediately but get added to [queues](/v1/reference/queues/). -------------------------------------------------------------------------------- /docs/v2/liquid-ajax-cart-processing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: liquidAjaxCart.processing 3 | layout: docs-v2 4 | --- 5 | 6 | # liquidAjaxCart.processing 7 | 8 |

    9 | A boolean read-only property of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object, 10 | which is `true` when there is a Shopify Cart API Ajax request in progress. 11 |

    12 | 13 | ## How it works 14 | 15 | The `liquidAjaxCart.processing` property returns `true` when the [Queue of requests](/v2/queue-of-requests/) is not empty, 16 | which means that Liquid Ajax Cart is currently executing Shopify Cart API Ajax requests 17 | until the [Queue of requests](/v2/queue-of-requests/) is empty. 18 | 19 | ## Use case 20 | 21 | Check this property when you are building a custom control, 22 | and you want to initiate a Shopify Cart API Ajax request only when 23 | there is no any other request in progress: 24 | 25 | {%- capture highlight_code -%} 26 | document.querySelector("#my-control").addEventListener("click", function() { 27 | if (!window.liquidAjaxCart?.init) 28 | return; 29 | 30 | // Ignore the click if Liquid Ajax Cart is processing a request 31 | if (window.liquidAjaxCart.processing) 32 | return; 33 | 34 | // Run the custom request is there is no other request in progress 35 | window.liquidAjaxCart.add({…}); 36 | }); 37 | {%- endcapture -%} 38 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 39 | -------------------------------------------------------------------------------- /docs/_includes/v2/footer.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_src/settings.ts: -------------------------------------------------------------------------------- 1 | import {FormattersObjectType, ConfigurationValue, MutationsListType} from './ts-types'; 2 | 3 | import {cartDomBinderRerender} from './dom-binder'; 4 | import {cartMutationsRun} from "./mutations"; 5 | 6 | type SettingsType = { 7 | binderFormatters: FormattersObjectType, 8 | requestErrorText: string, 9 | updateOnWindowFocus: boolean, 10 | quantityTagAllowZero: boolean, 11 | quantityTagDebounce: number, 12 | mutations: MutationsListType, 13 | extraRequestOnError: boolean 14 | } 15 | type SettingsKeysType = keyof SettingsType; 16 | 17 | const settings: SettingsType = { 18 | binderFormatters: {}, 19 | requestErrorText: 'There was an error while updating your cart. Please try again.', 20 | updateOnWindowFocus: true, 21 | quantityTagAllowZero: false, 22 | quantityTagDebounce: 300, 23 | mutations: [], 24 | extraRequestOnError: true 25 | } 26 | 27 | function configureCart(property: string, value: ConfigurationValue) { 28 | if (property in settings) { 29 | (settings[property as SettingsKeysType] as ConfigurationValue) = value; 30 | if (window.liquidAjaxCart.init) { 31 | if (property === 'binderFormatters') { 32 | cartDomBinderRerender(); 33 | } 34 | if (property === 'mutations') { 35 | cartMutationsRun(); 36 | } 37 | } 38 | } else { 39 | console.error(`Liquid Ajax Cart: unknown configuration parameter "${property}"`); 40 | } 41 | } 42 | 43 | export {settings, configureCart}; 44 | -------------------------------------------------------------------------------- /docs/v2/js-ajax-cart-init.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: js-ajax-cart-init 3 | layout: docs-v2 4 | --- 5 | 6 | # js-ajax-cart-init 7 | 8 |

    9 | A CSS class which is appended to the `html` tag when Liquid Ajax Cart is initialized. 10 |

    11 | 12 | ## Example 13 | 14 | Hiding the "Update" button on the cart page, as all the elements are ajaxified and no need to apply the changes manually: 15 | 16 | {%- capture highlight_code -%} 17 | {% raw %} 18 |
    19 |

    Cart page

    20 | 21 |
    22 | 23 |
    24 | 25 |
    26 | 29 | 32 |
    33 |
    34 | 35 | {% schema %} { "name": "Cart page" } {% endschema %} 36 | {% endraw %} 37 | {%- endcapture -%} 38 | {% include v2/codeblock.html title="sections/main-cart.liquid" language="liquid" code=highlight_code highlight_lines="9-11" %} 39 | 40 | {%- capture highlight_code -%} 41 | html.js-ajax-cart-init .my-cart-page__update-button { 42 | display: none; 43 | } 44 | {%- endcapture -%} 45 | {% include v2/codeblock.html title="assets/style.css" language="css" code=highlight_code %} 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "liquid-ajax-cart", 3 | "version": "2.2.0", 4 | "description": "Build a Shopify Ajax-cart without JavaScript coding", 5 | "private": false, 6 | "browser": "./liquid-ajax-cart.js", 7 | "files": [ 8 | "/liquid-ajax-cart.js" 9 | ], 10 | "scripts": { 11 | "screenshot": "node screenshot.js", 12 | "test": "echo \"Error: no test specified\" && exit 1", 13 | "webpack-watch": "webpack --mode=development --watch", 14 | "shopify-watch": "shopify theme dev --store=liquid-ajax-cart", 15 | "start": "npm-run-all --parallel webpack-watch shopify-watch", 16 | "build": "rimraf docs/v2/releases/last && webpack --mode=production && webpack --mode=production --env last=true && webpack --mode=production --env npm=true" 17 | }, 18 | "keywords": [ 19 | "shopify", 20 | "liquid", 21 | "ajax", 22 | "cart" 23 | ], 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/EvgeniyMukhamedjanov/liquid-ajax-cart.git" 27 | }, 28 | "author": "Evgeniy Mukhamedjanov (https://github.com/EvgeniyMukhamedjanov)", 29 | "license": "ISC", 30 | "homepage": "https://liquid-ajax-cart.js.org", 31 | "devDependencies": { 32 | "js-yaml": "^4.1.0", 33 | "npm-run-all": "^4.1.5", 34 | "puppeteer": "^21.5.0", 35 | "resize-img": "^2.0.0", 36 | "rimraf": "^3.0.2", 37 | "ts-loader": "^9.2.6", 38 | "typescript": "^4.5.4", 39 | "webpack": "^5.53.0", 40 | "webpack-cli": "^4.8.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /docs/v1/reference/configure.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Configuration 3 | layout: page 4 | --- 5 | 6 | # Configuration 7 | 8 | ### data-ajax-cart-configuration 9 | Add a `script` tag with the `data-ajax-cart-configuration` attribute and a JSON object with configuration parameters inside to set initial configuration of Liquid Ajax Cart: 10 | 11 | {% raw %} 12 | ```html 13 | {% comment %} Somewhere in layout/theme.liquid {% endcomment %} 14 | 15 | 21 | ``` 22 | {% endraw %} 23 | 24 | It is highly recommended to add the `script` to the `layout/theme.liquid` file to make the configuration accessible on all pages. 25 | 26 | This method doesn't support the [`productFormsFilter`](/v1/reference/productFormsFilter/) and the [`messageBuilder`](/v1/reference/messageBuilder/) parameters. To set them up use the `configureCart` function that supports all the parameters. 27 | 28 | 29 | ### configureCart() 30 | 31 | The function takes a configuration parameter and its new value: 32 | {% raw %} 33 | ```html 34 | 40 | ``` 41 | {% endraw %} -------------------------------------------------------------------------------- /docs/v1/reference/subscribeToCartSectionsUpdate.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: subscribeToCartSectionsUpdate() 3 | layout: page 4 | --- 5 | 6 | # subscribeToCartSectionsUpdate() 7 | 8 |

    @Kobi, especially for you.

    9 | 10 | The `subscribeToCartSectionsUpdate` function adds your callback function to the list of functions that will be called each time after [`data-ajax-cart-section`](/v1/reference/data-ajax-cart-section/) sections HTML is updated. 11 | 12 | The callback should be passed as the only parameter. 13 | 14 | ```javascript 15 | subscribeToCartSectionsUpdate( myCallback ); 16 | ``` 17 | 18 | ```html 19 | 26 | ``` 27 | 28 | Your callback will be called with an array of updated sections: 29 | 30 | ```json 31 | [ 32 | { 33 | "id": "my-cart", 34 | "elements": [ Element {} ] 35 | }, 36 | { 37 | "id": "my-mini-cart", 38 | "elements": [ Element {}, Element {} ] 39 | } 40 | ] 41 | ``` 42 | 43 | * `id` — Shopify section's name. 44 | * `elements` — an array of new `data-ajax-cart-section` HTML elements that replaced old ones. If the Shopify section is updated completely due to an error then the only item of the `elements` array will be the Shopify section's HTML element. -------------------------------------------------------------------------------- /docs/v1/reference/stateBinderFormatters.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: stateBinderFormatters 3 | layout: page 4 | --- 5 | 6 | # stateBinderFormatters 7 | 8 | The `stateBinderFormatters` configuration parameter lets you define custom formatters that you can use with the [`data-ajax-cart-bind-state`](/v1/reference/data-ajax-cart-bind-state/) attribute. 9 | 10 | For example, if you use the `option_selection.js` Shopify asset and its `Shopify.formatMoney` function you can specify your own formatter for money related values: 11 | 12 | {% raw %} 13 | ```html 14 | 36 | 37 | 38 | 39 | {{ cart.total_price | money_with_currency }} 40 | 41 | ``` 42 | {% endraw %} -------------------------------------------------------------------------------- /docs/v2/update-on-window-focus.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: updateOnWindowFocus 3 | layout: docs-v2 4 | --- 5 | 6 | # updateOnWindowFocus 7 | 8 |

    9 | A configuration parameter which toggles the functionality that updates everything 10 | related to Liquid Ajax Cart when the browser tab loses focus and gets focus back. 11 |

    12 | 13 | ## How it works 14 | 15 | Liquid Ajax Cart makes a Shopify Cart API Ajax request each time when the browser tab loses focus and gets focus back 16 | to keep [`data-ajax-cart-section`](/v2/data-ajax-cart-section/) containers and the [`liquidAjaxCart.cart`](/v2/liquid-ajax-cart-cart/) object up to date. 17 | 18 | It is necessary because a user can open two browser tabs with the same Shopify store, adds a product to the cart in the second tab, 19 | then goes back to the first one. The first tab "doesn't know" that the new product was added, so the user will see outdated data in the cart. 20 | The additional Ajax request is supposed to prevent this issue. 21 | 22 | You might want to disable this functionality during the development process because when you switch from DevTools to a page content, 23 | `window` object will get and lose focus all the time and cart sections will be updating constantly. 24 | 25 | Use the [`conf`](/v2/liquid-ajax-cart-conf/) method of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object 26 | to switch this functionality off: 27 | {%- capture highlight_code -%} 28 | liquidAjaxCart.conf("updateOnWindowFocus", false); 29 | {%- endcapture -%} 30 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 31 | -------------------------------------------------------------------------------- /docs/v1/reference/data-ajax-cart-quantity-input.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: data-ajax-cart-quantity-input 3 | layout: page 4 | --- 5 | 6 | # data-ajax-cart-quantity-input 7 | 8 | Add the `data-ajax-cart-quantity-input` attribute with a cart item's index or a cart item's key as the value to an input element to ajaxify the input field: once a user changes the input's value, Liquid Ajax Cart will send a Shopify [Cart API request](/v1/reference/requests/) to update the quantity. 9 | 10 | The request will be sent on input's `change` event and if a user presses the `Enter` key within the input field. 11 | 12 | If a user presses the `Esc` key within the input, its value will be reset to the current item's quantity according to the [State](/v1/reference/state/) object. 13 | 14 | The `data-ajax-cart-quantity-input` input fields become `readonly` when there is a Shopify Cart API request in progress (if the [State](/v1/reference/state/)’s `status.requestInProgress` property is `true`) 15 | 16 | Using a line item's index: 17 | {% raw %} 18 | ```html 19 | {% for item in cart.items %} 20 | 21 | {% endfor %} 22 | ``` 23 | {% endraw %} 24 | 25 | Using a line item's key is supported also, but there were found unexpected behaviour of the `/add/change.js` endpoint handler in some cases. Test it carefully with your store before going live: 26 | {% raw %} 27 | ```html 28 | {% for item in cart.items %} 29 | 30 | {% endfor %} 31 | ``` 32 | {% endraw %} -------------------------------------------------------------------------------- /docs/_sass/components/_highlight.scss: -------------------------------------------------------------------------------- 1 | @if $site-ui-mode == 'auto' { 2 | @media (prefers-color-scheme: dark) { 3 | @include highlight-dark-theme(); 4 | } 5 | 6 | @media (prefers-color-scheme: light) { 7 | @include highlight-light-theme(); 8 | } 9 | } 10 | @else if $site-ui-mode == 'dark' { 11 | @include highlight-dark-theme(); 12 | } 13 | @else if $site-ui-mode == 'light' { 14 | @include highlight-light-theme(); 15 | } 16 | 17 | .highlight { 18 | @include themer(background-color, ( 19 | 'dark': #3f3f3f, 20 | 'light': #f7f7f9, 21 | )); 22 | @include themer(border-color, ( 23 | 'dark': #222222, 24 | 'light': #e1e1e8, 25 | )); 26 | 27 | border-style: solid; 28 | border-width: 1px; 29 | border-radius: 4px; 30 | padding: 9px 14px; 31 | margin-bottom: 14px; 32 | } 33 | 34 | .highlight pre { 35 | background-color: transparent; 36 | border: 0; 37 | padding: 0; 38 | margin-top: 0; 39 | margin-bottom: 0; 40 | } 41 | 42 | .highlight pre, 43 | .highlight code { 44 | word-wrap: normal; 45 | word-break: normal; 46 | white-space: pre; 47 | } 48 | 49 | .highlight pre code { 50 | @include themer(color, ( 51 | 'dark': #fdce93, 52 | 'light': #333, 53 | )); 54 | 55 | font-size: inherit; 56 | white-space: pre; 57 | background-color: transparent; 58 | border: none; 59 | padding: 0; 60 | } 61 | 62 | .highlight pre .lineno { 63 | display: inline-block; 64 | color: #bebec5; 65 | margin-right: 10px; 66 | padding-right: 5px; 67 | text-align: right; 68 | width: 22px; 69 | } 70 | -------------------------------------------------------------------------------- /docs/v1/reference/data-ajax-cart-section-scroll.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: data-ajax-cart-section-scroll 3 | layout: page 4 | --- 5 | 6 | # data-ajax-cart-section-scroll 7 | 8 | If you have a scrollable area within a [`data-ajax-cart-section`](/v1/reference/data-ajax-cart-section/) section, the scroll position will be reset to top every time when the cart is changed because the section’s HTML will be completely replaced with a new one. 9 | 10 | Add the `data-ajax-cart-section-scroll` attribute to the scrollable area and Liquid Ajax Cart will keep the scroll position unchanged. 11 | 12 | ```html 13 | {% raw %}
    14 |

    Cart

    15 | 16 |
    17 | 18 | {% comment %} 19 | Scrollable area 20 | {% endcomment %} 21 | 22 |
    23 | 24 |
    {% endraw %} 25 | ``` 26 | 27 | If you have several scrollable areas, add the `data-ajax-cart-section-scroll` attribute with unique parameters so Liquid Ajax Cart can distinguish them after HTML update. 28 | 29 | ```html 30 | {% raw %}
    31 |

    Cart

    32 | 33 |
    34 | 35 | {% for item in cart.items %} 36 |
    37 | {% comment %} 38 | Despite it sounds crazy, lets imagine that each line-item is scrollable. 39 | Thus it needs the data-ajax-cart-section-scroll attribute with a unique parameter 40 | {% endcomment %} 41 |
    42 | {% endfor %} 43 | 44 |
    45 | 46 |
    {% endraw %} 47 | ``` 48 | -------------------------------------------------------------------------------- /docs/_includes/v2/styles/cards.scss: -------------------------------------------------------------------------------- 1 | .cards { 2 | display: grid; 3 | grid-template-columns: repeat(6, 1fr); 4 | gap: 2.25rem; 5 | margin-top: 2rem; 6 | } 7 | 8 | .cards__card { 9 | border: 1px solid #20344C; 10 | border-top: 3px solid #243953; 11 | background-color: rgba(26, 37, 63, .3); 12 | border-radius: .875rem; 13 | padding: 2rem 1.5rem 0; 14 | position: relative; 15 | transition: .15s; 16 | z-index: 1; 17 | display: flex; 18 | flex-direction: column; 19 | min-width: 0; 20 | grid-column: span 6; 21 | 22 | &:hover { 23 | transform: scale(1.02); 24 | background-color: rgba(26, 37, 63, .5); 25 | } 26 | 27 | .codeblock { 28 | margin-bottom: 0; 29 | padding-bottom: 0; 30 | margin-top: 1.75rem; 31 | } 32 | 33 | .codeblock__wrapper { 34 | border: 1px solid #20344C; 35 | border-bottom: 0; 36 | border-radius: .75rem .75rem 0 0; 37 | } 38 | 39 | &--3-6 { 40 | @media (min-width: 768px) { 41 | grid-column: span 3; 42 | } 43 | } 44 | 45 | &--4-6 { 46 | @media (min-width: 768px) { 47 | grid-column: span 3; 48 | } 49 | @media (min-width: 992px) { 50 | grid-column: span 4; 51 | } 52 | } 53 | 54 | &--2-6 { 55 | @media (min-width: 768px) { 56 | grid-column: span 3; 57 | } 58 | @media (min-width: 992px) { 59 | grid-column: span 2; 60 | } 61 | } 62 | } 63 | 64 | .cards__card-title { 65 | font-size: 1.15rem; 66 | margin-bottom: 1.25rem; 67 | font-weight: 700; 68 | } 69 | 70 | .cards__card-description { 71 | color: #b5bedd; 72 | flex-grow: 1; 73 | max-width: 47rem; 74 | 75 | a { 76 | color: inherit !important; 77 | } 78 | } -------------------------------------------------------------------------------- /docs/v2/binder-formatters.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: binderFormatters 3 | layout: docs-v2 4 | --- 5 | 6 | # binderFormatters 7 | 8 |

    9 | A configuration parameter which lets you define custom formatters 10 | to use with the [`data-ajax-cart-bind`](/v2/data-ajax-cart-bind/) attribute. 11 |

    12 | 13 | ## Code example 14 | 15 | For example, if you use the `option_selection.js` Shopify asset and its `Shopify.formatMoney` function, 16 | you can specify your own formatter for money related values. 17 | Use the [`conf`](/v2/liquid-ajax-cart-conf/) method of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object to do this: 18 | 19 | {%- capture highlight_code -%} 20 | liquidAjaxCart.conf('binderFormatters', { 21 | 'my_formatter': value => { 22 | // Don't change anything if the value is not a number 23 | if (typeof value !== 'number' && !(value instanceof Number)) { 24 | return value; 25 | } 26 | 27 | // Apply formatMoney function if it exists 28 | if (window.Shopify?.formatMoney) { 29 | return Shopify.formatMoney(value); 30 | } 31 | 32 | // Fallback to the "100 USD" format if there is no Shopify.formatMoney 33 | return `${ value.toFixed(2) } ${ window.liquidAjaxCart.cart.currency }`; 34 | } 35 | }); 36 | {%- endcapture -%} 37 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 38 | 39 | Applying the filter: 40 | {%- capture highlight_code -%} 41 | {% raw %} 42 | 43 | {{ cart.total_price | money_with_currency }} 44 | 45 | {% endraw %} 46 | {%- endcapture -%} 47 | {% include v2/codeblock.html language="liquid" code=highlight_code %} -------------------------------------------------------------------------------- /snippets/pagination-custom.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | 3 | This snippet renders a custom widget based on the current 'paginate' context, 4 | defined in { % paginate XXXX by 5 % } tags wrapping the content. 5 | The example below breaks the pagination down so you can setup your own styles and behavior if you wish. 6 | 7 | Basic Pagination Usage: 8 | 11 | 12 | Replace Text: 13 | 16 | 17 | More information: 18 | - index#pagination 19 | - http://docs.shopify.com/themes/liquid-variables/paginate 20 | 21 | {% endcomment %} 22 | 23 |
      24 | {% if paginate.previous %} 25 |
    • 26 | {% else %} 27 |
    • 28 | {% endif %} 29 | 30 | {% for part in paginate.parts %} 31 | {% if part.is_link %} 32 |
    • 33 | {{ part.title }} 34 |
    • 35 | {% else %} 36 | {% if part.title == paginate.current_page %} 37 |
    • {{ part.title }}
    • 38 | {% else %} 39 |
    • {{ part.title }}
    • 40 | {% endif %} 41 | {% endif %} 42 | {% endfor %} 43 | 44 | {% if paginate.next %} 45 |
    • 46 | {% else %} 47 |
    • 48 | {% endif %} 49 |
    50 | -------------------------------------------------------------------------------- /docs/_includes/styles/sidebar.scss: -------------------------------------------------------------------------------- 1 | .page-sidebar { 2 | overflow: auto; 3 | top: 20px; 4 | 5 | scrollbar-width: 2px; 6 | scrollbar-color: #dee2e6 #ebebeb; 7 | &::-webkit-scrollbar { 8 | width: 2px; 9 | height: 2px; 10 | } 11 | &::-webkit-scrollbar-track { 12 | background: #ebebeb; 13 | } 14 | &::-webkit-scrollbar-thumb { 15 | background: #dee2e6; 16 | } 17 | 18 | a { 19 | color: #777; 20 | border-bottom: 0; 21 | padding: 4px 0; 22 | } 23 | 24 | > ul { 25 | padding-left: 0; 26 | list-style: none; 27 | 28 | > li { 29 | margin-bottom: 10px; 30 | } 31 | } 32 | 33 | ul { 34 | 35 | & ul { 36 | padding-left: 15px; 37 | font-size: 80%; 38 | } 39 | 40 | li { 41 | list-style: none; 42 | } 43 | 44 | a { 45 | border-bottom: 0; 46 | display: block; 47 | // font-weight: 500; 48 | position: relative; 49 | 50 | &:focus, 51 | &:hover { 52 | color: #5e8e3e; 53 | background-color: transparent; 54 | } 55 | 56 | &.active, 57 | &.active:focus, 58 | &.active:hover { 59 | color: #5e8e3e; 60 | // background-color: rgba(#bfea52, .2); 61 | 62 | font-weight: 700; 63 | } 64 | 65 | // Unhide any nested ULs when this TOC section is active 66 | &.active + ul { 67 | display: block; 68 | } 69 | } 70 | } 71 | 72 | &#page-toc { 73 | position: sticky; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /docs/_includes/v2/styles/critical.scss: -------------------------------------------------------------------------------- 1 | :root, 2 | ::before, 3 | ::after { 4 | --header-height: 3rem; 5 | } 6 | 7 | .layout-home-v2 { 8 | --header-height: 4rem; 9 | } 10 | 11 | html { 12 | scroll-behavior: smooth; 13 | font-family: 'Inter', sans-serif; 14 | @media (min-width: 1920px) { 15 | font-size: 0.83vw; 16 | } 17 | } 18 | 19 | body { 20 | font-size: 1rem; 21 | line-height: 1.6; 22 | scroll-behavior: smooth; 23 | text-rendering: optimizespeed; 24 | overflow-y: scroll; 25 | } 26 | 27 | strong { 28 | font-weight: 600; 29 | } 30 | 31 | code { 32 | font-family: 'JetBrains Mono', SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; 33 | } 34 | :not(pre) > code { 35 | font-size: .9375em !important; 36 | color: inherit !important; 37 | background-color: #f9f9f9; 38 | //border: 1px solid #999999; 39 | padding: 0 .25em; 40 | border-radius: .125em; 41 | } 42 | 43 | .container { 44 | margin: 0 auto; 45 | max-width: 90rem; 46 | padding: 0 2rem; 47 | display: block; 48 | } 49 | 50 | .lead { 51 | font-size: 1.125rem; 52 | margin-bottom: 1.5rem !important; 53 | + .lead { 54 | margin-top: -1rem; 55 | } 56 | } 57 | 58 | .redirect-message { 59 | position: fixed; 60 | top: 50%; 61 | text-align: center; 62 | background: black; 63 | left: 0; 64 | right: 0; 65 | margin: 0 auto; 66 | max-width: 18.75rem; 67 | color: white; 68 | border-radius: 0.3rem; 69 | padding: 0.8rem; 70 | z-index: 100; 71 | 72 | a { 73 | color: white; 74 | } 75 | 76 | &:before { 77 | content: ''; 78 | position: fixed; 79 | left: 0; 80 | right: 0; 81 | top: 0; 82 | bottom: 0; 83 | background-color: rgba(0, 0, 0, .4); 84 | z-index: -1; 85 | } 86 | } -------------------------------------------------------------------------------- /docs/_includes/v2/styles/codeblock.scss: -------------------------------------------------------------------------------- 1 | .codeblock { 2 | margin-bottom: 1rem; 3 | padding-bottom: .5rem; 4 | } 5 | 6 | .codeblock__wrapper { 7 | background-color: #171f32 !important; 8 | //border: 1px solid ; 9 | border-radius: .75rem; 10 | overflow: hidden; 11 | } 12 | 13 | .codeblock__header { 14 | //background-color: black; 15 | //color: white; 16 | //background-color: #f0f7ee; 17 | font-family: 'JetBrains Mono', SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; 18 | font-size: .75rem; 19 | display: flex; 20 | align-items: stretch; 21 | //border-radius: .75rem .75rem 0 0; 22 | 23 | &:after { 24 | content: ''; 25 | width: auto; 26 | flex: 1 1 auto; 27 | background-color: #0e121d; 28 | } 29 | } 30 | 31 | .codeblock__header-title { 32 | flex: 0 0 auto; 33 | padding: .5rem .9rem; 34 | border-bottom: 1px solid #d5ffd387; 35 | color: white; 36 | } 37 | 38 | .codeblock__content { 39 | //background-color: #e7f2e39e !important; 40 | //border: 1px solid ; 41 | margin: 0 !important; 42 | //border-radius: .75rem; 43 | padding: 1rem; 44 | color: white; 45 | font-size: .875rem; 46 | 47 | //.codeblock__header + & { 48 | // border-radius: 0 0 .75rem .75rem; 49 | //} 50 | 51 | scrollbar-width: thin; 52 | scrollbar-color: rgba(255, 255, 255, .2) rgba(255, 255, 255, .1); 53 | 54 | &::-webkit-scrollbar { 55 | height: 8px; 56 | } 57 | 58 | &::-webkit-scrollbar-track { 59 | background-color: rgba(255, 255, 255, .1); 60 | //border-radius: 100px; 61 | } 62 | 63 | &::-webkit-scrollbar-thumb { 64 | background-color: rgba(255, 255, 255, .2); 65 | //border-radius: 100px; 66 | } 67 | } 68 | 69 | .language-console-text { 70 | line-height: 1 !important; 71 | } -------------------------------------------------------------------------------- /snippets/onboarding-featured-blog.liquid: -------------------------------------------------------------------------------- 1 |
    2 | {% for i in (1..section.settings.post_limit) %} 3 |
    4 |
    5 | {% if section.settings.blog_show_image %} 6 |
    7 | {% capture current %}{% cycle 1, 2, 3, 4, 5, 6 %}{% endcapture %} 8 | {{ 'collection-' | append: current | placeholder_svg_tag: 'placeholder-svg' }} 9 |
    10 | {% endif %} 11 | {% unless section.settings.post_limit == 1 and section.settings.blog_show_image %} 12 |

    {{ 'home_page.onboarding.blog_title' | t }} →

    13 | {% if section.settings.blog_show_excerpt %} 14 |
    15 | {{ 'home_page.onboarding.blog_excerpt' | t }} 16 |
    17 | {% endif %} 18 | {% endunless %} 19 |
    20 |
    21 | 22 | {% if section.settings.post_limit == 1 and section.settings.blog_show_image %} 23 |
    24 |
    25 |

    {{ 'home_page.onboarding.blog_title' | t }} →

    26 | {% if section.settings.blog_show_excerpt %} 27 |
    28 | {{ 'home_page.onboarding.blog_excerpt' | t }} 29 |
    30 | {% endif %} 31 |
    32 |
    33 | {% endif %} 34 | 35 | {% endfor %} 36 |
    -------------------------------------------------------------------------------- /docs/v2/liquid-ajax-cart-cart.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: liquidAjaxCart.cart 3 | layout: docs-v2 4 | --- 5 | 6 | # liquidAjaxCart.cart 7 | 8 |

    9 | A read-only property of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object, which returns the current cart state data. 10 |

    11 | 12 | ## How it works 13 | 14 | After each successful Shopify Cart API Ajax request, 15 | Liquid Ajax Cart retrieves the cart state data from the response and saves it the in the `liquidAjaxCart.cart` property. 16 | If a request is successful but the response doesn't have the cart state data (the `/cart/add.js` response is the case), 17 | Liquid Ajax Cart performs an additional `/cart/update.js` request to get the data. 18 | 19 | Use the `liquidAjaxCart.cart` property to read the latest cart state data. 20 | 21 | As the cart state data is updated after a Shopify Cart API Ajax request, 22 | subscribe to the [`liquid-ajax-cart:request-end`](/v2/event-request-end/) event 23 | if you want to run your JavaScript code when the cart state is updated. 24 | 25 | ## Structure 26 | 27 | {%- capture highlight_code -%} 28 | 29 | console.log(window.liquidAjaxCart.cart); 30 | 31 | {%- endcapture -%} 32 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 33 | 34 | Result: 35 | 36 | {%- capture highlight_code -%} 37 | { 38 | "token":"b7d3743e2c398043f209c5a3a9014f9d", 39 | "note":null, 40 | "attributes":{}, 41 | "original_total_price":1000, 42 | "total_price":1000, 43 | "total_discount":0, 44 | "total_weight":0, 45 | "item_count":1, 46 | "items":[{…}], 47 | "requires_shipping":false, 48 | "currency":"USD", 49 | "items_subtotal_price":1000, 50 | "cart_level_discount_applications":[] 51 | } 52 | {%- endcapture -%} 53 | {% include v2/codeblock.html language="json" code=highlight_code %} -------------------------------------------------------------------------------- /docs/v1/reference/data-ajax-cart-toggle-class-button.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: data-ajax-cart-toggle-class-button 3 | layout: page 4 | --- 5 | 6 | 7 | # data-ajax-cart-toggle-class-button 8 | 9 | Add the `data-ajax-cart-toggle-class-button` attribute to an HTML element, pass a CSS class name as a parameter, and Liquid Ajax Cart will "toggle" the CSS class for the `body` tag when a user clicks on the element. 10 | 11 | The CSS class will be added to the `body` tag if it doesn't have the CSS class. The CSS class will be removed from the `body` tag if it has the CSS class. 12 | 13 | The usecase is "Show/Hide Cart" button. It is used in the header of the demo store: "Cart" link shows and hides the right-side cart. 14 | 15 | {% raw %} 16 | ```html 17 | 18 |
    {% section 'my-cart' %}
    19 | 20 | 26 | 27 | 28 | 29 | 30 | 32 | My Cart 33 | 34 | 35 | 39 | ``` 40 | {% endraw %} 41 | 42 | If you want to create a button that will only add or only remove a CSS class — specify the additional parameter: 43 | 44 | ```html 45 | 48 | 49 | 52 | ``` 53 | -------------------------------------------------------------------------------- /snippets/newsletter-form.liquid: -------------------------------------------------------------------------------- 1 |
    2 | {% form 'customer' %} 3 | {{ form.errors | default_errors }} 4 | {% if form.posted_successfully? %} 5 |

    {{ 'general.newsletter_form.confirmation' | t }}

    6 | {% else %} 7 | 8 | 9 | 10 | {% endif %} 11 | {% endform %} 12 |
    13 |
    14 | {% form 'customer' %} 15 | {{ form.errors | default_errors }} 16 | {% if form.posted_successfully? %} 17 |

    {{ 'general.newsletter_form.confirmation' | t }}

    18 | {% else %} 19 | 20 |
    21 | 22 | 23 | 24 | 25 |
    26 | {% endif %} 27 | {% endform %} 28 |
    29 | -------------------------------------------------------------------------------- /docs/v1/reference/updateOnWindowFocus.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: updateOnWindowFocus 3 | layout: page 4 | --- 5 | 6 | # updateOnWindowFocus 7 | 8 | Liquid Ajax Cart makes a Shopify Cart API request each time when the browser tab loses focus and gets focus back to keep [`data-ajax-cart-section`](/v1/reference/data-ajax-cart-section/) containers and the [State](/v1/reference/state/) object up to date. 9 | 10 | It is necessary because a user can open two browser tabs with the same Shopify store, adds a product to the cart in the second tab and then goes back to the first one. The first tab "doesn't know" about the new product in the cart but once the tab gets focus it will get updated. 11 | 12 | You might want to disable this functionality during the development process because when you switch from DevTools to a page content and back the `window` object will get and lose focus all the time and cart sections will be updating constantly. Use the `updateOnWindowFocus` configuration parameter to turn this functionality off. 13 | 14 | Disable using the `data-ajax-cart-configuration` attribute: 15 | {% raw %} 16 | ```html 17 | {% comment %} Somewhere in layout/theme.liquid {% endcomment %} 18 | 19 | 24 | ``` 25 | {% endraw %} 26 | 27 | Disable using the `configureCart` function: 28 | {% raw %} 29 | ```html 30 | 35 | ``` 36 | {% endraw %} 37 | 38 | You can change the parameter right in the browser's console by typing the following command: 39 | ```javascript 40 | liquidAjaxCart.configureCart('updateOnWindowFocus', false) 41 | ``` -------------------------------------------------------------------------------- /docs/v2/liquid-ajax-cart.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The liquidAjaxCart object 3 | layout: docs-v2 4 | --- 5 | 6 | # The liquidAjaxCart object 7 | 8 |

    9 | An object which exposes the methods and properties of the Liquid Ajax Cart library. 10 | The `liquidAjaxCart` object is defined as a property of the `window` object to be accessible from everywhere. 11 |

    12 | 13 | ## Methods and properties 14 | 15 | A few of them are available as soon as the library code is loaded: 16 | * [`conf()`](/v2/liquid-ajax-cart-conf/) — sets configuration parameter values; 17 | * [`init`](/v2/liquid-ajax-cart-init/) — initialization status (boolean). 18 | 19 | The rest of them are available only after the [initialization](/v2/lifecycle-events-api/#initialization): 20 | 21 | * [`get()`](/v2/liquid-ajax-cart-get/) — makes a Shopify Cart API `GET /cart.js` Ajax request; 22 | * [`add()`](/v2/liquid-ajax-cart-add/) — makes a `POST /cart/add.js` request; 23 | * [`change()`](/v2/liquid-ajax-cart-change/) — makes a `POST /cart/change.js` request; 24 | * [`update()`](/v2/liquid-ajax-cart-update/) — makes a `POST /cart/update.js` request; 25 | * [`clear()`](/v2/liquid-ajax-cart-clear/) — makes a `POST /cart/clear.js` request; 26 | * [`cart`](/v2/liquid-ajax-cart-cart/) — current cart state (JSON); 27 | * [`processing`](/v2/liquid-ajax-cart-processing/) — `true` if there is a request in progress now (boolean). 28 | 29 | ## Access after initialization 30 | 31 | Since most of the `liquidAjaxCart` methods and properties are available only after the initialization, 32 | use the [`liquid-ajax-cart:init`](/v2/event-init/) event 33 | along with the [`liquidAjaxCart.init`](/v2/liquid-ajax-cart-init/) property 34 | when your code depends on Liquid Ajax Cart and should be executed as soon as the library is fully available: 35 | {% include v2/content/init-event-example.html %} -------------------------------------------------------------------------------- /_src/controls/product-form-element.ts: -------------------------------------------------------------------------------- 1 | import {cartRequestAdd} from "../ajax-api"; 2 | import {CUSTOM_ELEMENT_PREFIX} from "../const"; 3 | 4 | const ELEMENT_TAG = `${CUSTOM_ELEMENT_PREFIX}-product-form`; 5 | const DATA_ATTR_LOADING = 'processing'; 6 | 7 | class HTMLProductFormElement extends HTMLElement { 8 | connectedCallback() { 9 | const $element = this; 10 | 11 | const $innerForms = this.querySelectorAll('form') 12 | if ($innerForms.length !== 1) { 13 | console.error( 14 | `Liquid Ajax Cart: "${ELEMENT_TAG}" element must have one "form" element as a child, ${$innerForms.length} found`, 15 | $element 16 | ); 17 | return; 18 | } 19 | 20 | const $form = $innerForms[0]; 21 | 22 | const formActionUrl = new URL($form.action); 23 | if (formActionUrl.pathname !== `${window.Shopify?.routes?.root || '/'}cart/add`) { 24 | console.error( 25 | `Liquid Ajax Cart: "${ELEMENT_TAG}" element's form "action" attribute value isn't a product form action URL`, 26 | $form, 27 | $element 28 | ); 29 | return; 30 | } 31 | 32 | $form.addEventListener('submit', event => { 33 | if (!$element.hasAttribute(DATA_ATTR_LOADING)) { 34 | const formData = new FormData($form); 35 | $element.setAttribute(DATA_ATTR_LOADING, ''); 36 | 37 | cartRequestAdd(formData, { 38 | lastCallback: () => { 39 | $element.removeAttribute(DATA_ATTR_LOADING) 40 | }, 41 | info: { 42 | "initiator": $element 43 | } 44 | }) 45 | } 46 | event.preventDefault(); 47 | }); 48 | } 49 | } 50 | 51 | function cartProductFormElementInit() { 52 | customElements.define(ELEMENT_TAG, HTMLProductFormElement); 53 | } 54 | 55 | export { 56 | cartProductFormElementInit, 57 | HTMLProductFormElement 58 | } -------------------------------------------------------------------------------- /docs/_includes/jekyll-docs-theme/anchor_headings.html: -------------------------------------------------------------------------------- 1 | {% assign fm_anchorClass = layout.anchor_headings.anchorClass | default: page.anchor_headings.anchorClass | default: "" %} 2 | 3 | {% capture anchorClass -%} 4 | {{- include.anchorClass -}} 5 | {%- if fm_anchorClass -%} 6 | .{{- fm_anchorClass -}} 7 | {%- endif -%} 8 | {%- endcapture %} 9 | 10 | {% assign beforeHeading = page.anchor_headings.beforeHeading | default: layout.anchor_headings.beforeHeading | default: false %} 11 | {% assign anchorAttrs = page.anchor_headings.anchorAttrs | default: layout.anchor_headings.anchorAttrs | default: '' %} 12 | {% assign anchorBody = page.anchor_headings.anchorBody | default: layout.anchor_headings.anchorBody | default: "#" %} 13 | {% assign anchorTitle = page.anchor_headings.anchorTitle | default: layout.anchor_headings.anchorTitle | default: '' %} 14 | {% assign h_min = page.anchor_headings.h_min | default: layout.anchor_headings.h_min | default: 1 %} 15 | {% assign h_max = page.anchor_headings.h_max | default: layout.anchor_headings.h_max | default: 6 %} 16 | {% assign bodyPrefix = page.anchor_headings.bodyPrefix | default: layout.anchor_headings.bodyPrefix | default: '' %} 17 | {% assign bodySuffix = page.anchor_headings.bodySuffix | default: layout.anchor_headings.bodySuffix | default: '' %} 18 | 19 | {% unless page.disable_anchors or page.url | slice: 0, 11 == '/v1/reference/' %} 20 | {% include jekyll-docs-theme/vendor/anchor_headings.html 21 | html=content 22 | beforeHeading=beforeHeading 23 | anchorAttrs=anchorAttrs 24 | anchorBody=anchorBody 25 | anchorClass=anchorClass 26 | anchorTitle=anchorTitle 27 | h_min=h_min 28 | h_max=h_max 29 | bodyPrefix=bodyPrefix 30 | bodySuffix=bodySuffix 31 | %} 32 | {% else %} 33 | {{ content }} 34 | {% endunless %} 35 | -------------------------------------------------------------------------------- /docs/_includes/home/youtube-link.css: -------------------------------------------------------------------------------- 1 | .youtube-link { 2 | border-bottom: none !important; 3 | display: block; 4 | transition: transform .3s; 5 | transform-origin: left bottom; 6 | transform:skew(0); 7 | } 8 | .youtube-link:hover { 9 | transform:skew(-5deg); 10 | } 11 | .youtube-link:before { 12 | content: ''; 13 | width: 0; 14 | height: 0; 15 | border-style: solid; 16 | border-width: 5px 0 5px 12px; 17 | border-color: transparent transparent transparent #000000; 18 | border-style: solid; 19 | margin-right: 5px; 20 | display: inline-block; 21 | transition: border-width .1s; 22 | } 23 | .youtube-link:hover:before { 24 | border-color: transparent transparent transparent #FF0000; 25 | } 26 | 27 | .youtube-link__timing { 28 | display: inline-block; 29 | background-color: #606060; 30 | border-radius: 3px; 31 | color: white; 32 | font-size: 14px; 33 | padding: 0 4px; 34 | line-height: 1.3; 35 | margin-left: 5px; 36 | position: relative; 37 | /* overflow: hidden; */ 38 | } 39 | .youtube-link__timing:before { 40 | content: ''; 41 | position: absolute; 42 | left: 0; 43 | bottom: 0; 44 | width: 0; 45 | border-radius: 3px; 46 | top: 0; 47 | background-color: #DD0000; 48 | } 49 | .youtube-link:hover .youtube-link__timing:before { 50 | width: 100%; 51 | transition: .1s .2s; 52 | } 53 | 54 | .youtube-link__title { 55 | position: relative; 56 | padding: 3px 0; 57 | overflow: hidden; 58 | transition: color .15s; 59 | } 60 | .youtube-link__title:before, 61 | .youtube-link__title:after { 62 | content: ''; 63 | position: absolute; 64 | height: 1px; 65 | width: 100%; 66 | bottom: 0; 67 | left: 0; 68 | background-color: rgba(0, 0, 0, .3); 69 | } 70 | .youtube-link__title:after { 71 | width: 0; 72 | background-color: #FF0000; 73 | height: 2px; 74 | } 75 | .youtube-link:hover .youtube-link__youtube { 76 | color: #EE0000; 77 | } 78 | .youtube-link:hover .youtube-link__title:after { 79 | width: 100%; 80 | transition: width .2s linear; 81 | } -------------------------------------------------------------------------------- /snippets/collection-tags.liquid: -------------------------------------------------------------------------------- 1 | {%- if collection.all_tags.size > 0 -%} 2 |
    3 | 4 | {% comment %}Good for /collections/all collection and regular collections{% endcomment %} 5 | {%- if collection.handle -%} 6 | {%- capture collection_url -%} 7 | {%- if collection.url == blank -%} 8 | {{ routes.all_products_collection_url }}{%- unless collection.sort_by == blank -%}?sort_by={{ collection.sort_by }}{%- endunless -%} 9 | {%- else -%} 10 | {{ collection.url }}{%- unless collection.sort_by == blank -%}?sort_by={{ collection.sort_by }}{%- endunless -%} 11 | {%- endif -%} 12 | {%- endcapture -%} 13 | {% comment %}Good for automatic type collections{% endcomment %} 14 | {%- elsif collection.current_type -%} 15 | {% assign collection_url = collection.current_type | url_for_type | sort_by: collection.sort_by %} 16 | {% comment %}Good for automatic vendor collections{% endcomment %} 17 | {%- elsif collection.current_vendor -%} 18 | {% assign collection_url = collection.current_vendor | url_for_vendor | sort_by: collection.sort_by %} 19 | {%- endif -%} 20 | 27 |
    28 | {%- endif -%} 29 | 30 | 39 | -------------------------------------------------------------------------------- /docs/v1/reference/addToCartCssClass.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: addToCartCssClass 3 | layout: page 4 | --- 5 | 6 | # addToCartCssClass 7 | 8 | The `addToCartCssClass` configuration parameter lets you specify a CSS class that will be attached to the `body` tag after successful adding a product to the cart. 9 | 10 | The usecase — opening a cart drawer after a user clicks an "Add to cart" button. 11 | 12 | Setting up using the `data-ajax-cart-configuration` attribute: 13 | {% raw %} 14 | ```html 15 | {% comment %} Somewhere in layout/theme.liquid {% endcomment %} 16 | 17 | 22 | ``` 23 | {% endraw %} 24 | 25 | Setting up using the `configureCart` function: 26 | {% raw %} 27 | ```html 28 | 33 | ``` 34 | {% endraw %} 35 | 36 | ### Removing the class after a while 37 | 38 | You can specify the time in milliseconds after which the class should be removed from the `body` tag. 39 | 40 | The usecase — opening a mini-cart popup for 3 seconds. 41 | 42 | Setting up using the `data-ajax-cart-configuration` attribute: 43 | {% raw %} 44 | ```html 45 | {% comment %} Somewhere in layout/theme.liquid {% endcomment %} 46 | 47 | 52 | ``` 53 | {% endraw %} 54 | 55 | Setting up using the `configureCart` function: 56 | {% raw %} 57 | ```html 58 | 63 | ``` 64 | {% endraw %} -------------------------------------------------------------------------------- /docs/_includes/jekyll-docs-theme/toc.html: -------------------------------------------------------------------------------- 1 | {% assign fm_class = layout.table_of_contents.class | default: page.table_of_contents.class | default: "" %} 2 | {% assign fm_anchor_class = layout.table_of_contents.anchor_class | default: page.table_of_contents.anchor_class | default: "" %} 3 | 4 | {% capture class -%} 5 | {{- include.class -}} 6 | {%- if fm_class != "" -%} 7 | .{{- fm_class -}} 8 | {%- endif -%} 9 | {%- endcapture %} 10 | 11 | {% capture anchor_class %} 12 | {{- include.anchor_class -}} 13 | {%- if fm_anchor_class != "" -%} 14 | .{{- fm_anchor_class -}} 15 | {%- endif -%} 16 | {% endcapture %} 17 | 18 | {% assign sanitize = page.table_of_contents.sanitize | default: layout.table_of_contents.sanitize | default: false %} 19 | {% assign h_min = page.table_of_contents.h_min | default: layout.table_of_contents.h_min | default: 2 %} 20 | {% assign h_max = page.table_of_contents.h_max | default: layout.table_of_contents.h_max | default: 5 %} 21 | {% assign ordered = page.table_of_contents.ordered | default: layout.table_of_contents.ordered | default: false %} 22 | {% assign item_class = include.item_class | page.table_of_contents.item_class | default: layout.table_of_contents.item_class | default: '' %} 23 | {% assign baseurl = page.table_of_contents.baseurl | default: layout.table_of_contents.baseurl | default: '' %} 24 | {% assign skipNoIDs = page.table_of_contents.skipNoIDs | default: layout.table_of_contents.skipNoIDs | default: false %} 25 | 26 | {% assign transformed_content = content | replace: 'Triggers the ', '' %} 27 | 28 | {% include jekyll-docs-theme/vendor/toc.html 29 | html=transformed_content 30 | id=include.id 31 | class=class 32 | sanitize=sanitize 33 | h_min=h_min 34 | h_max=h_max 35 | ordered=ordered 36 | item_class=item_class 37 | baseurl=baseurl 38 | anchor_class=anchor_class 39 | skipNoIDs=skipNoIDs 40 | %} 41 | -------------------------------------------------------------------------------- /docs/v2/data-ajax-cart-quantity-plus.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: data-ajax-cart-quantity-plus 3 | layout: docs-v2 4 | --- 5 | 6 | # data-ajax-cart-quantity-plus 7 | 8 |

    9 | An attribute which identifies a "Plus" button inside a [``](/v2/ajax-cart-quantity/) custom tag. 10 |

    11 | 12 | {%- capture highlight_code -%} 13 | {% raw %} 14 |
    15 |

    Cart ({{ cart.item_count }})

    16 | 17 |
    18 | {% for line_item in cart.items %} 19 | {% assign line_item_index = forloop.index %} 20 | 21 | 22 |
    Price: {{ line_item.final_price | money }}
    23 | 24 |
    25 | Quantity: 26 | 27 | 29 | Minus one 30 | 31 | 32 | 33 | 38 | 39 | 41 | Plus one 42 | 43 | 44 | 45 | 46 | {% endraw %} 47 | {%- endcapture -%} 48 | {% include v2/codeblock.html title="sections/my-ajax-cart.liquid" language="liquid" code=highlight_code highlight_lines="26" %} 49 | 50 | Find more details on the [``](/v2/ajax-cart-quantity/) page. -------------------------------------------------------------------------------- /docs/v2/data-ajax-cart-quantity-minus.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: data-ajax-cart-quantity-minus 3 | layout: docs-v2 4 | --- 5 | 6 | # data-ajax-cart-quantity-minus 7 | 8 |

    9 | An attribute which identifies a "Minus" button inside a [``](/v2/ajax-cart-quantity/) custom tag. 10 |

    11 | 12 | {%- capture highlight_code -%} 13 | {% raw %} 14 |
    15 |

    Cart ({{ cart.item_count }})

    16 | 17 |
    18 | {% for line_item in cart.items %} 19 | {% assign line_item_index = forloop.index %} 20 | 21 | 22 |
    Price: {{ line_item.final_price | money }}
    23 | 24 |
    25 | Quantity: 26 | 27 | 29 | Minus one 30 | 31 | 32 | 33 | 38 | 39 | 41 | Plus one 42 | 43 | 44 | 45 | 46 | {% endraw %} 47 | {%- endcapture -%} 48 | {% include v2/codeblock.html title="sections/my-ajax-cart.liquid" language="liquid" code=highlight_code highlight_lines="14" %} 49 | 50 | Find more details on the [``](/v2/ajax-cart-quantity/) page. -------------------------------------------------------------------------------- /docs/v1/reference/sections.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Ajaxified sections 3 | layout: page 4 | --- 5 | 6 | # Ajaxified sections 7 | 8 | Liquid Ajax Cart reloads HTML code of the HTML containers that marked with the [`data-ajax-cart-section`](/v1/reference/data-ajax-cart-section/) attribute every time when the Shopify cart is changed. 9 | 10 | It uses [Bundled section rendering](https://shopify.dev/api/ajax/reference/cart#bundled-section-rendering) under the hood to ask Shopify to provide re-rendered HTML code for theme sections with each Cart API request response. Due to this, the `data-ajax-cart-section` must be applied only within sections. 11 | 12 | After Liquid Ajax Cart received a response of a Shopify Cart API request with the re-rendered sections' HTML, it replaces HTML of the `data-ajax-cart-section` containers within the section with the new ones. 13 | 14 | ##### Immutable elements 15 | 16 | If you want to have an immutable HTML element within a [`data-ajax-cart-section`](/v1/reference/data-ajax-cart-section/) container — add the `data-ajax-cart-static-element` attribute to this element. HTML of the immutable element will *not* be replaced when its section gets updated. 17 | 18 | ##### Scrollable area 19 | 20 | If you have a scrollable area within a `data-ajax-cart-section` container, the scroll position will be reset to top every time when the cart is changed because the section's HTML will be completely replaced with a new one. To keep the scroll position the same add the [`data-ajax-cart-section-scroll`](/v1/reference/data-ajax-cart-section-scroll/) attribute to the scrollable area. 21 | 22 | 23 | ##### JavaScript callback 24 | 25 | If you want to run your JavaScript code after the HTML code of the `data-ajax-cart-section` sections are reloaded — use the [`subscribeToCartSectionsUpdate`](/v1/reference/subscribeToCartSectionsUpdate/) function. 26 | 27 | ##### Example 28 | Since the cart sections are plain Shopify liquid theme sections, you are free to use any Liquid tags, objects and filters. 29 | 30 | {% include code/section.html %} 31 | -------------------------------------------------------------------------------- /docs/v2/extra-request-on-error.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: extraRequestOnError 3 | layout: docs-v2 4 | --- 5 | 6 | # extraRequestOnError 7 | 8 |

    9 | A configuration parameter which makes Liquid Ajax Cart send an additional request 10 | when the current request has returned an error. 11 |

    12 | 13 | ## Why it is needed 14 | 15 | Sometimes Shopify responds with an error to a Shopify Cart API Ajax request but actually makes changes in the cart. 16 | In order to get the updated cart state and HTML, Liquid Ajax Cart performs an additional `/cart/update.js` request. 17 | 18 | If your Shopify store doesn't have this bug, you should switch this feature off to avoid sending redundant requests. 19 | 20 | ## Use cases 21 | 22 | Let's say your Shopify store has a product with 5 items in stock. 23 | A user with the empty cart tries adding more items than in stock to the cart (for example 10). 24 | All Shopify stores respond with an error message to such requests 25 | but some of them also modify the user's cart by adding all available stock (5 items) to it. 26 | 27 | A video example of this behavior is attached to the [corresponding GitHub issue](https://github.com/Shopify/dawn/issues/2994). 28 | 29 | If the `extraRequestOnError` is `true`, Liquid Ajax Cart sends an additional request 30 | to get the updated cart state and HTML in order to fix this unexpected behavior. 31 | 32 | The same behavior is noticed when a user has some items in the cart 33 | and tries to change the quantity to add more items than available in stock. 34 | 35 | If your Shopify store doesn't have this behavior 36 | you should consider set this configuration parameter to `false` 37 | to avoid sending redundant requests. 38 | 39 | Use the [`conf`](/v2/liquid-ajax-cart-conf/) method of the [`liquidAjaxCart`](/v2/liquid-ajax-cart/) object 40 | to switch the extra request off: 41 | {%- capture highlight_code -%} 42 | liquidAjaxCart.conf("extraRequestOnError", false); 43 | {%- endcapture -%} 44 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 45 | -------------------------------------------------------------------------------- /templates/customers/register.liquid: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 | 5 |
    6 |

    {{ 'customer.register.title' | t }}

    7 |
    8 | 9 | {% comment %} 10 | This form must use 'create_customer' 11 | {% endcomment %} 12 | {% form 'create_customer' %} 13 | 14 | {{ form.errors | default_errors }} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |

    29 | 30 |

    31 | {{ 'customer.register.cancel' | t }} 32 | 33 | {% endform %} 34 | 35 |
    36 | 37 |
    38 | -------------------------------------------------------------------------------- /snippets/search-bar.liquid: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | 3 | A snippet to include a search bar anywhere in your theme. 4 | Note we are using 'input-group' for the layout. Look under Forms > Input Groups for some demos. 5 | 6 | More information: 7 | - http://docs.shopify.com/themes/liquid-variables/search 8 | 9 | To return only products in results: 10 | - http://docs.shopify.com/manual/configuration/store-customization/return-only-product-in-storefront-search-results 11 | - Or manually add type=product to the search URL as a query parameter 12 | - Uncomment hidden input with value="product" below 13 | 14 | {% endcomment %} 15 | 16 | {% if search-bar == 'header' %} 17 | 25 | {% else %} 26 | 36 | {% endif %} 37 | -------------------------------------------------------------------------------- /docs/v2/event-queue-end.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: liquid-ajax-cart:queue-end 3 | layout: docs-v2 4 | --- 5 | 6 | # liquid-ajax-cart:queue-end 7 | 8 |

    9 | An event which is fired at the `document` when a Liquid Ajax Cart has executed 10 | all the Shopify Cart API Ajax requests from the [Queue](/v2/queue-of-requests/) and 11 | it is switching back to the "idle" mode. 12 |

    13 | 14 | ## How it works 15 | 16 | Liquid Ajax Cart doesn't perform Shopify Cart API Ajax requests immediately, it adds them to the [Queue](/v2/queue-of-requests/). 17 | When a request is executed, it is removed from the [Queue](/v2/queue-of-requests/). 18 | If there is no other request to perform, Liquid Ajax Cart triggers the `liquid-ajax-cart:queue-end` event. 19 | 20 | {% include v2/content/lifecycle-events-reference.html %} 21 | 22 | {%- capture highlight_code -%} 23 | document.addEventListener("liquid-ajax-cart:queue-end", function() { 24 | console.log("A queue of requests is finished"); 25 | console.log("The current cart state is: ", window.liquidAjaxCart.cart); 26 | }); 27 | {%- endcapture -%} 28 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 29 | 30 | ## Sending requests from the event listener 31 | 32 | If you want to send a Shopify Cart API request from a `liquid-ajax-cart:queue-end` event listener, 33 | you have a chance to get into infinity loop of requests: 34 | 35 | * a queue of requests is finishes and fires the `liquid-ajax-cart:queue-end` event, 36 | * your event listener initiates a request, 37 | * Liquid Ajax Cart creates a new queue of requests and puts the request there 38 | * when the new queue is finishes, it fires the `liquid-ajax-cart:queue-end` event ... 39 | 40 | In order to prevent this, make sure that you have a strong condition that won't let the loop happen: 41 | {%- capture highlight_code -%} 42 | let ranOnce = false; 43 | 44 | document.addEventListener("liquid-ajax-cart:queue-end", function(event) { 45 | // condition to prevent infinity loop: 46 | if (!ranOnce) { 47 | ranOnce = true; 48 | 49 | // send your request 50 | window.liquidAjaxCart.add(...); 51 | } 52 | }); 53 | {%- endcapture -%} 54 | {% include v2/codeblock.html language="javascript" code=highlight_code %} 55 | -------------------------------------------------------------------------------- /screenshot.js: -------------------------------------------------------------------------------- 1 | const puppeteer = require('puppeteer'); 2 | const fs = require('node:fs'); 3 | const yaml = require('js-yaml'); 4 | const resizeImg = require('resize-img'); 5 | 6 | const executablePath = 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'; 7 | 8 | async function captureScreenshots() { 9 | try { 10 | const data = fs.readFileSync('docs/_config.yml', 'utf8'); 11 | const parsedData = yaml.load(data); 12 | const browser = await puppeteer.launch({ 13 | executablePath, 14 | headless: 'new' 15 | }); 16 | const page = await browser.newPage(); 17 | await page.setViewport({ 18 | width: 1540, 19 | height: 771, 20 | }); 21 | 22 | for (const {image, url, selector, autoscreenshot} of parsedData.links.portfolio) { 23 | // if (autoscreenshot !== 'yes') continue; 24 | await page.goto(url, { 25 | timeout: 0 26 | }); 27 | 28 | await new Promise(r => setTimeout(r, 2000)); //waiting for the page to load completely 29 | if (selector) { 30 | const selectorArr = await selector.split(','); 31 | for (const item of selectorArr) { 32 | if (await page.$(item)) { 33 | const element = await page.waitForSelector(item); 34 | await element.click(); 35 | console.log(`✅ Clicked to '${item}' selector to hide it (${url})`); 36 | } else console.log(`❌ Selector '${item}' isn't found (${url})`); 37 | } 38 | await new Promise(r => setTimeout(r, 1000)); //waiting for the popup to close completely 39 | } 40 | await page.screenshot({path: `docs/assets/screens/${image}`}); 41 | console.log(`✅ Screenshot captured ${url} - ${image}`); 42 | 43 | const resizeImage = await resizeImg(fs.readFileSync(`docs/assets/screens/${image}`), { 44 | width: 527, 45 | height: 264 46 | }); 47 | fs.writeFileSync(`docs/assets/screens/${image}`, resizeImage); 48 | console.log(`✅ Screenshot size was changed to 527x264 (${image})`); 49 | console.log('-------------------------------------------------------------------'); 50 | } 51 | 52 | await browser.close(); 53 | } catch (err) { 54 | console.log("❌ Error: ", err.message); 55 | } 56 | } 57 | 58 | captureScreenshots(); -------------------------------------------------------------------------------- /templates/customers/account.liquid: -------------------------------------------------------------------------------- 1 |
    2 |

    {{ 'customer.account.title' | t }}

    3 |
    4 | 5 |
    6 | 7 |
    8 |

    {{ 'customer.orders.title' | t }}

    9 | 10 | {% comment %} 11 | If we have past orders, loop through each one 12 | {% endcomment %} 13 | 14 | {% paginate customer.orders by 20 %} 15 | 16 | {% if customer.orders.size != 0 %} 17 | 18 |
    19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | {% for order in customer.orders %} 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | {% endfor %} 39 | 40 |
    {{ 'customer.orders.order_number' | t }}{{ 'customer.orders.date' | t }}{{ 'customer.orders.payment_status' | t }}{{ 'customer.orders.fulfillment_status' | t }}{{ 'customer.orders.total' | t }}
    {{ order.name | link_to: order.customer_url }}{{ order.created_at | date: format: 'date' }}{{ order.financial_status_label }}{{ order.fulfillment_status_label }}{{ order.total_price | money }}
    41 |
    42 | 43 | {% else %} 44 | 45 |

    {{ 'customer.orders.none' | t }}

    46 | 47 | {% endif %} 48 | 49 | {% if paginate.pages > 1 %} 50 |
    51 | {% include 'pagination-custom' %} 52 |
    53 | {% endif %} 54 | 55 | {% endpaginate %} 56 | 57 |
    58 | 59 | 66 | 67 |
    68 | -------------------------------------------------------------------------------- /docs/_includes/navigation.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 | You're looking at the documentation for Liquid Ajax Cart v1. 5 | Go to Liquid Ajax Cart v2 6 |
    7 |
    8 |
    9 |
    10 | 11 | 12 |
    13 |
      14 | {% for p in site.links.main %} 15 | {% assign p_active = false %} 16 | {% if page.url == p.url %} 17 | {% assign p_active = true %} 18 | {% elsif p.url != '/v1/' and page.url.size > p.url.size %} 19 | {% assign page_url_slice = page.url | slice: 0, p.url.size %} 20 | {% if page_url_slice == p.url %} 21 | {% assign p_active = true %} 22 | {% endif %} 23 | {% endif %} 24 |
    • 25 | 26 | {{ p.title }} 27 | 28 |
    • 29 | {% endfor %} 30 |
    31 |
      32 | {% for p in site.links.header %} 33 | {% assign p_active = false %} 34 | {% if page.url == p.url %} 35 | {% assign p_active = true %} 36 | {% elsif p.url != '/v1/' and page.url.size > p.url.size %} 37 | {% assign page_url_slice = page.url | slice: 0, p.url.size %} 38 | {% if page_url_slice == p.url %} 39 | {% assign p_active = true %} 40 | {% endif %} 41 | {% endif %} 42 |
    • 43 | 44 | {{ p.title }} 45 | 46 |
    • 47 | {% endfor %} 48 |
    49 |
    50 |
    51 |
    52 |
    53 | -------------------------------------------------------------------------------- /_src/state.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AppStateType, 3 | AppStateCartType, 4 | EventRequestEndType 5 | } from './ts-types'; 6 | 7 | import { 8 | EVENT_REQUEST_END_INTERNAL, 9 | } from './ajax-api'; 10 | import {DATA_ATTR_PREFIX} from "./const"; 11 | 12 | const DATA_ATTR_INITIAL_STATE = `${DATA_ATTR_PREFIX}-initial-state`; 13 | 14 | let cart: AppStateCartType = null; 15 | let previousCart: AppStateCartType | undefined = undefined 16 | 17 | function cartStateInit(): Promise { 18 | 19 | document.addEventListener(EVENT_REQUEST_END_INTERNAL, (event: EventRequestEndType) => { 20 | const {requestState} = event.detail; 21 | let newCart: AppStateCartType; 22 | if (requestState.extraResponseData?.ok && requestState.extraResponseData.body.token) { 23 | newCart = requestState.extraResponseData.body as AppStateCartType; 24 | } else if (requestState.responseData?.ok && requestState.responseData.body.token) { 25 | newCart = requestState.responseData.body as AppStateCartType; 26 | } 27 | 28 | if (newCart) { 29 | previousCart = cart; 30 | cart = newCart; 31 | 32 | event.detail.previousCart = previousCart; 33 | event.detail.cart = cart; 34 | } 35 | }); 36 | 37 | const initialStateContainer = document.querySelector(`[${DATA_ATTR_INITIAL_STATE}]`); 38 | if (initialStateContainer) { 39 | try { 40 | cart = JSON.parse(initialStateContainer.textContent); 41 | } catch (e) { 42 | console.error(`Liquid Ajax Cart: can't parse cart JSON from the "${DATA_ATTR_INITIAL_STATE}" script`); 43 | console.error(e); 44 | } 45 | } 46 | 47 | return new Promise((resolve, reject) => { 48 | if (cart) { 49 | resolve(); 50 | return; 51 | } 52 | fetch(`${window.Shopify?.routes?.root || '/'}cart.js`, { 53 | headers: { 54 | 'Content-Type': 'application/json' 55 | } 56 | }).then(response => { 57 | return response.json(); 58 | }).then(data => { 59 | cart = data; 60 | resolve(); 61 | }).catch(error => { 62 | console.error(error); 63 | reject('Can\'t load the cart state from the "/cart.js" endpoint'); 64 | }) 65 | }) 66 | } 67 | 68 | function getCartState(): AppStateType { 69 | return { 70 | cart, 71 | previousCart 72 | } 73 | } 74 | 75 | export {cartStateInit, getCartState}; --------------------------------------------------------------------------------