├── .gitignore ├── .tool-versions ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Gruntfile.coffee ├── LICENSE ├── README.md ├── bower.json ├── dist ├── cart.js ├── cart.min.js ├── rivets-cart.js └── rivets-cart.min.js ├── docs ├── built-with │ └── built-with.jade ├── docs.json ├── guide │ ├── guide.jade │ └── sections │ │ ├── core-api.md │ │ ├── core-api │ │ ├── adding-items.md │ │ ├── attributes.md │ │ ├── callbacks.md │ │ ├── cart-state.md │ │ ├── configuration.md │ │ ├── removing-items.md │ │ └── updating-items.md │ │ ├── data-api.md │ │ ├── data-api │ │ ├── adding-items.md │ │ ├── removing-items.md │ │ ├── submitting-forms.md │ │ └── toggling-items.md │ │ ├── dom-binding.md │ │ ├── events.md │ │ ├── getting-started.md │ │ ├── getting-started │ │ ├── browser-support.md │ │ ├── installation.md │ │ ├── module-loaders.md │ │ ├── next-steps.md │ │ └── setup.md │ │ ├── introduction.md │ │ └── introduction │ │ └── what.md ├── images │ ├── icon-500x500.png │ └── icon-64x64.png ├── index │ ├── index.jade │ └── sections │ │ ├── can-it-do-more.md │ │ ├── demo-advanced-code.md │ │ ├── demo-advanced.jade │ │ ├── demo-simple-code.md │ │ ├── demo-simple.jade │ │ ├── further-questions.md │ │ └── what-is-cart-js.md ├── less │ ├── bootstrap │ │ ├── alerts.less │ │ ├── badges.less │ │ ├── bootstrap.less │ │ ├── breadcrumbs.less │ │ ├── button-groups.less │ │ ├── buttons.less │ │ ├── carousel.less │ │ ├── close.less │ │ ├── code.less │ │ ├── component-animations.less │ │ ├── dropdowns.less │ │ ├── forms.less │ │ ├── glyphicons.less │ │ ├── grid.less │ │ ├── input-groups.less │ │ ├── jumbotron.less │ │ ├── labels.less │ │ ├── list-group.less │ │ ├── media.less │ │ ├── mixins.less │ │ ├── mixins │ │ │ ├── alerts.less │ │ │ ├── background-variant.less │ │ │ ├── border-radius.less │ │ │ ├── buttons.less │ │ │ ├── center-block.less │ │ │ ├── clearfix.less │ │ │ ├── forms.less │ │ │ ├── gradients.less │ │ │ ├── grid-framework.less │ │ │ ├── grid.less │ │ │ ├── hide-text.less │ │ │ ├── image.less │ │ │ ├── labels.less │ │ │ ├── list-group.less │ │ │ ├── nav-divider.less │ │ │ ├── nav-vertical-align.less │ │ │ ├── opacity.less │ │ │ ├── pagination.less │ │ │ ├── panels.less │ │ │ ├── progress-bar.less │ │ │ ├── reset-filter.less │ │ │ ├── resize.less │ │ │ ├── responsive-visibility.less │ │ │ ├── size.less │ │ │ ├── tab-focus.less │ │ │ ├── table-row.less │ │ │ ├── text-emphasis.less │ │ │ ├── text-overflow.less │ │ │ └── vendor-prefixes.less │ │ ├── modals.less │ │ ├── navbar.less │ │ ├── navs.less │ │ ├── normalize.less │ │ ├── pager.less │ │ ├── pagination.less │ │ ├── panels.less │ │ ├── popovers.less │ │ ├── print.less │ │ ├── progress-bars.less │ │ ├── responsive-embed.less │ │ ├── responsive-utilities.less │ │ ├── scaffolding.less │ │ ├── tables.less │ │ ├── theme.less │ │ ├── thumbnails.less │ │ ├── tooltip.less │ │ ├── type.less │ │ ├── utilities.less │ │ ├── variables.less │ │ └── wells.less │ ├── cartjs.less │ └── cartjs │ │ ├── buttons.less │ │ ├── callouts.less │ │ ├── cartjs.less │ │ ├── code.less │ │ ├── examples.less │ │ ├── images.less │ │ ├── jumbotrons.less │ │ ├── layout.less │ │ ├── navbar.less │ │ ├── navs.less │ │ ├── tables.less │ │ ├── thumbnails.less │ │ ├── type.less │ │ └── variables.less ├── reference │ ├── reference.jade │ └── sections │ │ ├── core-api.md │ │ ├── core-api │ │ ├── add-item.md │ │ ├── add-items.md │ │ ├── clear-attributes.md │ │ ├── clear.md │ │ ├── get-attribute.md │ │ ├── get-attributes.md │ │ ├── get-note.md │ │ ├── remove-item-by-id.md │ │ ├── remove-item.md │ │ ├── set-attribute.md │ │ ├── set-attributes.md │ │ ├── set-note.md │ │ ├── update-item-by-id.md │ │ ├── update-item-quantities-by-id.md │ │ └── update-item.md │ │ ├── data-api.md │ │ ├── data-api │ │ ├── data-cart-add.md │ │ ├── data-cart-remove-id.md │ │ ├── data-cart-remove.md │ │ ├── data-cart-submit.md │ │ ├── data-cart-toggle-attribute.md │ │ ├── data-cart-toggle.md │ │ ├── data-cart-update-id.md │ │ └── data-cart-update.md │ │ ├── dom-binding.md │ │ ├── events.md │ │ ├── events │ │ ├── ready.md │ │ ├── request-complete.md │ │ └── request-started.md │ │ ├── options.md │ │ └── options │ │ ├── data-api.md │ │ ├── debug.md │ │ ├── money-format.md │ │ ├── money-with-currency-format.md │ │ ├── request-body-class.md │ │ ├── rivets-models.md │ │ ├── weight-precision.md │ │ └── weight-unit.md ├── snippets │ └── variables.jade └── theme │ ├── assets │ ├── atlascoffeeclub.jpg │ ├── author-disco.png │ ├── author-gavin.png │ ├── bevybar.jpg │ ├── bootstrap.min.js │ ├── budweiser.jpg │ ├── carbon.jpg │ ├── cartjs.min.css │ ├── cartjs.zip │ ├── core-api-cart-state.png │ ├── dualitas.jpg │ ├── favicon.ico │ ├── focal-theme.jpg │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ ├── go-defense.jpg │ ├── greater-goods.jpg │ ├── intributeto.jpg │ ├── ippodotea.jpg │ ├── kagami-theme.jpg │ ├── keetsa.jpg │ ├── loader.gif │ ├── mast-brothers.jpg │ ├── moderncitizen.jpg │ ├── netaya.jpg │ ├── olsatools.jpg │ ├── pure-health-delivered.jpg │ ├── rallier.jpg │ ├── rivets-cart-compatibility.min.js │ ├── rivets-cart.js │ ├── rivets-cart.min.js │ ├── sargossa.jpg │ ├── shopify.i18n.min.js │ ├── susi-studio.jpg │ ├── tattly.jpg │ ├── the-foodbank-project.jpg │ ├── trytheworld.jpg │ ├── usabaseball.jpg │ ├── writeyboards.jpg │ └── yeezy.jpg │ ├── config │ ├── settings.html │ └── settings_data.json │ ├── layout │ └── theme.liquid │ ├── snippets │ ├── footer.liquid │ ├── navbar.liquid │ └── variables.liquid │ └── templates │ ├── 404.liquid │ ├── article.liquid │ ├── blog.liquid │ ├── cart.liquid │ ├── collection.liquid │ ├── customers │ ├── account.liquid │ ├── activate_account.liquid │ ├── addresses.liquid │ ├── login.liquid │ ├── order.liquid │ ├── register.liquid │ └── reset_password.liquid │ ├── index.liquid │ ├── page.built-with.liquid │ ├── page.contact.liquid │ ├── page.guide.liquid │ ├── page.liquid │ ├── page.reference.liquid │ ├── product.liquid │ └── search.liquid ├── npm-shrinkwrap.json ├── package.json ├── spec ├── cartjs │ └── formatters.js ├── fixtures │ └── carts.js ├── runner.html └── shopify │ ├── currencies.js │ └── option_selection.js └── src ├── cart.coffee ├── cartjs.coffee ├── core.coffee ├── data.coffee ├── export.coffee ├── item.coffee ├── queue.coffee ├── rivets.coffee └── utils.coffee /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_Store 3 | /docs/theme/config.yml 4 | /node_modules 5 | /bower_components 6 | /cartjs.zip 7 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | python 2.7.13 2 | nodejs 5.12.0 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | before_script: 5 | - npm install -g grunt-cli 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | ## 1.1.0 - 2020-11-14 5 | ### Added 6 | - Explicitly pass `cache: false` in Ajax calls by default. 7 | - Add support for `selling_plan` property to `CartJS.addItem` method. 8 | 9 | ### Changed 10 | - Fix for non-Rivets build triggering reference errors. 11 | - Include hyphen and underscore as valid separators in properties for form submission. 12 | 13 | ## 1.0.2 - 2020-08-14 14 | ### Added 15 | - Cache-busting `v` parameter when fetching cart contents. 16 | 17 | ## 1.0.1 - 2020-05-17 18 | ### Changed 19 | - Minor documentation changes. 20 | 21 | ## 1.0.0 - 2020-05-16 22 | ### Added 23 | - Support for adding multiple line items with new `CartJS.addItems()` method. 24 | 25 | ### Changed 26 | - Updated some documentation. v1.0.0 - only took 6 years! 27 | 28 | ## 0.4.3 - 2019-08-20 29 | ### Added 30 | - Warning when trying to use money formatters without Shopify library support. 31 | 32 | ### Changed 33 | - Fixed bug preventing spaces in line item property names in `data-cart-submit` forms. 34 | 35 | ## 0.4.2 - 2019-08-20 36 | ### Added 37 | - Additional "built with" sites, dependency locks. 38 | 39 | ## 0.4.1 - 2016-08-16 40 | ### Added 41 | - New Rivets formatters: `times`, `divided_by`, `modulo` 42 | 43 | ### Changed 44 | - Fix issue with unnecessary line item properties being added with form submit 45 | 46 | ## 0.4.0 - 2016-02-11 47 | ### Added 48 | - New Rivets formatter: `array_element`, `array_first`, `array_last` 49 | - CONTRIBUTING.md 50 | - Simple Mocha-based test framework 51 | - `pluralize` formatter 52 | - `slice` formatter 53 | 54 | ### Changed 55 | - Fixed jQuery dependency from load-time to run-time 56 | 57 | ### Removed 58 | - IE8 Compatibility mode 59 | 60 | ## 0.3.9 - 2015-11-11 61 | ### Added 62 | - Two new Rivets formatters: `includes` and `match` 63 | 64 | ## 0.3.8 - 2015-10-27 65 | ### Added 66 | - `cart.ready` event, fired after initialisation finishes. 67 | 68 | ## 0.3.7 - 2015-10-26 69 | ### Changed 70 | - `getImageSizedUrl` filter now handles empty product images. 71 | 72 | ## 0.3.6 - 2015-10-24 73 | ### Added 74 | - New weight formatters `weight` and `weight_with_unit`, with corresponding 75 | settings `weightUnit` and `weightPrecision`. 76 | 77 | ## 0.3.5 - 2015-08-04 78 | ### Added 79 | - Include non-minified version of `rivets-cart.js` in `dist` 80 | 81 | ## 0.3.4 - 2015-07-16 82 | ### Added 83 | - Minor `console.log` compatibility fix for IE8 and IE9 browser support 84 | 85 | ## 0.3.3 - 2015-07-04 86 | ### Added 87 | - Compatible version of `rivets-cart.min.js` for non-ES5 browser support 88 | 89 | ## 0.3.2 - 2015-07-03 90 | ### Added 91 | - Made `getCart` a public method to allow force cart refreshes 92 | 93 | ### Changed 94 | - Fix for missing `removeItemById` public method 95 | 96 | ## 0.3.1 - 2015-06-28 97 | ### Changed 98 | - Fix for undefined Currency issue if not using Currency plugin. 99 | 100 | ## 0.3.0 - 2015-06-27 101 | ### Added 102 | - Support for dynamically rendering currency changes through money filters 103 | 104 | ### Changed 105 | - Upgraded Rivets.js library to v0.8.1 106 | 107 | ## 0.2.7 - 2015-05-18 108 | ### Added 109 | - Add `debug` setting for outputting of useful information to the console 110 | 111 | ## 0.2.6 - 2015-04-02 112 | ### Changed 113 | - Fixed incorrect method call when un-checking a checkbox using `data-cart-toggle` 114 | 115 | ## 0.2.5 - 2015-04-01 116 | ### Added 117 | - Add `prepend` and `append` formatters to Rivets 118 | 119 | ## 0.2.4 - 2015-03-13 120 | ### Added 121 | - Ability to specify callbacks through an `options` hash argument in Core API 122 | 123 | ## 0.2.3 - 2015-02-25 124 | ### Changed 125 | - Fixed potential issue using .data() instead of .attr() to access `data-` attributes 126 | - Added quantity adjustment example to advanced code example 127 | 128 | ## 0.2.2 - 2015-01-25 129 | ### Added 130 | - New `updateItemQuantitiesById` Core API method 131 | 132 | ## 0.2.1 - 2014-11-27 133 | ### Added 134 | - This new-format CHANGELOG, based on http://keepachangelog.com 135 | 136 | ### Changed 137 | - Further improvements to documentation, including better code examples 138 | 139 | ## 0.2.0 - 2014-10-11 140 | ### Added 141 | - New Data API methods for updating and clearing items 142 | - New `data-cart-render` methods for simple DOM updating 143 | 144 | ### Changed 145 | - Major improvements to documentation 146 | 147 | ### Removed 148 | - `getCart()` method no longer publicly exported 149 | 150 | ## 0.1.0 - 2014-10-09 151 | ### Added 152 | - Initial implementation; first "official" release 153 | - Core API 154 | - Data API 155 | - Rivets.js DOM bindings 156 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Cart.js 2 | We love to accept pull requests from anyone interested in helping out with the 3 | Cart.js project. Note that by participating in this project, you agree to both: 4 | 5 | - abide by Disco's [Open Source Code of Conduct]; 6 | - license your contribution under the [MIT License]. 7 | 8 | [Open Source Code of Conduct]: https://www.discolabs.com/open-source-code-of-conduct/ 9 | [MIT License]: LICENSE 10 | 11 | 12 | ## Submitting a Pull Request 13 | Fork, then clone the repo: 14 | 15 | git clone git@github.com:your-username/cartjs.git 16 | 17 | Install all dependencies for building and running tests: 18 | 19 | npm install 20 | 21 | Make sure the tests pass: 22 | 23 | npm test 24 | 25 | Make your change. Add tests for your change. Make the tests pass: 26 | 27 | npm test 28 | 29 | Push to your fork and [submit a pull request], based off the `develop` branch. 30 | 31 | [submit a pull request]: https://github.com/discolabs/cartjs/compare/ 32 | 33 | **Please ask first** before embarking on any significant pull request to avoid 34 | spending lots of time working on something we may not wish to merge. 35 | 36 | 37 | ## Cart.js Development Philosophy 38 | The overarching goal of Cart.js is to make common dynamic Javascript 39 | functionality as easy as possible for Shopify developers to implement. To help 40 | achieve that goal, we try to stick to the following philosophical guidelines: 41 | 42 | - **User-Friendly**: A junior web developer new to Shopify development should be 43 | able to pick up and find the library useful within a couple of hours. There 44 | shouldn't be any complex configuration or code required to use Cart.js. Docs 45 | should be as comprehensive as possible and easy to follow. 46 | - **Real-World Code**: Features should only be added when they've proven useful 47 | on real-world Shopify stores. Issues and feature requests made in a vacuum 48 | should be rejected until a concrete case can be made for them. 49 | - **Opinionated**: Pick a sensible way of doing things that works for 90% of use 50 | cases and make that the default, instead of allowing many different 51 | configurations. 52 | -------------------------------------------------------------------------------- /Gruntfile.coffee: -------------------------------------------------------------------------------- 1 | module.exports = (grunt) -> 2 | 3 | # Initialise 4 | grunt.initConfig 5 | pkg: grunt.file.readJSON('package.json') 6 | 7 | meta: 8 | banner: 9 | '// Cart.js\n' + 10 | '// version: <%= pkg.version %>\n' + 11 | '// author: <%= pkg.author %>\n' + 12 | '// license: <%= pkg.licenses[0].type %>\n' 13 | 14 | coffee: 15 | build: 16 | options: 17 | join: true 18 | files: 19 | 'dist/cart.js': [ 20 | 'src/cart.coffee' 21 | 'src/item.coffee' 22 | 'src/cartjs.coffee' 23 | 'src/utils.coffee' 24 | 'src/queue.coffee' 25 | 'src/core.coffee' 26 | 'src/data.coffee' 27 | 'src/rivets.coffee' 28 | 'src/export.coffee' 29 | ] 30 | 31 | concat: 32 | build: 33 | options: 34 | banner: '<%= meta.banner %>' 35 | files: 36 | 'dist/rivets-cart.js': [ 37 | 'node_modules/sightglass/index.js', 38 | 'node_modules/rivets/dist/rivets.js', 39 | 'dist/cart.js' 40 | ] 41 | 42 | uglify: 43 | build: 44 | options: 45 | banner: '<%= meta.banner %>' 46 | report: 'gzip' 47 | files: 48 | 'dist/cart.min.js': 'dist/cart.js' 49 | 'dist/rivets-cart.min.js': 'dist/rivets-cart.js' 50 | 51 | clean: 52 | build: 53 | src: [] 54 | 55 | terraform: 56 | docs: 57 | options: 58 | data: { 59 | docs: grunt.file.readJSON('docs/docs.json'), 60 | version: '<%= pkg.version %>' 61 | } 62 | files: 63 | 'docs/theme/snippets/variables.liquid': 'docs/snippets/variables.jade' 64 | 'docs/theme/templates/index.liquid': 'docs/index/index.jade' 65 | 'docs/theme/templates/page.guide.liquid': 'docs/guide/guide.jade' 66 | 'docs/theme/templates/page.reference.liquid': 'docs/reference/reference.jade' 67 | 'docs/theme/templates/page.built-with.liquid': 'docs/built-with/built-with.jade' 68 | 69 | compress: 70 | docs: 71 | options: 72 | archive: 'cartjs.zip' 73 | files: [ 74 | flatten: true 75 | expand: true 76 | cwd: 'dist/' 77 | src: '*.js' 78 | ] 79 | 80 | copy: 81 | docs: 82 | files: [ 83 | src: 'dist/rivets-cart.min.js' 84 | dest: 'docs/theme/assets/rivets-cart.min.js' 85 | , 86 | src: 'cartjs.zip' 87 | dest: 'docs/theme/assets/cartjs.zip' 88 | , 89 | src: 'node_modules/shopify.i18n.js/dist/shopify.i18n.min.js' 90 | dest: 'docs/theme/assets/shopify.i18n.min.js' 91 | ] 92 | 93 | less: 94 | docs: 95 | options: 96 | compress: true 97 | files: 98 | 'docs/theme/assets/cartjs.min.css': 'docs/less/cartjs.less' 99 | 100 | watch: 101 | build: 102 | files: 'src/*.coffee' 103 | tasks: ['build'] 104 | docs: 105 | files: 'docs/**/*.less' 106 | tasks: ['less:docs'] 107 | 108 | mocha_phantomjs: 109 | test: ['spec/**/*.html'] 110 | 111 | grunt.loadNpmTasks 'grunt-contrib-clean' 112 | grunt.loadNpmTasks 'grunt-contrib-compress' 113 | grunt.loadNpmTasks 'grunt-contrib-concat' 114 | grunt.loadNpmTasks 'grunt-contrib-copy' 115 | grunt.loadNpmTasks 'grunt-contrib-coffee' 116 | grunt.loadNpmTasks 'grunt-contrib-less' 117 | grunt.loadNpmTasks 'grunt-contrib-uglify' 118 | grunt.loadNpmTasks 'grunt-contrib-watch' 119 | grunt.loadNpmTasks 'grunt-terraform' 120 | grunt.loadNpmTasks 'grunt-mocha-phantomjs' 121 | 122 | grunt.registerTask 'default', ['watch'] 123 | grunt.registerTask 'build', ['coffee:build', 'concat:build', 'uglify:build', 'clean:build'] 124 | grunt.registerTask 'test', ['build', 'mocha_phantomjs'] 125 | grunt.registerTask 'docs', ['build', 'terraform:docs', 'compress:docs', 'copy:docs', 'less:docs'] 126 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2016 Disco 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![npm version](https://badge.fury.io/js/shopify-cartjs.svg)](https://badge.fury.io/js/shopify-cartjs) 2 | [![Bower version](https://badge.fury.io/bo/shopify-cartjs.svg)](https://badge.fury.io/bo/shopify-cartjs) 3 | 4 | # Cart.js 5 | Cart.js is a Javascript library that makes it easy to add dynamic cart features 6 | to Shopify themes. 7 | 8 | It abstracts away the difficult parts of working with Shopify's AJAX API and 9 | provides a simple, consistent interface to manipulating a customer's cart. 10 | Without having to worry about the quirks in Shopify's endpoints or about making 11 | all of your requests synchronous, you can just write code like this: 12 | 13 | ```js 14 | function example() { 15 | // Clear the existing cart. 16 | CartJS.clear(); 17 | 18 | // Add 3x "12345678" items, with a custom "size" property of "XL". 19 | CartJS.addItem(12345678, 3, { 20 | "size": "XL" 21 | }); 22 | 23 | // Add multiple items in a single call. 24 | CartJS.addItems([ 25 | { 26 | id: 12345678, 27 | quantity: 3, 28 | properties: { 29 | "size": "XL" 30 | } 31 | }, 32 | { 33 | id: 87654321, 34 | quantity: 2 35 | } 36 | ]); 37 | 38 | // Set a custom cart note. 39 | CartJS.setNote('This is a custom cart note.'); 40 | } 41 | ``` 42 | 43 | Neat, huh? But that's just the beginning. 44 | 45 | Cart.js bundles two powerful optional modules that make it even easier to build 46 | dynamic carts into your themes: 47 | 48 | 49 | ### Data API Module 50 | Lets you use simple `data-*` markup attributes to hook in to Cart.js methods, 51 | without having to write *any* Javascript yourself. 52 | 53 | For example, to create a button that added a particular product to your cart, 54 | all that's required is: 55 | 56 | ```html 57 | 58 | ``` 59 | 60 | 61 | ### DOM Binding Module 62 | In combination with [Rivets.js][], the DOM Binding module lets you write HTML 63 | templates in your `.liquid` files that are re-rendered dynamically when the 64 | contents of your cart change, like this: 65 | 66 | ```html 67 |
68 | You currently have {cart.item_count} item(s) in your cart, for a total of {cart.total_price | money_with_currency}. 69 |
70 | ``` 71 | 72 | 73 | ## Getting Started and Documentation 74 | Documentation and examples are available on the [home page][]. 75 | 76 | You can check out a list of who's using Cart.js in production on the 77 | [Built with Cart.js][] page. 78 | 79 | [home page]: https://cartjs.org?utm_source=github&utm_medium=readme&utm_campaign=cartjs 80 | [Built with Cart.js]: https://cartjs.org/pages/built-with-cart-js 81 | 82 | 83 | ## Dependencies 84 | Cart.js currently depends on [jQuery][] for its AJAX helpers, custom event 85 | bindings and utility methods. This usually isn't a problem as most Shopify 86 | themes ship with jQuery. 87 | 88 | [Rivets.js] is required if you want to use the DOM Binding module. The 89 | distribution of Cart.js includes a minified asset (`rivets-cart.min.js`) which 90 | contains both the Cart.js library and a bundled version of Rivets.js. 91 | 92 | [Rivets.js]: http://rivetsjs.com 93 | [jQuery]: http://jquery.com 94 | 95 | 96 | ## Release History 97 | Refer to the [change log](https://github.com/discolabs/cartjs/blob/master/CHANGELOG.md) 98 | for a full list of changes. 99 | 100 | 101 | ## Contributions 102 | Contributions are very much welcome! Read our [contribution guidelines][] for 103 | details on submitting pull requests that will be accepted. 104 | 105 | [contribution guidelines]: https://github.com/discolabs/cartjs/blob/master/CONTRIBUTING.md 106 | 107 | --- 108 | 109 | #### About the Author 110 | [Gavin Ballard][] is the founder, CEO, and occasional developer at [Disco Labs][], 111 | a Shopify Plus partner agency specialising in solutions for merchants with complex 112 | needs. 113 | 114 | [Gavin Ballard]: http://gavinballard.com/?utm_source=github&utm_medium=readme&utm_campaign=cartjs 115 | [Disco Labs]: https://www.discolabs.com/?utm_source=github&utm_medium=readme&utm_campaign=cartjs 116 | 117 | #### Thanks 118 | Thanks to the following people who have contributed their time and code to Cart.js! 119 | 120 | * [Michaël Gallego](https://github.com/bakura10) 121 | * [Michael Shannon](https://github.com/michaelrshannon) 122 | * [Stewart Knapman](https://github.com/stewartknapman) 123 | * [Jonathan Moore](https://github.com/jonathanmoore) 124 | * [Ty Carlson](https://github.com/tywayne) 125 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shopify-cartjs", 3 | "version": "1.1.0", 4 | "authors": [ 5 | "Gavin Ballard " 6 | ], 7 | "description": "A Javascript library to power cart management for Shopify themes.", 8 | "main": "dist/cart.js", 9 | "keywords": [ 10 | "shopify", 11 | "ajax" 12 | ], 13 | "license": "MIT", 14 | "homepage": "https://cartjs.org", 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /docs/built-with/built-with.jade: -------------------------------------------------------------------------------- 1 | | {% include 'variables' %} 2 | 3 | .jumbotron 4 | section.container 5 | h2 Built with Cart.js 6 | p This pages lists sites using Cart.js in the wild. 7 | p 8 | a(href= 'https://github.com/discolabs/cartjs/issues/new?title=New%20site%20for%20%22Built%20With%22%20Page:%20http://')= "Add a site to this list." 9 | 10 | hr 11 | 12 | .row 13 | for site, anchor in docs.builtwith 14 | .col-md-4.col-sm-6 15 | .thumbnail 16 | a(href= site.url, target= '_blank') 17 | img(src= "{{ '" + anchor + ".jpg' | asset_url }}", class='img-thumbnail') 18 | .caption 19 | h4= site.title 20 | a(href= site.url, target= '_blank')= site.url 21 | -------------------------------------------------------------------------------- /docs/guide/guide.jade: -------------------------------------------------------------------------------- 1 | | {% include 'variables' %} 2 | 3 | .jumbotron 4 | section.container 5 | .row 6 | article.col-md-10.guide 7 | for section, anchor in docs.guide 8 | h2(id= anchor)= section.title 9 | != partial('sections/' + anchor) 10 | 11 | for subsection, subanchor in section.sections 12 | h3(id= anchor + '-' + subanchor)= subsection.title 13 | != partial('sections/' + anchor + '/' + subanchor) 14 | 15 | aside.col-md-2.hidden-sm.hidden-xs 16 | .aside 17 | nav#nav(data-spy="affix", data-offset-top="102") 18 | ul.nav.nav-docs 19 | for section, anchor in docs.guide 20 | li 21 | a(href= '#' + anchor)= section.title 22 | 23 | ul.nav 24 | for subsection, subanchor in section.sections 25 | li 26 | a(href= '#' + anchor + '-' + subanchor)= subsection.nav || subsection.title 27 | -------------------------------------------------------------------------------- /docs/guide/sections/core-api.md: -------------------------------------------------------------------------------- 1 | The Core API consists of methods called on the global `CartJS` object. 2 | You can use the Core API to do pretty much everything you'd expect of a cart manipulation library - add items, update quantities and custom properties, and so on. 3 | 4 | A full list of methods can be found in the [API Reference][]. 5 | 6 | [API Reference]: /pages/reference/#core-api 7 | -------------------------------------------------------------------------------- /docs/guide/sections/core-api/adding-items.md: -------------------------------------------------------------------------------- 1 | Adding items to your cart is as simple as calling `CartJS.addItem()`, and passing the ID of the variant you'd like to add as the first argument. 2 | 3 | Assume we have a Shopify store that's selling widgets, and that one of those widgets has a variant with an ID of `12345678` that costs $9.99. 4 | Let's create a button customers can click to add a widget to their cart, and then hook it up to some Javascript code via jQuery: 5 | 6 | ```html 7 | 8 | 9 | 14 | ``` 15 | 16 | Now when a customer clicks our button, Cart.js will make an Ajax request and add a single Widget to the customer's cart. 17 | 18 | When using the `addItem()` method, you can optionally specify the quantity to add and a hash of custom line item properties. 19 | You can also specify the special optional `selling_plan` property, which will be used by Cart.js to specify the [selling plan](https://shopify.dev/docs/themes/liquid/reference/objects/selling-plan) the item will be sold with. 20 | 21 | Let's update our code to add five widgets when we click the button, to use the selling plan `1425` and to set a custom "added_by" property on the resulting line item: 22 | 23 | ```html 24 | 25 | 26 | 34 | ``` 35 | 36 | If we loaded this example, clicked "Add Five Widgets", then typed `CartJS.cart.items` in to our browser's Javascript console, we'd see something like this (simplified for this example): 37 | 38 | ```js 39 | [ 40 | { 41 | "handle": "widget-1", 42 | "id" 12345678, 43 | "price": 999, 44 | "line_price": 4995, 45 | "properties": { 46 | "added_by": "Cart.js" 47 | }, 48 | "quantity": 5, 49 | "title": "Widget 1", 50 | "variant_id": 12345678, 51 | "selling_plan_allocation": { 52 | "selling_plan": { 53 | "id": 1425 54 | } 55 | } 56 | } 57 | ] 58 | ``` 59 | 60 | That's it! 61 | You can call `addItem()` as many times as you like in the same function, and Cart.js will queue up Ajax requests as needed. 62 | 63 |
64 |

Adding multiple line items at once

65 | 66 |

67 | If you're adding multiple line items at once, you can use the `CartJS.addItems()` method, rather than multiple calls to `CartJS.addItem()`. 68 |

69 | 70 |

71 | This method leverages new functionality added to the Shopify Ajax API in January 2020 that supports multiple items being added at once. 72 |

73 |
74 | 75 |
76 |

Note on multiple line items with the same variant ID

77 | 78 |

79 | Shopify will collate multiple line items for the same variant into one — for example, if we clicked "Add Five Widgets" in the example above again, we'd end up with one line item with `"quantity": 10` instead of two line item with `"quantity: 5"`. 80 |

81 | 82 |

83 | However, this *doesn't* apply when you add the same variant with custom line item properties that differ — if we changed the value of the `added_by` property and clicked the button, we'd end up with separate line items. 84 |

85 |
86 | -------------------------------------------------------------------------------- /docs/guide/sections/core-api/attributes.md: -------------------------------------------------------------------------------- 1 | In addition to cart items, Shopify also provides support for cart attributes, which are used to store custom information about an order. 2 | For example, a common use case for attributes is to store a flag indicating whether the customer would like their order gift wrapped. 3 | 4 | Cart.js provides some conveniences around manipulating these attributes. 5 | Let's take the gift wrap example and see how we could implement it with a simple checkbox: 6 | 7 | ```html 8 | 12 | 13 | 19 | ``` 20 | 21 | Now, any time a customer checks or un-checks the options, CartJS will make an update request to the Shopify server. 22 | 23 | Cart.js provides convenience methods for setting multiple attributes at once, clearing attributes, and setting the special-case `note` attribute. 24 | For a full list of supported methods, see the [API Reference][]. 25 | 26 | [API Reference]: /pages/reference/#core-api 27 | -------------------------------------------------------------------------------- /docs/guide/sections/core-api/callbacks.md: -------------------------------------------------------------------------------- 1 | All Core API methods that result in an Ajax request being made to the server allow you to specify one or more callback functions, just like a regular jQuery `$.ajax()` request. 2 | Callbacks are specified through an `options` hash, passed as the final optional argument to the core methods. 3 | 4 | To take a common example, we'll often want to provide callback methods to handle possible results when we try to add an item to our cart. 5 | We want to inform the user of the success or failure of their action, and potentially take some other action. 6 | 7 | ```html 8 | 9 | 10 |
11 | 12 | 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/guide/sections/core-api/cart-state.md: -------------------------------------------------------------------------------- 1 | If we want to inspect the state of our cart at any time, we can access the `CartJS.cart` object. 2 | You can read any of the standard cart properties (such as `item_count` or `requires_shipping`, for example), as well as a list of the current `items` in the cart. 3 | 4 | While developing with Cart.js, it's often useful to open your browser's Javascript console and inspect the cart state, or test out Cart.js methods. 5 | Here's an example from the developer console in Chrome: 6 | 7 |
8 | Screenshot of the Chrome developer console. 9 |
10 | 11 |
12 |

