Product Catalog

This example uses a common control slicer to filter in DataViews.

<p>This example uses a common control slicer to filter in DataViews. This demo implements an Amazon-like filter panel with the Card Layout Engine to present a product catalog.</p> <p>The slicer allows the user to filter the data in the grid using multiple options. This demo filters TVs by size, resolution, and customer reviews.</p> <p>Try using the filters in the filter panel to pick the type of items that are shown in the grid.</p>
<!DOCTYPE html> <html lang="en"> <head> <base href="/dataviewsjs/demos/en/sample/Showcase/ProductCatalog/purejs/" /> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="keywords" content="filtering" /> <meta name="description" content="This example uses a common control slicer to filter in DataViews." /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Product Catalog | 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/css/bootstrap-snippet.min.css" rel="stylesheet" type="text/css" /> <link href="/dataviewsjs/demos/node_modules/@fortawesome/fontawesome-free/css/all.min.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.cardlayout.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: 'E674186349827489#B0LYWQMpFdP3WSHlVaGdjTFtyLCxUQjdFV5MHey9kTyBnY0pkY6tWcr34caJjSPlEVlR6QpJnZEdjSj9kbkRUZChzMsRFS99mN4ZGO72yK7FXe5tmN59Eai5UM7dEVvgUeYN5MqdUTIpWTpBnSTJEWv24YwoFWr9mWEl6UNVmVMxUd5ckUQdlUNV4MDhENaV5KNNWbJtiSwFUYCVUax4GUuBjZDN7T5dWdDpFNyJjSxJkes3mUt94QrdnMK5mZORGeFZ4QyFTMmdWOWdlMmJ4ZJhTS5MmZatyZ7k5c0JXVB3mWVNke7AFRiojITJCLikjNBNjNzcjI0ICSiwSN8AjN9YjMwUTM0IicfJye35XX3JSWUVVOiojIDJCLiEjdgMlSzdXZpZVY4FGRiojIOJyebpjIkJHUiwiI9MDMykDMggDM8ATOxAjMiojI4J7QiwiIt36YukHdpNWZwFmcn9iKiojIz5GRiwiIj9WSgkHdpNUZwFmcHJiOiEmTDJCLlVnc4pjIsZXRiwiI9gDN7IDO9QzM6gTM4cjNiojIklkI1pjIEJCLi4TPn3UZuJ7cPZTW5hUMtN7MJN6aQFnT5gmd9FEZ4EETlFmW63kU8IGdiRGTJZle5UDbZJHTR34T0JzZoZmbalXQwNmM8EndEFEdSVlMiVnckFmQUJTOahmc7AzRHhlU4I4Vs3kN6lHaHR4LuhWULNIe', SJS_LICENSE_KEY: '*.grapecity.com,E613631884219496#B0qRgJHWSJ7NyBlc8BjNMRHW7g7YldTZXFTQuFnW4hVOCplVSlVV09ERlhEZuVTVKlTazE4Q6VGSw2CdWZUWSVmbjVXbrxmWFVWR8ZzQro7U84WMGdlbuVHb73kS5kjUTN4NvFVdLdXWVR4Nox6Z7UUSysEcXJEMsN6bDN4TxMDVwVmWBRzKxhkTzAXTaJmdD3CRFJTd8R4R6M5RklWa6oUaLlXMwR4R8ZUdtRWVxUUaQh6VXNDdEhlZ7FHR6QXTPJTVvkWcyZnbSdHRtZHcYF6TKN4axYGcZNjTDF7TvFTTr24VqZjVHVjcLd7QkRmdNxkI0IyUiwiI5gDOEF4QGVjI0ICSiwiMzkTO9kTOyMTM0IicfJye35XX3JSSGljQiojIDJCLiITMuYHITpEIkFWZyB7UiojIOJyebpjIkJHUiwiI4MDMyEDMgkDM8ATOxAjMiojI4J7QiwiIt36YukHdpNWZwFmcn9iKiojIz5GRiwiIj9WagkHdpNUZwFmcHJiOiEmTDJCLlVnc4pjIsZXRiwiI6kDN9EjM4gDOxMjNzEjNiojIklkIs4XZzxWYmpjIyNHZisnOiwmbBJye0ICRiwiI34TQ72kNBV6YXpXdGxGWxdHcol4MyUGUHJVbQVHRx44Sw84YxRkS4QnZadDNmhWWxV5QxFlTlZEbBJ5N8gUNQlDb7J6Kl36YHVnb4NGN92UMFdlNORFU8VDSaFlQSVlS4EHTrA5Ohh', }, }; </script> <script src="/dataviewsjs/demos/node_modules/lodash/lodash.min.js" type="text/javascript"></script> <script src="//cdn.grapecity.com/spreadjs/hosted/scripts/gc.spread.common.12.0.0.min.js" type="text/javascript" ></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.cardlayout.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> <div class="demo-container"> <div class="mobile-filter-entry"> <div class="filter-condition"> <span class="filter-label">Filter</span> <span class="fa fa-angle-down"></span> </div> </div> <div class="filter-panel"> <div class="filter-header">Refine by</div> <div id="tv_display_size" class="slicer"></div> <div id="tv_resolution" class="slicer"></div> <div id="customer_review_star" class="slicer"></div> </div> <div id="grid"></div> </div> <script src="data.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> </body> </html>
var rowTemplate = '<div>\n <div data-column="image"></div>\n <div data-column="description"></div>\n <div data-column="brand"></div>\n <div data-column="price"></div>\n <div data-column="starsIcon"></div>\n</div>'; var imagePresenter = '<img class="tv-image" src={{=it.image}} />'; var descriptionPresenter = '<a><b>{{=it.description}}</b></a>'; var brandPresenter = '<div class="tv-brand"><label>by {{=it.brand}}</label></div>'; var pricePresenter = '<div>${{=it.price}}</div>'; var startPresenter = '<div class="stars-box {{=it.starsIcon}}"></div>'; var cols = [ { id: 'image', caption: 'Image', dataField: 'image', presenter: imagePresenter, }, { id: 'description', caption: 'Description', dataField: 'description', presenter: descriptionPresenter, }, { id: 'brand', caption: 'Brand', dataField: 'brand', presenter: brandPresenter, }, { id: 'price', caption: 'Price', dataField: 'price', presenter: pricePresenter, }, { id: 'starsIcon', caption: 'StarsIcon', dataField: 'starsIcon', presenter: startPresenter, }, { id: 'size', caption: 'TV Display Size', dataField: 'size', }, { id: 'refreshRate', caption: 'RefreshRate', dataField: 'refreshRate', }, { id: 'resolution', caption: 'Television Resolution', dataField: 'resolution', }, { id: 'starsValue', caption: 'Avg. Customer Review', dataField: 'starsValue', }, ]; var getCaption = function getCaption(id) { return _.find(cols, function(col) { return col.id === id; }).caption; }; var layout = new GC.DataViews.CardLayout({ cardHeight: 300, cardWidth: 210, rowTemplate: rowTemplate, }); var dataView = new GC.DataViews.DataView(document.getElementById('grid'), data, cols, layout); function Filter(container, columnName, rangeInfo) { this.container = container; this.columnName = columnName; this.rangeInfo = rangeInfo; dataSource.attachListener(this); this.onDataLoaded(); } Object.assign(Filter.prototype, { onDataLoaded: function onDataLoaded() { var _this = this; var container = this.container; var html = this.render(); container.append(html); container.find('.slicer-item input[type=checkbox]').on('click', function(e) { e.preventDefault(); }); container.find('.slicer-item').on('mousedown', function(e) { var slicerItem = $(e.currentTarget); var targetInput = slicerItem.find('input[type=checkbox]'); if (!targetInput.prop('disabled')) { if (targetInput) { targetInput.prop('checked', !targetInput.prop('checked')); } var condition = _this.getFilterCondition(); if (!condition) { dataSource.doUnfilter(_this.columnName); } else { dataSource.doFilter(_this.columnName, condition); } } }); }, onFiltered: function onFiltered(args) { this.clearSlicerItemClass(); this.updateSlicerItem(); var newData = _.map(args.rowIndexes, function(index) { return data[index]; }); dataView.data.setSource_(newData); // Need to be replaced dataView.invalidate(); }, clearSlicerItemClass: function clearSlicerItemClass() { var items = this.container.find('.slicer-item'); var classes = ['filtered', 'filteredOutByOther']; _.each(items, function(item) { _.each(classes, function(itemClass) { $(item).removeClass(itemClass); }); $(item) .find('input[type=checkbox]') .prop('disabled', false); }); }, render: function render() { var _this2 = this; var columnName = this.columnName; var data = this.rangeInfo || dataSource.getExclusiveData(columnName); var header = '<div class="filter-details">'.concat(getCaption(columnName), '</div>'); var body = _.map(data, function(it, idx) { if (_this2.rangeInfo) { var count = dataSource.getData(columnName, it.range).length; return _this2.renderItem(it.label, count); } else { var _count = dataSource.getRowIndexes(columnName, idx).length; return _this2.renderItem(it, _count); } }).join(''); return header + body; }, renderItem: function renderItem(label, count) { var span = '<span>'.concat(label, '</span>'); var badge = '<span class="count-badge">('.concat(count, ')</span>'); return '<div class="slicer-item"><input type="checkbox" />'.concat(span).concat(badge, '</div>'); }, getFilterCondition: function getFilterCondition() { var _this3 = this; var container = this.container; var inputs = container.find('input[type=checkbox]'); if (this.rangeInfo) { var ranges = []; _.each(inputs, function(item, i) { if (item.checked) { ranges.push(_this3.rangeInfo[i].range); } }); return ranges.length ? { ranges: ranges, } : null; } else { var indexes = []; _.each(inputs, function(item, i) { if (item.checked) { indexes.push(i); } }); return indexes.length ? { exclusiveRowIndexes: indexes, } : null; } }, updateSlicerItem: function updateSlicerItem() { var _getItemStates = getItemStates(dataSource, this.rangeInfo, this.columnName), filtered = _getItemStates.filtered, filteredOut = _getItemStates.filteredOut; var items = this.container.find('.slicer-item'); for (var k = 0; k < items.length; k++) { if (filtered.has(k)) { $(items[k]).addClass('filtered'); } if (filteredOut.has(k)) { this.filterOut(items[k]); } } }, filterOut: function filterOut(item) { $(item) .addClass('filteredOutByOther') .find('input[type=checkbox]') .prop('disabled', true); }, }); var sizeRanges = [ { range: { min: -Infinity, max: 32, }, label: '32 Inches & Under', }, { range: { min: 33, max: 43, }, label: '33 to 43 Inches', }, { range: { min: 44, max: 49, }, label: '44 to 49 Inches', }, { range: { min: 50, max: 59, }, label: '50 to 59 Inches', }, { range: { min: 60, max: 69, }, label: '60 to 69 Inches', }, { range: { min: 70, max: Infinity, }, label: '70 Inches & Up', }, ]; var reviewRanges = _.rangeRight(1, 5).map(function(min) { return { range: { min: min, max: Infinity, }, label: '<span><span class="stars-box stars-'.concat(min, '"></span><span class="label">&Up</span></span>'), }; }); new Filter($('#tv_display_size'), 'size', sizeRanges); new Filter($('#tv_resolution'), 'resolution'); new Filter($('#customer_review_star'), 'starsValue', reviewRanges); $('.filter-condition').click(function() { $('.filter-panel').toggle(); }); window.addEventListener('resize', function() { var isMobile = $('.mobile-filter-entry').is(':visible'); $('.filter-panel').toggle(!isMobile); });
var SITE_ROOT = window.process.env.SITE_ROOT; var data = [ { size: 42, refreshRate: 60, resolution: '1080p', price: 399.49, brand: 'LG', starsIcon: 'stars-4-5', starsValue: 4.5, image: SITE_ROOT + '/images/51RgQIPeyfL._AA160_.jpg', shipToChina: true, description: 'LG Electronics 42LF5600 42-Inch 1080p 60Hz LED TV', }, { size: 105, refreshRate: 120, resolution: '4K', price: 119999.99, brand: 'Samsung', starsIcon: 'stars-4', starsValue: 4, image: SITE_ROOT + '/images/411r27g4Y4L._AA160_.jpg', shipToChina: true, description: 'Samsung UN105S9 Curved 105-Inch 4K Ultra HD 120Hz 3D Smart LED TV', }, { size: 32, refreshRate: 60, resolution: '720p', price: 237.99, brand: 'Samsung', starsIcon: 'stars-5', starsValue: 5, image: SITE_ROOT + '/images/510PicygL._AA160_.jpg', shipToChina: false, description: 'Samsung UN32J4000 32-Inch 720p LED TV', }, { size: 22, refreshRate: 60, resolution: '1080p', price: 167.99, brand: 'Samsung', starsIcon: 'stars-4-5', starsValue: 4.5, image: SITE_ROOT + '/images/41yd3HTcniL._AA160_.jpg', shipToChina: false, description: 'Samsung UN22F5000 22-Inch 1080p 60Hz LED HDTV (2013 Model)', }, { size: 42, refreshRate: 60, resolution: '1080p', price: 499.99, brand: 'LG', starsIcon: 'stars-3', starsValue: 3, image: SITE_ROOT + '/images/517B8PMhPNL._AA160_.jpg', shipToChina: false, description: 'LG 42LB5600 42-Inch TV (2014 Model)', }, { size: 45, refreshRate: 60, resolution: '1080p', price: 259.99, brand: 'Samsung', starsIcon: 'stars-4', starsValue: 4, image: SITE_ROOT + '/images/516z8QST2CL._AA160_.jpg', shipToChina: true, description: 'Samsung UN32H5203 45-Inch 1080p 60Hz Smart LED TV', }, { size: 46, refreshRate: 60, resolution: '1080p', price: 497.99, brand: 'Samsung', starsIcon: 'stars-3', starsValue: 3, image: SITE_ROOT + '/images/41H0LXbYcXL._AA160_.jpg', shipToChina: true, description: 'Samsung UN32J6300 46-Inch 1080p Smart LED TV', }, { size: 32, refreshRate: 60, resolution: '720p', price: 179.99, brand: 'Upstar', starsIcon: 'stars-4-5', starsValue: 4.5, image: SITE_ROOT + '/images/41JXS3PTiJL._AA160_.jpg', shipToChina: false, description: 'Upstar P32ES8 32-Inch 720p 60Hz LED TV', }, { size: 40, refreshRate: 60, resolution: '480p', price: 327.99, brand: 'Samsung', starsIcon: 'stars-4-5', starsValue: 4.5, image: SITE_ROOT + '/images/51JegzA81lL._AA160_.jpg', shipToChina: false, description: 'Samsung UN40H5003 40-Inch 480p 60Hz LED TV', }, { size: 55, refreshRate: 120, resolution: '1080p', price: 727.25, brand: 'LG', starsIcon: 'stars-4-5', starsValue: 4.5, image: SITE_ROOT + '/images/51yUo1AhEdL._AA160_.jpg', shipToChina: false, description: 'LG Electronics 55LB5900 55-Inch 1080p 120Hz LED TV (2014 Model)', }, { size: 55, refreshRate: 120, resolution: '1080p', price: 679.99, brand: 'LG', starsIcon: 'stars-4', starsValue: 4, image: SITE_ROOT + '/images/4112L6fBNLL._AA160_.jpg', shipToChina: false, description: 'LG Electronics 55LF6000 55-Inch 1080p 120Hz LED TV', }, { size: 24, refreshRate: 60, resolution: '1080p', price: 178.99, brand: 'VIZIO', starsIcon: 'stars-4', starsValue: 4, image: SITE_ROOT + '/images/51tJrIAnF0L._AA160_.jpg', shipToChina: true, description: 'VIZIO E241i-B1 24-Inch 1080p 60Hz Smart LED HDTV (Black)', }, { size: 40, refreshRate: 60, resolution: '1080p', price: 353.7, brand: 'TCL', starsIcon: 'stars-5', starsValue: 5, image: SITE_ROOT + '/images/41iZ3NkxiL._AA160_.jpg', shipToChina: true, description: 'TCL 40FS4610R 40-Inch 1080p Smart LED TV (Roku TV)', }, { size: 55, refreshRate: 60, resolution: '1080p', price: 1000.42, brand: 'Samsung', starsIcon: 'stars-3', starsValue: 3, image: SITE_ROOT + '/images/41H0LXbYcXL._AA160_.jpg', shipToChina: false, description: 'Samsung UN55J6300 55-Inch 1080p Smart LED TV', }, { size: 39, refreshRate: 60, resolution: '1080p', price: 279.99, brand: 'VIZIO', starsIcon: 'stars-5', starsValue: 5, image: SITE_ROOT + '/images/41Voh4kl2hL._AA160_.jpg', shipToChina: false, description: 'VIZIO E390-A1 39-Inch 1080p 60Hz LED TV (Refurbished)', }, { size: 60, refreshRate: 120, resolution: '1080p', price: 899.99, brand: 'LG', starsIcon: 'stars-4', starsValue: 4, image: SITE_ROOT + '/images/51Gx1C4mEFL._AA160_.jpg', shipToChina: false, description: 'LG Electronics 60LB5900 60-Inch 1080p 120Hz LED TV (2014 Model)', }, { size: 32, refreshRate: 60, resolution: '1080p', price: 299.99, brand: 'LG', starsIcon: 'stars-4-5', starsValue: 4.5, image: SITE_ROOT + '/images/51RgQIPeyfL._AA160_.jpg', shipToChina: false, description: 'LG Electronics 32LF5600 32-Inch 1080p 60Hz LED TV', }, { size: 40, refreshRate: 60, resolution: '1080p', price: 307.99, brand: 'TCL', starsIcon: 'stars-4-5', starsValue: 4.5, image: SITE_ROOT + '/images/416bLnX49L._AA160_.jpg', shipToChina: false, description: 'TCL LE40FHDE3010 40-Inch 1080p 60Hz LED TV', }, { size: 28, refreshRate: 60, resolution: '720p', price: 165.99, brand: 'Samsung', starsIcon: 'stars-4-5', starsValue: 4.5, image: SITE_ROOT + '/images/51y45mtIPgL._AA160_.jpg', shipToChina: false, description: 'Samsung UN28H4000 28-Inch 720p 60Hz LED TV', }, { size: 43, refreshRate: 60, resolution: '1080p', price: 445.49, brand: 'VIZIO', starsIcon: 'stars-4-5', starsValue: 4.5, image: SITE_ROOT + '/images/51OEEpDqNHL._AA160_.jpg', shipToChina: false, description: 'VIZIO E43-C2 43-Inch 1080p Smart LED HDTV', }, ]; var dataNames = _.keys(data[0]); var dataValues = _.map(data, function(item) { return _.values(item); }); var dataSource = new GC.Spread.Slicers.GeneralSlicerData(dataValues, dataNames); var getItemStates = function getItemStates(dataSource, rangeState, columnName) { var byOtherColumns = GC.Spread.Slicers.FilteredOutDataType.byOtherColumns; var filteredIndexes = dataSource.getFilteredIndexes(columnName); var filteredOutIndexes = dataSource.getFilteredOutIndexes(columnName, byOtherColumns); var filtered = new Set(); var filteredOut = new Set(); if (rangeState) { var exclusiveData = dataSource.getExclusiveData(columnName); var filteredValues = filteredIndexes.map(function(i) { return exclusiveData[i]; }); var filteredOutValues = filteredOutIndexes.map(function(i) { return exclusiveData[i]; }); var _loop = function _loop(k) { var range = rangeState[k].range; var inrange = function inrange(val) { return val >= range.min && val <= range.max; }; if (filteredValues.some(inrange)) { filtered.add(k); } if (filteredOutValues.some(inrange)) { filteredOut.add(k); } }; for (var k = 0; k < rangeState.length; k++) { _loop(k); } } else { filteredIndexes.forEach(function(k) { filtered.add(k); }); filteredOutIndexes.forEach(function(k) { filteredOut.add(k); }); } return { filtered: filtered, filteredOut: filteredOut, }; };
label { font-weight: normal; margin: 0; } .card-layout.gc-grid { border: 0; } .card-layout .gc-row { padding: 3px; text-align: center; } .card-layout .gc-row .gc-cell { justify-content: center; } #grid { height: 100%; left: 220px; position: absolute; right: 0; } .demo-container { height: 100%; position: relative; -webkit-user-select: none; -ms-user-select: none; user-select: none; width: 100%; } .filter-panel { border: 0; display: block; float: left; height: 100%; overflow: auto; padding-left: 8px; position: static; width: 219px; z-index: auto; } .filter-header { color: #999; font-size: 17px; padding-bottom: 10px; padding-top: 6px; } .filter-details { font-size: 14px; font-weight: 700; padding-bottom: 3px; } .stars-box { background-image: url("/dataviewsjs/demos/images/star-ratings.png"); display: inline-block; height: 13px; overflow: hidden; vertical-align: middle; width: 65px; margin-right: 4px; } .stars-0 { background-position: -65px 0; } .stars-0-5 { background-position: -52px -19px; } .stars-1 { background-position: -52px 0; } .stars-1-5 { background-position: -39px -19px; } .stars-2 { background-position: -39px 0; } .stars-2-5 { background-position: -26px -19px; } .stars-3 { background-position: -26px 0; } .stars-3-5 { background-position: -13px -19px; } .stars-4 { background-position: -13px 0; } .stars-4-5 { background-position: 0 -18px; } .stars-5 { background-position: 0 0; } .tv-image { margin-left: 10px; } .tv-brand { color: #d3d3d3; font-size: 13px; } .tv-price { color: #b12704; } .mobile-filter-entry { display: none; } .filter-condition { border: 1px solid #d3d3d3; cursor: pointer; display: inline-block; font-size: 16px; height: 25px; text-align: center; width: 100px; } .filter-condition .filter-label { margin-right: 5px; } .slicer { margin: 10px 0; } .slicer-item { align-items: center; cursor: pointer; display: flex; margin: 2px 0; } .slicer-item.selected { color: #337ab7; } .slicer-item.selected .label { font-weight: bold; } .slicer-item:hover { color: #e47911; } .slicer-item.filtered { background-color: #fff; } .slicer-item.filteredOutByOther { color: #a6a8b1; } .slicer-item.filteredOutBySelf { background-color: #fff; } .slicer-item input { margin-right: 4px; } .slicer-item .count-badge { margin-left: 4px; color: #a29999; } @media only screen and (max-width: 768px) { #grid { height: 90%; position: static; } .filter-panel { background: #fff; border: 1px solid #d3d3d3; display: none; height: calc(100% - 25px); margin-top: -1px; overflow: auto; padding: 5px 0 0 10px; position: absolute; width: 100%; z-index: 1; } .mobile-filter-entry { display: block; height: 25px; } } /*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlNob3djYXNlL1Byb2R1Y3RDYXRhbG9nL3B1cmVqcy9zdHlsZXMuc2NzcyIsIlNob3djYXNlL1Byb2R1Y3RDYXRhbG9nL3B1cmVqcy9zdHlsZXMuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UsbUJBQUE7RUFDQSxTQUFBO0FDQ0Y7O0FERUE7RUFDRSxTQUFBO0FDQ0Y7O0FERUE7RUFDRSxZQUFBO0VBQ0Esa0JBQUE7QUNDRjtBRENFO0VBQ0UsdUJBQUE7QUNDSjs7QURHQTtFQUNFLFlBQUE7RUFDQSxXQUFBO0VBQ0Esa0JBQUE7RUFDQSxRQUFBO0FDQUY7O0FER0E7RUFDRSxZQUFBO0VBQ0Esa0JBQUE7RUFDQSx5QkFBQTtNQUFBLHFCQUFBO1VBQUEsaUJBQUE7RUFDQSxXQUFBO0FDQUY7O0FER0E7RUFDRSxTQUFBO0VBQ0EsY0FBQTtFQUNBLFdBQUE7RUFDQSxZQUFBO0VBQ0EsY0FBQTtFQUNBLGlCQUFBO0VBQ0EsZ0JBQUE7RUFDQSxZQUFBO0VBQ0EsYUFBQTtBQ0FGOztBREdBO0VBQ0UsV0FBQTtFQUNBLGVBQUE7RUFDQSxvQkFBQTtFQUNBLGdCQUFBO0FDQUY7O0FER0E7RUFDRSxlQUFBO0VBQ0EsZ0JBQUE7RUFDQSxtQkFBQTtBQ0FGOztBREdBO0VBQ0UsbUVBQUE7RUFDQSxxQkFBQTtFQUNBLFlBQUE7RUFDQSxnQkFBQTtFQUNBLHNCQUFBO0VBQ0EsV0FBQTtFQUNBLGlCQUFBO0FDQUY7O0FER0E7RUFDRSw0QkFBQTtBQ0FGOztBREdBO0VBQ0UsZ0NBQUE7QUNBRjs7QURHQTtFQUNFLDRCQUFBO0FDQUY7O0FER0E7RUFDRSxnQ0FBQTtBQ0FGOztBREdBO0VBQ0UsNEJBQUE7QUNBRjs7QURHQTtFQUNFLGdDQUFBO0FDQUY7O0FER0E7RUFDRSw0QkFBQTtBQ0FGOztBREdBO0VBQ0UsZ0NBQUE7QUNBRjs7QURHQTtFQUNFLDRCQUFBO0FDQUY7O0FER0E7RUFDRSw0QkFBQTtBQ0FGOztBREdBO0VBQ0Usd0JBQUE7QUNBRjs7QURHQTtFQUNFLGlCQUFBO0FDQUY7O0FER0E7RUFDRSxjQUFBO0VBQ0EsZUFBQTtBQ0FGOztBREdBO0VBQ0UsY0FBQTtBQ0FGOztBREdBO0VBQ0UsYUFBQTtBQ0FGOztBREdBO0VBQ0UseUJBQUE7RUFDQSxlQUFBO0VBQ0EscUJBQUE7RUFDQSxlQUFBO0VBQ0EsWUFBQTtFQUNBLGtCQUFBO0VBQ0EsWUFBQTtBQ0FGO0FERUU7RUFDRSxpQkFBQTtBQ0FKOztBRElBO0VBQ0UsY0FBQTtBQ0RGOztBRElBO0VBQ0UsbUJBQUE7RUFDQSxlQUFBO0VBR0EsYUFBQTtFQUNBLGFBQUE7QUNERjtBREdFO0VBQ0UsY0FBQTtBQ0RKO0FER0k7RUFDRSxpQkFBQTtBQ0ROO0FES0U7RUFDRSxjQUFBO0FDSEo7QURNRTtFQUNFLHNCQUFBO0FDSko7QURPRTtFQUNFLGNBQUE7QUNMSjtBRFFFO0VBQ0Usc0JBQUE7QUNOSjtBRFNFO0VBQ0UsaUJBQUE7QUNQSjtBRFVFO0VBQ0UsZ0JBQUE7RUFDQSxjQUFBO0FDUko7O0FEWUE7RUFDRTtJQUNFLFdBQUE7SUFDQSxnQkFBQTtFQ1RGOztFRFlBO0lBQ0UsZ0JBQUE7SUFDQSx5QkFBQTtJQUNBLGFBQUE7SUFDQSx5QkFBQTtJQUNBLGdCQUFBO0lBQ0EsY0FBQTtJQUNBLHFCQUFBO0lBQ0Esa0JBQUE7SUFDQSxXQUFBO0lBQ0EsVUFBQTtFQ1RGOztFRFlBO0lBQ0UsY0FBQTtJQUNBLFlBQUE7RUNURjtBQUNGIiwiZmlsZSI6IlNob3djYXNlL1Byb2R1Y3RDYXRhbG9nL3B1cmVqcy9zdHlsZXMuY3NzIiwic291cmNlc0NvbnRlbnQiOlsibGFiZWwge1xuICBmb250LXdlaWdodDogbm9ybWFsO1xuICBtYXJnaW46IDA7XG59XG5cbi5jYXJkLWxheW91dC5nYy1ncmlkIHtcbiAgYm9yZGVyOiAwO1xufVxuXG4uY2FyZC1sYXlvdXQgLmdjLXJvdyB7XG4gIHBhZGRpbmc6IDNweDtcbiAgdGV4dC1hbGlnbjogY2VudGVyO1xuXG4gIC5nYy1jZWxsIHtcbiAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgfVxufVxuXG4jZ3JpZCB7XG4gIGhlaWdodDogMTAwJTtcbiAgbGVmdDogMjIwcHg7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgcmlnaHQ6IDA7XG59XG5cbi5kZW1vLWNvbnRhaW5lciB7XG4gIGhlaWdodDogMTAwJTtcbiAgcG9zaXRpb246IHJlbGF0aXZlO1xuICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgd2lkdGg6IDEwMCU7XG59XG5cbi5maWx0ZXItcGFuZWwge1xuICBib3JkZXI6IDA7XG4gIGRpc3BsYXk6IGJsb2NrO1xuICBmbG9hdDogbGVmdDtcbiAgaGVpZ2h0OiAxMDAlO1xuICBvdmVyZmxvdzogYXV0bztcbiAgcGFkZGluZy1sZWZ0OiA4cHg7XG4gIHBvc2l0aW9uOiBzdGF0aWM7XG4gIHdpZHRoOiAyMTlweDtcbiAgei1pbmRleDogYXV0bztcbn1cblxuLmZpbHRlci1oZWFkZXIge1xuICBjb2xvcjogIzk5OTtcbiAgZm9udC1zaXplOiAxN3B4O1xuICBwYWRkaW5nLWJvdHRvbTogMTBweDtcbiAgcGFkZGluZy10b3A6IDZweDtcbn1cblxuLmZpbHRlci1kZXRhaWxzIHtcbiAgZm9udC1zaXplOiAxNHB4O1xuICBmb250LXdlaWdodDogNzAwO1xuICBwYWRkaW5nLWJvdHRvbTogM3B4O1xufVxuXG4uc3RhcnMtYm94IHtcbiAgYmFja2dyb3VuZC1pbWFnZTogdXJsKCcvZGF0YXZpZXdzanMvZGVtb3MvaW1hZ2VzL3N0YXItcmF0aW5ncy5wbmcnKTtcbiAgZGlzcGxheTogaW5saW5lLWJsb2NrO1xuICBoZWlnaHQ6IDEzcHg7XG4gIG92ZXJmbG93OiBoaWRkZW47XG4gIHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7XG4gIHdpZHRoOiA2NXB4O1xuICBtYXJnaW4tcmlnaHQ6IDRweDtcbn1cblxuLnN0YXJzLTAge1xuICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAtNjVweCAwO1xufVxuXG4uc3RhcnMtMC01IHtcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogLTUycHggLTE5cHg7XG59XG5cbi5zdGFycy0xIHtcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogLTUycHggMDtcbn1cblxuLnN0YXJzLTEtNSB7XG4gIGJhY2tncm91bmQtcG9zaXRpb246IC0zOXB4IC0xOXB4O1xufVxuXG4uc3RhcnMtMiB7XG4gIGJhY2tncm91bmQtcG9zaXRpb246IC0zOXB4IDA7XG59XG5cbi5zdGFycy0yLTUge1xuICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAtMjZweCAtMTlweDtcbn1cblxuLnN0YXJzLTMge1xuICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAtMjZweCAwO1xufVxuXG4uc3RhcnMtMy01IHtcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogLTEzcHggLTE5cHg7XG59XG5cbi5zdGFycy00IHtcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogLTEzcHggMDtcbn1cblxuLnN0YXJzLTQtNSB7XG4gIGJhY2tncm91bmQtcG9zaXRpb246IDAgLTE4cHg7XG59XG5cbi5zdGFycy01IHtcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogMCAwO1xufVxuXG4udHYtaW1hZ2Uge1xuICBtYXJnaW4tbGVmdDogMTBweDtcbn1cblxuLnR2LWJyYW5kIHtcbiAgY29sb3I6ICNkM2QzZDM7XG4gIGZvbnQtc2l6ZTogMTNweDtcbn1cblxuLnR2LXByaWNlIHtcbiAgY29sb3I6ICNiMTI3MDQ7XG59XG5cbi5tb2JpbGUtZmlsdGVyLWVudHJ5IHtcbiAgZGlzcGxheTogbm9uZTtcbn1cblxuLmZpbHRlci1jb25kaXRpb24ge1xuICBib3JkZXI6IDFweCBzb2xpZCAjZDNkM2QzO1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbiAgZm9udC1zaXplOiAxNnB4O1xuICBoZWlnaHQ6IDI1cHg7XG4gIHRleHQtYWxpZ246IGNlbnRlcjtcbiAgd2lkdGg6IDEwMHB4O1xuXG4gIC5maWx0ZXItbGFiZWwge1xuICAgIG1hcmdpbi1yaWdodDogNXB4O1xuICB9XG59XG5cbi5zbGljZXIge1xuICBtYXJnaW46IDEwcHggMDtcbn1cblxuLnNsaWNlci1pdGVtIHtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBkaXNwbGF5OiAtd2Via2l0LWJveDtcbiAgZGlzcGxheTogLW1zLWZsZXhib3g7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIG1hcmdpbjogMnB4IDA7XG5cbiAgJi5zZWxlY3RlZCB7XG4gICAgY29sb3I6ICMzMzdhYjc7XG5cbiAgICAubGFiZWwge1xuICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7XG4gICAgfVxuICB9XG5cbiAgJjpob3ZlciB7XG4gICAgY29sb3I6ICNlNDc5MTE7XG4gIH1cblxuICAmLmZpbHRlcmVkIHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmO1xuICB9XG5cbiAgJi5maWx0ZXJlZE91dEJ5T3RoZXIge1xuICAgIGNvbG9yOiAjYTZhOGIxO1xuICB9XG5cbiAgJi5maWx0ZXJlZE91dEJ5U2VsZiB7XG4gICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZjtcbiAgfVxuXG4gIGlucHV0IHtcbiAgICBtYXJnaW4tcmlnaHQ6IDRweDtcbiAgfVxuXG4gIC5jb3VudC1iYWRnZSB7XG4gICAgbWFyZ2luLWxlZnQ6IDRweDtcbiAgICBjb2xvcjogI2EyOTk5OTtcbiAgfVxufVxuXG5AbWVkaWEgb25seSBzY3JlZW4gYW5kIChtYXgtd2lkdGg6IDc2OHB4KSB7XG4gICNncmlkIHtcbiAgICBoZWlnaHQ6IDkwJTtcbiAgICBwb3NpdGlvbjogc3RhdGljO1xuICB9XG5cbiAgLmZpbHRlci1wYW5lbCB7XG4gICAgYmFja2dyb3VuZDogI2ZmZjtcbiAgICBib3JkZXI6IDFweCBzb2xpZCAjZDNkM2QzO1xuICAgIGRpc3BsYXk6IG5vbmU7XG4gICAgaGVpZ2h0OiBjYWxjKDEwMCUgLSAyNXB4KTtcbiAgICBtYXJnaW4tdG9wOiAtMXB4O1xuICAgIG92ZXJmbG93OiBhdXRvO1xuICAgIHBhZGRpbmc6IDVweCAwIDAgMTBweDtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgd2lkdGg6IDEwMCU7XG4gICAgei1pbmRleDogMTtcbiAgfVxuXG4gIC5tb2JpbGUtZmlsdGVyLWVudHJ5IHtcbiAgICBkaXNwbGF5OiBibG9jaztcbiAgICBoZWlnaHQ6IDI1cHg7XG4gIH1cbn1cbiIsImxhYmVsIHtcbiAgZm9udC13ZWlnaHQ6IG5vcm1hbDtcbiAgbWFyZ2luOiAwO1xufVxuXG4uY2FyZC1sYXlvdXQuZ2MtZ3JpZCB7XG4gIGJvcmRlcjogMDtcbn1cblxuLmNhcmQtbGF5b3V0IC5nYy1yb3cge1xuICBwYWRkaW5nOiAzcHg7XG4gIHRleHQtYWxpZ246IGNlbnRlcjtcbn1cbi5jYXJkLWxheW91dCAuZ2Mtcm93IC5nYy1jZWxsIHtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG59XG5cbiNncmlkIHtcbiAgaGVpZ2h0OiAxMDAlO1xuICBsZWZ0OiAyMjBweDtcbiAgcG9zaXRpb246IGFic29sdXRlO1xuICByaWdodDogMDtcbn1cblxuLmRlbW8tY29udGFpbmVyIHtcbiAgaGVpZ2h0OiAxMDAlO1xuICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gIHVzZXItc2VsZWN0OiBub25lO1xuICB3aWR0aDogMTAwJTtcbn1cblxuLmZpbHRlci1wYW5lbCB7XG4gIGJvcmRlcjogMDtcbiAgZGlzcGxheTogYmxvY2s7XG4gIGZsb2F0OiBsZWZ0O1xuICBoZWlnaHQ6IDEwMCU7XG4gIG92ZXJmbG93OiBhdXRvO1xuICBwYWRkaW5nLWxlZnQ6IDhweDtcbiAgcG9zaXRpb246IHN0YXRpYztcbiAgd2lkdGg6IDIxOXB4O1xuICB6LWluZGV4OiBhdXRvO1xufVxuXG4uZmlsdGVyLWhlYWRlciB7XG4gIGNvbG9yOiAjOTk5O1xuICBmb250LXNpemU6IDE3cHg7XG4gIHBhZGRpbmctYm90dG9tOiAxMHB4O1xuICBwYWRkaW5nLXRvcDogNnB4O1xufVxuXG4uZmlsdGVyLWRldGFpbHMge1xuICBmb250LXNpemU6IDE0cHg7XG4gIGZvbnQtd2VpZ2h0OiA3MDA7XG4gIHBhZGRpbmctYm90dG9tOiAzcHg7XG59XG5cbi5zdGFycy1ib3gge1xuICBiYWNrZ3JvdW5kLWltYWdlOiB1cmwoXCIvZGF0YXZpZXdzanMvZGVtb3MvaW1hZ2VzL3N0YXItcmF0aW5ncy5wbmdcIik7XG4gIGRpc3BsYXk6IGlubGluZS1ibG9jaztcbiAgaGVpZ2h0OiAxM3B4O1xuICBvdmVyZmxvdzogaGlkZGVuO1xuICB2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlO1xuICB3aWR0aDogNjVweDtcbiAgbWFyZ2luLXJpZ2h0OiA0cHg7XG59XG5cbi5zdGFycy0wIHtcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogLTY1cHggMDtcbn1cblxuLnN0YXJzLTAtNSB7XG4gIGJhY2tncm91bmQtcG9zaXRpb246IC01MnB4IC0xOXB4O1xufVxuXG4uc3RhcnMtMSB7XG4gIGJhY2tncm91bmQtcG9zaXRpb246IC01MnB4IDA7XG59XG5cbi5zdGFycy0xLTUge1xuICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAtMzlweCAtMTlweDtcbn1cblxuLnN0YXJzLTIge1xuICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAtMzlweCAwO1xufVxuXG4uc3RhcnMtMi01IHtcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogLTI2cHggLTE5cHg7XG59XG5cbi5zdGFycy0zIHtcbiAgYmFja2dyb3VuZC1wb3NpdGlvbjogLTI2cHggMDtcbn1cblxuLnN0YXJzLTMtNSB7XG4gIGJhY2tncm91bmQtcG9zaXRpb246IC0xM3B4IC0xOXB4O1xufVxuXG4uc3RhcnMtNCB7XG4gIGJhY2tncm91bmQtcG9zaXRpb246IC0xM3B4IDA7XG59XG5cbi5zdGFycy00LTUge1xuICBiYWNrZ3JvdW5kLXBvc2l0aW9uOiAwIC0xOHB4O1xufVxuXG4uc3RhcnMtNSB7XG4gIGJhY2tncm91bmQtcG9zaXRpb246IDAgMDtcbn1cblxuLnR2LWltYWdlIHtcbiAgbWFyZ2luLWxlZnQ6IDEwcHg7XG59XG5cbi50di1icmFuZCB7XG4gIGNvbG9yOiAjZDNkM2QzO1xuICBmb250LXNpemU6IDEzcHg7XG59XG5cbi50di1wcmljZSB7XG4gIGNvbG9yOiAjYjEyNzA0O1xufVxuXG4ubW9iaWxlLWZpbHRlci1lbnRyeSB7XG4gIGRpc3BsYXk6IG5vbmU7XG59XG5cbi5maWx0ZXItY29uZGl0aW9uIHtcbiAgYm9yZGVyOiAxcHggc29saWQgI2QzZDNkMztcbiAgY3Vyc29yOiBwb2ludGVyO1xuICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gIGZvbnQtc2l6ZTogMTZweDtcbiAgaGVpZ2h0OiAyNXB4O1xuICB0ZXh0LWFsaWduOiBjZW50ZXI7XG4gIHdpZHRoOiAxMDBweDtcbn1cbi5maWx0ZXItY29uZGl0aW9uIC5maWx0ZXItbGFiZWwge1xuICBtYXJnaW4tcmlnaHQ6IDVweDtcbn1cblxuLnNsaWNlciB7XG4gIG1hcmdpbjogMTBweCAwO1xufVxuXG4uc2xpY2VyLWl0ZW0ge1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICBjdXJzb3I6IHBvaW50ZXI7XG4gIGRpc3BsYXk6IC13ZWJraXQtYm94O1xuICBkaXNwbGF5OiAtbXMtZmxleGJveDtcbiAgZGlzcGxheTogZmxleDtcbiAgbWFyZ2luOiAycHggMDtcbn1cbi5zbGljZXItaXRlbS5zZWxlY3RlZCB7XG4gIGNvbG9yOiAjMzM3YWI3O1xufVxuLnNsaWNlci1pdGVtLnNlbGVjdGVkIC5sYWJlbCB7XG4gIGZvbnQtd2VpZ2h0OiBib2xkO1xufVxuLnNsaWNlci1pdGVtOmhvdmVyIHtcbiAgY29sb3I6ICNlNDc5MTE7XG59XG4uc2xpY2VyLWl0ZW0uZmlsdGVyZWQge1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmO1xufVxuLnNsaWNlci1pdGVtLmZpbHRlcmVkT3V0QnlPdGhlciB7XG4gIGNvbG9yOiAjYTZhOGIxO1xufVxuLnNsaWNlci1pdGVtLmZpbHRlcmVkT3V0QnlTZWxmIHtcbiAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZjtcbn1cbi5zbGljZXItaXRlbSBpbnB1dCB7XG4gIG1hcmdpbi1yaWdodDogNHB4O1xufVxuLnNsaWNlci1pdGVtIC5jb3VudC1iYWRnZSB7XG4gIG1hcmdpbi1sZWZ0OiA0cHg7XG4gIGNvbG9yOiAjYTI5OTk5O1xufVxuXG5AbWVkaWEgb25seSBzY3JlZW4gYW5kIChtYXgtd2lkdGg6IDc2OHB4KSB7XG4gICNncmlkIHtcbiAgICBoZWlnaHQ6IDkwJTtcbiAgICBwb3NpdGlvbjogc3RhdGljO1xuICB9XG5cbiAgLmZpbHRlci1wYW5lbCB7XG4gICAgYmFja2dyb3VuZDogI2ZmZjtcbiAgICBib3JkZXI6IDFweCBzb2xpZCAjZDNkM2QzO1xuICAgIGRpc3BsYXk6IG5vbmU7XG4gICAgaGVpZ2h0OiBjYWxjKDEwMCUgLSAyNXB4KTtcbiAgICBtYXJnaW4tdG9wOiAtMXB4O1xuICAgIG92ZXJmbG93OiBhdXRvO1xuICAgIHBhZGRpbmc6IDVweCAwIDAgMTBweDtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgd2lkdGg6IDEwMCU7XG4gICAgei1pbmRleDogMTtcbiAgfVxuXG4gIC5tb2JpbGUtZmlsdGVyLWVudHJ5IHtcbiAgICBkaXNwbGF5OiBibG9jaztcbiAgICBoZWlnaHQ6IDI1cHg7XG4gIH1cbn0iXX0= */