this.cart = cart;
this.fluidbook = this.cart.fluidbook;
this.data = this.fluidbook.settings.basketReferences;
+ this.filters = {};
this.init();
}
return this.openSelection(cb);
},
+ updateFilters: function () {
+ var hasVisible = false;
+ $('#grandvision-selection .item').each(function () {
+ var hide = false;
+ var a = $(this);
+ $("#grandvision-selection .filters select").each(function () {
+ var vals = $(this).val();
+ if (vals.length === 0) {
+ return;
+ }
+ var name = $(this).attr('name');
+ var attrvalues = $(a).attr('data-' + name).split(',');
+ var inter = vals.filter(function (n) {
+ return attrvalues.indexOf(n) !== -1;
+ });
+ if (inter.length === 0) {
+ hide = true;
+ }
+ });
+ if (hide) {
+ $(a).hide();
+ } else {
+ hasVisible = true;
+ $(a).show();
+ }
+
+ });
+
+ if (hasVisible) {
+ $("#emptyres").hide();
+ } else {
+ $("#emptyres").show();
+ }
+ },
+
openSelection: function (cb) {
+ var $this = this;
var res = '<div id="grandvision-cart">';
res += this.fluidbook.menu.getCaption('', true);
res += '</div>';
this.fluidbook.menu.viewWrap(res, 'cart-grandvision-selection', 'data-max-width="1200" data-min-width="1200"');
+
+ $("#grandvision-cart select").each(function () {
+ var allValues = $this.filters[$(this).attr('name')].values;
+ $this.filters[$(this).attr('name')].multiselect = $(this).multiSelect({
+ 'noneText': $(this).data('label'),
+ presets: [
+ {
+ name: 'All',
+ options: allValues,
+ },
+ ]
+ }).on('change', function () {
+ $this.updateFilters();
+ });
+ });
+
+
if (cb !== undefined) {
cb();
}
},
+
+
cartSelection: function () {
var $this = this;
- var res = '<div id="grandvision-selection">';
- res += '<h2>My Selection</h2>';
- res += '<div class="filters"></div>';
- res += '<div class="items">';
+
+ this.filters = {
+ brand: {col: 'BRAND', label: 'Brand', values: []},
+ category: {col: 'Category', label: 'Category', values: []},
+ gender: {col: 'Gender', label: 'Gender', values: []},
+ material: {col: 'Material', label: 'Material', values: []}
+ };
+
+ var selection = '';
$.each(this.items, function (k, item) {
var data = $this.getProductData(item);
var infos = ['Brand: ' + data.BRAND, 'Color: ' + data['Color Code']];
}
infos.push('EAN: ' + item);
- res += '<div class="item" data-ref="' + item + '">';
- res += '<div class="img"><img src="data/commerce/' + item + '-front.jpg" /></div>';
- res += '<h3>' + data['Model Code'] + '</h3>';
- res += '<div class="infos">' + infos.join(' | ') + '</div>';
- res += '</div>';
+ $.each($this.filters, function (fname, filter) {
+ if ($this.filters[fname].values.indexOf(data[filter.col]) === -1) {
+ $this.filters[fname].values.push(data[filter.col]);
+ }
+ });
+
+ selection += '<div class="item" data-ref="' + item + '" data-brand="' + data.BRAND + '" data-category="' + data.Category + '" data-gender="' + data.Gender + '" data-material="' + data.Material + '">';
+ selection += '<div class="img">';
+ if (data.front) {
+ selection += '<img src="data/commerce/' + item + '-front.jpg" />';
+ }
+ selection += '</div>';
+ selection += '<div class="infos"><h3>' + data['Model Code'] + '</h3>';
+ selection += '<p>' + infos.join(' | ') + '</p></div>';
+ selection += '</div>';
});
+
+ var res = '<div id="grandvision-selection">';
+ res += '<h2>My Selection</h2>';
+ res += '<div class="filters">';
+ $.each(this.filters, function (name, data) {
+ res += '<select multiple data-label="' + data.label + '" name="' + name + '">';
+ $.each(data.values, function (k, v) {
+ res += '<option value="' + v + '">' + v + '</option>';
+ });
+ res += '</select>';
+ });
+ res += '</div>';
+ res += '<div class="items">';
+ res += selection;
res += '</div>';
+ res += '<div id="emptyres">No selected item match filters</div>';
res += '</div>';
return res;
},
--- /dev/null
+// jquery.multi-select.js
+// by mySociety
+// https://github.com/mysociety/jquery-multi-select
+
+;(function ($) {
+
+ "use strict";
+
+ var pluginName = "multiSelect",
+ defaults = {
+ 'containerHTML': '<div class="multi-select-container">',
+ 'menuHTML': '<div class="multi-select-menu">',
+ 'buttonHTML': '<span class="multi-select-button">',
+ 'menuItemsHTML': '<div class="multi-select-menuitems">',
+ 'menuItemHTML': '<label class="multi-select-menuitem">',
+ 'presetsHTML': '<div class="multi-select-presets">',
+ 'modalHTML': undefined,
+ 'menuItemTitleClass': 'multi-select-menuitem--titled',
+ 'activeClass': 'multi-select-container--open',
+ 'noneText': '-- Select --',
+ 'allText': undefined,
+ 'presets': undefined,
+ 'positionedMenuClass': 'multi-select-container--positioned',
+ 'positionMenuWithin': undefined,
+ 'viewportBottomGutter': 20,
+ 'menuMinHeight': 200
+ };
+
+ /**
+ * @constructor
+ */
+ function MultiSelect(element, options) {
+ this.element = element;
+ this.$element = $(element);
+ this.settings = $.extend({}, defaults, options);
+ this._defaults = defaults;
+ this._name = pluginName;
+ this.init();
+ }
+
+ function arraysAreEqual(array1, array2) {
+ if (array1.length != array2.length) {
+ return false;
+ }
+
+ array1.sort();
+ array2.sort();
+
+ for (var i = 0; i < array1.length; i++) {
+ if (array1[i] !== array2[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ $.extend(MultiSelect.prototype, {
+
+ init: function () {
+ this.checkSuitableInput();
+ this.findLabels();
+ this.constructContainer();
+ this.constructButton();
+ this.constructMenu();
+ this.constructModal();
+
+ this.setUpBodyClickListener();
+ this.setUpLabelsClickListener();
+
+ this.$element.hide();
+ },
+
+ checkSuitableInput: function (text) {
+ if (this.$element.is('select[multiple]') === false) {
+ throw new Error('$.multiSelect only works on <select multiple> elements');
+ }
+ },
+
+ findLabels: function () {
+ this.$labels = $('label[for="' + this.$element.attr('id') + '"]');
+ },
+
+ constructContainer: function () {
+ this.$container = $(this.settings['containerHTML']);
+ this.$element.data('multi-select-container', this.$container);
+ this.$container.insertAfter(this.$element);
+ },
+
+ constructButton: function () {
+ var _this = this;
+ this.$button = $(this.settings['buttonHTML']);
+ this.$button.attr({
+ 'role': 'button',
+ 'aria-haspopup': 'true',
+ 'tabindex': 0,
+ 'aria-label': this.$labels.eq(0).text()
+ })
+ .on('keydown.multiselect', function (e) {
+ var key = e.which;
+ var returnKey = 13;
+ var escapeKey = 27;
+ var spaceKey = 32;
+ var downArrow = 40;
+ if ((key === returnKey) || (key === spaceKey)) {
+ e.preventDefault();
+ _this.$button.click();
+ } else if (key === downArrow) {
+ e.preventDefault();
+ _this.menuShow();
+ var group = _this.$presets || _this.$menuItems;
+ group.children(":first").focus();
+ } else if (key === escapeKey) {
+ _this.menuHide();
+ }
+ }).on('click.multiselect', function (e) {
+ _this.menuToggle();
+ })
+ .appendTo(this.$container);
+
+ this.$element.on('change.multiselect', function () {
+ _this.updateButtonContents();
+ });
+
+ this.updateButtonContents();
+ },
+
+ updateButtonContents: function () {
+ var _this = this;
+ var options = [];
+ var selected = [];
+
+ this.$element.find('option').each(function () {
+ var text = /** @type string */ ($(this).text());
+ options.push(text);
+ if ($(this).is(':selected')) {
+ selected.push($.trim(text));
+ }
+ });
+
+ this.$button.empty();
+
+ if (selected.length == 0) {
+ this.$button.removeClass('active').text(this.settings['noneText']);
+ } else if ((selected.length === options.length) && this.settings['allText']) {
+ this.$button.removeClass('active').text(this.settings['allText']);
+ } else {
+ this.$button.addClass('active').text(this.settings['noneText'] + ' : ' + selected.join(', '));
+ }
+ },
+
+ constructMenu: function () {
+ var _this = this;
+
+ this.$menu = $(this.settings['menuHTML']);
+ this.$menu.attr({
+ 'role': 'menu'
+ }).on('keyup.multiselect', function (e) {
+ var key = e.which;
+ var escapeKey = 27;
+ if (key === escapeKey) {
+ _this.menuHide();
+ _this.$button.focus();
+ }
+ })
+ .appendTo(this.$container);
+
+ this.constructMenuItems();
+
+ if (this.settings['presets']) {
+ this.constructPresets();
+ }
+ },
+
+ constructMenuItems: function () {
+ var _this = this;
+
+ this.$menuItems = $(this.settings['menuItemsHTML']);
+ this.$menu.append(this.$menuItems);
+
+ this.$element.on('change.multiselect', function (e, internal) {
+ // Don't need to update the menu items if this
+ // change event was fired by our tickbox handler.
+ if (internal !== true) {
+ _this.updateMenuItems();
+ }
+ });
+
+ this.updateMenuItems();
+ },
+
+ updateMenuItems: function () {
+ var _this = this;
+ this.$menuItems.empty();
+
+ this.$element.children('optgroup,option').each(function (index, element) {
+ var $item;
+ if (element.nodeName === 'OPTION') {
+ $item = _this.constructMenuItem($(element), index);
+ _this.$menuItems.append($item);
+ } else {
+ _this.constructMenuItemsGroup($(element), index);
+ }
+ });
+ },
+
+ upDown: function (type, e) {
+ var key = e.which;
+ var upArrow = 38;
+ var downArrow = 40;
+
+ if (key === upArrow) {
+ e.preventDefault();
+ var prev = $(e.currentTarget).prev();
+ if (prev.length) {
+ prev.focus();
+ } else if (this.$presets && type === 'menuitem') {
+ this.$presets.children(':last').focus();
+ } else {
+ this.$button.focus();
+ }
+ } else if (key === downArrow) {
+ e.preventDefault();
+ var next = $(e.currentTarget).next();
+ if (next.length || type === 'menuitem') {
+ next.focus();
+ } else {
+ this.$menuItems.children(':first').focus();
+ }
+ }
+ },
+
+ constructPresets: function () {
+ var _this = this;
+ this.$presets = $(this.settings['presetsHTML']);
+ this.$menu.append(this.$presets);
+
+ $.each(this.settings['presets'], function (i, preset) {
+ var unique_id = _this.$element.attr('name') + '_preset_' + i;
+ var $item = $(_this.settings['menuItemHTML'])
+ .attr({
+ 'for': unique_id,
+ 'role': 'menuitem'
+ })
+ .text(' ' + preset.name)
+ .on('keydown.multiselect', _this.upDown.bind(_this, 'preset'))
+ .appendTo(_this.$presets);
+
+ var $input = $('<input>')
+ .attr({
+ 'type': 'checkbox',
+ 'name': _this.$element.attr('name') + '_presets',
+ 'id': unique_id
+ })
+ .prependTo($item);
+
+ $input.on('change.multiselect', function () {
+ if ($(this).prop('checked')) {
+ _this.$element.val(preset.options);
+ } else {
+ _this.$element.val([]);
+ }
+ _this.$element.trigger('change');
+ });
+ });
+ _this.$presets.append('<button>Valider</button>');
+ this.$presets.on('click','button',function(){
+ _this.menuHide();
+ return false;
+ });
+
+ this.$element.on('change.multiselect', function () {
+ _this.updatePresets();
+ });
+
+ this.updatePresets();
+ },
+
+ updatePresets: function () {
+ var _this = this;
+
+ $.each(this.settings['presets'], function (i, preset) {
+ var unique_id = _this.$element.attr('name') + '_preset_' + i;
+ var $input = _this.$presets.find('#' + unique_id);
+
+ if (arraysAreEqual(preset.options || [], _this.$element.val() || [])) {
+ $input.prop('checked', true);
+ } else {
+ $input.prop('checked', false);
+ }
+ });
+ },
+
+ constructMenuItemsGroup: function ($optgroup, optgroup_index) {
+ var _this = this;
+
+ $optgroup.children('option').each(function (option_index, option) {
+ var $item = _this.constructMenuItem($(option), optgroup_index + '_' + option_index);
+ var cls = _this.settings['menuItemTitleClass'];
+ if (option_index !== 0) {
+ cls += 'sr';
+ }
+ $item.addClass(cls).attr('data-group-title', $optgroup.attr('label'));
+ _this.$menuItems.append($item);
+ });
+ },
+
+ constructMenuItem: function ($option, option_index) {
+ var unique_id = this.$element.attr('name') + '_' + option_index;
+ var $item = $(this.settings['menuItemHTML'])
+ .attr({
+ 'for': unique_id,
+ 'role': 'menuitem'
+ })
+ .on('keydown.multiselect', this.upDown.bind(this, 'menuitem'))
+ .text(' ' + $option.text());
+
+ var $input = $('<input>')
+ .attr({
+ 'type': 'checkbox',
+ 'id': unique_id,
+ 'value': $option.val()
+ })
+ .prependTo($item);
+
+ if ($option.is(':disabled')) {
+ $input.attr('disabled', 'disabled');
+ }
+ if ($option.is(':selected')) {
+ $input.prop('checked', 'checked');
+ }
+
+ $input.on('change.multiselect', function () {
+ if ($(this).prop('checked')) {
+ $option.prop('selected', true);
+ } else {
+ $option.prop('selected', false);
+ }
+
+ // .prop() on its own doesn't generate a change event.
+ // Other plugins might want to do stuff onChange.
+ $option.trigger('change', [true]);
+ });
+
+ return $item;
+ },
+
+ constructModal: function () {
+ var _this = this;
+
+ if (this.settings['modalHTML']) {
+ this.$modal = $(this.settings['modalHTML']);
+ this.$modal.on('click.multiselect', function () {
+ _this.menuHide();
+ })
+ this.$modal.insertBefore(this.$menu);
+ }
+ },
+
+ setUpBodyClickListener: function () {
+ var _this = this;
+
+ // Hide the $menu when you click outside of it.
+ $('html').on('click.multiselect', function () {
+ _this.menuHide();
+ });
+
+ // Stop click events from inside the $button or $menu from
+ // bubbling up to the body and closing the menu!
+ this.$container.on('click.multiselect', function (e) {
+ e.stopPropagation();
+ });
+ },
+
+ setUpLabelsClickListener: function () {
+ var _this = this;
+ this.$labels.on('click.multiselect', function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ _this.menuToggle();
+ });
+ },
+
+ menuShow: function () {
+ $('html').trigger('click.multiselect'); // Close any other open menus
+ this.$container.addClass(this.settings['activeClass']);
+
+ if (this.settings['positionMenuWithin'] && this.settings['positionMenuWithin'] instanceof $) {
+ var menuLeftEdge = this.$menu.offset().left + this.$menu.outerWidth();
+ var withinLeftEdge = this.settings['positionMenuWithin'].offset().left +
+ this.settings['positionMenuWithin'].outerWidth();
+
+ if (menuLeftEdge > withinLeftEdge) {
+ this.$menu.css('width', (withinLeftEdge - this.$menu.offset().left));
+ this.$container.addClass(this.settings['positionedMenuClass']);
+ }
+ }
+
+ var menuBottom = this.$menu.offset().top + this.$menu.outerHeight();
+ var viewportBottom = $(window).scrollTop() + $(window).height();
+ if (menuBottom > viewportBottom - this.settings['viewportBottomGutter']) {
+ this.$menu.css({
+ 'maxHeight': Math.max(
+ viewportBottom - this.settings['viewportBottomGutter'] - this.$menu.offset().top,
+ this.settings['menuMinHeight']
+ ),
+ 'overflow': 'scroll'
+ });
+ } else {
+ this.$menu.css({
+ 'maxHeight': '',
+ 'overflow': ''
+ });
+ }
+ },
+
+ menuHide: function () {
+ this.$container.removeClass(this.settings['activeClass']);
+ this.$container.removeClass(this.settings['positionedMenuClass']);
+ this.$menu.css('width', 'auto');
+ },
+
+ menuToggle: function () {
+ if (this.$container.hasClass(this.settings['activeClass'])) {
+ this.menuHide();
+ } else {
+ this.menuShow();
+ }
+ }
+
+ });
+
+ $.fn[pluginName] = function (options) {
+ return this.each(function () {
+ if (!$.data(this, "plugin_" + pluginName)) {
+ $.data(this, "plugin_" + pluginName,
+ new MultiSelect(this, options));
+ }
+ });
+ };
+
+})(jQuery);