Shopping Cart

This example shows how you can use the DataViews calculation engine to reduce coding required for typical needs, such as a Shopping Cart.

This example shows how you can use the DataViews calculation engine to reduce coding required for typical needs, such as a Shopping Cart. This demo simulates the order screen of a book store shopping cart. The product list is a grid view and the total on the right is a calculated field outside the grid. The calculation engine is used to update the subtotal column as well as the Total and Total Savings fields. Try adding items to the cart and see how the fields are updated at the bottom of the grid.
<!DOCTYPE html> <html lang="en"> <head> <base href="/dataviewsjs/demos/en/sample/Showcase/ShoppingCart/purejs/" /> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="keywords" content="calculate, calculation, formula, expression, editing, editor" /> <meta name="description" content="This example shows how you can use the DataViews calculation engine to reduce coding required for typical needs, such as a Shopping Cart." /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Shopping Cart | Showcase | GrapeCity DataViewsJS JavaScript Demos</title> <link href="/dataviewsjs/demos/node_modules/normalize.css/normalize.css" rel="stylesheet" type="text/css" /> <link href="/dataviewsjs/demos/static/css/base.css" rel="stylesheet" type="text/css" /> <link href="/dataviewsjs/demos/static/dataviews/gc.dataviews.core.min.css" rel="stylesheet" type="text/css" /> <link href="/dataviewsjs/demos/static/dataviews/gc.dataviews.grid.min.css" rel="stylesheet" type="text/css" /> <link href="styles.css" rel="stylesheet" type="text/css" /> <!-- Google Tag Manager --> <script> (function (w, d, s, l, i) { w[l] = w[l] || []; w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' }); var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true; j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f); })(window, document, 'script', 'dataLayer', 'GTM-WT462SJ'); </script> <!-- End Google Tag Manager --> <script src="/dataviewsjs/demos/static/js/app-polyfills.min.js" type="text/javascript"></script> <script type="text/javascript"> window.process = { env: { NODE_ENV: 'production', USE_NPM: false, USE_CDN: false, SITE_ROOT: '/dataviewsjs/demos', FRAMEWORK: 'purejs', DVJS_LICENSE_KEY: 'GrapeCity-Internal-Use-Only,GrapeCity,E195393772372914#B0KV4Ny56Vr5Wb7w6buJWeGRWb4NXUnNXRlFWWXl6SoN5VzVkYslmQ95WTENkTllVQzd4QhpEejdDNJZlWOp6M7oERQNnWspkaaB5QMhnR7dmUkRnVJR4L5cHTKNkZZdDbRBzZIxmSSR6NrpVQaVUQrBlc6ImYysSd4UlUEZGbw2kMl9UOzQVMId6ZXtUN83CO5RzaZt4VY5kM5pkUGpUUUV7UExUeGpUdTV5dFJ4bPhTc8pGeXJHWrkzNlFzdUtWTr5UQDdVckdGbSVUWr2yMPNzctZVRxEEW9lEbsZHUKJnVaRXT5p6Z0tWMqJGVrtSTIZnaopGSWZXbVNjY0hzQB5We4dnUr3ER8MkI0IyUiwiIGZUNwEkN5MjI0ICSiwSM9ETO6czNygTM0IicfJye#4Xfd5nIZRVV9IiOiMkIsISM6ByUKN7dllmVhRXYEJiOi8kI1tlOiQmcQJCLiEDMzATOwAyMwgDMwIDMyIiOiQncDJCLiI7au26YukHdpNWZwFmcn9iKsAnau26YukHdpNWZwFmcn9iKs86Yu46bj9Se4l6YlBXYydmLqwSbvNmL6VGZ9RXajVGchJ7ZuoCLt36YukHdpNWZwFmcn9iKiojIz5GRiwiI9RXaDVGchJ7RiojIh94QiwSZ5JHd0ICb6VkIsICNxkjM7MjM7czM9MTN9EjI0ICZJJye0ICRiwiI34zZN3yZGNlUnJDe5wkQPVlcBh7SppmUNBlU9dWS7J4ZMRES4MTZkRXTxM7Uq5GeQdHcyFHVup6dQd6ZDpEVrNDSh9kbNdzZrl4dwdPQ', SJS_LICENSE_KEY: '*.grapecity.com,E613631884219496#B0qRgJHWSJ7NyBlc8BjNMRHW7g7YldTZXFTQuFnW4hVOCplVSlVV09ERlhEZuVTVKlTazE4Q6VGSw2CdWZUWSVmbjVXbrxmWFVWR8ZzQro7U84WMGdlbuVHb73kS5kjUTN4NvFVdLdXWVR4Nox6Z7UUSysEcXJEMsN6bDN4TxMDVwVmWBRzKxhkTzAXTaJmdD3CRFJTd8R4R6M5RklWa6oUaLlXMwR4R8ZUdtRWVxUUaQh6VXNDdEhlZ7FHR6QXTPJTVvkWcyZnbSdHRtZHcYF6TKN4axYGcZNjTDF7TvFTTr24VqZjVHVjcLd7QkRmdNxkI0IyUiwiI5gDOEF4QGVjI0ICSiwiMzkTO9kTOyMTM0IicfJye35XX3JSSGljQiojIDJCLiITMuYHITpEIkFWZyB7UiojIOJyebpjIkJHUiwiI4MDMyEDMgkDM8ATOxAjMiojI4J7QiwiIt36YukHdpNWZwFmcn9iKiojIz5GRiwiIj9WagkHdpNUZwFmcHJiOiEmTDJCLlVnc4pjIsZXRiwiI6kDN9EjM4gDOxMjNzEjNiojIklkIs4XZzxWYmpjIyNHZisnOiwmbBJye0ICRiwiI34TQ72kNBV6YXpXdGxGWxdHcol4MyUGUHJVbQVHRx44Sw84YxRkS4QnZadDNmhWWxV5QxFlTlZEbBJ5N8gUNQlDb7J6Kl36YHVnb4NGN92UMFdlNORFU8VDSaFlQSVlS4EHTrA5Ohh', }, }; </script> <script src="/dataviewsjs/demos/node_modules/jquery/dist/jquery.min.js" type="text/javascript"></script> <script src="/dataviewsjs/demos/static/dataviews/gc.dataviews.common.min.js" type="text/javascript"></script> <script src="/dataviewsjs/demos/static/dataviews/gc.dataviews.core.min.js" type="text/javascript"></script> <script src="/dataviewsjs/demos/static/dataviews/gc.dataviews.grid.min.js" type="text/javascript"></script> <script src="/dataviewsjs/demos/static/js/license.js" type="text/javascript"></script> </head> <body class="theme-default"> <!-- Google Tag Manager (noscript) --> <noscript ><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-WT462SJ" height="0" width="0" style="display: none; visibility: hidden;" ></iframe ></noscript> <!-- End Google Tag Manager (noscript) --> <noscript>You need to enable JavaScript to run this app.</noscript> <template id="rowTmpl" style="display: none;"> <div class="gc-cell"> <div class="product-item"> <div data-column="productImage" class="product-item-image"></div> <div class="product-item-details"> <div data-column="productTitle"></div> </div> </div> <div data-column="productPrice" class="product-price"></div> <div data-column="productSubtotal" class="product-subtotal"></div> <div class="product-quantity"> <div data-column="productQuantity" class="product-quantity-number"></div> </div> </div> </template> <div class="container"> <div id="grid"></div> <div id="total" class="product-total"></div> </div> <script src="locale.js" type="text/javascript"></script> <script src="data.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> </body> </html>
var cols = [ { id: 'productId', dataField: 'id', visible: false, }, { id: 'productImage', caption: '', dataField: 'productImageUrl,productLink,productTitle', presenter: '<img class="product-item-image-resize" src="{{=it.productImageUrl}}" alt="{{=it.productTitle}}">', }, { id: 'productTitle', caption: 'Title', dataField: 'title', }, { id: 'productPrice', caption: 'Price', dataField: 'price', format: '$#,##0.00', }, { id: 'productQuantity', caption: 'Quantity', dataField: 'quantity', presenter: '<input data-id="{{=it.productId}}" min="0" value="{{=it.productQuantity}}" type="number" style="width:100%;" oninput="window.refreshQuantity(this)" />', }, { id: 'productDelete', action: [ { name: 'delete', presenter: '<div data-action="delete" style="background-color:red;color:white;width:80px;height:100%;position:relative"><span style="position:absolute;left:30%;top:40%">Delete</span></div>', handler: function handler() { return window.deleteRow(); }, }, ], width: 80, swipeDirection: 'left', }, { id: 'productSubtotal', caption: 'Subtotal', dataField: '=[productPrice] * [productQuantity]', visible: false, }, { id: 'productImageUrl', visible: false, dataField: 'url', }, { id: 'productLink', visible: false, dataField: 'link', }, { id: 'discountThreshold', visible: false, dataField: 'discountThreshold', }, ]; var layout = new GC.DataViews.GridLayout({ rowHeight: 127, showRowHeader: false, allowColumnReorder: false, allowColumnResize: false, allowSwipe: true, colHeaderHeight: 24, rowTemplate: '#rowTmpl', }); var dataView = new GC.DataViews.DataView(document.getElementById('grid'), data, cols, layout); refreshTotalPrice(); // focus data.view by default document.getElementById('grid').focus(); function refreshTotalPrice() { var formulaStringTotal = 'if(sum([productSubtotal]) > 199.99, sum([productSubtotal]) * 0.6, sum([productSubtotal]))'; var formulaStringPrice = 'sum([productSubtotal])'; var formulaStringQuantity = 'sum([productQuantity])'; var total = dataView.data.evaluate(formulaStringTotal); var price = dataView.data.evaluate(formulaStringPrice); var saving = price - total; var quantity = dataView.data.evaluate(formulaStringQuantity); var totalPriceSpan = document.getElementById('total'); var savingPercentage = price === 0 ? 0 : ((saving / price) * 100).toFixed(0); totalPriceSpan.innerHTML = '\n<div>\n <span style="font-size: 16px; font-weight: bold">\n <span>' .concat(locale.total, ' (') .concat(quantity, ' ') .concat(locale.items, '): </span>\n <span style="color:green">$') .concat(total.toFixed(2), '</span>\n </span>\n</div>\n<div>\n <span>') .concat(locale.totalSavings, ': </span>\n <span style="color:green">$') .concat(saving.toFixed(2), '</span>\n ') .concat(price === 0 ? '' : '<span>('.concat(savingPercentage, '%)</span>'), '\n</div>'); } window.deleteRow = function deleteRow(args) { var answer = confirm('Are you sure to delete row?'); if (answer) { dataView.data.removeDataItems(args.hitInfo.row); dataView.invalidate(); refreshTotalPrice(); } args.closeActionColumnPanel(); }; window.refreshQuantity = function refreshQuantity(input) { var id = parseInt($(input).data('id')); var rowData = data.find(function (t) { return t.id === id; }); if (rowData) { rowData.quantity = input.value ? parseInt(input.value) : 0; dataView.data.reCalculate(); dataView.invalidate(); refreshTotalPrice(); // focus recreated input $('input[data-id="'.concat(id, '"]')).focus(); } };
var SITE_ROOT = window.process.env.SITE_ROOT; var data = [ { id: 1, url: SITE_ROOT + '/images/51j6OH4qYhL_SS100_.jpg', link: '//www.amazon.com/gp/product/1628600837/ref=ox_sc_act_title_1?ie=UTF8&psc=1&smid=ATVPDKIKX0DER', title: 'Becoming a Supple Leopard 2nd Edition: The Ultimate Guide to Resolving Pain, Preventing Injury, and Optimizing Athletic Performance', price: 59.95, quantity: 1, }, { id: 2, url: SITE_ROOT + '/images/41ophY78M2L_SS100_.jpg', link: '//www.amazon.com/gp/product/0062190377/ref=ox_sc_act_title_2?ie=UTF8&psc=1&smid=ATVPDKIKX0DER', title: 'Seveneves: A Novel', price: 35.0, quantity: 1, }, { id: 3, url: SITE_ROOT + '/images/6195J3AhbdL_SL500_SY135_.jpg', link: '//www.amazon.com/The-Whole30-30-Day-Health-Freedom/dp/0544609719/ref=pd_cart_recs_2_2_p?ie=UTF8&refRID=0C2KPAAFEMW69ZXA0XBN', title: 'The whole 30: The 30 Days Guild to Total Healthy and Food Freedom', price: 30.0, quantity: 1, }, ];
var locale = { total: 'Total', items: 'items', totalSavings: 'Total savings' };
.container { height: 500px; overflow: auto; } #grid { border: 0; float: left; height: 410px; width: 800px; } .gc-row { padding: 3px 0; } .gc-grid, .gc-cell { border: 0; text-overflow: clip; } .gc-grid .gc-cell-content, .gc-cell .gc-cell-content { white-space: normal; } .gc-cell-border { border: 0; } .gc-column-header-cell { background-color: transparent; color: inherit; font-weight: normal; } .gc-column-header-cell.gc-cell-border { border: none; } .c4, .c5 { text-align: center; justify-content: center; } /*product presentation:*/ .product-item { display: inline-flex; align-items: center; width: 400px; } .product-item-image { display: inline-flex; align-items: center; justify-content: center; width: 120px; } .product-item-image-resize { border-radius: 4px; height: 120px; padding: 0; } .product-item-details { width: 280px; } .product-price, .product-quantity { display: inline-block; text-align: center; vertical-align: middle; width: 100px; } .product-total { background: #f1f1f1; border: solid 1px #e0e0e0; border-radius: 4px; color: #777; display: inline-block; float: right; font-family: "Roboto", sans-serif; font-weight: 300; margin-right: 1em; margin-top: 1em; padding: 1em; width: 25%; } .product-total .total-info { font-size: 16px; font-weight: bold; } .product-total .green { color: green; } @media only screen and (max-width: 768px) { .container { height: 420px; } #grid { float: none; width: 100%; } .product-total { float: none; width: 90%; } } /*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlNob3djYXNlL1Nob3BwaW5nQ2FydC9wdXJlanMvc3R5bGVzLnNjc3MiLCJTaG93Y2FzZS9TaG9wcGluZ0NhcnQvcHVyZWpzL3N0eWxlcy5jc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7RUFDRSxhQUFBO0VBQ0EsY0FBQTtBQ0NGOztBREVBO0VBQ0UsU0FBQTtFQUNBLFdBQUE7RUFDQSxhQUFBO0VBQ0EsWUFBQTtBQ0NGOztBREVBO0VBQ0UsY0FBQTtBQ0NGOztBREVBOztFQUVFLFNBQUE7RUFDQSxtQkFBQTtBQ0NGO0FEQ0U7O0VBQ0UsbUJBQUE7QUNFSjs7QURFQTtFQUNFLFNBQUE7QUNDRjs7QURFQTtFQUNFLDZCQUFBO0VBQ0EsY0FBQTtFQUNBLG1CQUFBO0FDQ0Y7QURDRTtFQUNFLFlBQUE7QUNDSjs7QURHQTs7RUFFRSxrQkFBQTtFQUNBLHVCQUFBO0FDQUY7O0FER0Esd0JBQUE7QUFFQTtFQUNFLG9CQUFBO0VBQ0EsbUJBQUE7RUFDQSxZQUFBO0FDREY7O0FESUE7RUFDRSxvQkFBQTtFQUNBLG1CQUFBO0VBQ0EsdUJBQUE7RUFDQSxZQUFBO0FDREY7O0FESUE7RUFDRSxrQkFBQTtFQUNBLGFBQUE7RUFDQSxVQUFBO0FDREY7O0FESUE7RUFDRSxZQUFBO0FDREY7O0FESUE7O0VBRUUscUJBQUE7RUFDQSxrQkFBQTtFQUNBLHNCQUFBO0VBQ0EsWUFBQTtBQ0RGOztBRElBO0VBQ0UsbUJBQUE7RUFDQSx5QkFBQTtFQUNBLGtCQUFBO0VBQ0EsV0FBQTtFQUNBLHFCQUFBO0VBQ0EsWUFBQTtFQUNBLGlDQUFBO0VBQ0EsZ0JBQUE7RUFDQSxpQkFBQTtFQUNBLGVBQUE7RUFDQSxZQUFBO0VBQ0EsVUFBQTtBQ0RGO0FER0U7RUFDRSxlQUFBO0VBQ0EsaUJBQUE7QUNESjtBRElFO0VBQ0UsWUFBQTtBQ0ZKOztBRE1BO0VBQ0U7SUFDRSxhQUFBO0VDSEY7O0VETUE7SUFDRSxXQUFBO0lBQ0EsV0FBQTtFQ0hGOztFRE1BO0lBQ0UsV0FBQTtJQUNBLFVBQUE7RUNIRjtBQUNGIiwiZmlsZSI6IlNob3djYXNlL1Nob3BwaW5nQ2FydC9wdXJlanMvc3R5bGVzLmNzcyIsInNvdXJjZXNDb250ZW50IjpbIi5jb250YWluZXIge1xuICBoZWlnaHQ6IDUwMHB4O1xuICBvdmVyZmxvdzogYXV0bztcbn1cblxuI2dyaWQge1xuICBib3JkZXI6IDA7XG4gIGZsb2F0OiBsZWZ0O1xuICBoZWlnaHQ6IDQxMHB4O1xuICB3aWR0aDogODAwcHg7XG59XG5cbi5nYy1yb3cge1xuICBwYWRkaW5nOiAzcHggMDtcbn1cblxuLmdjLWdyaWQsXG4uZ2MtY2VsbCB7XG4gIGJvcmRlcjogMDtcbiAgdGV4dC1vdmVyZmxvdzogY2xpcDtcblxuICAuZ2MtY2VsbC1jb250ZW50IHtcbiAgICB3aGl0ZS1zcGFjZTogbm9ybWFsO1xuICB9XG59XG5cbi5nYy1jZWxsLWJvcmRlciB7XG4gIGJvcmRlcjogMDtcbn1cblxuLmdjLWNvbHVtbi1oZWFkZXItY2VsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICBjb2xvcjogaW5oZXJpdDtcbiAgZm9udC13ZWlnaHQ6IG5vcm1hbDtcblxuICAmLmdjLWNlbGwtYm9yZGVyIHtcbiAgICBib3JkZXI6IG5vbmU7XG4gIH1cbn1cblxuLmM0LFxuLmM1IHtcbiAgdGV4dC1hbGlnbjogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbn1cblxuLypwcm9kdWN0IHByZXNlbnRhdGlvbjoqL1xuXG4ucHJvZHVjdC1pdGVtIHtcbiAgZGlzcGxheTogaW5saW5lLWZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIHdpZHRoOiA0MDBweDtcbn1cblxuLnByb2R1Y3QtaXRlbS1pbWFnZSB7XG4gIGRpc3BsYXk6IGlubGluZS1mbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgd2lkdGg6IDEyMHB4O1xufVxuXG4ucHJvZHVjdC1pdGVtLWltYWdlLXJlc2l6ZSB7XG4gIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgaGVpZ2h0OiAxMjBweDtcbiAgcGFkZGluZzogMDtcbn1cblxuLnByb2R1Y3QtaXRlbS1kZXRhaWxzIHtcbiAgd2lkdGg6IDI4MHB4O1xufVxuXG4ucHJvZHVjdC1wcmljZSxcbi5wcm9kdWN0LXF1YW50aXR5IHtcbiAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xuICB0ZXh0LWFsaWduOiBjZW50ZXI7XG4gIHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7XG4gIHdpZHRoOiAxMDBweDtcbn1cblxuLnByb2R1Y3QtdG90YWwge1xuICBiYWNrZ3JvdW5kOiAjZjFmMWYxO1xuICBib3JkZXI6IHNvbGlkIDFweCAjZTBlMGUwO1xuICBib3JkZXItcmFkaXVzOiA0cHg7XG4gIGNvbG9yOiAjNzc3O1xuICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gIGZsb2F0OiByaWdodDtcbiAgZm9udC1mYW1pbHk6ICdSb2JvdG8nLCBzYW5zLXNlcmlmO1xuICBmb250LXdlaWdodDogMzAwO1xuICBtYXJnaW4tcmlnaHQ6IDFlbTtcbiAgbWFyZ2luLXRvcDogMWVtO1xuICBwYWRkaW5nOiAxZW07XG4gIHdpZHRoOiAyNSU7XG5cbiAgLnRvdGFsLWluZm8ge1xuICAgIGZvbnQtc2l6ZTogMTZweDtcbiAgICBmb250LXdlaWdodDogYm9sZDtcbiAgfVxuXG4gIC5ncmVlbiB7XG4gICAgY29sb3I6IGdyZWVuO1xuICB9XG59XG5cbkBtZWRpYSBvbmx5IHNjcmVlbiBhbmQgKG1heC13aWR0aDogNzY4cHgpIHtcbiAgLmNvbnRhaW5lciB7XG4gICAgaGVpZ2h0OiA0MjBweDtcbiAgfVxuXG4gICNncmlkIHtcbiAgICBmbG9hdDogbm9uZTtcbiAgICB3aWR0aDogMTAwJTtcbiAgfVxuXG4gIC5wcm9kdWN0LXRvdGFsIHtcbiAgICBmbG9hdDogbm9uZTtcbiAgICB3aWR0aDogOTAlO1xuICB9XG59XG4iLCIuY29udGFpbmVyIHtcbiAgaGVpZ2h0OiA1MDBweDtcbiAgb3ZlcmZsb3c6IGF1dG87XG59XG5cbiNncmlkIHtcbiAgYm9yZGVyOiAwO1xuICBmbG9hdDogbGVmdDtcbiAgaGVpZ2h0OiA0MTBweDtcbiAgd2lkdGg6IDgwMHB4O1xufVxuXG4uZ2Mtcm93IHtcbiAgcGFkZGluZzogM3B4IDA7XG59XG5cbi5nYy1ncmlkLFxuLmdjLWNlbGwge1xuICBib3JkZXI6IDA7XG4gIHRleHQtb3ZlcmZsb3c6IGNsaXA7XG59XG4uZ2MtZ3JpZCAuZ2MtY2VsbC1jb250ZW50LFxuLmdjLWNlbGwgLmdjLWNlbGwtY29udGVudCB7XG4gIHdoaXRlLXNwYWNlOiBub3JtYWw7XG59XG5cbi5nYy1jZWxsLWJvcmRlciB7XG4gIGJvcmRlcjogMDtcbn1cblxuLmdjLWNvbHVtbi1oZWFkZXItY2VsbCB7XG4gIGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50O1xuICBjb2xvcjogaW5oZXJpdDtcbiAgZm9udC13ZWlnaHQ6IG5vcm1hbDtcbn1cbi5nYy1jb2x1bW4taGVhZGVyLWNlbGwuZ2MtY2VsbC1ib3JkZXIge1xuICBib3JkZXI6IG5vbmU7XG59XG5cbi5jNCxcbi5jNSB7XG4gIHRleHQtYWxpZ246IGNlbnRlcjtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG59XG5cbi8qcHJvZHVjdCBwcmVzZW50YXRpb246Ki9cbi5wcm9kdWN0LWl0ZW0ge1xuICBkaXNwbGF5OiBpbmxpbmUtZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgd2lkdGg6IDQwMHB4O1xufVxuXG4ucHJvZHVjdC1pdGVtLWltYWdlIHtcbiAgZGlzcGxheTogaW5saW5lLWZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICB3aWR0aDogMTIwcHg7XG59XG5cbi5wcm9kdWN0LWl0ZW0taW1hZ2UtcmVzaXplIHtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBoZWlnaHQ6IDEyMHB4O1xuICBwYWRkaW5nOiAwO1xufVxuXG4ucHJvZHVjdC1pdGVtLWRldGFpbHMge1xuICB3aWR0aDogMjgwcHg7XG59XG5cbi5wcm9kdWN0LXByaWNlLFxuLnByb2R1Y3QtcXVhbnRpdHkge1xuICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgdmVydGljYWwtYWxpZ246IG1pZGRsZTtcbiAgd2lkdGg6IDEwMHB4O1xufVxuXG4ucHJvZHVjdC10b3RhbCB7XG4gIGJhY2tncm91bmQ6ICNmMWYxZjE7XG4gIGJvcmRlcjogc29saWQgMXB4ICNlMGUwZTA7XG4gIGJvcmRlci1yYWRpdXM6IDRweDtcbiAgY29sb3I6ICM3Nzc7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbiAgZmxvYXQ6IHJpZ2h0O1xuICBmb250LWZhbWlseTogXCJSb2JvdG9cIiwgc2Fucy1zZXJpZjtcbiAgZm9udC13ZWlnaHQ6IDMwMDtcbiAgbWFyZ2luLXJpZ2h0OiAxZW07XG4gIG1hcmdpbi10b3A6IDFlbTtcbiAgcGFkZGluZzogMWVtO1xuICB3aWR0aDogMjUlO1xufVxuLnByb2R1Y3QtdG90YWwgLnRvdGFsLWluZm8ge1xuICBmb250LXNpemU6IDE2cHg7XG4gIGZvbnQtd2VpZ2h0OiBib2xkO1xufVxuLnByb2R1Y3QtdG90YWwgLmdyZWVuIHtcbiAgY29sb3I6IGdyZWVuO1xufVxuXG5AbWVkaWEgb25seSBzY3JlZW4gYW5kIChtYXgtd2lkdGg6IDc2OHB4KSB7XG4gIC5jb250YWluZXIge1xuICAgIGhlaWdodDogNDIwcHg7XG4gIH1cblxuICAjZ3JpZCB7XG4gICAgZmxvYXQ6IG5vbmU7XG4gICAgd2lkdGg6IDEwMCU7XG4gIH1cblxuICAucHJvZHVjdC10b3RhbCB7XG4gICAgZmxvYXQ6IG5vbmU7XG4gICAgd2lkdGg6IDkwJTtcbiAgfVxufSJdfQ== */