Don't write values via the cart object

13 | 14 |

15 | You should only ever *read* values from `CartJS.cart`, and avoid altering the object directly. 16 |

17 | 18 |

19 | Assigning a value with code like `CartJS.cart.items[0].quantity = 5;` will make the change locally in the browser, but won't save it to the server. 20 | This means that the changes will be lost when the customer refreshes or navigates to a new page, or when Cart.js fetches an updated version of the cart from Shopify. 21 |

22 |
23 | -------------------------------------------------------------------------------- /docs/guide/sections/core-api/configuration.md: -------------------------------------------------------------------------------- 1 | In the "Setup" section above, we saw that we need to call `CartJS.init()` before use, like this: 2 | 3 | {% raw %} 4 | ```html 5 | 13 | ``` 14 | {% endraw %} 15 | 16 | As you can see, the `init()` method takes two arguments. 17 | The first argument is required, and is provided by rendering the current Shopify cart as a JSON object through the {% raw %}`{{ cart | json }}`{% endraw %} Liquid tag. 18 | 19 | The second argument is an optional hash of configuration options. 20 | A full list of these options is available in the [Option Reference][]. 21 | 22 | [Option Reference]: /pages/reference/#options 23 | -------------------------------------------------------------------------------- /docs/guide/sections/core-api/removing-items.md: -------------------------------------------------------------------------------- 1 | Removing items works in a similar way to updating items -- just call the `removeItem()` method, passing the line number of the line item you'd like to remove. 2 | As with the update method, if you'd like to remove all line items with a particular variant ID, you can use `removeItemById()` instead. 3 | 4 | If you'd like to empty the cart completely, just call the `clear()` method: 5 | 6 | ```html 7 | 8 | 9 | 14 | ``` 15 | -------------------------------------------------------------------------------- /docs/guide/sections/core-api/updating-items.md: -------------------------------------------------------------------------------- 1 | Updating the quantities or properties of line items is just as simple as adding them -- we just make a call to the `updateItem()` method. 2 | 3 | Let's continue from our example above, and say we want to have a button that doubles the number of widgets in our order. 4 | 5 | ```html 6 | 7 | 8 | 14 | ``` 15 | 16 |
17 |

