PageSourceSearch

https://intern.katholikentag.de/wilma/static/public/shop/js/cart.js

js katholikentag.de collected 2026-09-26 03:59:39 UTC 13,174 bytes, 349 lines download raw bytes

1/*
2 * FRED SHOP
3 * (C) Copyright 2016 eGenius oHG (http://www.egenius.de) and others.
4 */
5
6var app = app || {};
7var _paq = _paq || [];
8
9Handlebars.registerHelper('t', function (i18n_key) {
10    var result = i18n.t(i18n_key);
11
12    return new Handlebars.SafeString(result);
13});
14
15Handlebars.registerHelper('eur', function (amount) {
16    var result = accounting.formatMoney(amount);
17
18    return new Handlebars.SafeString(result);
19});
20
21// Settings object that controls default parameters for library methods:
22accounting.settings = {
23    currency: {
24        symbol: "€", // default currency symbol is '$'
25        format: "%v %s", // controls output: %s = symbol, %v = value/number (can be object: see below)
26        decimal: ",", // decimal point separator
27        thousand: ".", // thousands separator
28        precision: 2   // decimal places
29    },
30    number: {
31        precision: 0, // default precision on numbers is 0
32        thousand: ".",
33        decimal: ","
34    }
35};
36
37app.Item = Backbone.Model.extend({
38    product: null,
39    itemId: null,
40    quantity: 0,
41    option: null,
42    itemGross: 0,
43    lineGross: 0,
44    
45    initialize: function() {
46        _.bindAll(this, "getItemGross");
47        _.bindAll(this, "getLineGross");
48        
49        this.on("change:product", function(model, product) { 
50            model.cid = product.id;
51            model.itemId = product.id;
52            model.product = product;
53            model.trigger("calculate",model);
54        });
55        this.on("change:option", function(model, option) { 
56            if (option) {
57                model.cid = model.product.id+"|"+option.optionId;
58                model.itemId = option.optionId;
59                model.option = option;
60            }
61            model.trigger("calculate",model);
62        });
63        this.on("change:quantity", function(model, quantity) { 
64            model.quantity = quantity;
65            model.trigger("calculate",model);
66        });
67        this.on("calculate", function(model) {
68            model.itemGross = model.getItemGross();
69            model.lineGross = model.getLineGross();
70        });
71    },
72    
73    getItemGross: function() {
74        var result = parseFloat(this.product.get("priceGross"));
75        
76        var item = this;        
77        $.each(this.product.get("productScalePriceList"), function(index,scale) {
78            if (item.quantity >= scale.quantity) {
79                result = scale.priceGross;
80            }
81        });
82        
83        return result;
84    },
85    
86    getLineGross: function() {
87        return this.quantity * this.getItemGross();
88    }
89});
90
91app.ShoppingCart = Backbone.Collection.extend({
92    model: app.Item,
93    storageKeyCart: PebblesConfig.storageKeyCart,
94    storageKeyFredItems: PebblesConfig.storageKeyFredItems,
95    totalGross: 0,
96    shippingCosts: 0,
97    subTotal: 0,
98    trackChanges: false,
99    
100    initialize: function() {        
101        _.bindAll(this, "addFromNode");
102        _.bindAll(this, "addItem");
103        _.bindAll(this, "setItemQuantity");
104        _.bindAll(this, "getTotalGross");
105        _.bindAll(this, "fredItems");
106        _.bindAll(this, "checkout");
107        
108        this.on("reset", function(collection, options) { 
109            collection.totalGross = 0;
110            collection.shippingCosts = 0;
111            collection.subTotal = 0;
112            
113            collection.sync("delete");
114            collection.trigger("render");
115        });
116        
117        this.on("update", function(collection, options) {             
118            collection.sync("update");
119            collection.totalGross = collection.getTotalGross();
120            collection.shippingCosts = (collection.totalGross >= PebblesConfig.freeShippingFromRevenue) ? 0 : collection.getShippingCosts();
121            collection.subTotal = collection.totalGross + collection.shippingCosts;
122            
123            if (collection.trackChanges) collection.tracking();
124            collection.trigger("render");
125        });        
126        
127        // Assign the Deferred issued by fetch() as a property
128        this.deferred = this.fetch(); // calls overridden sync()        
129    },
130    
131    addFromNode: function(button) {
132        var scope = button.closest(".product");
133        var productId = scope.find(".item_id").html();
134        
135        var form = scope.find("form")[0];        
136        if (!form.reportValidity()) return;
137
138        var quantity = parseInt(scope.find(".item_quantity").val());
139        var opt = scope.find(".item_option").val();
140        var option = (typeof(opt)==="undefined") ? null : JSON.parse(opt);
141
142        if (PebblesConfig.checkItemsOnStock) {
143            app.catalog.fetchProductData(productId).done(function (apiResponse) {
144                var product = (apiResponse && apiResponse.productList) ? apiResponse.productList[0] : null;
145                if (option) {
146                    product = product.productOptionList.find(function(optionEntry) {
147                        return optionEntry.productId === option.optionId;
148                    });
149                }
150                var key = productId + ( (option) ? "|" + option.optionId : "" );                
151                var item = app.cart.get(key);
152
153                var requiredQuantity = quantity + ( (item) ? item.quantity : 0 );
154                if (requiredQuantity > product.itemsOnStock) {
155                    var msgOutOfStock = PebblesConfig.messages.ShopProductOutOfStock.replace("{itemsOnStock}", product.itemsOnStock);
156                    scope.find(".product_detail_outofstock").show().find("div").html( msgOutOfStock );    
157                } else {
158                    scope.find(".product_detail_outofstock").hide().find("div").html( "" );
159                    app.cart.addItem(productId, quantity, option);
160                }
161            });
162        } else {
163            this.addItem(productId, quantity, option);
164        }
165    },
166
167    addItem: function(productId, quantity, option) {
168        if (typeof(option) === "undefined") option = null;       
169        var key = productId + ( (option) ? "|" + option.optionId : "" );                
170        var item = this.get(key);
171        if (item) {
172            item.set("quantity", item.quantity+quantity);            
173            if (item.quantity <= 0) this.remove(item);
174        } else {
175            item = new app.Item();
176            var product = app.catalog.products.get( productId );
177            if (typeof(product) === "undefined") {
178                this.remove(item);
179            } else {
180                item.set("product", app.catalog.products.get( productId ));
181                item.set("option", option);
182                item.set("quantity", quantity);
183                
184                this.add(item);    
185            }
186        }
187        
188        this.trigger("update",this);
189    },
190    
191    setItemQuantity: function(productId, quantity, option) {
192        if (typeof(option) === "undefined") option = null;        
193        var key = productId + ( (option) ? "|" + option.optionId : "" );                
194        var item = this.get(key);
195        if (item) {  
196            item.set("quantity", quantity);
197        }
198        
199        this.trigger("update",this);
200    },
201    
202    getItemQuantitySum: function() {
203        return this.reduce(function(memo, item) { 
204                return memo + item.quantity; 
205        }, 0);
206    },
207    
208    getTotalGross: function() {
209        return this.reduce(function(memo, item) { 
210                return memo + item.lineGross; 
211        }, 0);
212    },
213    
214    getShippingCosts: function() {
215        return this.reduce(function(memo, item) { 
216                var shippingCosts = parseFloat(item.product.get("shippingCosts"));
217                return (shippingCosts>memo) ? shippingCosts : memo; 
218        }, 0);
219    },
220    
221    tracking: function() {
222        if (PebblesConfig.trackingImplementation=="piwik") {
223            this.each(function(item) {
224                _paq.push(['addEcommerceItem',
225                    item.product.id, // (required) SKU: Product unique identifier
226                    item.product.get("productName") + ( (item.option) ? (" - "+item.option.optionAttribute+": "+item.option.optionValue) :"") , // (optional) Product name
227                    [], // (optional) Product category, string or array of up to 5 categories
228                    item.quantity, // (recommended) Product price
229                    item.get("itemGross") // (optional, default to 1) Product quantity
230                ]);            
231            });
232            
233            _paq.push(['trackEcommerceCartUpdate',app.cart.getTotalGross()]); // (required) Cart amount       
234            _paq.push(["setDocumentTitle", "Shop: Cart Update"]);    
235            _paq.push(['trackPageView']); 
236        }
237    },
238    
239    fredItems: function() {
240        return this.map(function(item) { 
241            return {
242                isOption: (item.option!==null),
243                productId: item.itemId,
244                quantity: item.quantity
245            };
246        });
247    },
248    
249    sync: function(method, model, options) {
250        var shoppingCart = this;
251        var defer = $.Deferred();
252        
253        if ( (method === "create") || (method === "update") ) {
254            
255            var cartData = new Array();        
256            this.each(function(model) {
257               var item = {
258                   productId    : model.product.id,
259                   quantity     : model.quantity,
260                   option       : model.option
261               };           
262               cartData.push(item);       
263            });        
264            PebblesConfig.storage.setItem(this.storageKeyCart, JSON.stringify(cartData));
265            PebblesConfig.storage.setItem(this.storageKeyFredItems, JSON.stringify(this.fredItems()));
266        } else if (method === "delete") {
267            PebblesConfig.storage.removeItem(this.storageKeyCart);
268        } else {
269            var storedCart = PebblesConfig.storage.getItem(shoppingCart.storageKeyCart);
270            if (storedCart) {
271                var cartData = JSON.parse(storedCart);
272                $.each(cartData, function(index, value) {
273                    shoppingCart.addItem(value.productId, value.quantity, value.option);                    
274                });
275            }
276            this.trackChanges = true;
277        }
278        
279        defer.resolve();
280        return defer.promise();
281    },
282    
283    checkout: function() {
284        var form = $("<form style='display:block'></form>").appendTo("body");
285        form.attr('action', PebblesConfig.checkoutUrl);
286        form.attr('method', "POST");
287
288        // add items to data                   
289        fredItems = JSON.stringify( this.fredItems() );
290        form.append($("<input>
290").attr("type","hidden").attr("name","items").val(fredItems));
291
292        if (PebblesConfig.accessToken) {
293            form.append($("<input>").attr("type","hidden").attr("name","accessToken").val(PebblesConfig.accessToken));
294            form.append($("<input>").attr("type","hidden").attr("name","entryId").val(PebblesConfig.entryId));
295        }
296
297        form.submit();
298
299        form.remove();
300    }
301});
302
303/*******************************************************************
304 *	CART VIEW
305 *******************************************************************/
306 app.ShoppingCartView = Backbone.View.extend({  
307    btnTemplate: Handlebars.compile($("#btnShoppingCartTemplate").html()),
308    itemsTemplate: Handlebars.compile($("#itemsShoppingCartTemplate").html()),
309    timeout: null,
310    initialize: function(){
311        this.btnEl = $("#btnShoppingCart");
312        this.itemsEl = $("#cart_items");
313        this.collection.on("render", this.render, this);
314    },      
315    render: function () {
316        if (PebblesConfig.disableCart) {
317            console.debug("shopping cart disabled - skipping renderinng");
318            $(".productBasketStickyWrap").hide();
319            return;
320        }
321
322        console.debug("shopping cart render");
323
324        var view = this;
325
326        view.collection.deferred.then(function () {
327            var templateData = {
328                items: view.collection.toArray(),
329                totalGross: view.collection.totalGross,
330                freeShippingFromRevenue: PebblesConfig.freeShippingFromRevenue,
331                noFreeShipping: PebblesConfig.noFreeShipping,
332                shippingCosts: view.collection.shippingCosts,
333                subTotal: view.collection.subTotal,
334                itemQuantitySum: view.collection.getItemQuantitySum()
335            };
336
337            var btnRendered = view.btnTemplate(templateData);
338            view.btnEl.html(btnRendered);
339
340            var itemsRendered = view.itemsTemplate(templateData);
341            view.itemsEl.html(itemsRendered);
342
343            // view.items = $("#cart_items");            
344        });
345
346        return view;
347    }
348});
349

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.