Update compound filters demo.
parent
6934fd3079
commit
eec4bfc157
@ -1,70 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
title: Shuffle Adaptive Demo
|
||||
description: A responsive demo using the adaptive Twitter Bootstrap grid with compound filtering
|
||||
image: /demos/adaptive.jpg
|
||||
extraJS: [ "demos/gallery.js" ]
|
||||
extraCSS: [ "/css/gallery.css" ]
|
||||
---
|
||||
|
||||
<section class="container">
|
||||
<div class="row">
|
||||
<h2 class="col-12@sm">Adaptive Layout with Compound Filters</h2>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="gallery container">
|
||||
|
||||
<div class="filter-options row">
|
||||
|
||||
<div class="col-6@sm">
|
||||
<div class="filter-group filter--colors js-colors">
|
||||
<h5 class="filter__label">Colors</h5>
|
||||
<button class="btn btn--go" data-filter-value="green"><span class="visuallyhidden">Green</span></button>
|
||||
<button class="btn btn--primary" data-filter-value="blue"><span class="visuallyhidden">Blue</span></button>
|
||||
<button class="btn btn--danger" data-filter-value="red"><span class="visuallyhidden">Red</span></button>
|
||||
<button class="btn btn--warning" data-filter-value="orange"><span class="visuallyhidden">Orange</span></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6@sm">
|
||||
<div class="filter-group filter--shapes js-shapes">
|
||||
<h5 class="filter-group__label">Shapes</h5>
|
||||
<span class="ib">
|
||||
<input type="checkbox" value="circle" id="cb-circle"> <label for="cb-circle">Circle</label>
|
||||
</span>
|
||||
<span class="ib">
|
||||
<input type="checkbox" value="diamond" id="cb-diamond"> <label for="cb-diamond">Diamond</label>
|
||||
</span>
|
||||
<span class="ib">
|
||||
<input type="checkbox" value="square" id="cb-square"> <label for="cb-square">Square</label>
|
||||
</span>
|
||||
<span class="ib">
|
||||
<input type="checkbox" value="triangle" id="cb-triangle"> <label for="cb-triangle">Triangle</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="shape-up js-shuffle">
|
||||
{% for shape in site.shapes %}
|
||||
<div class="col-3@sm shape shape--{{ shape.shape }} shape--{{ shape.color }}" data-shape="{{ shape.shape }}" data-color="{{ shape.color }}">
|
||||
<div class="aspect">
|
||||
<div class="shape__inner">
|
||||
<div class="shape__space">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
<h2>Shuffle.js</h2>
|
||||
<p>{{ site.longDescription }}</p>
|
||||
</div>
|
||||
</section>
|
@ -0,0 +1,78 @@
|
||||
---
|
||||
layout: default
|
||||
title: Shuffle Compound Filters Demo
|
||||
description: A demo with compound filtering
|
||||
image: /demos/adaptive.jpg
|
||||
extraJS: [ "demos/compound-filters.js" ]
|
||||
extraCSS: [ "/css/gallery.css" ]
|
||||
prism: true
|
||||
---
|
||||
|
||||
<section class="container">
|
||||
<div class="row">
|
||||
<h2 class="col-12@sm">Compound Filters</h2>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="gallery container">
|
||||
|
||||
<div class="filter-options row">
|
||||
|
||||
<div class="col-6@sm">
|
||||
<div class="filter-group filter--colors js-colors">
|
||||
<h5 class="filter__label">Colors</h5>
|
||||
<button class="btn btn--go" data-value="green"><span class="visuallyhidden">Green</span></button>
|
||||
<button class="btn btn--primary" data-value="blue"><span class="visuallyhidden">Blue</span></button>
|
||||
<button class="btn btn--danger" data-value="red"><span class="visuallyhidden">Red</span></button>
|
||||
<button class="btn btn--warning" data-value="orange"><span class="visuallyhidden">Orange</span></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6@sm">
|
||||
<div class="filter-group filter--shapes js-shapes">
|
||||
<h5 class="filter-group__label">Shapes</h5>
|
||||
<span class="ib">
|
||||
<input type="checkbox" value="circle" id="cb-circle"> <label for="cb-circle">Circle</label>
|
||||
</span>
|
||||
<span class="ib">
|
||||
<input type="checkbox" value="diamond" id="cb-diamond"> <label for="cb-diamond">Diamond</label>
|
||||
</span>
|
||||
<span class="ib">
|
||||
<input type="checkbox" value="square" id="cb-square"> <label for="cb-square">Square</label>
|
||||
</span>
|
||||
<span class="ib">
|
||||
<input type="checkbox" value="triangle" id="cb-triangle"> <label for="cb-triangle">Triangle</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="shape-up js-shuffle">
|
||||
{% for shape in site.shapes %}
|
||||
<div class="col-3@sm shape shape--{{ shape.shape }} shape--{{ shape.color }}" data-shape="{{ shape.shape }}" data-color="{{ shape.color }}">
|
||||
<div class="aspect">
|
||||
<div class="shape__inner">
|
||||
<div class="shape__space"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="the-sizer col-1@xs col-1@sm"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<div class="container has-code-block">
|
||||
<div class="row">
|
||||
<div class="col-12@sm">
|
||||
<h2>Source code for this demo</h2>
|
||||
<p>Link to <a href="{{ site.baseurl }}/js/demos/compound-filters.js">demo source</a></p>
|
||||
<div class="code-block">
|
||||
<pre rel="JavaScript" data-src="{{ site.baseurl }}/js/demos/compound-filters.js"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
@ -0,0 +1,150 @@
|
||||
'use strict';
|
||||
|
||||
var Shuffle = window.shuffle;
|
||||
|
||||
// ES7 will have Array.prototype.includes.
|
||||
function arrayIncludes(array, value) {
|
||||
return array.indexOf(value) !== -1;
|
||||
}
|
||||
|
||||
// Convert an array-like object to a real array.
|
||||
function toArray(thing) {
|
||||
return Array.prototype.slice.call(thing);
|
||||
}
|
||||
|
||||
var Demo = function (element) {
|
||||
this.shapes = toArray(document.querySelectorAll('.js-shapes input'));
|
||||
this.colors = toArray(document.querySelectorAll('.js-colors button'));
|
||||
|
||||
this.shuffle = new Shuffle(element, {
|
||||
easing: 'cubic-bezier(0.165, 0.840, 0.440, 1.000)', // easeOutQuart
|
||||
sizer: '.the-sizer',
|
||||
});
|
||||
|
||||
this.filters = {
|
||||
shapes: [],
|
||||
colors: [],
|
||||
};
|
||||
|
||||
this._bindEventListeners();
|
||||
};
|
||||
|
||||
/**
|
||||
* Bind event listeners for when the filters change.
|
||||
*/
|
||||
Demo.prototype._bindEventListeners = function () {
|
||||
this._onShapeChange = this._handleShapeChange.bind(this);
|
||||
this._onColorChange = this._handleColorChange.bind(this);
|
||||
|
||||
this.shapes.forEach(function (input) {
|
||||
input.addEventListener('change', this._onShapeChange);
|
||||
}, this);
|
||||
|
||||
this.colors.forEach(function (button) {
|
||||
button.addEventListener('click', this._onColorChange);
|
||||
}, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the values of each checked input.
|
||||
* @return {Array.<string>}
|
||||
*/
|
||||
Demo.prototype._getCurrentShapeFilters = function () {
|
||||
return this.shapes.filter(function (input) {
|
||||
return input.checked;
|
||||
}).map(function (input) {
|
||||
return input.value;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the values of each `active` button.
|
||||
* @return {Array.<string>}
|
||||
*/
|
||||
Demo.prototype._getCurrentColorFilters = function () {
|
||||
return this.colors.filter(function (button) {
|
||||
return button.classList.contains('active');
|
||||
}).map(function (button) {
|
||||
return button.getAttribute('data-value');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* A shape input check state changed, update the current filters and filte.r
|
||||
*/
|
||||
Demo.prototype._handleShapeChange = function () {
|
||||
this.filters.shapes = this._getCurrentShapeFilters();
|
||||
this.filter();
|
||||
};
|
||||
|
||||
/**
|
||||
* A color button was clicked. Update filters and display.
|
||||
* @param {Event} evt Click event object.
|
||||
*/
|
||||
Demo.prototype._handleColorChange = function (evt) {
|
||||
var button = evt.currentTarget;
|
||||
|
||||
// Treat these buttons like radio buttons where only 1 can be selected.
|
||||
if (button.classList.contains('active')) {
|
||||
button.classList.remove('active');
|
||||
} else {
|
||||
this.colors.forEach(function (btn) {
|
||||
btn.classList.remove('active');
|
||||
});
|
||||
|
||||
button.classList.add('active');
|
||||
}
|
||||
|
||||
this.filters.colors = this._getCurrentColorFilters();
|
||||
this.filter();
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter shuffle based on the current state of filters.
|
||||
*/
|
||||
Demo.prototype.filter = function () {
|
||||
if (this.hasActiveFilters()) {
|
||||
this.shuffle.filter(this.itemPassesFilters.bind(this));
|
||||
} else {
|
||||
this.shuffle.filter(Shuffle.ALL_ITEMS);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* If any of the arrays in the `filters` property have a length of more than zero,
|
||||
* that means there is an active filter.
|
||||
* @return {boolean}
|
||||
*/
|
||||
Demo.prototype.hasActiveFilters = function () {
|
||||
return Object.keys(this.filters).some(function (key) {
|
||||
return this.filters[key].length > 0;
|
||||
}, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine whether an element passes the current filters.
|
||||
* @param {Element} element Element to test.
|
||||
* @return {boolean} Whether it satisfies all current filters.
|
||||
*/
|
||||
Demo.prototype.itemPassesFilters = function (element) {
|
||||
var shapes = this.filters.shapes;
|
||||
var colors = this.filters.colors;
|
||||
var shape = element.getAttribute('data-shape');
|
||||
var color = element.getAttribute('data-color');
|
||||
|
||||
// If there are active shape filters and this shape is not in that array.
|
||||
if (shapes.length > 0 && !arrayIncludes(shapes, shape)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there are active color filters and this color is not in that array.
|
||||
if (colors.length > 0 && !arrayIncludes(colors, color)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
window.demo = new Demo(document.querySelector('.js-shuffle'));
|
||||
});
|
@ -1,172 +0,0 @@
|
||||
|
||||
var Exports = {
|
||||
Modules : {}
|
||||
};
|
||||
|
||||
Exports.Modules.Gallery = (function($, undefined) {
|
||||
var $grid,
|
||||
$shapes,
|
||||
$colors,
|
||||
shapes = [],
|
||||
colors = [],
|
||||
|
||||
// Using shuffle with specific column widths
|
||||
columnWidths = {
|
||||
1170: 70,
|
||||
940: 60,
|
||||
724: 42
|
||||
},
|
||||
gutterWidths = {
|
||||
1170: 30,
|
||||
940: 20,
|
||||
724: 20
|
||||
},
|
||||
|
||||
init = function() {
|
||||
setVars();
|
||||
initFilters();
|
||||
initShuffle();
|
||||
},
|
||||
|
||||
setVars = function() {
|
||||
$grid = $('.js-shuffle');
|
||||
$shapes = $('.js-shapes');
|
||||
$colors = $('.js-colors');
|
||||
},
|
||||
|
||||
initShuffle = function() {
|
||||
// instantiate the plugin
|
||||
$grid.shuffle({
|
||||
speed : 250,
|
||||
easing : 'cubic-bezier(0.165, 0.840, 0.440, 1.000)', // easeOutQuart
|
||||
columnWidth: function( containerWidth ) {
|
||||
var colW = columnWidths[ containerWidth ];
|
||||
|
||||
// Default to container width
|
||||
if ( colW === undefined ) {
|
||||
colW = containerWidth;
|
||||
}
|
||||
return colW;
|
||||
},
|
||||
gutterWidth: function( containerWidth ) {
|
||||
var gutter = gutterWidths[ containerWidth ];
|
||||
|
||||
// Default to zero
|
||||
if ( gutter === undefined ) {
|
||||
gutter = 0;
|
||||
}
|
||||
return gutter;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
initFilters = function() {
|
||||
// shapes
|
||||
$shapes.find('input').on('change', function() {
|
||||
var $checked = $shapes.find('input:checked'),
|
||||
groups = [];
|
||||
|
||||
// At least one checkbox is checked, clear the array and loop through the checked checkboxes
|
||||
// to build an array of strings
|
||||
if ($checked.length !== 0) {
|
||||
$checked.each(function() {
|
||||
groups.push(this.value);
|
||||
});
|
||||
}
|
||||
shapes = groups;
|
||||
|
||||
filter();
|
||||
});
|
||||
|
||||
// colors
|
||||
$colors.find('button').on('click', function() {
|
||||
var $this = $(this),
|
||||
$alreadyChecked,
|
||||
checked = [],
|
||||
active = 'active',
|
||||
isActive;
|
||||
|
||||
// Already checked buttons which are not this one
|
||||
$alreadyChecked = $this.siblings('.' + active);
|
||||
|
||||
$this.toggleClass( active );
|
||||
|
||||
// Remove active on already checked buttons to act like radio buttons
|
||||
if ( $alreadyChecked.length ) {
|
||||
$alreadyChecked.removeClass( active );
|
||||
}
|
||||
|
||||
isActive = $this.hasClass( active );
|
||||
|
||||
if ( isActive ) {
|
||||
checked.push( $this.data( 'filterValue' ) );
|
||||
}
|
||||
|
||||
colors = checked;
|
||||
|
||||
filter();
|
||||
});
|
||||
},
|
||||
|
||||
filter = function() {
|
||||
if ( hasActiveFilters() ) {
|
||||
$grid.shuffle('shuffle', function($el) {
|
||||
return itemPassesFilters( $el.data() );
|
||||
});
|
||||
} else {
|
||||
$grid.shuffle( 'shuffle', 'all' );
|
||||
}
|
||||
},
|
||||
|
||||
itemPassesFilters = function(data) {
|
||||
|
||||
// If a shapes filter is active
|
||||
if ( shapes.length > 0 && !valueInArray(data.shape, shapes) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a colors filter is active
|
||||
if ( colors.length > 0 && !valueInArray(data.color, colors) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
hasActiveFilters = function() {
|
||||
return colors.length > 0 || shapes.length > 0;
|
||||
},
|
||||
|
||||
valueInArray = function(value, arr) {
|
||||
return $.inArray(value, arr) !== -1;
|
||||
};
|
||||
|
||||
// arrayContainsArray = function(arrToTest, requiredArr) {
|
||||
// var i = 0,
|
||||
// dictionary = {},
|
||||
// j;
|
||||
|
||||
// // Convert groups into object which we can test the keys
|
||||
// for (j = 0; j < arrToTest.length; j++) {
|
||||
// dictionary[ arrToTest[j] ] = true;
|
||||
// }
|
||||
|
||||
// // Loop through selected shapes, if that feature is not in this elements groups, return false
|
||||
// for (; i < requiredArr.length; i++) {
|
||||
// if ( dictionary[ requiredArr[i] ] === undefined ) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// };
|
||||
|
||||
return {
|
||||
init: init
|
||||
};
|
||||
}(jQuery));
|
||||
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
Exports.Modules.Gallery.init();
|
||||
});
|
Loading…
Reference in New Issue