Existing items referenced by index, not variant ID

18 | 19 |

20 | One important thing to note is that the `updateItem()` method takes the ***line number*** (the "index") of the item in the cart you'd like to update, not the variant ID. 21 | This is because it's possible (and quite common) to have multiple items in the cart with the same variant ID but with different properties. 22 |

23 | 24 |

25 | Shopify uses a 1-based index for line items, so the index of the first line item in a cart is `1`, not `0` as is common in many programming languages. 26 |

27 | 28 |

29 | If you'd like to update an item using just the variant ID, you can use `updateItemById()`, which operates the same way as `updateItem()` but takes the variant ID as the first parameter. 30 |

31 |
32 | -------------------------------------------------------------------------------- /docs/guide/sections/data-api.md: -------------------------------------------------------------------------------- 1 | The Data API is the easiest way to start using Cart.js, and for a lot of use cases it'll be all you need. 2 | 3 | All you need to do is add the appropriate `data-` attributes to your code, and the event listeners automatically set up by Cart.js will do the rest. 4 | 5 | This guide provides a quick overview - for a full list of available markup attributes, check out the [Data API Reference][]. 6 | 7 | [Data API Reference]: /pages/reference#data-api 8 | -------------------------------------------------------------------------------- /docs/guide/sections/data-api/adding-items.md: -------------------------------------------------------------------------------- 1 | To create an element that adds an item to the cart on a `click` event, just mark up an element with a `data-cart-add` attribute, and set the value of the attribute to the ID of the variant you'd like to add: 2 | 3 | ```html 4 | 5 | ``` 6 | 7 | Of course, you can always use Liquid to render these elements dynamically in your templates: 8 | 9 | {% raw %} 10 | ```html 11 | {% for variant in product.variants %} 12 | 13 | {% endfor %} 14 | ``` 15 | {% endraw %} 16 | 17 | You can also optionally specify a quantity and selling plan for the add action: 18 | 19 | ```html 20 | 21 | ``` 22 | -------------------------------------------------------------------------------- /docs/guide/sections/data-api/removing-items.md: -------------------------------------------------------------------------------- 1 | To create an element that removes a line item from the cart on a `click` event, use `data-cart-remove` or `data-cart-remove-id`. 2 | 3 | The difference between these two is that `data-cart-remove` expects the index of the line item you'd like to remove from the cart, while `data-cart-remove-id` expects a variant ID. 4 | 5 | See [Updating Items][] in the Core API section for an explanation of why this distinction is required. 6 | 7 | ```html 8 | 9 | ``` 10 | 11 | [Updating Items]: #core-api-updating-items 12 | -------------------------------------------------------------------------------- /docs/guide/sections/data-api/submitting-forms.md: -------------------------------------------------------------------------------- 1 | If you've already got a working Shopify theme, you'll already have a couple of `
` elements around the place that you use to add items to the cart - for example, in your `product.liquid` template. 2 | 3 | You can convert these existing forms to use Cart.js simply by adding a `data-cart-submit` attribute to the `` element: 4 | 5 | {% raw %} 6 | ```html 7 | 8 | 13 | 14 | 15 |
16 | ``` 17 | {% endraw %} 18 | 19 | When the customer clicks "Buy Now", Cart.js will intercept the form submission and convert it to an Ajax request. 20 | All of the usual inputs - `id` to specify the variant ID, `quantity` to specify the quantity, `selling_plan` to specify the selling plan, and `properties[]` to specify line item properties - are supported. 21 | 22 |
23 |

Form submission doesn't work with files

24 |

25 | Because Ajax requests don't support `POST` requests with `enctype="multipart/form-data"`, Cart.js won't be able to submit your form if it contains `` elements. 26 |

27 |

28 | This is something that we hope to auto-detect in future, but for now you should avoid using `data-cart-submit` on forms that need to upload files. 29 |

30 |
31 | 32 |
33 |

Form submission doesn't work with checkout forms

34 |

35 | Be careful not to add the `data-cart-submit` attribute to forms that target `action="/checkout"`, as Cart.js will intercept the event and customers won't be redirected to the checkout. 36 |

37 |
38 | -------------------------------------------------------------------------------- /docs/guide/sections/data-api/toggling-items.md: -------------------------------------------------------------------------------- 1 | If you want to give your customers the ability to "toggle" items in or out of their cart, you can use a `data-cart-toggle` attribute on an element that fires a `change` event (like a checkbox or radio input). 2 | 3 | A common use case for this is having an "added extra" on the cart page before the customer checks out - for example, a gift card. 4 | 5 | Let's say we have a selection of gift cards a customer can choose from, and that we've created a collection containing them: 6 | 7 | {% raw %} 8 | ```html 9 | {% for gift_card_product in collections.gift-cards.products %} 10 | 14 | {% endfor %} 15 | ``` 16 | {% endraw %} 17 | 18 | This code will render a checkbox that a customer can turn on or off to add or remove the desired gift card from their card. 19 | -------------------------------------------------------------------------------- /docs/guide/sections/dom-binding.md: -------------------------------------------------------------------------------- 1 | Full documentation for the DOM Binding module is coming soon. 2 | 3 | In the meantime, you can check out the example on the [front page][] in combination with the [Rivets.js documentation][] to get an idea of how things work. 4 | 5 | [front page]: / 6 | [Rivets.js documentation]: http://rivetsjs.com/ 7 | -------------------------------------------------------------------------------- /docs/guide/sections/events.md: -------------------------------------------------------------------------------- 1 | To make it easy to respond to changes in the customer's cart, Cart.js fires a number of custom jQuery events that you can bind listeners to. 2 | 3 | All events are triggered on the `document`, are prefixed with a `cart` namespace, and pass the current cart object as the first custom event argument. 4 | 5 | For example, if we wanted to update a `` element with the number of items in the cart after a request, we could listen for the `cart.requestComplete` event like so: 6 | 7 | {% raw %} 8 | ```html 9 | You have {{ cart.item_count }} items in your cart. 10 | 11 | 16 | ``` 17 | {% endraw %} 18 | 19 | A complete list of the events triggered by Cart.js is available in the [Event Reference][]. 20 | 21 | [Event Reference]: /pages/reference#events 22 | -------------------------------------------------------------------------------- /docs/guide/sections/getting-started.md: -------------------------------------------------------------------------------- 1 | Getting started with Cart.js is designed to be pretty easy. 2 | 3 | You just need to fetch a copy of the library, include it in your theme, and call a single initialisation method. 4 | Then you can make calls to Cart.js from within your theme code. 5 | -------------------------------------------------------------------------------- /docs/guide/sections/getting-started/browser-support.md: -------------------------------------------------------------------------------- 1 | If you're using only the Core and Data functionality of Cart.js (that is, 2 | you're using the `cart.js` or `cart.min.js` library in your theme), then the 3 | range of browsers your theme will support is limited purely by the version of 4 | jQuery you're using. That means that using a `1.x` version of jQuery will allow 5 | you to support IE6+, Chrome, Firefox, Safari 5.1+ and up. 6 | 7 | If you're using the DOM Binding functionality (that is, you're using the 8 | `rivets-cart.min.js` library in your theme), then you may see problems on 9 | browsers that don't support the ES5 Javascript standard (namely, Internet 10 | Explorer 8 and below). 11 | 12 | As of November 2015, Shopify no longer requires themes submitted to the theme 13 | store to support Internet Explorer 8, so as long as you don't have a special use 14 | case that requires supporting these older browsers, you can happily use the DOM 15 | Binding library in your themes. 16 | 17 |
18 |

What's the issue with older browsers?

19 | 20 |

21 | Non-ES5 browsers (namely, IE8) don't support EcmaScript 5's 22 | `Object.defineProperty()` method, which Rivets.js uses to observe 23 | changes on data models and trigger DOM updates. 24 |

25 | 26 |

27 | Earlier versions of Cart.js provided a workaround for this by bundling 28 | a number of ES5 shims and polyfills into the library, as well as 29 | forcibly binding and re-binding Rivets views whenever a charge to the 30 | cart occurred. This "compatibility mode" was dropped once Shopify 31 | changed their theme guidelines to only require support for Internet 32 | Explorer 9+. 33 |

34 |
35 | -------------------------------------------------------------------------------- /docs/guide/sections/getting-started/installation.md: -------------------------------------------------------------------------------- 1 | Cart.js is available via the `npm` or `bower` package managers, from 2 | [cdnjs](https://cdnjs.com), or simply by downloading the latest version of the 3 | library. 4 | 5 | #### NPM 6 | ```shell 7 | npm install shopify-cartjs 8 | ``` 9 | 10 | #### Bower 11 | ```shell 12 | bower install shopify-cartjs 13 | ``` 14 | 15 | #### CDNJS 16 | ```html 17 | 18 | 19 | 20 | ``` 21 | 22 | #### Download 23 | Download the latest version of the library: cartjs.zip. 24 | -------------------------------------------------------------------------------- /docs/guide/sections/getting-started/module-loaders.md: -------------------------------------------------------------------------------- 1 | If you're using Cart.js and Rivets with module loaders like Webpack, you'll 2 | need to make a couple of minor tweaks to ensure things work smoothly. 3 | 4 | Ensure you're pulling in jQuery and Rivets in your `webpack.config.js` or 5 | equivalent: 6 | 7 | {% raw %} 8 | ```js 9 | new webpack.ProvidePlugin({ $: "jquery", rivets: "rivets", }), 10 | ``` 11 | {% endraw %} 12 | 13 | and also make sure that Rivets is available globally in your entrypoint file: 14 | 15 | {% raw %} 16 | ```js 17 | global.rivets = rivets; 18 | ``` 19 | {% endraw %} -------------------------------------------------------------------------------- /docs/guide/sections/getting-started/next-steps.md: -------------------------------------------------------------------------------- 1 | Now that you gotten Cart.js set up with your theme, you're ready to start using the library. 2 | 3 | The recommended (and easiest) way to interact with Cart.js is via the Data API. 4 | All this requires is adding some additional markup to your HTML and Cart.js will take care of the rest - you don't need to write any additional Javascript. 5 | 6 | If you want to do something that's not supported by the Data API, or use Cart.js from within your own custom Javascript, then you can use the Core API to call methods on the `CartJS` object directly. 7 | Of course, these two approaches aren't mutually exclusive - you can always use the Data API for the majority of your cart functionality, drop down to the Core API only when needed. 8 | 9 |
10 |

11 | The Core API is covered first in the documentation below, as it provides the foundation for the Data API. 12 |

13 | 14 |

15 | However, if you just want to get stuck in to using Cart.js, feel free to go straight to the coverage of the Data API. 16 |

17 |
18 | 19 | Once you've gotten the hang of the Core and Data APIs, you might be interested in using Cart.js in conjunction with Rivets.js to create HTML templates that are automatically updated along with your cart. 20 | That's covered in the [DOM Binding][] section later on. 21 | 22 | [DOM Binding]: #dom-binding 23 | -------------------------------------------------------------------------------- /docs/guide/sections/getting-started/setup.md: -------------------------------------------------------------------------------- 1 | The Cart.js distribution comes packaged with three versions of the library: 2 | 3 |
4 |

5 | `cart.js` is the unminified source code, containing the Core and Data APIs. 6 |

7 | 8 |

9 | `cart.min.js` is a minified version of the library, and also contains the Core and Data APIs. 10 |

11 | 12 |

13 | `rivets-cart.min.js` is a minified version of Cart.js that also bundles the Rivets.js library. 14 | Together, they provide support for the DOM Binding functionality. 15 |

16 |
17 | 18 | Once you've selected the version you'd like to use, add the relevant file to your theme's `/assets` directory. 19 | 20 | You then just need to include the script on your page and call `CartJS.init()`. 21 | The best place to do this is at the bottom of your theme's `theme.liquid` file, so that Cart.js functionality is available across your whole site. 22 | 23 | Because Cart.js depends on jQuery, you should load it after you've included the jQuery library. 24 | 25 | {% raw %} 26 | ```html 27 | ... contents of your theme.liquid ... 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 42 | 43 | 44 | 45 | ``` 46 | {% endraw %} 47 | 48 | Note that the call to `CartJS.init()` requires that {% raw %}`{{ cart | json }}`{% endraw %} is passed as an argument. 49 | This tells Liquid to render the initial cart state as a JSON object and pass it to Cart.js. 50 | 51 |
52 |

Dependency when formatting monetary values

53 | 54 |

55 | If you're using any of the money-formatting features of Cart.js (such as the `| money` filter in the DOM Binding 56 | module or the `data-cart-render` attributes of the Data API), you'll need to make sure that Shopify's currency 57 | Javascript library is loaded. 58 |

59 | 60 |

61 | Do this simply by ensuring that the `option_selection.js` library is loaded on all of your theme's pages, using 62 | a line something like `{% raw %}{{ 'option_selection.js' | shopify_asset_url | script_tag }}{% endraw %}` in your `theme.liquid`. 63 |

64 |
65 | -------------------------------------------------------------------------------- /docs/guide/sections/introduction.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discolabs/cartjs/3d60425769d593c5e0968fd22d12ff78c63bcc4f/docs/guide/sections/introduction.md -------------------------------------------------------------------------------- /docs/guide/sections/introduction/what.md: -------------------------------------------------------------------------------- 1 | Cart.js is a very small open source Javascript library that makes the addition of powerful Ajax cart functionality to your Shopify theme a breeze. 2 | 3 | It's designed to be simple to use, while providing some really powerful and nifty features, like: 4 | 5 | 10 | 11 | You don't need to worry about ensuring your Ajax requests are synchronous, binding event listeners, or updating the DOM. 12 | -------------------------------------------------------------------------------- /docs/images/icon-500x500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discolabs/cartjs/3d60425769d593c5e0968fd22d12ff78c63bcc4f/docs/images/icon-500x500.png -------------------------------------------------------------------------------- /docs/images/icon-64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discolabs/cartjs/3d60425769d593c5e0968fd22d12ff78c63bcc4f/docs/images/icon-64x64.png -------------------------------------------------------------------------------- /docs/index/index.jade: -------------------------------------------------------------------------------- 1 | | {% include 'variables' %} 2 | 3 | section.jumbotron.jumbotron-primary 4 | .container.text-center 5 | h3 A Javascript library to power your Shopify theme's cart. 6 | a.btn.btn-lg.btn-outline-inverse(href="{{ 'cartjs.zip' | asset_url }}") Download Cart.js v{{ version }} 7 | 8 | section.jumbotron 9 | .container 10 | .row 11 | .col-md-8.col-md-offset-2 12 | != partial('sections/what-is-cart-js') 13 | 14 | .row 15 | .col-md-10.col-md-offset-1 16 | .example.example-live 17 | != partial('sections/demo-simple') 18 | 19 | .example-code.collapse(id="demo-simple-code") 20 | != partial('sections/demo-simple-code') 21 | 22 | .example-footer 23 | a(data-toggle="collapse" href="#demo-simple-code") Show markup for this example 24 | 25 | 26 | .row 27 | .col-md-8.col-md-offset-2 28 | != partial('sections/can-it-do-more') 29 | 30 | .row 31 | .col-md-10.col-md-offset-1 32 | .example.example-live 33 | != partial('sections/demo-advanced') 34 | 35 | .example-code.collapse(id="demo-advanced-code") 36 | != partial('sections/demo-advanced-code') 37 | 38 | .example-footer 39 | a(data-toggle="collapse" href="#demo-advanced-code") Show markup for this example 40 | 41 | .row 42 | .col-md-8.col-md-offset-2 43 | != partial('sections/further-questions') 44 | -------------------------------------------------------------------------------- /docs/index/sections/can-it-do-more.md: -------------------------------------------------------------------------------- 1 | ## Can it do more? 2 | 3 | Yes! 4 | There's a whole lot more to Cart.js, from converting your existing product forms to Ajax with a single attribute to fully dynamic HTML template support. 5 | 6 | And if you ever want to write your own Javascript directly, you can hook in to our custom events and API. 7 | 8 | You can start learning about Cart.js with the [guide][], or check out the full [reference][]. 9 | 10 | [guide]: /pages/guide 11 | [reference]: /pages/reference 12 | -------------------------------------------------------------------------------- /docs/index/sections/demo-advanced-code.md: -------------------------------------------------------------------------------- 1 | ```html 2 | 3 |
4 | 5 | 9 | 10 | 11 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 45 | 46 | 51 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 |
ItemPriceQtyLine Price
38 | 39 |
    40 |
  • 41 | {property.name}: {property.value} 42 |
  • 43 |
