Repository: dlerm/shopify-wishlist Branch: master Commit: e88dcf528ac5 Files: 16 Total size: 14.7 KB Directory structure: gitextract_v887apka/ ├── .gitignore ├── LICENSE ├── README.md ├── assets/ │ └── Wishlist.js ├── config.yml ├── gulpfile.js ├── package.json ├── sections/ │ ├── product-card-template.liquid │ └── wishlist-template.liquid ├── snippets/ │ ├── button-wishlist.liquid │ └── icon-heart.liquid ├── tasks/ │ ├── clean.js │ ├── copy.js │ └── upload.js └── templates/ ├── page.wishlist.json └── product.card.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # OS generated files # ###################### *.DS_Store* .DS_Store? ._* .Spotlight-V100 .Trashes ehthumbs.db Thumbs.db # Helper files # ###################### _* # Build tools # ###################### node_modules/ dist/ .env ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2021 Daniel Lerman Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Shopify Wishlist A set of files used to implement a simple customer wishlist on a Shopify store. _Version: 2.3.0_ - Compatible with Online Store 2.0 Previous Versions: - [v2.1.0 (Online Store 1.0)](https://github.com/dlerm/shopify-wishlist/tree/version/2.1.0) - [v2.0.0](https://github.com/dlerm/shopify-wishlist/tree/version/2.0.0) - [v1.0.0](https://github.com/dlerm/shopify-wishlist/tree/version/1.0.0) ## Installation To begin using **Shopify Wishlist**, you must copy some of the files in this repo into your Shopify theme code. _Note_: This setup assumes that you have a snippet for displaying a product card. **Files to copy:** |Repo File|Shopify Theme Location| |:--:|:--:| |[`button-wishlist.liquid`](https://github.com/dlerm/shopify-wishlist/blob/master/snippets/button-wishlist.liquid)|`snippets/`| |[`icon-heart.liquid`](https://github.com/dlerm/shopify-wishlist/blob/master/snippets/icon-heart.liquid)| `snippets/`| |[`wishlist-template.liquid`](https://github.com/dlerm/shopify-wishlist/blob/master/sections/wishlist-template.liquid)| `sections/`| |[`product-card-template.liquid`](https://github.com/dlerm/shopify-wishlist/blob/master/sections/product-card-template.liquid)| `sections/`| |[`page.wishlist.json`](https://github.com/dlerm/shopify-wishlist/blob/master/templates/page.wishlist.json)|`templates/`| |[`product.card.json`](https://github.com/dlerm/shopify-wishlist/blob/master/templates/product.card.json)|`templates/`| |[`Wishlist.js`](https://github.com/dlerm/shopify-wishlist/blob/master/assets/Wishlist.js)|`assets/`| 1. Place the `button-wishlist.liquid` snippet inside your existing product card snippet, or on the `product.liquid` template - `{%- render 'button-wishlist', product: product -%}` - This will allow customer's to add/remove items to/from their wishlist 2. Replace the snippet in the `product-card-template.liquid` section with your existing product card snippet - Same snippet from step 1 - Your product card snippet may use a different product variable name, double check it :+1: 3. Add your product card element classname to the `selectors` object in `Wishlist.js` - Example: If your product card classname is `.product-item`, the `selectors` variable would look like this: ``` const selectors = { button: '[button-wishlist]', grid: '[grid-wishlist]', productCard: '.product-item', // your classname here }; ``` 4. Create a new page in the Shopify admin: - Admin > Online Store > Pages > Add Page - Set the new page's `template` to `page.wishlist` - This page will display a customer's saved wishlist items 5. Place the script in `theme.liquid` before the closing `` tag - `` That's it! When viewing your Shopify store, you should see the wishlist buttons inside your product cards (likely on collections pages) or on the product template. A click on the wishlist button will add/remove the item from the customer's wishlist and trigger active styling on the button. After adding wishlist items, you can view your wishlist by navigating to the page created in step 3. [Demo Shopify Store](https://lerman-labs.myshopify.com/collections/all) ## Notes - This wishlist uses Javascript and localStorage to save the customer's wishlist on their browser. The localStorage will not persist if the user clears browser storage or browses in incognito mode. - As customers browser products and adds them to their wishlist, the script will automatically set any wishlist buttons to active state if the corresponding product is already included in the wishlist. - These files come with no styling or structure so that you can customize as needed. This is intended to bring you the base functionality of a wishlist with no frills. - If you are working in an unpublished theme, you will need to create the new templates on the published theme as well. The Shopify admin will only allow you to assign a page to a template if the template exists on the published theme. - If you are upgrading to the Online Store 2.0 version, you will be required to delete the older `.liquid` wishlist and product card templates. ================================================ FILE: assets/Wishlist.js ================================================ const LOCAL_STORAGE_WISHLIST_KEY = 'shopify-wishlist'; const LOCAL_STORAGE_DELIMITER = ','; const BUTTON_ACTIVE_CLASS = 'active'; const GRID_LOADED_CLASS = 'loaded'; const selectors = { button: '[button-wishlist]', grid: '[grid-wishlist]', productCard: '.product-card', }; document.addEventListener('DOMContentLoaded', () => { initButtons(); initGrid(); }); document.addEventListener('shopify-wishlist:updated', (event) => { console.log('[Shopify Wishlist] Wishlist Updated ✅', event.detail.wishlist); initGrid(); }); document.addEventListener('shopify-wishlist:init-product-grid', (event) => { console.log('[Shopify Wishlist] Wishlist Product List Loaded ✅', event.detail.wishlist); }); document.addEventListener('shopify-wishlist:init-buttons', (event) => { console.log('[Shopify Wishlist] Wishlist Buttons Loaded ✅', event.detail.wishlist); }); const fetchProductCardHTML = (handle) => { const productTileTemplateUrl = `/products/${handle}?view=card`; return fetch(productTileTemplateUrl) .then((res) => res.text()) .then((res) => { const text = res; const parser = new DOMParser(); const htmlDocument = parser.parseFromString(text, 'text/html'); const productCard = htmlDocument.documentElement.querySelector(selectors.productCard); return productCard.outerHTML; }) .catch((err) => console.error(`[Shopify Wishlist] Failed to load content for handle: ${handle}`, err)); }; const setupGrid = async (grid) => { const wishlist = getWishlist(); const requests = wishlist.map(fetchProductCardHTML); const responses = await Promise.all(requests); const wishlistProductCards = responses.join(''); grid.innerHTML = wishlistProductCards; grid.classList.add(GRID_LOADED_CLASS); initButtons(); const event = new CustomEvent('shopify-wishlist:init-product-grid', { detail: { wishlist: wishlist } }); document.dispatchEvent(event); }; const setupButtons = (buttons) => { buttons.forEach((button) => { const productHandle = button.dataset.productHandle || false; if (!productHandle) return console.error('[Shopify Wishlist] Missing `data-product-handle` attribute. Failed to update the wishlist.'); if (wishlistContains(productHandle)) button.classList.add(BUTTON_ACTIVE_CLASS); button.addEventListener('click', () => { updateWishlist(productHandle); button.classList.toggle(BUTTON_ACTIVE_CLASS); }); }); }; const initGrid = () => { const grid = document.querySelector(selectors.grid) || false; if (grid) setupGrid(grid); }; const initButtons = () => { const buttons = document.querySelectorAll(selectors.button) || []; if (buttons.length) setupButtons(buttons); else return; const event = new CustomEvent('shopify-wishlist:init-buttons', { detail: { wishlist: getWishlist() } }); document.dispatchEvent(event); }; const getWishlist = () => { const wishlist = localStorage.getItem(LOCAL_STORAGE_WISHLIST_KEY) || false; if (wishlist) return wishlist.split(LOCAL_STORAGE_DELIMITER); return []; }; const setWishlist = (array) => { const wishlist = array.join(LOCAL_STORAGE_DELIMITER); if (array.length) localStorage.setItem(LOCAL_STORAGE_WISHLIST_KEY, wishlist); else localStorage.removeItem(LOCAL_STORAGE_WISHLIST_KEY); const event = new CustomEvent('shopify-wishlist:updated', { detail: { wishlist: array } }); document.dispatchEvent(event); return wishlist; }; const updateWishlist = (handle) => { const wishlist = getWishlist(); const indexInWishlist = wishlist.indexOf(handle); if (indexInWishlist === -1) wishlist.push(handle); else wishlist.splice(indexInWishlist, 1); return setWishlist(wishlist); }; const wishlistContains = (handle) => { const wishlist = getWishlist(); return wishlist.includes(handle); }; const resetWishlist = () => { return setWishlist([]); }; ================================================ FILE: config.yml ================================================ development: password: ${PASSWORD} theme_id: ${THEME_ID} store: ${URL} ================================================ FILE: gulpfile.js ================================================ const gulp = require('gulp'); require('require-dir')('./tasks'); // build gulp.task( 'build', gulp.series('clean:dist', 'copy') ); // watch gulp.task( 'watch', gulp.series( gulp.parallel( 'copy:watch', ), gulp.series('upload:watch') ) ); // dev gulp.task('dev', gulp.series('build', 'watch')); // default gulp.task('default', gulp.series('dev')); ================================================ FILE: package.json ================================================ { "name": "shopify-wishlist", "version": "2.3.0", "author": "Daniel Lerman", "description": "💙 A set of files used to implement a simple customer wishlist on a Shopify store", "keywords": [ "shopify", "theme", "wishlist" ], "bugs": "https://github.com/dlerm/shopify-wishlist/issues", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/dlerm/shopify-wishlist" }, "scripts": { "start": "gulp", "build": "gulp build" }, "dependencies": {}, "devDependencies": { "@shopify/themekit": "^1.1.9", "dotenv": "^9.0.0", "gulp": "^4.0.2", "gulp-changed": "^4.0.2", "gulp-clean": "^0.4.0", "gulp-flatten": "^0.4.0", "gulp-if": "^3.0.0", "gulp-rename": "^2.0.0", "gulp-watch": "^5.0.1", "require-dir": "^1.2.0" } } ================================================ FILE: sections/product-card-template.liquid ================================================ {% comment %} Shopify Wishlist Usage: - Replace the snippet name ('product-card') with your existing product card snippet - Pass the product object as a snippet variable named 'product' {% endcomment %} {%- render 'product-card', product: product -%} {% schema %} { "templates": ["product"] } {% endschema %} ================================================ FILE: sections/wishlist-template.liquid ================================================ {% comment %} Shopify Wishlist Usage: - Create a new page in the Shopify admin - Admin > Online store > Pages > Add page - Set the new page's template to: 'page.wishlist' - Do NOT remove the `grid-wishlist` attribute Notes: - The grid will be populated with product cards using Javascript - Any content inside of the `[grid-wishlist]` element will be completely replaced by the product cards Tip: - Place a loading element inside the `[grid-wishlist]` element and it will automatically be removed once the product cards have loaded - Add any liquid code before/after the grid element {% endcomment %}
Loading...