Update compound filters demo.

pull/111/head
Glen Cheney 8 years ago
parent 6934fd3079
commit eec4bfc157

@ -43,9 +43,9 @@ demos:
- url: 'demos/2013-06-19-adding-removing'
slug: adding-removing
label: Adding and removing items
- url: 'demos/2013-05-02-adaptive'
slug: adaptive
label: Adaptive bootstrap grid with compound filters
- url: 'demos/2013-05-02-compound-filters'
slug: compound-filters
label: Compound filtering
- url: 'demos/2013-05-03-images'
slug: images
label: Using images

@ -28,4 +28,4 @@ $('.js-shuffle-search').on('keyup change', function() {
});</code></pre>
</div>
<p class="demo-link-container">Check out the <a href="{{ site.baseurl }}{% post_url 2013-05-02-adaptive %}">compounded filters demo</a>.</p>
<p class="demo-link-container">Check out the <a href="{{ site.baseurl }}{% post_url 2013-05-02-compound-filters %}">compounded filters demo</a>.</p>

@ -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>

@ -102,28 +102,17 @@
background-color: transparent;
}
@media (min-width: 1200px) {
// IE8 filter alpha wasn't working with the positioning stuff
.lt-ie9 .shape {
.aspect {
position: static;
width: 100%;
height: 250px;
overflow: visible;
padding-bottom: 0;
}
.shape__inner {
position: static;
width: 100%;
height: 100%;
.shape--triangle .shape__space {
@include equilateralTriangle(270px);
}
}
@media (min-width: 1200px) {
@media (min-width: 1392px) {
.shape--triangle .shape__space {
@include equilateralTriangle(270px);
@include equilateralTriangle(284px);
}
}
@ -156,55 +145,3 @@
}
}
body::before {
content: 'Default - 940px';
position: fixed;
z-index: 5;
bottom: 0;
left: 0;
width: 100%;
height: 25px;
background-color: hsla(110, 50%, 60%, .6);
transition: background .2s ease;
}
@media (min-width: 1200px) {
body::before {
content: 'Large Desktop - 1200px+';
background-color: hsla(10, 50%, 60%, .6);
}
}
@media (min-width: 768px) and (max-width: 979px) {
body::before {
content: 'Portrait tablet to landscape and desktop - > 768px && < 979px';
background-color: hsla(50, 50%, 60%, .6);
}
}
@media (max-width: 767px) {
body::before {
content: 'Phones to Tablets - < 767px';
background-color: hsla(210, 50%, 60%, .6);
}
}
@media (max-width: 480px) {
body::before {
content: 'Phones - < 480px';
background-color: hsla(300, 50%, 60%, .6);
}
}

@ -65,18 +65,6 @@
border-width: 0 110px 191px 110px;
background-color: transparent; }
.lt-ie9 .shape .aspect {
position: static;
width: 100%;
height: 250px;
overflow: visible;
padding-bottom: 0; }
.lt-ie9 .shape .shape__inner {
position: static;
width: 100%;
height: 100%; }
@media (min-width: 1200px) {
.shape--triangle .shape__space {
padding-top: 18px;
@ -84,6 +72,13 @@
width: 0;
border-width: 0 135px 234px 135px; } }
@media (min-width: 1392px) {
.shape--triangle .shape__space {
padding-top: 19px;
height: 0;
width: 0;
border-width: 0 142px 246px 142px; } }
@media (min-width: 768px) and (max-width: 979px) {
.shape--triangle .shape__space {
padding-top: 11px;
@ -112,35 +107,3 @@
height: 0;
width: 0;
border-width: 0 160px 277px 160px; } }
body::before {
content: 'Default - 940px';
position: fixed;
z-index: 5;
bottom: 0;
left: 0;
width: 100%;
height: 25px;
background-color: rgba(119, 204, 102, 0.6);
-webkit-transition: background .2s ease;
transition: background .2s ease; }
@media (min-width: 1200px) {
body::before {
content: 'Large Desktop - 1200px+';
background-color: rgba(204, 119, 102, 0.6); } }
@media (min-width: 768px) and (max-width: 979px) {
body::before {
content: 'Portrait tablet to landscape and desktop - > 768px && < 979px';
background-color: rgba(204, 187, 102, 0.6); } }
@media (max-width: 767px) {
body::before {
content: 'Phones to Tablets - < 767px';
background-color: rgba(102, 153, 204, 0.6); } }
@media (max-width: 480px) {
body::before {
content: 'Phones - < 480px';
background-color: rgba(204, 102, 204, 0.6); } }

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…
Cancel
Save