44 |
47 | - 48 | 49 | + 50 | 52 | × 53 |
You don't have any items in your cart.
67 | 68 | 69 | ``` 70 | -------------------------------------------------------------------------------- /docs/index/sections/demo-advanced.jade: -------------------------------------------------------------------------------- 1 | .row 2 | .col-md-4 3 | form(data-cart-submit) 4 | .form-group 5 | label(for="demo-advanced-id") Select a Product 6 | select.form-control.input-sm(id="demo-advanced-id" name="id") 7 | !="{% for product in collections.frontpage.products %}" 8 | option(value="{{ product.variants.first.id }}") {{ product.title }} 9 | !="{% endfor %}" 10 | 11 | .form-group 12 | label(for="demo-advanced-quantity") Choose a Quantity 13 | select.form-control.input-sm(id="demo-advanced-quantity" name="quantity") 14 | option 1 15 | option 2 16 | option 3 17 | option 4 18 | option 5 19 | 20 | .form-group 21 | label(for="demo-advanced-custom-label") Add a Custom Label (Optional) 22 | input.form-control.input-sm(type="text", name="properties[Custom Label]") 23 | 24 | .form-group 25 | button.btn.btn-default(type="submit") Add to Cart 26 | 27 | .col-md-8 28 | table.table.table-bordered.table-condensed.table-striped.table-vertical-middle(data-cart-view="data-cart-view") 29 | 30 | thead 31 | tr 32 | th Item 33 | th.text-center Price 34 | th.text-center(colspan="2") Qty 35 | th.text-right Line Price 36 | 37 | tbody 38 | tr(rv-each-item="cart.items") 39 | td 40 | strong(rv-text="item.title") 41 | ul.list-unstyled(rv-hide="item.propertyArray | empty") 42 | li(rv-each-property="item.propertyArray < properties") 43 | small.text-muted {property.name}: {property.value} 44 | td.text-center(rv-html="item.price | money Currency.currentCurrency") 45 | 46 | td.text-center 47 | a(href="#" rv-data-cart-update="index | plus 1" rv-data-cart-quantity="item.quantity | minus 1")  -  48 | span(rv-text="item.quantity") 49 | a(href="#" rv-data-cart-update="index | plus 1" rv-data-cart-quantity="item.quantity | plus 1")  +  50 | 51 | td.text-center 52 | a.close(href="#" rv-data-cart-remove="index | plus 1") × 53 | td.text-right(rv-html="item.line_price | money Currency.currentCurrency") 54 | 55 | tr(rv-show="cart.item_count | lt 1") 56 | td.text-center(colspan="5") You don't have any items in your cart. 57 | 58 | tfoot(rv-show="cart.item_count | gt 0") 59 | tr 60 | td.text-muted.small(colspan="4" rv-html="cart.total_weight | weight_with_unit") 61 | td.text-right(rv-html="cart.total_price | money Currency.currentCurrency") 62 | 63 | p.text-center 64 | img.cart-visible-loading(src="{{ 'loader.gif' | asset_url }}" width="16" height="11") 65 | -------------------------------------------------------------------------------- /docs/index/sections/demo-simple-code.md: -------------------------------------------------------------------------------- 1 | ```html 2 |

