discolabs / cartjs Goto Github PK
View Code? Open in Web Editor NEWA Javascript library to power cart management for Shopify themes.
Home Page: https://cartjs.org
License: MIT License
A Javascript library to power cart management for Shopify themes.
Home Page: https://cartjs.org
License: MIT License
Could be done simply through the use of a data-cart-quantity
and data-cart-*
attributes.
Hi again (sorry for all the problems :'(),
I'm trying to integrate myself shipping estimator until it is done natively. I'm trying to use native Rivets code for that. But I fail to make Rivets work.
In my code, I've reproduce a small use case (my code is included AFTER CartJS + Rivets):
<table id="my-table">
<tr rv-each-row="rows">
<td rv-text="row.name"></td>
</tr>
</table>
Then in my JS code:
$table = $("#my-table");
var state = {};
state.rows = [];
rivets.bind($table, state);
state.rows.push({name: "bar"});
state.rows.push({name: "bar"});
state.rows.push({name: "bar"});
I expect it to display bar three times. However that's not the case. It displays nothing.
Interestingly, if I replace "rivets-cart.min.js" by "rivets+sigthlass 0.8.1" (found in Rivets website), then "cart.min.js"... the pure Rivets part work correctly (so it displays three bars)... but in turn the CartJS displayed items does not work.
What am I doing wrong?
Thansk!
Allow the updating of existing line items with a data-cart-update
attribute.
Using Prism or equivalent highlighter (something compatible with the Markdown generate grunt-terraform
uses).
Hi :),
I think I'm having a major bug here. Also, I have a strange result: interpolation works, but using HTML binding never works here (or in strange circumstances).
If I take the example in your home page, the following code:
<tr rv-each-item="cart.items">
<td>
<strong rv-text="item.vendor"></strong>
<ul rv-hide="item.propertyArray | empty">
<li rv-each-property="item.propertyArray < properties" rv-text="property.value"></li>
</ul>
</td>
</tr>
This displays the vendor. However, if I remove the ul:
<tr rv-each-item="cart.items">
<td>
<strong rv-text="item.vendor"></strong>
</td>
</tr>
The vendor does not appear anymore. In my full example, I simply have nothign that appears:
<div class="cart--desktop" data-cart-view="data-cart-view" rv-show="cart.item_count | gt 0">
<div class="table__scroll">
<table>
<thead>
<tr>
<th>{{ 'cart.items.product' | t }}</th>
<th>{{ 'cart.items.price' | t }}</th>
<th>{{ 'cart.items.quantity' | t }}</th>
<th>{{ 'cart.items.subtotal' | t }}</th>
<th></th>
</tr>
</thead>
<tbody>
<tr rv-each-item="cart.items">
<td class="cart-item__product">
<a rv-href="item.url" oncanplay="cart-item__link">
<img class="cart-item__image" rv-src="item.image | productImageSize small">
</a>
<div class="cart-item__info">
<span class="cart-item__brand" rv-text="item.vendor"></span>
<span class="cart-item__title" rv-text="item.product_title"></span>
<span class="cart-item__variant" rv-text="item.variant_title"></span>
</div>
</td>
<td class="cart-item__price" rv-html="item.price | money"></td>
<td class="cart-item__quantity">
{item.quantity}
<div class="quantity__actions">
<a href="#" rv-data-cart-update="index | plus 1" rv-data-cart-quantity="item.quantity | minus 1">
<i class="icon-minus"></i>
</a>
<a href="#" rv-data-cart-update="index | plus 1" rv-data-cart-quantity="item.quantity | plus 1">
<i class="icon-plus"></i>
</a>
</div>
</td>
<td class="cart-item__subtotal"></td>
<td class="cart-item__remove">
<a href="#" rv-data-cart-remove="index | plus 1">
<i class="icon-cross"></i>
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
Replacing everything by interpolation (using {item.vendor} for instance, properly works.
In all cases, the Currency conversion never works. It properly changes the currency symbol, but always return a 0 value.
Thanks :)
Hi,
It should be nice if you could also include this one unminified in the dist folder ;).
Hi !
I've had a customer that was trying to output the weight of the cart, however it seems CartJS does not have any weight formatter to do that.
Bye!
Hi,
One of our customer is using our theme. However, they'd like to be able to use display the product's tags in the cart. But it seems that CartJS do not expose those properties.
Would it be possible to expose the full "product" object (currently, only a subset with "product_id", "product_description", "product_title" and "product_type" are exposed, it would be nice to have a "product" hash with all the properties).
Thanks!
Hi there,
Is it possible to adjust the formatMoney filter to display item price without without the decimal and cents? For example, just like what this Liquid filter would output:
Liquid
${{ product.price | money_without_currency | remove: '.00' }}
Result
$140
Thanks!
People are doing some really great things with Cart.js, so it would be great to showcase their sites on cartjs.org. This issue can serve as a way for anyone using Cart.js to let us know they'd like to be considered for inclusion on the site.
Currently, I know of (and have received permission to list):
Looks like when a checkbox with data-cart-toggle
is being un-checked, the function called is CartJS.Core.removeAll(id)
which doesn't exist. Should it be CartJS.Core.removeItemById(id)
instead? https://github.com/discolabs/cartjs/blob/master/dist/cart.js#L435
For example, using rv-href
to link to products and the productImageSize
filter.
Useful for when trying to add an item with insufficient stock, for example.
Test
Hi :),
First of all thank you for the library, it looks nice!
I've been trying it and I'm having an issue with the currency converison that Shopify recommends (https://docs.shopify.com/manual/configuration/store-customization/currencies-and-translations/currencies/how-to-show-multiple-currencies).
It works perfectly for any span with class money, but for things rendered by CartJS those are not converted. I'm suspected that the issue is that when the Shopify script run to convert elements, Rivets has not yet rendered its stuff, hence doesn ot converting the values.
Did you have the occasion to play with that?
Thansk!
Hi again,
Sorry for pinging you again. I'm still trying to integrate animation. So here is my try: when clicking on the element, I first toggle the element using jQuery, then I remove the item using CartJS:
removeProduct: function(event) {
var element = $(event.currentTarget),
item = element.closest('.mini-cart__item'),
variantToRemove = item.attr('data-variant');
item.toggle(150, function() {
CartJS.updateItemById(variantToRemove, 0);
});
return false;
}
What happen is the following:
jQuery performs its animation, and set the element as display: none. Then, CartJS remove the element. But it seems that because the lement is hidden, binding does not work correctly, and instead of removing the first one that was hidden, it actually removes the first one and then... add all the classes that was on the first element (display: none), and apply it to the second element (hence making it invisisible).
I'm not sure if this is clear, but the simplest is to try it to understand the issue :).
I can't find a way to switch variant for a product directly in the cart. The idea is : if you want the other one, just update the sku without changing properties but updating price as well.
Hi,
One of our customer just reported an issue: if a product does not have any image, the productImageSize helper fails, and hence nothing is rendered. This is inconsistent with the default Shopify behaviour where it uses their placeholder image instead.
If a quantity
isn't provided to updateItem
(it's undefined
), I guess the quantity should stay as is.
Currently, it's set to 1
.
Hi :),
It seems that the method "removeItemById" is not defined. Actually, if I oepn the inspector even in your demo page, CartJS.removeItemById is undefined method.
Hi,
We are on the verge of releasing our second theme, but during the last step of validation, we were asked that the theme sold on Theme Store must be "usable" without JavaScript.
By usable they mean: you must be able to go to the homepage, selecting a product, adding it to the cart, and going to checkout.
Obviously, the issue is that because the cart is rendered client-side, I had to duplicate all my code, put it inside a "noscript" tag, and display it. This is a bit annoying as I have duplicated code.
I'm not sure if this is possible, but is there any way to actually render using Liquid server side, adding the various attribute, but still being able to take advantage of JS binding? I've tried it but unfortunately I couldn't find any way of doing it :(.
Thanks!
First off, cartjs looks incredibly helpful for creating ajax carts with Shopify. Keep up the great work!
I'd like to use it on my custom bootstrap site, but am not sure how to initialize it properly.
In the cartjs documentation (which is great by the way) it says under configuration to call CartJS.init()
and pass a liquid cart object as JSON. As I'm not using liquid, how can I create a liquid-cart-like JSON object and pass it to cartjs?
The only other related documentation I've found so far that might help is about Adding to cart from a remote website.
Hi - I have been trying to implement cart.js on my shop, and it is looking great so far. Thanks!
Let's say I am trying to generate a mini cart that sits in the header, and I have the following in my theme.liquid file:
<aside id="cart-drawer" data-cart-view="data-cart-view">
<!-- FOR EACH ITEM IN CART -->
<div class="cart-drawer-item" rv-each-item="cart.items">
<div class="cart-drawer-item-image"><a rv-href="item.url" href=""><img rv-src="item.image | productImageSize 'small'" src=""/></a></div>
<div class="cart-drawer-title-price">
<div class="cart-drawer-item-title" rv-text="item.title"></div>
<div class="cart-drawer-item-price" rv-html="item.line_price | money Currency.currentCurrency"> </div>
</div>
</div>
<!-- END FOR EACH ITEM IN CART -->
</aside>
This works perfectly on the product.liquid and index.liquid pages, but for some reason it doesn't seem to be pulling anything on the cart.liquid and collection.liquid pages. It's confusing me: As it's part of theme.liquid, shouldn't it either work on every page or not work at all? Do you have any ideas why this might be? Thanks again!
Hi :),
After a lot of debugging, I still had issue with CartJS not working on IE8/9. The strange thing is that as soon as I opened the developer tools of IE... boom, CartJS was working. I was a bit surprised to say the least, and it appears that this is due to this bug: http://stackoverflow.com/questions/7742781/why-javascript-only-works-after-opening-developer-tools-in-ie-once
I've removed any reference to console.log in my own code, but the last two occurrences are... in CartJS. while it's wrapped and checked existence of console, it seems that the sole existence of console.log in the source code make everything crash.
I already had such crazy issues with IE8, where a variable called "case" would make everything crash, even if it was situated in a code that wasn't called.
I'd therefore suggest that you simply remove any occurrence of that in the production code. Alternatively, adding this small code make the problem disappears completely:
if(!window.console) {
console={};
console.log = function(){};
}
Crazy IE....
I cannot seem to get the money formatting to work with DOM binding. I copied the code exactly as it appears in the demo and cannot get a formatted money string. It does render the correct money value but with no decimals or formatting.
<div data-cart-view="data-cart-view">
<p rv-text="cart.total_price | money"></p>
</div>
The Shopify API allows addition of an ID via Update.js, we were writing the following for the API before we discovered Cartjs (which is great, by the way!).
The Update function here uses Change.js (which will not add a new variant to cart, only modify a variant that is already in the cart) doesn't match that of the Shopify Update.js, so for the sake of clarity, I would suggest adjusting to use Update.js, rename it to changeItemById or just document the fact this will only Change exiting cart items and not add new ones.
Use case:
A client has 4 variants, of which only 1 may be in the cart at one time (they are delivery options/enhancements). I appreciate this is probably a rare occurrence.
Because the updateItemById function uses Change.js the solution with cartjs is to remove all, then add the applicable variant:
CartJS.updateItemById(1118014272, 0); CartJS.updateItemById(1118014280, 0); CartJS.updateItemById(1118014284, 0); CartJS.updateItemById(1118014276, 0); CartJS.addItem(1118014284, 1);
If Cartjs were to use update.js this could be simplified to:
CartJS.updateItemById(1118014272, 0); CartJS.updateItemById(1118014280, 0); CartJS.updateItemById(1118014284, 1); CartJS.updateItemById(1118014276, 0);
It could be further reduced of course by interrogating the cart for the existence of the 'wrong' variant and removing that one, and adding the 'correct' one - but this is so much more straightforward - one of the appeals of Cartjs!
Not sure how much of an impact one less call makes, but thought I'd take the time to mention it. For me it was more the assumption that updateItem matched Update.js functionality. Not likely to be an issue for those that aren't already familiar with the Shopify AJAX API.
Obviously also not a problem for updateItem(); as it refers to cart lines not variant IDs.
Thanks,
Oli
Hi there,
Firstly, just wanted to say thanks so much for putting this great library together and I'm really looking forward to future roll-outs of docs and enhancements!
Here's a question for you:
Essentially, I've broken out how I display product title and it's variants in the cart for UX purposes and would like to not show variants that contain 'Default Title', while testing for variants that contain 'Giftwrap' to show specific messaging…if that makes sense.
Regarding the giftwrap logic, this code block is absolutely bloated:
<div rv-show="item.variant_options.1 | eq 'Wrap'">
<span class="meta">Giftwrap added</span>
</div>
<div rv-show="item.variant_options.0 | eq 'Wrap'">
<span class="meta">Giftwrap added</span>
</div>
And, conversely, I'm at an impasse with not showing a variant if it equates to 'Default Title' because I haven't been able to find any evaluators that work in Rivets to test for "does not equal" or that simply state 'else'.
For example, you'd think this would work:
<div rv-show="item.variant_options.1 | != 'Default Title">
<span class="var" rv-text="item.variant_options.0"></span>
</div>
All that said, I know Rivets.js discourages evaluating logic inside the binding declarations, so I'm curious if there's a better way to go about these 2 tests further upstream. If so, do you have some pointers on how?
I get by, but I'm no javascript ninja, so thanks so much for you help!
L
Look at existing updates[]
structure and use that.
Hi,
This is just a recap of #29 , to follow the process.
Our theme can be bought here in the Theme Store: https://themes.shopify.com/themes/kagami/styles/kyoto
Preset Kyoto: https://kagami-tokyo.myshopify.com
Preset Baptiste: https://kagami-paris.myshopify.com
(I know, URLs don't match preset names, Shopify just forgot to check the uniqueness of it and asked us to modify the preset names after releasing :D)
Developed this a couple months ago, and recently went live :D
Working on our current project, I noticed on inspecting CartJS.cart.items
in the console that each item
had a tags
property - my first assumption was that this was pulling in the line_item's product's tags, but it was empty, even though the product does have tags. I know that a line_item only has limited product/variant properties bundled by Shopify, but I couldn't tell if I was misunderstanding the use of this property, or if it was a bug.
This would probably be a pretty common use case. API would probably use something like data-cart-adjust
.
US version also available at budredlights.com
Hi :),
It would be nice to have a native support for shipping rates around the Shopify shipping rates API.
Thanks!
Would be nice to get some basic coverage going for 0.4, before expanding it in 0.5 and moving to plugins for 0.6.
Currently, only cart.requestStarted
and cart.requestComplete
are supported. Want to make this a little better, like cart.itemAdded
, cart.itemUpdated
, cart.attributeUpdated
et cetera.
Hi,
When developing a theme, you cannot know in advance which properties a product have. As a consequence, this:
CartJS.addItem(12345678, 3, {
"size": "XL"
});
Is not possible because we cannot know that it will have the "size" property. The problem is that jQuery does not have any nice built-in function to extract the data from a form in a way that is easily consumed by CartJS. Here is the boilerplate code I've been doing:
var formData = this.serializeForm(this.element.find('.product__form'));
CartJS.addItem(formData['id'], formData['quantity'], formData['properties'], {});
where serializeForm is as follow:
Plugin.prototype.serializeForm = function(form) {
var hash = {};
function stringKey(key, value) {
var beginBracket = key.lastIndexOf('[');
if (beginBracket == -1) {
var hash = {};
hash[key] = value;
return hash;
}
var newKey = key.substr(0, beginBracket),
newValue = {};
newValue[key.substring(beginBracket + 1, key.length - 1)] = value;
return stringKey(newKey, newValue);
}
var els = form.find(':input').get();
$.each(els, function() {
if (this.name && !this.disabled && (this.checked || /select|textarea/i.test(this.nodeName) || /hidden|text|search|tel|url|email|password|datetime|date|month|week|time|datetime-local|number|range|color/i.test(this.type))) {
var val = $(this).val();
$.extend(true, hash, stringKey(this.name, val));
}
});
return hash;
},
I'm not the author of this complicated code, but basically, it allows to parse the keys (such as "properties[foo]") and returns something like:
{
"id": 123,
"quantity": 1,
"properties": {
"size": "XL",
"other": "foo"
}
}
This boilerplate code is required all the time in themes. Therefore, it would be nice to have a "addItemFromForm" method that would accept any jQuery object representing a form, and do this logic internally.
I'd be happy to contribute for that, I just want to be sure you don't have a better idea for that first ;).
Bye!
I have a very simple button
<button data-cart-add="{{ product.id }}" data-cart-quantity="1">{{ product.title }}</button>
which tries to add an item to the cart but I get an error:
Cannot find variant
The product has no variants so i am a little confused why that would be the case.
Ever had this happen before?
Cart.js v0.3.5
Hi,
I've tried this on IE8 and 9 but it does not seem to work. Do we need special polyfills? I'm not using the dist CartJS, but rather CartJS + Rivets + Sightglass separately.
Thanks a lot ;)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.