3 | You have 4 | 5 | items in your cart for a total of 6 | . 7 | 8 | 9 |

10 | 11 | 12 | 13 | 14 | ``` 15 | -------------------------------------------------------------------------------- /docs/index/sections/demo-simple.jade: -------------------------------------------------------------------------------- 1 | .well.well-sm. 2 | Loading... 3 | You have 4 | 5 | items in your cart for a total of 6 | . 7 | 8 | .row 9 | .col-xs-4 10 | button.btn.btn-block.btn-default(data-cart-add="716934999" data-cart-quantity="1") +Hat 11 | .col-xs-4 12 | button.btn.btn-block.btn-default(data-cart-add="716986707" data-cart-quantity="2") +Coats 13 | .col-xs-4 14 | button.btn.btn-block.btn-default(data-cart-clear="") Clear 15 | -------------------------------------------------------------------------------- /docs/index/sections/further-questions.md: -------------------------------------------------------------------------------- 1 | ## Further Questions 2 | 3 | ### Is it stable? 4 | Cart.js is one of the most widely used front end Shopify libraries. It's being 5 | used in production by a vast number of Shopify stores, including our own 6 | clients. 7 | 8 | While it doesn't receive frequent updates, it is generally maintained and we do 9 | make the effort to respond to bug reports and feature requests in a timely 10 | manner. 11 | 12 | If you're interested in using Cart.js, we'll be happy to answer any questions 13 | you have or help you get up and running. 14 | 15 | ### Who's using it? 16 | Aside from our own clients (some of whom are running very sizable Shopify 17 | stores), a number of other sites are using Cart.js in the wild. Check out the 18 | [Built with Cart.js][] page for a list (don't forget to [add your own site][] 19 | once you've built something using the library). 20 | 21 | ### What's the browser support like? 22 | Pretty good! Because the core Cart.js libraries use jQuery for Ajax requests 23 | and DOM manipulation, the only limiting factor is the version of jQuery you 24 | decide to use. This means that themes using a `1.x` version of jQuery with 25 | Cart.js will be able to support IE6+, Chrome, Firefox, Safari 5.1+ and up. 26 | 27 | If you're using the DOM binding functionality, there are some potential issues 28 | with older browser that don't support the ES5 Javascript standard (in practice, 29 | this means Internet Explorer 8 and below). See [Browser Support][] in the Guide 30 | for more detail. 31 | 32 | ### I have a bug report / feature request. 33 | Please add it to the [issues tracker][] on GitHub. 34 | 35 | ### Can I contribute? 36 | Absolutely! 37 | Just head to the [GitHub][] page, fork the repository and manage development 38 | through issues and pull requests. 39 | 40 | If you're keen to help but don't know where to start, contact me 41 | [on Twitter][]. 42 | 43 | --- 44 | 45 | [Built with Cart.js]: /pages/built-with-cart-js 46 | [add your own site]: https://github.com/discolabs/cartjs/issues/new?title=New%20site%20for%20%22Built%20With%22%20Page:%20http:// 47 | [Browser Support]: /pages/guide#getting-started-browser-support 48 | [issues tracker]: https://github.com/discolabs/cartjs/issues 49 | [GitHub]: https://github.com/discolabs/cartjs 50 | [on Twitter]: https://twitter.com/gavinballard 51 | -------------------------------------------------------------------------------- /docs/index/sections/what-is-cart-js.md: -------------------------------------------------------------------------------- 1 | ## What is Cart.js? 2 | 3 | Cart.js is a very small open source Javascript library that makes the addition of powerful Ajax cart functionality to your Shopify theme a breeze. 4 | 5 | It's designed to be simple to use, while providing some really powerful and nifty features, like: 6 | 7 | - **Simple, consistent API** for cart manipulation; 8 | - **Data API** for markup-only use without needing to write a line of Javascript; 9 | - **DOM Binding** to dynamically render HTML templates as your cart changes. 10 | 11 | You don't need to worry about ensuring your Ajax requests are synchronous, binding event listeners, or updating the DOM. 12 | -------------------------------------------------------------------------------- /docs/less/bootstrap/alerts.less: -------------------------------------------------------------------------------- 1 | // 2 | // Alerts 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base styles 7 | // ------------------------- 8 | 9 | .alert { 10 | padding: @alert-padding; 11 | margin-bottom: @line-height-computed; 12 | border: 1px solid transparent; 13 | border-radius: @alert-border-radius; 14 | 15 | // Headings for larger alerts 16 | h4 { 17 | margin-top: 0; 18 | // Specified for the h4 to prevent conflicts of changing @headings-color 19 | color: inherit; 20 | } 21 | // Provide class for links that match alerts 22 | .alert-link { 23 | font-weight: @alert-link-font-weight; 24 | } 25 | 26 | // Improve alignment and spacing of inner content 27 | > p, 28 | > ul { 29 | margin-bottom: 0; 30 | } 31 | > p + p { 32 | margin-top: 5px; 33 | } 34 | } 35 | 36 | // Dismissible alerts 37 | // 38 | // Expand the right padding and account for the close button's positioning. 39 | 40 | .alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0. 41 | .alert-dismissible { 42 | padding-right: (@alert-padding + 20); 43 | 44 | // Adjust close link position 45 | .close { 46 | position: relative; 47 | top: -2px; 48 | right: -21px; 49 | color: inherit; 50 | } 51 | } 52 | 53 | // Alternate styles 54 | // 55 | // Generate contextual modifier classes for colorizing the alert. 56 | 57 | .alert-success { 58 | .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text); 59 | } 60 | .alert-info { 61 | .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text); 62 | } 63 | .alert-warning { 64 | .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text); 65 | } 66 | .alert-danger { 67 | .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text); 68 | } 69 | -------------------------------------------------------------------------------- /docs/less/bootstrap/badges.less: -------------------------------------------------------------------------------- 1 | // 2 | // Badges 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base class 7 | .badge { 8 | display: inline-block; 9 | min-width: 10px; 10 | padding: 3px 7px; 11 | font-size: @font-size-small; 12 | font-weight: @badge-font-weight; 13 | color: @badge-color; 14 | line-height: @badge-line-height; 15 | vertical-align: baseline; 16 | white-space: nowrap; 17 | text-align: center; 18 | background-color: @badge-bg; 19 | border-radius: @badge-border-radius; 20 | 21 | // Empty badges collapse automatically (not available in IE8) 22 | &:empty { 23 | display: none; 24 | } 25 | 26 | // Quick fix for badges in buttons 27 | .btn & { 28 | position: relative; 29 | top: -1px; 30 | } 31 | .btn-xs & { 32 | top: 0; 33 | padding: 1px 5px; 34 | } 35 | 36 | // Hover state, but only for links 37 | a& { 38 | &:hover, 39 | &:focus { 40 | color: @badge-link-hover-color; 41 | text-decoration: none; 42 | cursor: pointer; 43 | } 44 | } 45 | 46 | // Account for badges in navs 47 | a.list-group-item.active > &, 48 | .nav-pills > .active > a > & { 49 | color: @badge-active-color; 50 | background-color: @badge-active-bg; 51 | } 52 | .nav-pills > li > a > & { 53 | margin-left: 3px; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /docs/less/bootstrap/bootstrap.less: -------------------------------------------------------------------------------- 1 | // Core variables and mixins 2 | @import "variables"; 3 | @import "mixins"; 4 | 5 | // Reset and dependencies 6 | @import "normalize"; 7 | @import "print"; 8 | @import "glyphicons"; 9 | 10 | // Core CSS 11 | @import "scaffolding"; 12 | @import "type"; 13 | @import "code"; 14 | @import "grid"; 15 | @import "tables"; 16 | @import "forms"; 17 | @import "buttons"; 18 | 19 | // Components 20 | @import "component-animations"; 21 | @import "dropdowns"; 22 | @import "button-groups"; 23 | @import "input-groups"; 24 | @import "navs"; 25 | @import "navbar"; 26 | @import "breadcrumbs"; 27 | @import "pagination"; 28 | @import "pager"; 29 | @import "labels"; 30 | @import "badges"; 31 | @import "jumbotron"; 32 | @import "thumbnails"; 33 | @import "alerts"; 34 | @import "progress-bars"; 35 | @import "media"; 36 | @import "list-group"; 37 | @import "panels"; 38 | @import "responsive-embed"; 39 | @import "wells"; 40 | @import "close"; 41 | 42 | // Components w/ JavaScript 43 | @import "modals"; 44 | @import "tooltip"; 45 | @import "popovers"; 46 | @import "carousel"; 47 | 48 | // Utility classes 49 | @import "utilities"; 50 | @import "responsive-utilities"; 51 | -------------------------------------------------------------------------------- /docs/less/bootstrap/breadcrumbs.less: -------------------------------------------------------------------------------- 1 | // 2 | // Breadcrumbs 3 | // -------------------------------------------------- 4 | 5 | 6 | .breadcrumb { 7 | padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal; 8 | margin-bottom: @line-height-computed; 9 | list-style: none; 10 | background-color: @breadcrumb-bg; 11 | border-radius: @border-radius-base; 12 | 13 | > li { 14 | display: inline-block; 15 | 16 | + li:before { 17 | content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space 18 | padding: 0 5px; 19 | color: @breadcrumb-color; 20 | } 21 | } 22 | 23 | > .active { 24 | color: @breadcrumb-active-color; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /docs/less/bootstrap/buttons.less: -------------------------------------------------------------------------------- 1 | // 2 | // Buttons 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base styles 7 | // -------------------------------------------------- 8 | 9 | .btn { 10 | display: inline-block; 11 | margin-bottom: 0; // For input.btn 12 | font-weight: @btn-font-weight; 13 | text-align: center; 14 | vertical-align: middle; 15 | cursor: pointer; 16 | background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 17 | border: 1px solid transparent; 18 | white-space: nowrap; 19 | .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base); 20 | .user-select(none); 21 | 22 | &, 23 | &:active, 24 | &.active { 25 | &:focus { 26 | .tab-focus(); 27 | } 28 | } 29 | 30 | &:hover, 31 | &:focus { 32 | color: @btn-default-color; 33 | text-decoration: none; 34 | } 35 | 36 | &:active, 37 | &.active { 38 | outline: 0; 39 | background-image: none; 40 | .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); 41 | } 42 | 43 | &.disabled, 44 | &[disabled], 45 | fieldset[disabled] & { 46 | cursor: not-allowed; 47 | pointer-events: none; // Future-proof disabling of clicks 48 | .opacity(.65); 49 | .box-shadow(none); 50 | } 51 | } 52 | 53 | 54 | // Alternate buttons 55 | // -------------------------------------------------- 56 | 57 | .btn-default { 58 | .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border); 59 | } 60 | .btn-primary { 61 | .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border); 62 | } 63 | // Success appears as green 64 | .btn-success { 65 | .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border); 66 | } 67 | // Info appears as blue-green 68 | .btn-info { 69 | .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border); 70 | } 71 | // Warning appears as orange 72 | .btn-warning { 73 | .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border); 74 | } 75 | // Danger and error appear as red 76 | .btn-danger { 77 | .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border); 78 | } 79 | 80 | 81 | // Link buttons 82 | // ------------------------- 83 | 84 | // Make a button look and behave like a link 85 | .btn-link { 86 | color: @link-color; 87 | font-weight: normal; 88 | cursor: pointer; 89 | border-radius: 0; 90 | 91 | &, 92 | &:active, 93 | &[disabled], 94 | fieldset[disabled] & { 95 | background-color: transparent; 96 | .box-shadow(none); 97 | } 98 | &, 99 | &:hover, 100 | &:focus, 101 | &:active { 102 | border-color: transparent; 103 | } 104 | &:hover, 105 | &:focus { 106 | color: @link-hover-color; 107 | text-decoration: underline; 108 | background-color: transparent; 109 | } 110 | &[disabled], 111 | fieldset[disabled] & { 112 | &:hover, 113 | &:focus { 114 | color: @btn-link-disabled-color; 115 | text-decoration: none; 116 | } 117 | } 118 | } 119 | 120 | 121 | // Button Sizes 122 | // -------------------------------------------------- 123 | 124 | .btn-lg { 125 | // line-height: ensure even-numbered height of button next to large input 126 | .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large); 127 | } 128 | .btn-sm { 129 | // line-height: ensure proper height of button next to small input 130 | .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small); 131 | } 132 | .btn-xs { 133 | .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small); 134 | } 135 | 136 | 137 | // Block button 138 | // -------------------------------------------------- 139 | 140 | .btn-block { 141 | display: block; 142 | width: 100%; 143 | } 144 | 145 | // Vertically space out multiple block buttons 146 | .btn-block + .btn-block { 147 | margin-top: 5px; 148 | } 149 | 150 | // Specificity overrides 151 | input[type="submit"], 152 | input[type="reset"], 153 | input[type="button"] { 154 | &.btn-block { 155 | width: 100%; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /docs/less/bootstrap/close.less: -------------------------------------------------------------------------------- 1 | // 2 | // Close icons 3 | // -------------------------------------------------- 4 | 5 | 6 | .close { 7 | float: right; 8 | font-size: (@font-size-base * 1.5); 9 | font-weight: @close-font-weight; 10 | line-height: 1; 11 | color: @close-color; 12 | text-shadow: @close-text-shadow; 13 | .opacity(.2); 14 | 15 | &:hover, 16 | &:focus { 17 | color: @close-color; 18 | text-decoration: none; 19 | cursor: pointer; 20 | .opacity(.5); 21 | } 22 | 23 | // Additional properties for button version 24 | // iOS requires the button element instead of an anchor tag. 25 | // If you want the anchor version, it requires `href="#"`. 26 | button& { 27 | padding: 0; 28 | cursor: pointer; 29 | background: transparent; 30 | border: 0; 31 | -webkit-appearance: none; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /docs/less/bootstrap/code.less: -------------------------------------------------------------------------------- 1 | // 2 | // Code (inline and block) 3 | // -------------------------------------------------- 4 | 5 | 6 | // Inline and block code styles 7 | code, 8 | kbd, 9 | pre, 10 | samp { 11 | font-family: @font-family-monospace; 12 | } 13 | 14 | // Inline code 15 | code { 16 | padding: 2px 4px; 17 | font-size: 90%; 18 | color: @code-color; 19 | background-color: @code-bg; 20 | border-radius: @border-radius-base; 21 | } 22 | 23 | // User input typically entered via keyboard 24 | kbd { 25 | padding: 2px 4px; 26 | font-size: 90%; 27 | color: @kbd-color; 28 | background-color: @kbd-bg; 29 | border-radius: @border-radius-small; 30 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); 31 | 32 | kbd { 33 | padding: 0; 34 | font-size: 100%; 35 | box-shadow: none; 36 | } 37 | } 38 | 39 | // Blocks of code 40 | pre { 41 | display: block; 42 | padding: ((@line-height-computed - 1) / 2); 43 | margin: 0 0 (@line-height-computed / 2); 44 | font-size: (@font-size-base - 1); // 14px to 13px 45 | line-height: @line-height-base; 46 | word-break: break-all; 47 | word-wrap: break-word; 48 | color: @pre-color; 49 | background-color: @pre-bg; 50 | border: 1px solid @pre-border-color; 51 | border-radius: @border-radius-base; 52 | 53 | // Account for some code outputs that place code tags in pre tags 54 | code { 55 | padding: 0; 56 | font-size: inherit; 57 | color: inherit; 58 | white-space: pre-wrap; 59 | background-color: transparent; 60 | border-radius: 0; 61 | } 62 | } 63 | 64 | // Enable scrollable blocks of code 65 | .pre-scrollable { 66 | max-height: @pre-scrollable-max-height; 67 | overflow-y: scroll; 68 | } 69 | -------------------------------------------------------------------------------- /docs/less/bootstrap/component-animations.less: -------------------------------------------------------------------------------- 1 | // 2 | // Component animations 3 | // -------------------------------------------------- 4 | 5 | // Heads up! 6 | // 7 | // We don't use the `.opacity()` mixin here since it causes a bug with text 8 | // fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552. 9 | 10 | .fade { 11 | opacity: 0; 12 | .transition(opacity .15s linear); 13 | &.in { 14 | opacity: 1; 15 | } 16 | } 17 | 18 | .collapse { 19 | display: none; 20 | 21 | &.in { display: block; } 22 | tr&.in { display: table-row; } 23 | tbody&.in { display: table-row-group; } 24 | } 25 | 26 | .collapsing { 27 | position: relative; 28 | height: 0; 29 | overflow: hidden; 30 | .transition(height .35s ease); 31 | } 32 | -------------------------------------------------------------------------------- /docs/less/bootstrap/grid.less: -------------------------------------------------------------------------------- 1 | // 2 | // Grid system 3 | // -------------------------------------------------- 4 | 5 | 6 | // Container widths 7 | // 8 | // Set the container width, and override it for fixed navbars in media queries. 9 | 10 | .container { 11 | .container-fixed(); 12 | 13 | @media (min-width: @screen-sm-min) { 14 | width: @container-sm; 15 | } 16 | @media (min-width: @screen-md-min) { 17 | width: @container-md; 18 | } 19 | @media (min-width: @screen-lg-min) { 20 | width: @container-lg; 21 | } 22 | } 23 | 24 | 25 | // Fluid container 26 | // 27 | // Utilizes the mixin meant for fixed width containers, but without any defined 28 | // width for fluid, full width layouts. 29 | 30 | .container-fluid { 31 | .container-fixed(); 32 | } 33 | 34 | 35 | // Row 36 | // 37 | // Rows contain and clear the floats of your columns. 38 | 39 | .row { 40 | .make-row(); 41 | } 42 | 43 | 44 | // Columns 45 | // 46 | // Common styles for small and large grid columns 47 | 48 | .make-grid-columns(); 49 | 50 | 51 | // Extra small grid 52 | // 53 | // Columns, offsets, pushes, and pulls for extra small devices like 54 | // smartphones. 55 | 56 | .make-grid(xs); 57 | 58 | 59 | // Small grid 60 | // 61 | // Columns, offsets, pushes, and pulls for the small device range, from phones 62 | // to tablets. 63 | 64 | @media (min-width: @screen-sm-min) { 65 | .make-grid(sm); 66 | } 67 | 68 | 69 | // Medium grid 70 | // 71 | // Columns, offsets, pushes, and pulls for the desktop device range. 72 | 73 | @media (min-width: @screen-md-min) { 74 | .make-grid(md); 75 | } 76 | 77 | 78 | // Large grid 79 | // 80 | // Columns, offsets, pushes, and pulls for the large desktop device range. 81 | 82 | @media (min-width: @screen-lg-min) { 83 | .make-grid(lg); 84 | } 85 | -------------------------------------------------------------------------------- /docs/less/bootstrap/input-groups.less: -------------------------------------------------------------------------------- 1 | // 2 | // Input groups 3 | // -------------------------------------------------- 4 | 5 | // Base styles 6 | // ------------------------- 7 | .input-group { 8 | position: relative; // For dropdowns 9 | display: table; 10 | border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table 11 | 12 | // Undo padding and float of grid classes 13 | &[class*="col-"] { 14 | float: none; 15 | padding-left: 0; 16 | padding-right: 0; 17 | } 18 | 19 | .form-control { 20 | // Ensure that the input is always above the *appended* addon button for 21 | // proper border colors. 22 | position: relative; 23 | z-index: 2; 24 | 25 | // IE9 fubars the placeholder attribute in text inputs and the arrows on 26 | // select elements in input groups. To fix it, we float the input. Details: 27 | // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855 28 | float: left; 29 | 30 | width: 100%; 31 | margin-bottom: 0; 32 | } 33 | } 34 | 35 | // Sizing options 36 | // 37 | // Remix the default form control sizing classes into new ones for easier 38 | // manipulation. 39 | 40 | .input-group-lg > .form-control, 41 | .input-group-lg > .input-group-addon, 42 | .input-group-lg > .input-group-btn > .btn { 43 | .input-lg(); 44 | } 45 | .input-group-sm > .form-control, 46 | .input-group-sm > .input-group-addon, 47 | .input-group-sm > .input-group-btn > .btn { 48 | .input-sm(); 49 | } 50 | 51 | 52 | // Display as table-cell 53 | // ------------------------- 54 | .input-group-addon, 55 | .input-group-btn, 56 | .input-group .form-control { 57 | display: table-cell; 58 | 59 | &:not(:first-child):not(:last-child) { 60 | border-radius: 0; 61 | } 62 | } 63 | // Addon and addon wrapper for buttons 64 | .input-group-addon, 65 | .input-group-btn { 66 | width: 1%; 67 | white-space: nowrap; 68 | vertical-align: middle; // Match the inputs 69 | } 70 | 71 | // Text input groups 72 | // ------------------------- 73 | .input-group-addon { 74 | padding: @padding-base-vertical @padding-base-horizontal; 75 | font-size: @font-size-base; 76 | font-weight: normal; 77 | line-height: 1; 78 | color: @input-color; 79 | text-align: center; 80 | background-color: @input-group-addon-bg; 81 | border: 1px solid @input-group-addon-border-color; 82 | border-radius: @border-radius-base; 83 | 84 | // Sizing 85 | &.input-sm { 86 | padding: @padding-small-vertical @padding-small-horizontal; 87 | font-size: @font-size-small; 88 | border-radius: @border-radius-small; 89 | } 90 | &.input-lg { 91 | padding: @padding-large-vertical @padding-large-horizontal; 92 | font-size: @font-size-large; 93 | border-radius: @border-radius-large; 94 | } 95 | 96 | // Nuke default margins from checkboxes and radios to vertically center within. 97 | input[type="radio"], 98 | input[type="checkbox"] { 99 | margin-top: 0; 100 | } 101 | } 102 | 103 | // Reset rounded corners 104 | .input-group .form-control:first-child, 105 | .input-group-addon:first-child, 106 | .input-group-btn:first-child > .btn, 107 | .input-group-btn:first-child > .btn-group > .btn, 108 | .input-group-btn:first-child > .dropdown-toggle, 109 | .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), 110 | .input-group-btn:last-child > .btn-group:not(:last-child) > .btn { 111 | .border-right-radius(0); 112 | } 113 | .input-group-addon:first-child { 114 | border-right: 0; 115 | } 116 | .input-group .form-control:last-child, 117 | .input-group-addon:last-child, 118 | .input-group-btn:last-child > .btn, 119 | .input-group-btn:last-child > .btn-group > .btn, 120 | .input-group-btn:last-child > .dropdown-toggle, 121 | .input-group-btn:first-child > .btn:not(:first-child), 122 | .input-group-btn:first-child > .btn-group:not(:first-child) > .btn { 123 | .border-left-radius(0); 124 | } 125 | .input-group-addon:last-child { 126 | border-left: 0; 127 | } 128 | 129 | // Button input groups 130 | // ------------------------- 131 | .input-group-btn { 132 | position: relative; 133 | // Jankily prevent input button groups from wrapping with `white-space` and 134 | // `font-size` in combination with `inline-block` on buttons. 135 | font-size: 0; 136 | white-space: nowrap; 137 | 138 | // Negative margin for spacing, position for bringing hovered/focused/actived 139 | // element above the siblings. 140 | > .btn { 141 | position: relative; 142 | + .btn { 143 | margin-left: -1px; 144 | } 145 | // Bring the "active" button to the front 146 | &:hover, 147 | &:focus, 148 | &:active { 149 | z-index: 2; 150 | } 151 | } 152 | 153 | // Negative margin to only have a 1px border between the two 154 | &:first-child { 155 | > .btn, 156 | > .btn-group { 157 | margin-right: -1px; 158 | } 159 | } 160 | &:last-child { 161 | > .btn, 162 | > .btn-group { 163 | margin-left: -1px; 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /docs/less/bootstrap/jumbotron.less: -------------------------------------------------------------------------------- 1 | // 2 | // Jumbotron 3 | // -------------------------------------------------- 4 | 5 | 6 | .jumbotron { 7 | padding: @jumbotron-padding; 8 | margin-bottom: @jumbotron-padding; 9 | color: @jumbotron-color; 10 | background-color: @jumbotron-bg; 11 | 12 | h1, 13 | .h1 { 14 | color: @jumbotron-heading-color; 15 | } 16 | p { 17 | margin-bottom: (@jumbotron-padding / 2); 18 | font-size: @jumbotron-font-size; 19 | font-weight: 200; 20 | } 21 | 22 | > hr { 23 | border-top-color: darken(@jumbotron-bg, 10%); 24 | } 25 | 26 | .container & { 27 | border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container 28 | } 29 | 30 | .container { 31 | max-width: 100%; 32 | } 33 | 34 | @media screen and (min-width: @screen-sm-min) { 35 | padding-top: (@jumbotron-padding * 1.6); 36 | padding-bottom: (@jumbotron-padding * 1.6); 37 | 38 | .container & { 39 | padding-left: (@jumbotron-padding * 2); 40 | padding-right: (@jumbotron-padding * 2); 41 | } 42 | 43 | h1, 44 | .h1 { 45 | font-size: (@font-size-base * 4.5); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /docs/less/bootstrap/labels.less: -------------------------------------------------------------------------------- 1 | // 2 | // Labels 3 | // -------------------------------------------------- 4 | 5 | .label { 6 | display: inline; 7 | padding: .2em .6em .3em; 8 | font-size: 75%; 9 | font-weight: bold; 10 | line-height: 1; 11 | color: @label-color; 12 | text-align: center; 13 | white-space: nowrap; 14 | vertical-align: baseline; 15 | border-radius: .25em; 16 | 17 | // Add hover effects, but only for links 18 | a& { 19 | &:hover, 20 | &:focus { 21 | color: @label-link-hover-color; 22 | text-decoration: none; 23 | cursor: pointer; 24 | } 25 | } 26 | 27 | // Empty labels collapse automatically (not available in IE8) 28 | &:empty { 29 | display: none; 30 | } 31 | 32 | // Quick fix for labels in buttons 33 | .btn & { 34 | position: relative; 35 | top: -1px; 36 | } 37 | } 38 | 39 | // Colors 40 | // Contextual variations (linked labels get darker on :hover) 41 | 42 | .label-default { 43 | .label-variant(@label-default-bg); 44 | } 45 | 46 | .label-primary { 47 | .label-variant(@label-primary-bg); 48 | } 49 | 50 | .label-success { 51 | .label-variant(@label-success-bg); 52 | } 53 | 54 | .label-info { 55 | .label-variant(@label-info-bg); 56 | } 57 | 58 | .label-warning { 59 | .label-variant(@label-warning-bg); 60 | } 61 | 62 | .label-danger { 63 | .label-variant(@label-danger-bg); 64 | } 65 | -------------------------------------------------------------------------------- /docs/less/bootstrap/list-group.less: -------------------------------------------------------------------------------- 1 | // 2 | // List groups 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base class 7 | // 8 | // Easily usable on