Shuffle 2.0!

pull/56/head
Glen Cheney 11 years ago
commit c9f86feaaa

5
.gitignore vendored

@ -0,0 +1,5 @@
.DS_Store
_site
.sass_cache/*
*.scssc

@ -1,223 +1,18 @@
# [jQuery Shuffle Plugin](http://vestride.github.com/Shuffle)
# [Shuffle](http://vestride.github.io/Shuffle)
Categorize, sort, and filter a responsive grid of items
Hey there! I'm working on a new version of shuffle. It uses [masonry layouts](http://masonry.desandro.com/) (so you can have different sized tiles), it can add/remove elements, and more. Check it out [on the masonry branch](https://github.com/Vestride/Shuffle/tree/masonry).
## Docs and Demos
[All found here](http://vestride.github.io/Shuffle)
## Features
## Shuffle 2.0
This is a large improvement to shuffle. Most notably, the ability for [masonry](http://masonry.desandro.com) layouts. Other additions include adding/removing items, enabling/disabling, multiple instances on a page, and more!
* Uses CSS Transitions!
* Responsive
* Filter items by groups
* Items can have multiple groups
* Sort elements
* Advanced filtering method (like searching)
## Running locally
This project uses [Jekyll](http://jekyllrb.com/), so head over to [their quickstart guide](http://jekyllrb.com/docs/quickstart/) to get set up.
## How to Use
## Improvements still to make
* FAQ page
* Use Deferred objects for callbacks
* Horizontal layout
Settings you can change (these are the defaults)
```js
var options = {
group : 'all' // Which category to show
speed : 800, // Speed of the transition (in milliseconds). 800 = .8 seconds
easing : 'ease-out' // css easing function to use
};
$('#grid').shuffle(options);
```
The easing function is one of `default`, `linear`, `ease-in`, `ease-out`, `ease-in-out`, or `cubic-bezier`.
### The HTML
The html structure. The only real important thing here is the 'data-groups' attribute. It has to be a [valid JSON](http://jsonlint.com/) array of strings.
```html
<div id="grid">
<div class="item" data-groups='["photography"]' data-date-created="2010-09-14" data-title="Baseball">
<img src="img/baseball.png" />
<div class="item-details">
<a href="#">Photography</a>
</div>
</div>
<div class="item" data-groups='["wallpaper", "3d"]' data-date-created="2011-08-14" data-title="Tennis">
<img src="img/tennis-ball.png" />
<div class="item-details">
<a href="#">3D Render, Wallpaper</a>
</div>
</div>
<div class="item" data-groups='["3d", "wallpaper"]' data-date-created="2009-05-27" data-title="iMac">
<img src="img/imac.png" />
<div class="item-details">
<a href="#">3D Render, Wallpaper</a>
</div>
</div>
<div class="item" data-groups='["graphics"]' data-date-created="2012-05-14" data-title="Master Chief">
<img src="img/master-chief.png" />
<div class="item-details">
<a href="#">Graphic Design</a>
</div>
</div>
</div>
```
Shuffle takes the width, margin-top, and marigin-right from the `.item`.
```css
#grid .item {
width: 230px;
margin-top: 20px;
margin-right: 20px;
}
```
## How to "Shuffle"
Say you have this markup for your options
```html
<ul class="filter-options">
<li data-group="all" class="active">Most Recent</li>
<li data-group="wallpaper">Wallpapers</li>
<li data-group="graphics">Graphic Design</li>
<li data-group="photography">Photography</li>
<li data-group="3d">3D Renders</li>
</ul>
```
And when you click on a li, you want the plugin to shuffle. Here's an example:
```js
$(document).ready(function(){
// Set up button clicks
$('.filter-options li').on('click', function() {
var $this = $(this),
$grid = $('#grid');
// Hide current label, show current label in title
$('.filter-options .active').removeClass('active');
$this.addClass('active');
// Filter elements
$grid.shuffle($this.data('group'));
});
// instantiate the plugin
$('#grid').shuffle({
group : 'all',
speed : 800,
easing : 'ease-out'
});
});
```
These events will be triggered at their respective times: `shrink.shuffle`, `shrunk.shuffle`, `filter.shuffle`, `filtered.shuffle`, and `sorted.shuffle`.
## Sorting
You can order the elements based off a function you supply. In the example above, each item has a `data-date-created` and `data-title` attribute. The filter buttons have a `data-sort` attribute with the value of the item&rsquo;s attribute. Then, with some JavaScript, we can get the correct attribute and provide a function to sort by.
```html
<li data-sort="title">Title</li>
```
```html
<div class="item" data-title="Baseball"></div>
```
```javascript
// Sorting options
$('.sort-options li').on('click', function() {
var $this = $(this),
$grid = $('#grid'),
sort = $this.data('sort'),
opts = {};
// Hide current label, show current label in title
$('.sort-options .active').removeClass('active');
$this.addClass('active');
// We're given the element wrapped in jQuery
if (sort === 'date-created') {
opts = {
by: function($el) {
return $el.data('date-created');
}
}
} else if (sort === 'title') {
opts = {
by: function($el) {
return $el.data('title').toLowerCase();
}
}
}
// Filter elements
$grid.shuffle('sort', opts);
});
```
The `opts` parameter can contain two properties. `reverse`, a boolean which will reverse the array. `by` is a function that is passed the element wrapped in jQuery. In the case above, we&rsquo;re returning the value of the data-date-created or data-title attributes.
Calling sort with an empty object will reset the elements to DOM order.
## Advanced Filtering
By passing a function to shuffle, you can customize the filtering to your hearts content. Shuffle will iterate over each item in the container and give your function the element wrapped in jQuery and the shuffle instance. Return `true` to keep the element or `false` to hide it.
### Example
```javascript
// Filters elements with a data-title attribute with less than 10 characters
$('#grid').shuffle(function($el, shuffle) {
return $el.data('title').length < 10;
});
```
### Searching
```javascript
// Advanced filtering
$('.filter .search').on('keyup change', function() {
var val = this.value.toLowerCase();
$('#grid').shuffle(function($el, shuffle) {
// Only search elements in the current group
if (shuffle.group !== 'all' && $.inArray(shuffle.group, $el.data('groups')) === -1) {
return false;
}
// Get the text inside our element and search for the value in the input
var text = $.trim($el.text()).toLowerCase();
return text.indexOf(val) != -1;
});
});
```
## Dependencies
* jQuery
* Modernizr
A custom Modernizr build has been included with the plugin. If you already have Modernizr on your site, you may delete it. If you don't know what Modernizr is, leave it!
## Supported Browsers
* Chrome
* Firefox
* IE 7+
* Opera
* Safari
_Browsers that don't support CSS transitions and transforms *cough* IE <= 9 *cough* will see a less cool, javascript based version of the effect._
## Changes
* 10.24.12 - Better handling of grid item dimensions. Added a minimal markup page.
* 9.20.12 - Added `destroy` method.
* 9.18.12 - Added sorting ability, made plugin responsive, added advanced filtering method. Updated to Modernizr 2.6.2.
* 7.21.12 - Rewrote plugin in more object oriented structure. Added custom events. Updated to Modernizr 2.6.1.
* 7.3.12 - Removed dependency on the css file and now apply the css with javascript. Updated Modernizr to 2.5.3.
## Links
* [Github repo](https://github.com/Vestride/Shuffle)
* [Inspired by Isotope](http://isotope.metafizzy.co/)
* [Me](http://glencheney.com)
Inspired by [Isotope](http://isotope.metafizzy.co/) and [Packery](http://packery.metafizzy.co/).

@ -0,0 +1,144 @@
source: .
destination: ./_site
plugins: ./_plugins
layouts: ./_layouts
include: ['.htaccess']
exclude: ['./_scss/*.*']
permalink: /:title
_url: http://glen.local:4000
__url: http://localhost:4000
___url: http://vestride.github.io/Shuffle/
defaultTitle: 'Shuffle.js'
defaultDescription: 'Categorize, sort, and filter a responsive grid of items'
defaultImage: '/img/hero.png'
demos:
- url: 'demos/2013-05-01-basic'
slug: basic
label: Basic masonry layout
screenshot: basic.webp
- url: 'demos/2013-06-19-adding-removing'
slug: adding-removing
label: Adding and removing items
screenshot: removing.webp
- url: 'demos/2013-05-02-adaptive'
slug: adaptive
label: Adaptive bootstrap grid with compound filters
screenshot: adaptive.webp
- url: 'demos/2013-05-03-images'
slug: images
label: Using images
screenshot: images.webp
shapes:
- shape: circle
color: blue
- shape: diamond
color: red
- shape: triangle
color: green
- shape: triangle
color: orange
- shape: square
color: red
- shape: diamond
color: green
- shape: circle
color: red
- shape: square
color: green
- shape: circle
color: orange
- shape: diamond
color: blue
- shape: square
color: orange
- shape: square
color: blue
items:
- groups: [ photography ]
date: 2010-09-14
title: Baseball
img: baseball.png
original: baseball.jpg
cols: 3
- groups: [ wallpaper, 3d ]
date: 2011-08-14
title: Tennis
img: tennis-ball.png
original: tennis-ball.jpg
description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
cols: 6
- groups: [ wallpaper, 3d ]
date: 2009-05-27
title: iMac
img: imac.png
original: imac.jpg
cols: 3
- groups: [ graphics ]
date: 2012-05-14
title: Master Chief
img: master-chief.png
original: Master_Chief_Portrait_by_Eightfold_Studios.jpg
description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'
extras: [ h2 ]
cols: 3
- groups: [ wallpaper, 3d ]
date: 2009-09-14
title: Eightfold
img: es-blue.png
original: es-blue.jpg
cols: 3
- groups: [ photography ]
date: 2012-03-14
title: Pumpkin
img: pumpkin.png
original: pumpkin.jpg
description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
cols: 6
- groups: [ wallpaper, 3d ]
date: 2013-05-19
title: Vestride
img: vestride-red.png
original: vestride-red.jpg
extras: [ h2 ]
cols: 6
- groups: [ graphics ]
date: 2013-02-01
title: Newegg
img: newegg.png
original: newegg.jpg
description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'
extras: [ h2 ]
cols: 3
- groups: [ wallpaper ]
date: 2000-01-01
title: Arc
img: eightfoldarc.png
original: eightfoldarc.jpg
cols: 3
- groups: [ photography ]
date: 2012-07-04
title: Ground
img: ground.png
original: ground!.jpg
cols: 3
- groups: [ wallpaper ]
date: 2011-08-12
title: Grass
img: grassy-hills.png
original: grassy-hills.tif
description: 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
cols: 6
- groups: [ wallpaper, 3d ]
date: 2013-05-19
title: Vestride
img: vestride-classy.png
original: vestride-classy.jpg
cols: 3

@ -0,0 +1,27 @@
<h2>Advanced Filtering</h2>
<p>By passing a function to shuffle, you can customize the filtering to your hearts content. Shuffle will iterate over each item and give your function the element wrapped in jQuery and the shuffle instance. Return <code>true</code> to keep the element or <code>false</code> to hide it.</p>
<h3>Example</h3>
<pre rel="JavaScript"><code class="language-javascript">// Filters elements with a data-title attribute with less than 10 characters
$('#grid').shuffle('shuffle', function($el, shuffle) {
return $el.data('title').length &lt; 10;
});</code></pre>
<h3>Searching</h3>
<pre rel="JavaScript"><code class="language-javascript">// Advanced filtering
$('.js-shuffle-search').on('keyup change', function() {
var val = this.value.toLowerCase();
$grid.shuffle('shuffle', function($el, shuffle) {
// Only search elements in the current group
if (shuffle.group !== 'all' &amp;&amp; $.inArray(shuffle.group, $el.data('groups')) === -1) {
return false;
}
var text = $.trim( $el.find('.picture-item__title').text() ).toLowerCase();
return text.indexOf(val) !== -1;
});
});</code></pre>
<p>For another example of advanced filters, check out the <a href="{% post_url demos/2013-05-02-adaptive %}">compounded filters demo</a>.</p>

@ -0,0 +1,9 @@
<h2>Changes</h2>
<ul>
<li>11.3.12 - Replaced layout system with <a href="http://masonry.desandro.com/">masonry</a>. Items can now be different sizes! Added addtional examples.</li>
<li>10.24.12 - Better handling of grid item dimensions. Added a minimal markup page.</li>
<li>9.20.12 - Added <code>destroy</code> method</li>
<li>9.18.12 - Added sorting ability and made plugin responsive. Updated to Modernizr 2.6.2</li>
<li>7.21.12 - Rewrote plugin in more object oriented structure. Added custom events. Updated to Modernizr 2.6.1</li>
<li>7.3.12 - Removed dependency on the css file and now apply the css with javascript</li>
</ul>

@ -0,0 +1,5 @@
<footer class="site-footer light-text-dark-box">
<div class="container-fluid">
<p class="site-footer__credit">Photos and drawings by <a href="http://eightfoldstudios.com" target="_blank">Eightfold Studios</a>.</p>
</div>
</footer>

@ -0,0 +1,23 @@
<h2>Events</h2>
<p>A list of events shuffle triggers:</p>
<ul>
<li><code class="language-javascript">'loading.shuffle'</code></li>
<li><code class="language-javascript">'done.shuffle'</code></li>
<li><code class="language-javascript">'shrink.shuffle'</code></li>
<li><code class="language-javascript">'shrunk.shuffle'</code></li>
<li><code class="language-javascript">'filter.shuffle'</code></li>
<li><code class="language-javascript">'filtered.shuffle'</code></li>
<li><code class="language-javascript">'layout.shuffle'</code></li>
<li><code class="language-javascript">'removed.shuffle'</code></li>
</ul>
<h3>Get notified when shuffle is done with setup</h3>
<pre rel="JavaScript"><code class="language-javascript">$grid.on('done.shuffle', function() {
console.log('Finished initializing shuffle!');
});</code></pre>
<h3>Do something when an item is removed</h3>
<pre rel="JavaScript"><code class="language-javascript">$grid.on('removed.shuffle', function( evt, $collection, shuffle ) {
console.log( this, evt, $collection, shuffle );
});</code></pre>

@ -0,0 +1,10 @@
<h2>Features</h2>
<ul>
<li>Uses CSS Transitions!</li>
<li>Responsive (try resizing the window!)</li>
<li>Filter items by groups</li>
<li>Items can have multiple groups and be different sizes</li>
<li>Sort items</li>
<li>Advanced filtering method (like searching)</li>
</ul>

@ -0,0 +1,2 @@
</body>
</html>

@ -0,0 +1,52 @@
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js modern" lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8" />
<title>{{ page.title }}</title>
{% capture description %}{% if page.description %}{{ page.description }}{% else %}{{ site.defaultDescription }}{% endif %}{% endcapture %}
{% capture image %}{% if page.image %}{{ page.image }}{% else %}{{ site.defaultImage }}{% endif %}{% endcapture %}
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta property="og:title" content="{{ page.title }}" />
<meta property="og:description" content="{{ description }}" />
<meta property="og:type" content="website" />
<meta property="og:url" content="{{ site.url }}{{ page.url }}" />
<meta property="og:image" content="{{ site.url }}{{ image }}" />
<meta property="og:site_name" content="" />
<meta property="fb:admins" content="771347349" />
<meta name="author" content="https://plus.google.com/u/0/100210640453700033824" />
<meta name="twitter:card" content="summary">
<meta name="twitter:creator" content="@Vestride">
<meta name="twitter:title" content="{{ page.title }}">
<meta name="twitter:description" content="{{ description }}">
<meta name="twitter:image" content="{{ site.url }}{{ image }}">
<link href="https://plus.google.com/u/0/100210640453700033824" rel="author" />
<link id="favicon" rel="icon" type="image/png" href="favicon.png" >
<!-- Prefetch DNS for external assets -->
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<link rel="dns-prefetch" href="//themes.googleusercontent.com">
<link rel="dns-prefetch" href="//www.google-analytics.com">
<link rel="dns-prefetch" href="//ajax.googleapis.com">
{% if page.prism %}<link rel="stylesheet" href="{{ site.url }}/css/prism.css" />{% endif %}
<link rel="stylesheet" href="{{ site.url }}/css/style.css" />
<link rel="stylesheet" href="{{ site.url }}/css/shuffle-styles.css" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Ubuntu:300,400,700">
{% if page.extraCSS %}
{% for href in page.extraCSS %}
<link rel="stylesheet" href="{{ href }}" />
{% endfor %}
{% endif %}
<!--[if lt IE 9]>
<script src="{{ site.url }}/js/html5shiv.js"></script>
<![endif]-->
</head>
<body class="{{ page.bodyClass }}">

@ -0,0 +1,43 @@
<nav class="site-nav collapsed" id="nav" role="primary">
<div class="js-tray site-nav__tray light-text-dark-box">
<div class="container-fluid site-nav__tray-inner">
<h3 class="site-nav__title">Shuffle.js</h3>
<div class="row-fluid">
<div class="span3">
<a class="btn btn--primary" href="/">Home</a>
</div>
<div class="span3">
<a class="btn btn--primary" href="https://github.com/Vestride/Shuffle">GitHub Repo</a>
</div>
<div class="span3">
<a class="btn btn--primary" href="https://twitter.com/Vestride">By @Vestride</a>
</div>
</div>
<h3 class="site-nav__title">Demos</h3>
<div class="row-fluid m-row js-demos site-nav__demos">
{% for post in site.demos %}
<div class="span3 m-span3 figure-wrap js-demo">
<a href="/{{ post.slug }}">
<figure>
<div class="keep-ratio four-three">
<img src="{{ site.url }}/img/demos/{{ post.slug }}.webp" alt="{{ post.label }}" />
</div>
<figcaption>{{ post.label }}</figcaption>
</figure>
</a>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="site-nav__band">
<div class="container-fluid">
<button class="js-nav-toggle pull-right" data-close-label="Close Nav">Open Nav</button>
</div>
</div>
</nav>

@ -0,0 +1,22 @@
<h2>Options</h2>
<p>Settings you can change (these are the defaults)</p>
<pre rel="JavaScript"><code class="language-javascript">// Overrideable options
Shuffle.options = {
group: 'all', // Filter group
speed: 250, // Transition/animation speed (milliseconds)
easing: 'ease-out', // css easing function to use
itemSelector: '', // e.g. '.picture-item'
sizer: null, // sizer element. Can be anything columnWidth is
gutterWidth: 0, // a static number or function that tells the plugin how wide the gutters between columns are (in pixels)
columnWidth: 0, // a static number or function that returns a number which tells the plugin how wide the columns are (in pixels)
delimeter: null, // if your group is not json, and is comma delimeted, you could set delimeter to ','
buffer: 0, // useful for percentage based heights when they might not always be exactly the same (in pixels)
initialSort: null, // Shuffle can be initialized with a sort object. It is the same object given to the sort method
throttle: $.throttle || null, // By default, shuffle will try to throttle the resize event. This option will change the method it uses
throttleTime: 300, // How often shuffle can be called on resize (in milliseconds)
sequentialFadeDelay: 150, // Delay between each item that fades in when adding items
supported: Modernizr.csstransforms &amp;&amp; Modernizr.csstransitions // supports transitions and transforms
};</code></pre>
<p>No options <em>need</em> to be specified, but <code>itemSelector</code> should be used. Other common options to change are <code>speed</code>, <code>easing</code>, <code>gutterWidth</code>, and <code>columnWidth</code> (or <code>sizer</code>).</p>

@ -0,0 +1,16 @@
{% comment %} Ghetto conversion to JSON {% endcomment %}
{% capture groups %}["{{ item.groups | join: '","' }}"]{% endcapture %}
{% if item.extras | size: > 0 %}
{% capture extras %} picture-item--{{ item.extras | join: " picture-item--" }}{% endcapture %}
{% else %}
{% assign extras = "" %}
{% endif %}
{% if item.cols %}{% assign cols = item.cols %}{% else %}{% assign cols = 3 %}{% endif %}
<figure class="span{{ cols }} m-span3 picture-item{{ extras }}" data-groups='{{ groups }}' data-date-created="{{ item.date }}" data-title="{{ item.title }}">
<img src="{{ site.url }}/img/{{ item.img }}" alt="" height="145" width="230" />
<div class="picture-item__details clearfix">
<figcaption class="picture-item__title pull-left"><a href="{{ site.url }}/img/originals/{{ item.original }}" target="_blank">{{ item.title }}</a></figcaption>
<p class="picture-item__tags pull-right">{{ item.groups | join: ', ' }}</p>
</div>
{% if item.description %}<p class="picture-item__description">{{ item.description }}</p>{% endif %}
</figure>

@ -0,0 +1,23 @@
<!--[if lt IE 9]>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<![endif]-->
<!--[if gte IE 9]><!-->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<!--<![endif]-->
<!-- Shuffle! -->
<script src="{{ site.url }}/jquery.shuffle.js"></script>
{% if page.prism %}
<!-- Syntax highlighting via Prism -->
<script src="{{ site.url }}/js/prism.js"></script>
{% endif %}
<!-- Make the nav work -->
<script src="{{ site.url }}/js/page.js"></script>
{% if page.extraJS && page.extraJS.length %}
{% for src in page.extraJS %}
<script src="{{ site.url }}/js/{{ src }}"></script>
{% endfor %}
{% endif %}

@ -0,0 +1,40 @@
<h2>Sorting</h2>
<p>You can order the elements based off a function you supply. In the demo above, each item has a <code>data-date-created</code> and <code>data-title</code> attribute. When the select option menu changes, a sort object is passed to shuffle.</p>
<pre rel="HTML"><code class="language-markup">&lt;select class="sort-options"&gt;
&lt;option value=""&gt;Default&lt;/option&gt;
&lt;option value="title"&gt;Title&lt;/option&gt;
&lt;option value="date-created"&gt;Date Created&lt;/option&gt;
&lt;/select&gt;</code></pre>
<pre rel="HTML"><code class="language-markup">&lt;figure class="picture-item" data-groups='[&quot;photography&quot;]' data-date-created="2010-09-14" data-title="Baseball"&gt;&hellip;&lt;/figure&gt;</code></pre>
<pre rel="JavaScript"><code class="language-javascript">// Sorting options
$('.sort-options').on('change', function() {
var sort = this.value,
opts = {};
// We're given the element wrapped in jQuery
if ( sort === 'date-created' ) {
opts = {
reverse: true,
by: function($el) {
return $el.data('date-created');
}
};
} else if ( sort === 'title' ) {
opts = {
by: function($el) {
return $el.data('title').toLowerCase();
}
};
}
// Filter elements
$grid.shuffle('sort', opts);
});</code></pre>
<p>The <code class="language-javascript">opts</code> parameter can contain two properties. <code class="language-javascript">reverse</code>, a boolean which will reverse the array. <code class="language-javascript">by</code> is a function that is passed the element wrapped in jQuery. In the case above, we&rsquo;re returning the value of the data-date-created or data-title attributes.</p>
<p>Calling sort with an empty object will reset the elements to DOM order.</p>

@ -0,0 +1,60 @@
<h2>Usage</h2>
<h3>The HTML Structure</h3>
<p>The only real important thing here is the <code class="language-markup token attr-name">data-groups</code> attribute. It has to be a <a href="http://jsonlint.com/">valid JSON</a> array of strings. Optionally, it can be a string delimeted by a value you provide. See <code>delimeter</code> in the <a href="#options">options</a>.</p>
<p>In this example, shuffle is using the fluid grid from the <a href="http://twitter.github.io/bootstrap/">Twitter Bootstrap</a>. It's also making use of the <a href="http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/"><abbr title="Block-Element-Modifier">BEM</abbr></a>.</p>
<pre rel="HTML"><code class="language-markup">&lt;div id="grid" class="row-fluid"&gt;
&lt;figure class="span3 picture-item" data-groups='["photography"]'&gt;
&lt;img src="/img/baseball.png" height="145" width="230" /&gt;
&lt;div class="picture-item__details"&gt;
&lt;figcaption class="picture-item__title"&gt;Baseball&lt;/figcaption&gt;
&lt;p class="picture-item__tags"&gt;photography&lt;/p&gt;
&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class="span6 picture-item" data-groups='["wallpaper","3d"]'&gt;
&lt;img src="/img/tennis-ball.png" height="145" width="230" /&gt;
&lt;div class="picture-item__details"&gt;
&lt;figcaption class="picture-item__title"&gt;Tennis&lt;/figcaption&gt;
&lt;p class="picture-item__tags"&gt;wallpaper, 3d&lt;/p&gt;
&lt;/div&gt;
&lt;p class="picture-item__description"&gt;Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.&lt;/p&gt;
&lt;/figure&gt;
&lt;figure class="span3 picture-item" data-groups='["wallpaper","3d"]'&gt;
&lt;img src="/img/imac.png" height="145" width="230" /&gt;
&lt;div class="picture-item__details"&gt;
&lt;figcaption class="picture-item__title"&gt;iMac&lt;/figcaption&gt;
&lt;p class="picture-item__tags"&gt;wallpaper, 3d&lt;/p&gt;
&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class="span3 picture-item picture-item--h2" data-groups='["graphics"]'&gt;
&lt;img src="/img/master-chief.png" height="145" width="230" /&gt;
&lt;div class="picture-item__details"&gt;
&lt;figcaption class="picture-item__title"&gt;Master Chief&lt;/figcaption&gt;
&lt;p class="picture-item__tags"&gt;graphics&lt;/p&gt;
&lt;/div&gt;
&lt;p class="picture-item__description"&gt;Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.&lt;/p&gt;
&lt;/figure&gt;
&lt;/div&gt;</code></pre>
<h3 id="columns">How column widths work</h3>
<p>The <code>columnWidth</code> option is used to calculate the column width. You have several options:</p>
<ol>
<li>Use a <strong>sizer</strong> element. This is the easest way to specify column and gutter widths. You can use an element or an element wrapped in jQuery. The column and gutter widths will be measured using this element. The <code>sizer</code> option is an alias for <code>columnWidth</code>. See <a href="{% post_url demos/2013-05-01-basic %}">a demo</a> using a sizer element or <a href="{{ site.url }}/js/demos/homepage.js">look at the js file</a> for the sizer demo.</li>
<li>Use a <strong>function</strong>. When a function is used, its first parameter will be the width of the shuffle element. You need to return the column width for shuffle to use (in pixels).</li>
<li>A <strong>number</strong>. This will explicitly set the column width to your number (in pixels).</li>
<li>By default, shuffle will use jQuery's <code class="language-javascript">outerWidth(true)</code> to calculate the column width of the first item and use that value.</li>
</ol>
<h3>A basic setup example</h3>
<p>Sets up the button clicks and runs shuffle</p>
<pre rel="JavaScript"><code class="language-javascript">$(document).ready(function() {
var $grid = $('#grid'),
$sizer = $grid.find('.shuffle__sizer');
$grid.shuffle({
itemSelector: '.picture-item',
sizer: $sizer
});
});</code></pre>

@ -0,0 +1,18 @@
{% include head.html %}
{% include nav.html %}
{% if page.includeHeader %}
<header class="container-fluid">
<div class="row-fluid">
<div class="span7">
<h1>Shuffle</h1>
<p>{{ site.defaultDescription }}</p>
<p>By <a href="https://twitter.com/Vestride" target="_blank">@Vestride</a></p>
</div>
</div>
</header>
{% endif %}
<main role="main" id="main" class="language-markup">
{{ content }}
</main>
{% include scripts.html %}
{% include foot.html %}

@ -0,0 +1,39 @@
---
layout: default
title: Basic Shuffle Demo
description: A basic demo using shuffle with a masonry layout. This example also uses a sizer element
image: /demos/basic.jpg
bodyClass: basic
extraJS: [ "demos/homepage.js" ]
---
<div class="container-fluid">
<div class="row-fluid">
<h2>Masonry with a sizer</h2>
</div>
</div>
<div class="container-fluid">
<div id="grid" class="row-fluid m-row shuffle--container shuffle--fluid">
{% for item in site.items %}
{% assign item = item %}
{% include picture-item.html %}
{% endfor %}
<div class="span3 m-span3 shuffle__sizer"></div>
</div>
</div>
<div class="container-fluid">
<div class="row-fluid">
<h2>Another Section</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
{% include credit-jake.html %}

@ -0,0 +1,75 @@
---
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="span12">Adaptive Layout with Compound Filters</h2>
</div>
</section>
<section class="gallery container">
<div class="filter-options row">
<div class="span6">
<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="span6">
<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="span3 shape shape--{{ shape.shape }} shape--{{ shape.color }}" data-shape="{{ shape.shape }}" data-color="{{ shape.color }}">
<div class="keep-ratio">
<div class="shape__inner">
<div class="shape__space">
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</section>
<section>
<div class="container">
<h2>Another section</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</section>

@ -0,0 +1,81 @@
---
layout: default
title: Using images with imagesloaded.js
description: A Shuffle.js demo using Desandro's imagesLoaded plugin. This comes in very handy when using shuffle with images affect the layout of shuffle items
image: /demos/images.jpg
extraJS: [ "imagesloaded.pkgd.js", "demos/images.js"]
prism: true
---
<div class="container-fluid">
<h2>Images!</h2>
<p>You can encounter problems when shuffle item dimensions depend on images. <a href="{% post_url demos/2013-06-29-image-problems %}">Like this demo</a>. There are three good solutions to this.</p>
<ol>
<li>Set an explicit height on <code>.shuffle-item</code>s like the <a href="{% post_url demos/2013-05-01-basic %}">basic demo</a>.</li>
<li>Similar to number 1, make the height of the image container a percentage of the width. This can be seen in the nav images above with the <code>div.keep-ratio</code>.</li>
<li>Get notified when images load (this page). In this case, I'm using <a href="http://desandro.github.io/imagesloaded/">Desandro's images loaded plugin</a>. Please note that imagesloaded does not support IE7.</li>
</ol>
</div>
<style>
.shuffle-wrap {
position: relative;
}
.shuffle--images {
position: relative;
visibility: hidden;
}
.shuffle--images.images-loaded {
visibility: visible;
}
.shuffle--images .img-item {
margin-top: 10px;
margin-left: 0;
}
.shuffle--images .img-item img {
width: 100%;
}
.loader {
position: absolute;
top: 50%;
left: 50%;
margin-top: -16px;
margin-left: -16px;
}
</style>
<div class="container-fluid shuffle-wrap">
<img id="loader" class="loader" alt="Loading..." src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAzMDAgMzAwIgogICAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4xIj4KICA8cGF0aCBkPSJNIDE1MCwwCiAgICAgICAgICAgYSAxNTAsMTUwIDAgMCwxIDEwNi4wNjYsMjU2LjA2NgogICAgICAgICAgIGwgLTM1LjM1NSwtMzUuMzU1CiAgICAgICAgICAgYSAtMTAwLC0xMDAgMCAwLDAgLTcwLjcxMSwtMTcwLjcxMSB6IgogICAgICAgIGZpbGw9IiMzZDdmZTYiPgogICAgPGFuaW1hdGVUcmFuc2Zvcm0gYXR0cmlidXRlTmFtZT0idHJhbnNmb3JtIiBhdHRyaWJ1dGVUeXBlPSJYTUwiCiAgICAgICAgICAgdHlwZT0icm90YXRlIiBmcm9tPSIwIDE1MCAxNTAiIHRvPSIzNjAgMTUwIDE1MCIKICAgICAgICAgICBiZWdpbj0iMHMiIGR1cj0iMXMiIGZpbGw9ImZyZWV6ZSIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIC8+CiAgPC9wYXRoPgo8L3N2Zz4K" />
<div class="shuffle--images row-fluid">
{% for item in site.items %}
<figure class="js-item img-item span3 m-span3">
<img src="{{ site.url }}/img/{{ item.img }}" alt="{{item.title}}"/>
<figcaption>{{ item.groups }}</figcaption>
</figure>
{% endfor %}
<div class="span3 m-span3" id="js-sizer"></div>
</div>
</div>
<section>
<div class="container-fluid">
<h2>Another section</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</section>
{% include credit-jake.html %}

@ -0,0 +1,87 @@
---
layout: default
title: Shuffle Adding and Removing Elements Demo
description: This demo of shuffle shows how to add and removing items.
image: /demos/adding-removing.jpg
extraJS: [ "demos/adding-removing.js" ]
---
<style>
/* Styles for shuffle */
.container {
counter-reset: boxes;
}
.box {
position: relative;
width: 18%;
margin-left: 2.5%;
height: 100px;
margin-top: 20px;
float: left;
background: #E74C3C;
counter-increment: boxes;
}
.box::before {
content: 'DOM order: ' counter(boxes);
position: absolute;
color: white;
top: .5em;
left: .5em;
}
.box.shuffle-item,
.box:first-child {
margin-left: 0;
}
.w2 {
width: 38.5%;
}
.w3 {
width: 59%;
}
.h2 {
height: 220px;
}
</style>
<section class="container">
<div class="row">
<h2 class="span12">Adding and Removing Items</h2>
</div>
</section>
<section class="container">
<button id="randomize">Randomize</button>
<button id="add">Add 5 Boxes</button>
<button id="remove">Remove Some Boxes</button>
</section>
<section class="container">
<div id="my-shuffle" class="items">
<div class="box"></div>
<div class="box h2 w2"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box w2"></div>
<div class="box"></div>
</div>
</section>
<section class="container">
<div class="row">
<div class="span12">
<h2>Another Section</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
</section>

@ -0,0 +1,52 @@
---
layout: default
title: Mobile Grid Layout Test
description: Testing out the mobile grid for this site
---
<div class="container-fluid">
<h2>Mobile Grid Demo</h2>
</div>
<style scoped>
article {
height: 30px;
background-color: gray;
color: white;
}
</style>
<div class="container-fluid">
<div class="row-fluid m-row">
<article class="span7 m-span3">
span7 | m-span3
</article>
<article class="span4 m-span1">
span4 | m-span1
</article>
<article class="span1 m-span2">
span1 | m-span2
</article>
</div>
<hr>
<div class="row-fluid m-row">
<article class="span6 m-span6"></article>
</div>
<hr>
<div class="row-fluid m-row">
<article class="span5 m-span3"></article>
<article class="span7 m-span3"></article>
</div>
<hr>
<article style="width:100%;text-align:center;">
100%
</article>
</div>

@ -0,0 +1,56 @@
---
layout: default
title: Image based items
description: A demo of how NOT to use images with shuffle
extraJS: [ "demos/images-broken.js"]
---
<div class="container-fluid">
<h2>This probably looks broken.</h2>
<p>Demo in which shuffle item dimensions are based on images without a fix. <a href="{% post_url demos/2013-05-03-images %}">See here</a> for a solution.</p>
<p>Resize the window and it'll fix itself.</p>
</div>
<style>
.shuffle--images {
position: relative;
}
.shuffle--images .img-item {
margin-top: 10px;
margin-left: 0;
}
.shuffle--images .img-item img {
width: 100%;
}
</style>
<div class="container-fluid">
<div class="shuffle--images row-fluid">
{% for item in site.items %}
<figure class="js-item img-item span3 m-span3">
<img src="{{ site.url }}/img/{{ item.img }}" alt="{{item.title}}"/>
<figcaption>{{ item.groups }}</figcaption>
</figure>
{% endfor %}
<div class="span3 m-span3" id="js-sizer"></div>
</div>
</div>
<section>
<div class="container">
<h2>Another section</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</section>
{% include credit-jake.html %}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,173 @@
.btn-group {
@include clearfix();
.btn {
float: left;
border-radius: 0;
&:first-child {
border-radius: 6px 0 0 6px;
}
&:last-child {
border-radius: 0 6px 6px 0;
}
}
}
.btn,
button {
display: inline-block;
padding: .75em .375em;
-webkit-appearance: none;
text-align: center;
color: white;
border-radius: .0625em;
border: 0;
background-color: $wetAsphalt;
transition: .2s ease-out;
&:hover {
background-color: lighten($wetAsphalt, 12);
text-decoration: none;
}
&.active,
&:active {
background-color: $midnightBlue;
box-shadow: inset 0 1px 2px rgba(0,0,0,.3);
}
&:active {
transition: none;
}
}
.btn--warning {
background-color: $carrot;
&:hover {
background-color: lighten($carrot, 8);
}
&.active,
&:active {
background-color: $pumpkin;
// background-color: $carrot;
}
}
.btn--primary {
background-color: $river;
&:hover {
background-color: lighten($river, 8);
}
&.active,
&:active {
// background-color: $belizeHole;
background-color: $river;
}
}
.btn--danger {
background-color: $alizarin;
&:hover {
background-color: lighten($alizarin, 8);
}
&.active,
&:active {
// background-color: $pomegranate;
background-color: $alizarin;
}
}
.btn--go {
background-color: $emerald;
&:hover {
background-color: lighten($emerald, 8);
}
&.active,
&:active {
// background-color: $nephritis;
background-color: $emerald;
}
}
.filter-group .btn {
position: relative;
$size: 20px;
// Circle and check
&.active:before,
&.active:after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: $size;
height: $size;
margin-left: -$size / 2;
margin-top: -$size / 2;
opacity: 0;
transition: .2s;
}
// Circle
&:before {
background-color: $gray10;
border-radius: 50%;
}
// Check
&:after {
background-size: 60%;
background-position: center center;
background-repeat: no-repeat;
background-image: url(../img/check.svg);
}
&.active:before,
&.active:after {
opacity: 1;
}
}
@media ( max-width: 47.9375em ) {
.btn,
button {
font-size: .875em;
}
}
@media ( max-width: 30em ) {
.btn,
button {
font-size: .75em;
}
}

@ -0,0 +1,718 @@
/*------------------------------------*\
$CSSWIZARDRY-GRIDS
\*------------------------------------*/
/**
* CONTENTS
* INTRODUCTION.........How the grid system works.
* VARIABLES............Your settings.
* MIXINS...............Library mixins.
* GRID SETUP...........Build the grid structure.
* WIDTHS...............Build our responsive widths around our breakpoints.
* PUSH.................Push classes.
* PULL.................Pull classes.
*/
/*------------------------------------*\
$INTRODUCTION
\*------------------------------------*/
/**
* csswizardry grids provides you with widths to suit a number of breakpoints
* designed around devices of a size you specify. Out of the box, csswizardry
* grids caters to the following types of device:
*
* palm -- palm-based devices, like phones and small tablets
* lap -- lap-based devices, like iPads or laptops
* portable -- all of the above
* desk -- stationary devices, like desktop computers
* regular -- any/all types of device
*
* These namespaces are then used in the library to give you the ability to
* manipulate your layouts based around them, for example:
*
<div class="grid__item one-whole lap--one-half desk--one-third">
*
* This would give you a grid item which is 100% width unless it is on a lap
* device, at which point it become 50% wide, or it is on a desktop device, at
* which point it becomes 33.333% width.
*
* csswizardry grids also has push and pull classes which allow you to nudge
* grid items left and right by a defined amount. These follow the same naming
* convention as above, but are prepended by either `push--` or `pull--`, for
* example:
*
`class="grid__item one-half push--one-half"`
*
* This would give you a grid item which is 50% width and pushed over to the
* right by 50%.
*
* All classes in csswizardry grids follow this patten, so you should fairly
* quickly be able to piece together any combinations you can imagine, for
* example:
*
`class="grid__item one-whole lap--one-half desk--one-third push--desk--one-third"`
*
`class="grid__item one-quarter palm--one-half push--palm--one-half"`
*
`class="grid__item palm--one-third desk--five-twelfths"`
*/
/*------------------------------------*\
$VARIABLES
\*------------------------------------*/
/**
* If you are building a non-responsive site but would still like to use
* csswizardry-grids, set this to false:
*/
$responsive: true!default;
/**
* Is this build mobile first? Setting to true means that all grids will be
* 100% width if you do not apply a more specific class to them.
*/
$mobile-first: true!default;
/**
* Set the spacing between your grid items.
*/
$gutter: 24px!default;
/**
* Would you like Sass silent classes, or regular CSS classes?
*/
$use-silent-classes: false!default;
/**
* Would you like push and pull classes enabled?
*/
$push: false!default;
$pull: false!default;
/**
* Using `inline-block` means that the grid items need their whitespace removing
* in order for them to work correctly. Set the following to true if you are
* going to achieve this by manually removing/commenting out any whitespace in
* your HTML yourself.
*
* Setting this to false invokes a hack which cannot always be guaranteed,
* please see the following for more detail:
*
* github.com/csswizardry/csswizardry-grids/commit/744d4b23c9d2b77d605b5991e54a397df72e0688
* github.com/csswizardry/inuit.css/issues/170#issuecomment-14859371
*/
$use-markup-fix: true!default;
/**
* Define your breakpoints. The first value is the prefix that shall be used for
* your classes (e.g. `.palm--one-half`), the second value is the media query
* that the breakpoint fires at.
*/
$breakpoints: (
'palm' '(max-width: 480px)',
'lap' '(min-width: 481px) and (max-width: 1023px)',
'portable' '(max-width: 1023px)',
'desk' '(min-width: 1024px)'
)!default;
/**
* Define which namespaced breakpoints you would like to generate for each of
* widths, push and pull. This is handy if you only need pull on, say, desk, or
* you only need a new width breakpoint at mobile sizes. It allows you to only
* compile as much CSS as you need. All are turned on by default, but you can
* add and remove breakpoints at will.
*
* Push and pull shall only be used if `$push` and/or `$pull` and `$responsive`
* have been set to true.
*/
$breakpoint-has-widths: ('palm', 'lap', 'portable', 'desk')!default;
$breakpoint-has-push: ('palm', 'lap', 'portable', 'desk')!default;
$breakpoint-has-pull: ('palm', 'lap', 'portable', 'desk')!default;
/**
* You do not need to edit anything from this line onward; csswizardry-grids is
* good to go. Happy griddin!
*/
$class-type: unquote(".");
@if $use-silent-classes == true{
$class-type: unquote("%");
}
/*------------------------------------*\
$MIXINS
\*------------------------------------*/
/**
* These mixins are for the library to use only, you should not need to modify
* them at all.
*
* Enclose a block of code with a media query as named in `$breakpoints`.
*/
@mixin grid-media-query($media-query){
$breakpoint-found: false;
@each $breakpoint in $breakpoints{
$name: nth($breakpoint, 1);
$declaration: nth($breakpoint, 2);
@if $media-query == $name and $declaration{
$breakpoint-found: true;
@media only screen and #{$declaration}{
@content;
}
}
}
@if $breakpoint-found == false{
@warn "Breakpoint #{$media-query} does not exist"
}
}
/**
* Drop relative positioning into silent classes which cant take advantage of
* the `[class*="push--"]` and `[class*="pull--"]` selectors.
*/
@mixin silent-relative(){
@if $use-silent-classes == true{
position:relative;
}
}
/*------------------------------------*\
$GRID SETUP
\*------------------------------------*/
/**
* 1. Allow the grid system to be used on lists.
* 2. Remove any margins and paddings that might affect the grid system.
* 3. Apply a negative `margin-left` to negate the columns gutters.
*/
#{$class-type}grid{
list-style:none; /* [1] */
margin:0; /* [2] */
padding:0; /* [2] */
margin-left:-$gutter; /* [3] */
@if $use-markup-fix != true{
letter-spacing:-0.31em;
}
}
@if $use-markup-fix != true{
/* Opera hack */
.opera:-o-prefocus,
#{$class-type}grid{
word-spacing:-0.43em;
}
}
/**
* 1. Cause columns to stack side-by-side.
* 2. Space columns apart.
* 3. Align columns to the tops of each other.
* 4. Full-width unless told to behave otherwise.
* 5. Required to combine fluid widths and fixed gutters.
*/
#{$class-type}grid__item{
display:inline-block; /* [1] */
padding-left:$gutter; /* [2] */
vertical-align:top; /* [3] */
@if $mobile-first == true{
width:100%; /* [4] */
}
-webkit-box-sizing:border-box; /* [5] */
-moz-box-sizing:border-box; /* [5] */
box-sizing:border-box; /* [5] */
@if $use-markup-fix != true{
letter-spacing:normal;
word-spacing:normal;
}
}
/**
* Reversed grids allow you to structure your source in the opposite order to
* how your rendered layout will appear. Extends `.grid`.
*/
#{$class-type}grid--rev{
direction:rtl;
text-align:left;
> #{$class-type}grid__item{
direction:ltr;
text-align:left;
}
}
/**
* Gutterless grids have all the properties of regular grids, minus any spacing.
* Extends `.grid`.
*/
#{$class-type}grid--full{
margin-left:0;
> #{$class-type}grid__item{
padding-left:0;
}
}
/**
* Align the entire grid to the right. Extends `.grid`.
*/
#{$class-type}grid--right{
text-align:right;
> #{$class-type}grid__item{
text-align:left;
}
}
/**
* Centered grids align grid items centrally without needing to use push or pull
* classes. Extends `.grid`.
*/
#{$class-type}grid--center{
text-align:center;
> #{$class-type}grid__item{
text-align:left;
}
}
/**
* Align grid cells vertically (`.grid--middle` or `.grid--bottom`). Extends
* `.grid`.
*/
#{$class-type}grid--middle{
> #{$class-type}grid__item{
vertical-align:middle;
}
}
#{$class-type}grid--bottom{
> #{$class-type}grid__item{
vertical-align:bottom;
}
}
/**
* Create grids with narrower gutters. Extends `.grid`.
*/
#{$class-type}grid--narrow{
margin-left:-($gutter / 2);
> #{$class-type}grid__item{
padding-left:$gutter / 2;
}
}
/**
* Create grids with wider gutters. Extends `.grid`.
*/
#{$class-type}grid--wide{
margin-left:-($gutter * 2);
> #{$class-type}grid__item{
padding-left:$gutter * 2;
}
}
/*------------------------------------*\
$WIDTHS
\*------------------------------------*/
/**
* Create our width classes, prefixed by the specified namespace.
*/
@mixin device-type($namespace:""){
/**
* Whole
*/
#{$class-type}#{$namespace}one-whole { width:100%; }
/**
* Halves
*/
#{$class-type}#{$namespace}one-half { width:50%; }
/**
* Thirds
*/
#{$class-type}#{$namespace}one-third { width:33.333%; }
#{$class-type}#{$namespace}two-thirds { width:66.666%; }
/**
* Quarters
*/
#{$class-type}#{$namespace}one-quarter { width:25%; }
#{$class-type}#{$namespace}two-quarters { @extend #{$class-type}#{$namespace}one-half; }
#{$class-type}#{$namespace}three-quarters { width:75%; }
/**
* Fifths
*/
#{$class-type}#{$namespace}one-fifth { width:20%; }
#{$class-type}#{$namespace}two-fifths { width:40%; }
#{$class-type}#{$namespace}three-fifths { width:60%; }
#{$class-type}#{$namespace}four-fifths { width:80%; }
/**
* Sixths
*/
#{$class-type}#{$namespace}one-sixth { width:16.666%; }
#{$class-type}#{$namespace}two-sixths { @extend #{$class-type}#{$namespace}one-third; }
#{$class-type}#{$namespace}three-sixths { @extend #{$class-type}#{$namespace}one-half; }
#{$class-type}#{$namespace}four-sixths { @extend #{$class-type}#{$namespace}two-thirds; }
#{$class-type}#{$namespace}five-sixths { width:83.333%; }
/**
* Eighths
*/
#{$class-type}#{$namespace}one-eighth { width:12.5%; }
#{$class-type}#{$namespace}two-eighths { @extend #{$class-type}#{$namespace}one-quarter; }
#{$class-type}#{$namespace}three-eighths { width:37.5%; }
#{$class-type}#{$namespace}four-eighths { @extend #{$class-type}#{$namespace}one-half; }
#{$class-type}#{$namespace}five-eighths { width:62.5%; }
#{$class-type}#{$namespace}six-eighths { @extend #{$class-type}#{$namespace}three-quarters; }
#{$class-type}#{$namespace}seven-eighths { width:87.5%; }
/**
* Tenths
*/
#{$class-type}#{$namespace}one-tenth { width:10%; }
#{$class-type}#{$namespace}two-tenths { @extend #{$class-type}#{$namespace}one-fifth; }
#{$class-type}#{$namespace}three-tenths { width:30%; }
#{$class-type}#{$namespace}four-tenths { @extend #{$class-type}#{$namespace}two-fifths; }
#{$class-type}#{$namespace}five-tenths { @extend #{$class-type}#{$namespace}one-half; }
#{$class-type}#{$namespace}six-tenths { @extend #{$class-type}#{$namespace}three-fifths; }
#{$class-type}#{$namespace}seven-tenths { width:70%; }
#{$class-type}#{$namespace}eight-tenths { @extend #{$class-type}#{$namespace}four-fifths; }
#{$class-type}#{$namespace}nine-tenths { width:90%; }
/**
* Twelfths
*/
#{$class-type}#{$namespace}one-twelfth { width:8.333%; }
#{$class-type}#{$namespace}two-twelfths { @extend #{$class-type}#{$namespace}one-sixth; }
#{$class-type}#{$namespace}three-twelfths { @extend #{$class-type}#{$namespace}one-quarter; }
#{$class-type}#{$namespace}four-twelfths { @extend #{$class-type}#{$namespace}one-third; }
#{$class-type}#{$namespace}five-twelfths { width:41.666% }
#{$class-type}#{$namespace}six-twelfths { @extend #{$class-type}#{$namespace}one-half; }
#{$class-type}#{$namespace}seven-twelfths { width:58.333%; }
#{$class-type}#{$namespace}eight-twelfths { @extend #{$class-type}#{$namespace}two-thirds; }
#{$class-type}#{$namespace}nine-twelfths { @extend #{$class-type}#{$namespace}three-quarters; }
#{$class-type}#{$namespace}ten-twelfths { @extend #{$class-type}#{$namespace}five-sixths; }
#{$class-type}#{$namespace}eleven-twelfths { width:91.666%; }
}
/**
* Our regular, non-responsive width classes.
*/
@include device-type();
/**
* Our responsive classes, if we have enabled them.
*/
@if $responsive == true{
@each $name in $breakpoint-has-widths {
@include grid-media-query($name) {
@include device-type('#{$name}--');
}
}
}
/*------------------------------------*\
$PUSH
\*------------------------------------*/
/**
* Push classes, to move grid items over to the right by certain amounts.
*/
@mixin push-setup($namespace: ""){
/**
* Whole
*/
#{$class-type}push--#{$namespace}one-whole { left:100%; @include silent-relative(); }
/**
* Halves
*/
#{$class-type}push--#{$namespace}one-half { left:50%; @include silent-relative(); }
/**
* Thirds
*/
#{$class-type}push--#{$namespace}one-third { left:33.333%; @include silent-relative(); }
#{$class-type}push--#{$namespace}two-thirds { left:66.666%; @include silent-relative(); }
/**
* Quarters
*/
#{$class-type}push--#{$namespace}one-quarter { left:25%; @include silent-relative(); }
#{$class-type}push--#{$namespace}two-quarters { @extend #{$class-type}push--#{$namespace}one-half; }
#{$class-type}push--#{$namespace}three-quarters { left:75%; @include silent-relative(); }
/**
* Fifths
*/
#{$class-type}push--#{$namespace}one-fifth { left:20%; @include silent-relative(); }
#{$class-type}push--#{$namespace}two-fifths { left:40%; @include silent-relative(); }
#{$class-type}push--#{$namespace}three-fifths { left:60%; @include silent-relative(); }
#{$class-type}push--#{$namespace}four-fifths { left:80%; @include silent-relative(); }
/**
* Sixths
*/
#{$class-type}push--#{$namespace}one-sixth { left:16.666%; @include silent-relative(); }
#{$class-type}push--#{$namespace}two-sixths { @extend #{$class-type}push--#{$namespace}one-third; }
#{$class-type}push--#{$namespace}three-sixths { @extend #{$class-type}push--#{$namespace}one-half; }
#{$class-type}push--#{$namespace}four-sixths { @extend #{$class-type}push--#{$namespace}two-thirds; }
#{$class-type}push--#{$namespace}five-sixths { left:83.333%; @include silent-relative(); }
/**
* Eighths
*/
#{$class-type}push--#{$namespace}one-eighth { left:12.5%; @include silent-relative(); }
#{$class-type}push--#{$namespace}two-eighths { @extend #{$class-type}push--#{$namespace}one-quarter; }
#{$class-type}push--#{$namespace}three-eighths { left:37.5%; @include silent-relative(); }
#{$class-type}push--#{$namespace}four-eighths { @extend #{$class-type}push--#{$namespace}one-half; }
#{$class-type}push--#{$namespace}five-eighths { left:62.5%; @include silent-relative(); }
#{$class-type}push--#{$namespace}six-eighths { @extend #{$class-type}push--#{$namespace}three-quarters; }
#{$class-type}push--#{$namespace}seven-eighths { left:87.5%; @include silent-relative(); }
/**
* Tenths
*/
#{$class-type}push--#{$namespace}one-tenth { left:10%; @include silent-relative(); }
#{$class-type}push--#{$namespace}two-tenths { @extend #{$class-type}push--#{$namespace}one-fifth; }
#{$class-type}push--#{$namespace}three-tenths { left:30%; @include silent-relative(); }
#{$class-type}push--#{$namespace}four-tenths { @extend #{$class-type}push--#{$namespace}two-fifths; }
#{$class-type}push--#{$namespace}five-tenths { @extend #{$class-type}push--#{$namespace}one-half; }
#{$class-type}push--#{$namespace}six-tenths { @extend #{$class-type}push--#{$namespace}three-fifths; }
#{$class-type}push--#{$namespace}seven-tenths { left:70%; @include silent-relative(); }
#{$class-type}push--#{$namespace}eight-tenths { @extend #{$class-type}push--#{$namespace}four-fifths; }
#{$class-type}push--#{$namespace}nine-tenths { left:90%; @include silent-relative(); }
/**
* Twelfths
*/
#{$class-type}push--#{$namespace}one-twelfth { left:8.333%; @include silent-relative(); }
#{$class-type}push--#{$namespace}two-twelfths { @extend #{$class-type}push--#{$namespace}one-sixth; }
#{$class-type}push--#{$namespace}three-twelfths { @extend #{$class-type}push--#{$namespace}one-quarter; }
#{$class-type}push--#{$namespace}four-twelfths { @extend #{$class-type}push--#{$namespace}one-third; }
#{$class-type}push--#{$namespace}five-twelfths { left:41.666%; @include silent-relative(); }
#{$class-type}push--#{$namespace}six-twelfths { @extend #{$class-type}push--#{$namespace}one-half; }
#{$class-type}push--#{$namespace}seven-twelfths { left:58.333%; @include silent-relative(); }
#{$class-type}push--#{$namespace}eight-twelfths { @extend #{$class-type}push--#{$namespace}two-thirds; }
#{$class-type}push--#{$namespace}nine-twelfths { @extend #{$class-type}push--#{$namespace}three-quarters; }
#{$class-type}push--#{$namespace}ten-twelfths { @extend #{$class-type}push--#{$namespace}five-sixths; }
#{$class-type}push--#{$namespace}eleven-twelfths { left:91.666%; @include silent-relative(); }
}
@if $push == true {
/**
* Not a particularly great selector, but the DRYest way to do things.
*/
[class*="push--"]{ position:relative; }
@include push-setup();
@if $responsive == true{
@each $name in $breakpoint-has-push {
@include grid-media-query($name) {
@include push-setup('#{$name}--');
}
}
}
}
/*------------------------------------*\
$PULL
\*------------------------------------*/
/**
* Pull classes, to move grid items back to the left by certain amounts.
*/
@mixin pull-setup($namespace: ""){
/**
* Whole
*/
#{$class-type}pull--#{$namespace}one-whole { right:100%; @include silent-relative(); }
/**
* Halves
*/
#{$class-type}pull--#{$namespace}one-half { right:50%; @include silent-relative(); }
/**
* Thirds
*/
#{$class-type}pull--#{$namespace}one-third { right:33.333%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}two-thirds { right:66.666%; @include silent-relative(); }
/**
* Quarters
*/
#{$class-type}pull--#{$namespace}one-quarter { right:25%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}two-quarters { @extend #{$class-type}pull--#{$namespace}one-half; }
#{$class-type}pull--#{$namespace}three-quarters { right:75%; @include silent-relative(); }
/**
* Fifths
*/
#{$class-type}pull--#{$namespace}one-fifth { right:20%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}two-fifths { right:40%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}three-fifths { right:60%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}four-fifths { right:80%; @include silent-relative(); }
/**
* Sixths
*/
#{$class-type}pull--#{$namespace}one-sixth { right:16.666%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}two-sixths { @extend #{$class-type}pull--#{$namespace}one-third; }
#{$class-type}pull--#{$namespace}three-sixths { @extend #{$class-type}pull--#{$namespace}one-half; }
#{$class-type}pull--#{$namespace}four-sixths { @extend #{$class-type}pull--#{$namespace}two-thirds; }
#{$class-type}pull--#{$namespace}five-sixths { right:83.333%; @include silent-relative(); }
/**
* Eighths
*/
#{$class-type}pull--#{$namespace}one-eighth { right:12.5%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}two-eighths { @extend #{$class-type}pull--#{$namespace}one-quarter; }
#{$class-type}pull--#{$namespace}three-eighths { right:37.5%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}four-eighths { @extend #{$class-type}pull--#{$namespace}one-half; }
#{$class-type}pull--#{$namespace}five-eighths { right:62.5%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}six-eighths { @extend #{$class-type}pull--#{$namespace}three-quarters; }
#{$class-type}pull--#{$namespace}seven-eighths { right:87.5%; @include silent-relative(); }
/**
* Tenths
*/
#{$class-type}pull--#{$namespace}one-tenth { right:10%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}two-tenths { @extend #{$class-type}pull--#{$namespace}one-fifth; }
#{$class-type}pull--#{$namespace}three-tenths { right:30%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}four-tenths { @extend #{$class-type}pull--#{$namespace}two-fifths; }
#{$class-type}pull--#{$namespace}five-tenths { @extend #{$class-type}pull--#{$namespace}one-half; }
#{$class-type}pull--#{$namespace}six-tenths { @extend #{$class-type}pull--#{$namespace}three-fifths; }
#{$class-type}pull--#{$namespace}seven-tenths { right:70%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}eight-tenths { @extend #{$class-type}pull--#{$namespace}four-fifths; }
#{$class-type}pull--#{$namespace}nine-tenths { right:90%; @include silent-relative(); }
/**
* Twelfths
*/
#{$class-type}pull--#{$namespace}one-twelfth { right:8.333%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}two-twelfths { @extend #{$class-type}pull--#{$namespace}one-sixth; }
#{$class-type}pull--#{$namespace}three-twelfths { @extend #{$class-type}pull--#{$namespace}one-quarter; }
#{$class-type}pull--#{$namespace}four-twelfths { @extend #{$class-type}pull--#{$namespace}one-third; }
#{$class-type}pull--#{$namespace}five-twelfths { right:41.666%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}six-twelfths { @extend #{$class-type}pull--#{$namespace}one-half; }
#{$class-type}pull--#{$namespace}seven-twelfths { right:58.333%; @include silent-relative(); }
#{$class-type}pull--#{$namespace}eight-twelfths { @extend #{$class-type}pull--#{$namespace}two-thirds; }
#{$class-type}pull--#{$namespace}nine-twelfths { @extend #{$class-type}pull--#{$namespace}three-quarters; }
#{$class-type}pull--#{$namespace}ten-twelfths { @extend #{$class-type}pull--#{$namespace}five-sixths; }
#{$class-type}pull--#{$namespace}eleven-twelfths { right:91.666%; @include silent-relative(); }
}
@if $pull == true{
/**
* Not a particularly great selector, but the DRYest way to do things.
*/
[class*="pull--"]{ position:relative; }
@include pull-setup();
@if $responsive == true{
@each $name in $breakpoint-has-pull {
@include grid-media-query($name) {
@include pull-setup('#{$name}--');
}
}
}
}

@ -0,0 +1,90 @@
.ib {
display: inline-block;
}
.keep-ratio {
position: relative;
width: 100%;
height: 0;
overflow: hidden;
padding-bottom: 100%;
&.four-three {
padding-bottom: 75%;
}
}
// Hide from both screenreaders and browsers: h5bp.com/u
.hidden {
display: none !important;
visibility: hidden;
}
// Hide only visually, but have it available for screenreaders: h5bp.com/v
.visuallyhidden {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
/*
* Clearfix: contain floats
*
* For modern browsers
* 1. The space content is one way to avoid an Opera bug when the
* `contenteditable` attribute is included anywhere else in the document.
* Otherwise it causes space to appear at the top and bottom of elements
* that receive the `clearfix` class.
* 2. The use of `table` rather than `block` is only necessary if using
* `:before` to contain the top-margins of child elements.
*/
.clearfix:before,
.clearfix:after {
content: " "; /* 1 */
display: table; /* 2 */
}
.clearfix:after {
clear: both;
}
/*
* For IE 6/7 only
* Include this rule to trigger hasLayout and contain floats.
*/
.clearfix {
*zoom: 1;
}
.pull-left {
float: left;
}
.pull-right {
float: right;
}
.hide-text {
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
.input-block-level {
display: block;
width: 100%;
min-height: 30px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}

@ -0,0 +1,174 @@
@import "variables";
* {
-moz-box-sizing: border-box;
box-sizing: border-box;
}
pre {
max-height: 30em;
}
img {
max-width: 100%;
height: auto;
}
/* lets have some constraints shall we */
.container-fluid {
width: 93%;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
}
.row.row--full {
margin-left: 0;
}
ul ul {
padding-left: 1.25em;
margin: 0;
list-style-type: circle;
}
.site-nav {
.site-nav__title {
color: $clouds;
&:first-child {
margin-top: 0;
}
}
.btn {
width: 100%;
}
.site-nav__tray {
transition: .2s;
overflow: hidden;
height: 300px;
background-color: $wetAsphalt;
}
.site-nav__tray-inner {
padding: 30px 0;
}
&.collapsed .site-nav__tray {
height: 0;
// IE7 wtf
.lt-ie8 & {
display: none;
}
}
.figure-wrap,
.figure-wrap img {
// Promote to its own layer. makes filters look ok on retina with images
-webkit-transform: translateZ(0);
-webkit-transition: .1s ease;
transition: .1s ease;
}
.site-nav__demos:hover .figure-wrap {
-webkit-transform: scale3d( 1, 1, 1 );
transform: scale3d( 1, 1, 1 );
img {
-webkit-filter: grayscale(1);
filter: grayscale(1);
}
}
.site-nav__demos:hover .figure-wrap.hovered {
-webkit-transform: scale3d( 1.05, 1.05, 1 );
transform: scale3d( 1.05, 1.05, 1 );
img {
-webkit-filter: none;
filter: none;
}
}
.figure-wrap:nth-child(4n + 1) {
margin-left: 0;
}
.figure-wrap > a {
display: block;
}
.figure-wrap figcaption {
margin-top: .5em;
}
.site-nav__band {
position: relative;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 4px;
background: $wetAsphalt;
}
}
}
.site-footer {
margin-top: 2em;
padding: 1em 0;
background-color: $wetAsphalt;
}
.site-footer__credit {
margin: 0;
text-align: right;
}
nav > a {
display: block;
margin: 5px 0;
}
// Filters
.filter__label {
margin: 0 0 3px;
}
.filter__search {
margin: 5px 0;
}
.sort-options {
margin-top: 10px;
}
@media ( max-width: 47.9375em ) {
.figure-wrap:nth-child(odd) {
margin-left: 0;
}
.figure-wrap:nth-child(n + 3) {
margin-top: 1em;
}
}

@ -0,0 +1,24 @@
$columns: 6;
$gutterWidth: 2; // 2% gutter width
$columnWidth: (100 - ( $gutterWidth * ( $columns - 1 ))) / $columns;
@media ( max-width: 47.9375em ) {
.m-row {
[class*="m-span"] {
float: left;
margin-left: $gutterWidth + 0%;
&:first-child {
margin-left: 0;
}
}
@for $i from 1 through 6 {
.m-span#{$i} {
width: ($i * $columnWidth) + (($i - 1) * $gutterWidth) + 0%;
}
}
}
}

@ -0,0 +1,396 @@
/*! normalize.css v2.1.2 | MIT License | git.io/normalize */
/* ==========================================================================
HTML5 display definitions
========================================================================== */
/**
* Correct `block` display not defined in IE 8/9.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
nav,
section,
summary {
display: block;
}
/**
* Correct `inline-block` display not defined in IE 8/9.
*/
audio,
canvas,
video {
display: inline-block;
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address styling not present in IE 8/9.
*/
[hidden] {
display: none;
}
/* ==========================================================================
Base
========================================================================== */
/**
* 1. Set default font family to sans-serif.
* 2. Prevent iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/**
* Remove default margin.
*/
body {
margin: 0;
}
/* ==========================================================================
Links
========================================================================== */
/**
* Address `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/* ==========================================================================
Typography
========================================================================== */
// /**
// * Address variable `h1` font-size and margin within `section` and `article`
// * contexts in Firefox 4+, Safari 5, and Chrome.
// */
// h1 {
// font-size: 2em;
// margin: 0.67em 0;
// }
/**
* Address styling not present in IE 8/9, Safari 5, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/**
* Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
*/
b,
strong {
font-weight: bold;
}
/**
* Address styling not present in Safari 5 and Chrome.
*/
dfn {
font-style: italic;
}
/**
* Address differences between Firefox and other browsers.
*/
hr {
-moz-box-sizing: content-box;
box-sizing: content-box;
height: 0;
}
/**
* Address styling not present in IE 8/9.
*/
mark {
background: #ff0;
color: #000;
}
/**
* Correct font family set oddly in Safari 5 and Chrome.
*/
code,
kbd,
pre,
samp {
font-family: monospace, serif;
font-size: 1em;
}
/**
* Improve readability of pre-formatted text in all browsers.
*/
pre {
white-space: pre-wrap;
}
/**
* Set consistent quote types.
*/
q {
quotes: "\201C" "\201D" "\2018" "\2019";
}
/**
* Address inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* ==========================================================================
Embedded content
========================================================================== */
/**
* Remove border when inside `a` element in IE 8/9.
*/
img {
border: 0;
}
/**
* Correct overflow displayed oddly in IE 9.
*/
svg:not(:root) {
overflow: hidden;
}
/* ==========================================================================
Figures
========================================================================== */
/**
* Address margin not present in IE 8/9 and Safari 5.
*/
figure {
margin: 0;
}
/* ==========================================================================
Forms
========================================================================== */
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct `color` not being inherited in IE 8/9.
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
*/
legend {
border: 0; /* 1 */
padding: 0; /* 2 */
}
/**
* 1. Correct font family not being inherited in all browsers.
* 2. Correct font size not being inherited in all browsers.
* 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
*/
button,
input,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 2 */
margin: 0; /* 3 */
}
/**
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
button,
input {
line-height: normal;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+.
* Correct `select` style inheritance in Firefox 4+ and Opera.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* 1. Address box sizing set to `content-box` in IE 8/9.
* 2. Remove excess padding in IE 8/9.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari 5 and Chrome
* on OS X.
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Remove inner padding and border in Firefox 4+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* 1. Remove default vertical scrollbar in IE 8/9.
* 2. Improve readability and alignment in all browsers.
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/* ==========================================================================
Tables
========================================================================== */
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}

@ -0,0 +1,102 @@
body {
font-family: 'Ubuntu', Verdana, sans-serif;
color: $gray30;
}
// Links
a {
text-decoration: none;
&,
&:visited {
color: $river;
}
&:hover {
text-decoration: underline;
}
&:active {
color: $emerald;
}
}
h2,
h3,
h4,
h5,
h6 {
color: $wetAsphalt;
}
// Headers
h1 {
margin: 20px 0;
font-weight: 300;
font-size: 4em;
line-height: 1;
color: $emerald;
}
h2 {
position: relative;
font-size: 2.5em;
margin-bottom: 18px;
// Bottom border BEHIND the descenders!
&::after {
content: '';
position: absolute;
bottom: 4px;
left: 0;
z-index: -1;
width: 100%;
height: 2px;
background-color: $emerald;
}
}
h3 {
margin: .6667em 0 0.5em;
font-size: 1.5em;
}
h4 {
font-size: 1.25em;
}
@media ( max-width: 47.9375em ) {
h1 {
font-size: 8vw;
margin: 3vw 0;
}
h2 {
font-size: 6vw;
margin: 2vw 0;
}
}
.unstyled {
list-style-type: none;
padding: 0;
margin: 0;
}
.light-text-dark-box {
p {
color: $clouds;
}
a {
color: $clouds;
&:hover {
color: white;
}
}
}

@ -0,0 +1,61 @@
// Colors from Flat UI
$turqoise: #1ABC9C;
$greenSea: #16A085;
$emerald: #2ECC71;
$nephritis: #27AE60;
$river: #3498DB;
$belizeHole: #2980B9;
$amethyst: #9B59B6;
$wisteria: #8E44AD;
$wetAsphalt: #34495E;
$midnightBlue: #2C3E50;
$sunflower: #F1C40F;
$orange: #F39C12;
$carrot: #E67E22;
$pumpkin: #D35400;
$alizarin: #E74C3C;
$pomegranate: #C0392B;
$clouds: #ECF0F1;
$silver: #BDC3C7;
$concrete: #95A5A6;
$asbestos: #7F8C8D;
//
$black: #000;
$gray10: $midnightBlue;
$gray30: #5D6D77;
$gray20: $wetAsphalt;
$gray40: $concrete;
$gray50: $asbestos;
$white: #FFF;
@mixin clearfix() {
&:before,
&:after {
content: " ";
display: table;
}
&:after {
clear: both;
}
& {
*zoom: 1;
}
}

@ -0,0 +1,225 @@
@import "variables";
@import "compass";
.filter-options {
margin-top: 20px;
margin-bottom: 40px;
}
.filter-group {
.filter-group__label {
margin: 0 0 5px;
}
button {
width: 40px;
height: 40px;
padding: 0;
}
label {
cursor: pointer;
}
}
.shape-up {
position: relative;
overflow: hidden;
}
.shape {
position: relative;
margin-left: 0;
margin-top: 10px;
.shape__inner {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.shape__space {
width: 100%;
height: 100%;
background-color: black;
border-style: solid;
border-width: 0;
border-color: transparent;
}
}
.shape--blue .shape__space {
background-color: $river;
border-bottom-color: $river;
}
.shape--red .shape__space {
background-color: $alizarin;
border-bottom-color: $alizarin;
}
.shape--orange .shape__space {
background-color: $orange;
border-bottom-color: $orange;
}
.shape--green .shape__space {
background-color: $emerald;
border-bottom-color: $emerald;
}
.shape--circle .shape__space {
border-radius: 50%;
}
.shape--square .shape__space {
// Nothing to see here
}
// 166 / sqrt(166^2 + 166^2) = scale
.shape--diamond .shape__space {
-webkit-transform: rotate(45deg) scale(0.707106781);
transform: rotate(45deg) scale(0.707106781);
}
$triangleSize: 220px;
$halfSize: $triangleSize / 2;
$fullSideWidth: round(sqrt(3) * $halfSize);
$leftOver: $triangleSize - $fullSideWidth;
.shape--triangle .shape__space {
padding-top: $leftOver / 2;
height: 0;
width: 0;
border-width: 0 $halfSize $fullSideWidth $halfSize;
background-color: transparent;
}
// IE8 filter alpha wasn't working with the positioning stuff
.lt-ie9 .shape {
.keep-ratio {
position: static;
width: 100%;
height: 250px;
overflow: visible;
padding-bottom: 0;
}
.shape__inner {
position: static;
width: 100%;
height: 100%;
}
}
@media (min-width: 1200px) {
$triangleSize: 270px;
$halfSize: $triangleSize / 2;
$fullSideWidth: round(sqrt(3) * $halfSize);
$leftOver: $triangleSize - $fullSideWidth;
.shape--triangle .shape__space {
padding-top: $leftOver / 2;
border-width: 0 $halfSize $fullSideWidth $halfSize;
}
}
@media (min-width: 768px) and (max-width: 979px) {
$triangleSize: 166px;
$halfSize: $triangleSize / 2;
$fullSideWidth: round(sqrt(3) * $halfSize);
$leftOver: $triangleSize - $fullSideWidth;
.shape--triangle .shape__space {
padding-top: $leftOver / 2;
border-width: 0 $halfSize $fullSideWidth $halfSize;
}
}
@media (max-width: 767px) {
$triangleSize: 200px;
$halfSize: $triangleSize / 2;
$fullSideWidth: round(sqrt(3) * $halfSize);
$leftOver: $triangleSize - $fullSideWidth;
.shape--triangle .shape__space {
padding-top: $leftOver / 2;
border-width: 0 $halfSize $fullSideWidth $halfSize;
}
}
@media (max-width: 480px) {
$triangleSize: 100px;
$halfSize: $triangleSize / 2;
$fullSideWidth: round(sqrt(3) * $halfSize);
$leftOver: $triangleSize - $fullSideWidth;
.shape--triangle .shape__space {
padding-top: $leftOver / 2;
border-width: 0 $halfSize $fullSideWidth $halfSize;
}
}
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);
-webkit-transition: background .2s ease;
-o-transition: background .2s ease;
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);
}
}

@ -0,0 +1,119 @@
@import "variables";
/*=============================================*\
Some styles to show off masonry layout
\*=============================================*/
$pictureGutter: 24px;
$itemHeight: 220px;
.picture-item {
height: 220px;
margin-top: $pictureGutter;
overflow: hidden;
background: $clouds;
&.shuffle-item {
margin-left: 0; /* shuffle items shouldn't have a left margin*/
}
&.picture-item--h2 {
height: ($itemHeight * 2) + $pictureGutter; /* 2x the height + 1 gutter */
}
// Ehh, i should really use something other than span6 to target this...
&.span6:not(.picture-item--h2) {
.picture-item__details {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
background-color: #333;
background-color: rgba(black, .6);
color: white;
}
.picture-item__description {
display: none;
}
}
img {
display: block;
width: 100%;
height: auto;
}
.picture-item__details,
.picture-item__description {
padding: 1em;
}
.picture-item__description {
margin: 0;
padding-top: 0;
padding-right: 2em;
}
.picture-item__tags {
margin: 0;
}
.picture-item__title {
}
}
/*
Shuffle needs either relative or absolute positioning on the container
It will set it for you, but it'll cause another style recalculation and layout.
AKA worse performance - so just set it here
*/
.shuffle--container {
position: relative;
overflow: hidden;
}
.shuffle--fluid .shuffle__sizer {
position: absolute;
opacity: 0;
visibility: hidden;
}
@media ( max-width: 47.9375em ) {
.picture-item {
height: auto;
margin-top: 20px;
&.picture-item--h2 {
height: auto;
}
.picture-item__details,
.picture-item__description {
font-size: .875em;
padding: .625em;
}
.picture-item__description {
padding-right: .875em;
padding-bottom: 1.25em;
}
}
.filter > .row-fluid,
.filter > .row-fluid > div {
margin: 10px 0;
}
.m-nofloat {
float: none;
}
}

@ -0,0 +1,11 @@
@import "variables";
@import "normalize";
// @import "csswizardry-grids";
@import "type";
@import "bootstrap";
@import "mobile-grid";
@import "main";
@import "buttons";
@import "helpers";

@ -0,0 +1,25 @@
# Require any additional compass plugins here.
# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "css"
sass_dir = "_scss"
images_dir = "img"
javascripts_dir = "js"
# You can select your preferred output style here (can be overridden via the command line):
# output_style = :expanded or :nested or :compact or :compressed
output_style = :expanded
# To enable relative paths to assets via compass helper functions. Uncomment:
# relative_assets = true
# To disable debugging comments that display the original location of your selectors. Uncomment:
line_comments = false
# If you prefer the indented syntax, you might want to regenerate this
# project again passing --syntax sass, or you can uncomment this:
# preferred_syntax = :sass
# and then run:
# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass

@ -0,0 +1,155 @@
.filter-options {
margin-top: 20px;
margin-bottom: 40px;
}
.filter-group .filter-group__label {
margin: 0 0 5px;
}
.filter-group button {
width: 40px;
height: 40px;
padding: 0;
}
.filter-group label {
cursor: pointer;
}
.shape-up {
position: relative;
overflow: hidden;
}
.shape {
position: relative;
margin-left: 0;
margin-top: 10px;
}
.shape .shape__inner {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.shape .shape__space {
width: 100%;
height: 100%;
background-color: black;
border-style: solid;
border-width: 0;
border-color: transparent;
}
.shape--blue .shape__space {
background-color: #3498db;
border-bottom-color: #3498db;
}
.shape--red .shape__space {
background-color: #e74c3c;
border-bottom-color: #e74c3c;
}
.shape--orange .shape__space {
background-color: #f39c12;
border-bottom-color: #f39c12;
}
.shape--green .shape__space {
background-color: #2ecc71;
border-bottom-color: #2ecc71;
}
.shape--circle .shape__space {
border-radius: 50%;
}
.shape--diamond .shape__space {
-webkit-transform: rotate(45deg) scale(0.70711);
transform: rotate(45deg) scale(0.70711);
}
.shape--triangle .shape__space {
padding-top: 14.5px;
height: 0;
width: 0;
border-width: 0 110px 191px 110px;
background-color: transparent;
}
.lt-ie9 .shape .keep-ratio {
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;
border-width: 0 135px 234px 135px;
}
}
@media (min-width: 768px) and (max-width: 979px) {
.shape--triangle .shape__space {
padding-top: 11px;
border-width: 0 83px 144px 83px;
}
}
@media (max-width: 767px) {
.shape--triangle .shape__space {
padding-top: 13.5px;
border-width: 0 100px 173px 100px;
}
}
@media (max-width: 480px) {
.shape--triangle .shape__space {
padding-top: 6.5px;
border-width: 0 50px 87px 50px;
}
}
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;
-o-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);
}
}

@ -0,0 +1,107 @@
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #a67f59;
background: hsla(0,0%,100%,.5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.regex,
.token.important {
color: #e90;
}
.token.important {
font-weight: bold;
}
.token.entity {
cursor: help;
}

@ -0,0 +1,90 @@
/*=============================================*\
Some styles to show off masonry layout
\*=============================================*/
.picture-item {
height: 220px;
margin-top: 24px;
overflow: hidden;
background: #ecf0f1;
}
.picture-item.shuffle-item {
margin-left: 0;
/* shuffle items shouldn't have a left margin*/
}
.picture-item.picture-item--h2 {
height: 464px;
/* 2x the height + 1 gutter */
}
.picture-item.span6:not(.picture-item--h2) .picture-item__details {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
background-color: #333;
background-color: rgba(0, 0, 0, 0.6);
color: white;
}
.picture-item.span6:not(.picture-item--h2) .picture-item__description {
display: none;
}
.picture-item img {
display: block;
width: 100%;
height: auto;
}
.picture-item .picture-item__details,
.picture-item .picture-item__description {
padding: 1em;
}
.picture-item .picture-item__description {
margin: 0;
padding-top: 0;
padding-right: 2em;
}
.picture-item .picture-item__tags {
margin: 0;
}
/*
Shuffle needs either relative or absolute positioning on the container
It will set it for you, but it'll cause another style recalculation and layout.
AKA worse performance - so just set it here
*/
.shuffle--container {
position: relative;
overflow: hidden;
}
.shuffle--fluid .shuffle__sizer {
position: absolute;
opacity: 0;
visibility: hidden;
}
@media (max-width: 47.9375em) {
.picture-item {
height: auto;
margin-top: 20px;
}
.picture-item.picture-item--h2 {
height: auto;
}
.picture-item .picture-item__details,
.picture-item .picture-item__description {
font-size: .875em;
padding: .625em;
}
.picture-item .picture-item__description {
padding-right: .875em;
padding-bottom: 1.25em;
}
.filter > .row-fluid,
.filter > .row-fluid > div {
margin: 10px 0;
}
.m-nofloat {
float: none;
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px" viewBox="38.953 38.347 20 20" enable-background="new 38.953 38.347 20 20" xml:space="preserve">
<path fill="#FFFFFF" d="M46.137,55.759l-6.184-6.224l3.003-3.022l3.269,3.287l8.812-8.865l2.916,2.935L46.137,55.759z"/>
</svg>

After

Width:  |  Height:  |  Size: 519 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 806 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

@ -0,0 +1,174 @@
---
layout: default
title: Shuffle.js
bodyClass: home
extraJS: [ "demos/homepage.js" ]
includeHeader: true
prism: true
---
<section id="downloads">
<div class="container-fluid">
<h2>Downloads</h2>
<div class="row-fluid">
<nav class="span6" role="secondary">
<a href="js/jquery.shuffle.js">jquery.shuffle.js</a>
<a href="js/jquery.shuffle.min.js">jquery.shuffle.min.js</a>
</nav>
</div>
</div>
</section>
<section id="demo">
<div class="container-fluid">
<h2>Example</h2>
</div>
<div class="container-fluid filter">
<div class="row-fluid">
<input class="filter__search js-shuffle-search" type="search" placeholder="Search..." />
</div>
<div class="row-fluid">
<div class="span9">
<p class="filter__label">Filter:</p>
<div class="filter-options btn-group">
<button class="btn btn--warning" data-group="wallpaper">Wallpapers</button>
<button class="btn btn--warning" data-group="graphics">Graphic Design</button>
<button class="btn btn--warning" data-group="photography">Photos</button>
<button class="btn btn--warning" data-group="3d">3D Renders</button>
</div>
</div>
<div class="span3">
<div class="m-nofloat pull-right">
<p class="filter__label">Sort:</p>
<select class="sort-options">
<option value>Default</option>
<option value="title">Title</option>
<option value="date-created">Date Created</option>
</select>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div id="grid" class="row-fluid m-row shuffle--container shuffle--fluid">
{% for item in site.items %}
{% assign item = item %}
{% include picture-item.html %}
{% endfor %}
<div class="span3 m-span3 shuffle__sizer"></div>
</div>
</div>
</section>
<section id="demos">
<div class="container-fluid">
<h2>Demos</h2>
<a href="#nav">In the nav</a>
</div>
</section>
<section id="features">
<div class="container-fluid">
{% include features.html %}
</div>
</section>
<section id="options">
<div class="container-fluid">
{% include options.html %}
</div>
</section>
<section id="usage">
<div class="container-fluid">
{% include usage.html %}
</div>
</section>
<section id="events">
<div class="container-fluid">
{% include events.html %}
</div>
</section>
<section id="sorting">
<div class="container-fluid">
{% include sorting.html %}
</div>
</section>
<section id="advanced-filters">
<div class="container-fluid">
{% include advanced-filters.html %}
</div>
</section>
<section id="extra-features">
<div class="container-fluid">
<h2>Extra Features</h2>
<p>Shuffle likely will not grow much farther than the current feature set. If you need something with drag and drop, filling in gaps, more layout modes, etc., I suggest looking into <a target="_blank" href="http://packery.metafizzy.co/">packery</a> or <a target="_blank" href="http://isotope.metafizzy.co/">isotope</a>.</p>
</div>
</section>
<section id="dependencies">
<div class="container-fluid">
<h2>Dependencies</h2>
<ul>
<li><a target="_blank" href="http://jquery.com">jQuery 1.9+</a></li>
<li><a target="_blank" href="http://modernizr.com">Modernizr</a>
<ul>
<li>A custom Modernizr build has been included with the plugin.</li>
<li>If you already have Modernizr on your site, you may delete it.</li>
<li>If you don't know what Modernizr is, leave it!</li>
</ul>
</li>
</ul>
</div>
</section>
<section id="browsers">
<div class="container-fluid">
<h2>Supported Browsers</h2>
<ul>
<li>Chrome</li>
<li>Firefox</li>
<li>IE 7+</li>
<li>Opera</li>
<li>Safari</li>
</ul>
<p>
Browsers that don't support CSS transitions and transforms <strong>*cough*</strong> IE &lt;= 9 <strong>*cough*</strong> will see a less cool, javascript based version of the effect.
</p>
</div>
</section>
<section id="links">
<div class="container-fluid">
<h2>Links</h2>
<ul>
<li><a href="https://github.com/Vestride/Shuffle">GitHub Repo</a></li>
<li><a href="http://isotope.metafizzy.co/">Inspired by Isotope</a></li>
<li><a href="http://glencheney.com">Me</a></li>
</ul>
</div>
</section>
<section id="changelog">
<div class="container-fluid">
{% include changelog.html %}
</div>
</section>
{% include credit-jake.html %}

File diff suppressed because it is too large Load Diff

@ -2,27 +2,87 @@
// If you're already using Modernizr, delete it from this file. If you don't know what Modernizr is, leave it :)
/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
* Build: http://modernizr.com/download/#-csstransforms-csstransforms3d-csstransitions-prefixed-teststyles-testprop-testallprops-prefixes-domprefixes
* Build: http://modernizr.com/download/#-csstransforms-csstransforms3d-csstransitions-cssclasses-prefixed-teststyles-testprop-testallprops-prefixes-domprefixes
*/
;window.Modernizr=function(a,b,c){function y(a){i.cssText=a}function z(a,b){return y(l.join(a+";")+(b||""))}function A(a,b){return typeof a===b}function B(a,b){return!!~(""+a).indexOf(b)}function C(a,b){for(var d in a){var e=a[d];if(!B(e,"-")&&i[e]!==c)return b=="pfx"?e:!0}return!1}function D(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:A(f,"function")?f.bind(d||b):f}return!1}function E(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+n.join(d+" ")+d).split(" ");return A(b,"string")||A(b,"undefined")?C(e,b):(e=(a+" "+o.join(d+" ")+d).split(" "),D(e,b,c))}var d="2.6.2",e={},f=b.documentElement,g="modernizr",h=b.createElement(g),i=h.style,j,k={}.toString,l=" -webkit- -moz- -o- -ms- ".split(" "),m="Webkit Moz O ms",n=m.split(" "),o=m.toLowerCase().split(" "),p={},q={},r={},s=[],t=s.slice,u,v=function(a,c,d,e){var h,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:g+(d+1),l.appendChild(j);return h=["&#173;",'<style id="s',g,'">',a,"</style>"].join(""),l.id=g,(m?l:n).innerHTML+=h,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=f.style.overflow,f.style.overflow="hidden",f.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),f.style.overflow=k),!!i},w={}.hasOwnProperty,x;!A(w,"undefined")&&!A(w.call,"undefined")?x=function(a,b){return w.call(a,b)}:x=function(a,b){return b in a&&A(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=t.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(t.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(t.call(arguments)))};return e}),p.csstransforms=function(){return!!E("transform")},p.csstransforms3d=function(){var a=!!E("perspective");return a&&"webkitPerspective"in f.style&&v("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},p.csstransitions=function(){return E("transition")};for(var F in p)x(p,F)&&(u=F.toLowerCase(),e[u]=p[F](),s.push((e[u]?"":"no-")+u));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)x(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof enableClasses!="undefined"&&enableClasses&&(f.className+=" "+(b?"":"no-")+a),e[a]=b}return e},y(""),h=j=null,e._version=d,e._prefixes=l,e._domPrefixes=o,e._cssomPrefixes=n,e.testProp=function(a){return C([a])},e.testAllProps=E,e.testStyles=v,e.prefixed=function(a,b,c){return b?E(a,b,c):E(a,"pfx")},e}(this,this.document);
;window.Modernizr=function(a,b,c){function z(a){j.cssText=a}function A(a,b){return z(m.join(a+";")+(b||""))}function B(a,b){return typeof a===b}function C(a,b){return!!~(""+a).indexOf(b)}function D(a,b){for(var d in a){var e=a[d];if(!C(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function E(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:B(f,"function")?f.bind(d||b):f}return!1}function F(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+o.join(d+" ")+d).split(" ");return B(b,"string")||B(b,"undefined")?D(e,b):(e=(a+" "+p.join(d+" ")+d).split(" "),E(e,b,c))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n="Webkit Moz O ms",o=n.split(" "),p=n.toLowerCase().split(" "),q={},r={},s={},t=[],u=t.slice,v,w=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},x={}.hasOwnProperty,y;!B(x,"undefined")&&!B(x.call,"undefined")?y=function(a,b){return x.call(a,b)}:y=function(a,b){return b in a&&B(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=u.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(u.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(u.call(arguments)))};return e}),q.csstransforms=function(){return!!F("transform")},q.csstransforms3d=function(){var a=!!F("perspective");return a&&"webkitPerspective"in g.style&&w("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},q.csstransitions=function(){return F("transition")};for(var G in q)y(q,G)&&(v=G.toLowerCase(),e[v]=q[G](),t.push((e[v]?"":"no-")+v));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)y(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},z(""),i=k=null,e._version=d,e._prefixes=m,e._domPrefixes=p,e._cssomPrefixes=o,e.testProp=function(a){return D([a])},e.testAllProps=F,e.testStyles=w,e.prefixed=function(a,b,c){return b?F(a,b,c):F(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+t.join(" "):""),e}(this,this.document);
/**
* jQuery Shuffle Plugin (https://github.com/Vestride/Shuffle)
* Uses CSS Transforms to filter down a grid of items (degrades to jQuery's animate).
// Shuffle Doesn't require this shuffle/debounce plugin, but it works better with it.
/*
* jQuery throttle / debounce - v1.1 - 3/7/2010
* http://benalman.com/projects/jquery-throttle-debounce-plugin/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this);
/*!
* jQuery Shuffle Plugin
* Uses CSS Transforms to filter down a grid of items.
* Dependencies: jQuery 1.9+, Modernizr 2.6.2. Optionally throttle/debounce by Ben Alman
* Inspired by Isotope http://isotope.metafizzy.co/
* Use it for whatever you want!
* Licensed under the MIT license.
* @author Glen Cheney (http://glencheney.com)
* @version 1.5.2
* @date 10/24/12
* @version 2.0
* @date 07/05/13
*/
;(function(d,g){d.fn.sorted=function(b){var c=d.extend({},d.fn.sorted.defaults,b),b=this.get();c.by!==d.noop&&(null!==c.by&&void 0!==c.by)&&b.sort(function(a,b){var f=c.by(d(a)),h=c.by(d(b));return f<h?-1:f>h?1:0});c.reverse&&b.reverse();return b};d.fn.sorted.defaults={reverse:!1,by:null};var i=function(b,c){var a=this;d.extend(a,d.fn.shuffle.options,c,d.fn.shuffle.settings);a.$container=b;a.$items=a.$container.children();a.$item=a.$items.first();a.marginTop=parseInt(a.$item.css("marginTop"),10);a.marginRight=
parseInt(a.$item.css("marginRight"),10);a.transitionName=a.prefixed("transition");a.transform=a.getPrefixed("transform");a.transitionEndName={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",msTransition:"MSTransitionEnd",transition:"transitionend"}[a.transitionName];a.itemCss={position:"absolute",top:0,left:0,opacity:1};a.$container.css("position","relative").get(0).style[a.transitionName]="height "+a.speed+"ms "+a.easing;a.$items.each(function(){d(this).css(a.itemCss);
a.supported&&(this.style[a.transitionName]=a.transform+" "+a.speed+"ms "+a.easing+", opacity "+a.speed+"ms "+a.easing);this.style.marginTop=0;this.style.marginRight=0});a.itemWidth=a.$item.outerWidth();a.itemHeight=a.$item.outerHeight();a.itemsPerRow=a.getItemsPerRow();a.windowHeight=d(window).height();a.windowWidth=d(window).width();d(window).on("resize.shuffle",function(){var b=d(window).height(),c=d(window).width();if(c!==a.windowWidth||b!==a.windowHeight)a.resized(),a.windowHeight=b,a.windowWidth=
c});if(0===a.itemWidth||0===a.itemHeight)d(window).on("load.shuffle",function(){a.itemWidth=a.$item.outerWidth();a.itemHeight=a.$item.outerHeight();a.itemsPerRow=a.getItemsPerRow();a.shuffle(a.group)});else a.shuffle(a.group)};i.prototype={constructor:i,shuffle:function(b){var c=this;b||(b="all");c.$items.removeClass("concealed filtered");d.isFunction(b)?c.$items.each(function(){var a=d(this);a.addClass(b(a,c)?"filtered":"concealed")}):(c.group=b,"all"!==b?c.$items.each(function(){var a=d(this).data("groups");
-1===d.inArray(b,a)?d(this).addClass("concealed"):d(this).addClass("filtered")}):c.$items.addClass("filtered"));c.visibleItems=c.$items.filter(".filtered").length;c.fire("shrink");c.shrink();c.fire("filter");c.filter();c.resizeContainer()},getItemsPerRow:function(){var b=this.$container.width(),c=Math.floor(b/this.itemWidth);c*(this.itemWidth+this.marginRight)-this.marginRight>b&&(c-=1);return c},resizeContainer:function(){var b=Math.ceil(this.visibleItems/this.itemsPerRow)*(this.itemHeight+this.marginTop)-
this.marginTop;this.$container.css("height",b+"px")},fire:function(b){this.$container.trigger(b+".shuffle",[this])},shrink:function(){var b=this,c=b.$items.filter(".concealed");0!==c.length&&(b.shrinkTransitionEnded=!1,c.each(function(){var a=d(this),c=parseInt(a.attr("data-x"),10),f=parseInt(a.attr("data-y"),10);c||(c=0);f||(f=0);b.transition({from:"shrink",$this:a,x:c,y:f,left:c+b.itemWidth/2+"px",top:f+b.itemHeight/2+"px",scale:0.001,opacity:0,height:"0px",width:"0px",callback:b.shrinkEnd})}))},
layout:function(b,c){var a=this,e=0;0!==b.length&&(a.layoutTransitionEnded=!1,d.each(b,function(f){var h=d(b[f]),g=f%a.itemsPerRow*(a.itemWidth+a.marginRight),i=Math.floor(f/a.itemsPerRow);0===f%a.itemsPerRow&&(e=i*(a.itemHeight+a.marginTop));h.attr({"data-x":g,"data-y":e});a.transition({from:"layout",$this:h,x:g,y:e,left:g+"px",top:e+"px",scale:1,opacity:1,height:a.itemHeight+"px",width:a.itemWidth+"px",callback:c})}))},filter:function(){if(this.keepSorted&&this.lastSort)this.sort(this.lastSort,
!0);else{var b=this.$items.filter(".filtered").get();this.layout(b,this.filterEnd)}},sort:function(b,c){var a=this,d=a.$items.filter(".filtered").sorted(b);a.layout(d,function(){c&&a.filterEnd();a.sortEnd()});a.lastSort=b},setPrefixedCss:function(b,c,a){b.css(this.prefixed(c),a)},getPrefixed:function(b){return(b=this.prefixed(b))?b.replace(/([A-Z])/g,function(b,a){return"-"+a.toLowerCase()}).replace(/^ms-/,"-ms-"):b},transition:function(b){var c=this,a,d=function(){!c.layoutTransitionEnded&&"layout"===
b.from?(b.callback.call(c),c.layoutTransitionEnded=!0):!c.shrinkTransitionEnded&&"shrink"===b.from&&(b.callback.call(c),c.shrinkTransitionEnded=!0)};c.supported?(a=c.threeD?"translate3d("+b.x+"px, "+b.y+"px, 0) scale3d("+b.scale+", "+b.scale+", 1)":"translate("+b.x+"px, "+b.y+"px) scale("+b.scale+", "+b.scale+")",b.$this.css("opacity",b.opacity),c.setPrefixedCss(b.$this,"transform",a),b.$this.one(c.transitionEndName,d)):b.$this.stop().animate({left:b.left,top:b.top,opacity:b.opacity,height:b.height,
width:b.width},c.speed,"swing",d)},resized:function(){this.itemWidth=this.$items.filter(".filtered").outerWidth();this.itemHeight=this.$items.filter(".filtered").outerHeight();this.itemsPerRow=this.getItemsPerRow();this.filter();this.resizeContainer()},shrinkEnd:function(){this.fire("shrunk")},filterEnd:function(){this.fire("filtered")},sortEnd:function(){this.fire("sorted")},destroy:function(){this.$container.removeAttr("style").removeData("shuffle");d(window).off(".shuffle");this.$items.removeAttr("style data-y data-x").removeClass("concealed filtered")}};
d.fn.shuffle=function(b,c){return this.each(function(){var a=d(this),e=a.data("shuffle");e||(e=new i(a,b),a.data("shuffle",e));d.isFunction(b)?e.shuffle(b):"string"===typeof b&&("sort"===b?e.sort(c):"destroy"===b?e.destroy():e.shuffle(b))})};d.fn.shuffle.options={group:"all",speed:800,easing:"ease-out",keepSorted:!0};d.fn.shuffle.settings={supported:g.csstransforms&&g.csstransitions,prefixed:g.prefixed,threeD:g.csstransforms3d}})(jQuery,Modernizr);
!function(t,e,i){"use strict"
t.fn.sorted=function(e){var n=t.extend({},t.fn.sorted.defaults,e),s=this.get(),r=!1
return s.length?n.randomize?t.fn.sorted.randomize(s):(n.by!==t.noop&&null!==n.by&&n.by!==i&&s.sort(function(e,s){if(r)return 0
var o=n.by(t(e)),a=n.by(t(s))
return o===i&&a===i?(r=!0,0):"sortFirst"===o||"sortLast"===a?-1:"sortLast"===o||"sortFirst"===a?1:a>o?-1:o>a?1:0}),r?this.get():(n.reverse&&s.reverse(),s)):[]},t.fn.sorted.defaults={reverse:!1,by:null,randomize:!1},t.fn.sorted.randomize=function(t){var e,i,n=t.length
if(!n)return t
for(;--n;)i=Math.floor(Math.random()*(n+1)),e=t[i],t[i]=t[n],t[n]=e
return t}
var n=0,s=function(e,i){var r=this
t.extend(r,s.options,i,s.settings),r.$container=e,r.$window=t(window),r.unique="shuffle_"+n++,r._fire("loading"),r._init(),r._fire("done")}
s.prototype={_init:function(){var e,i=this,n=t.proxy(i._onResize,i),s=i.throttle?i.throttle(i.throttleTime,n):n,r=i.initialSort?i.initialSort:null
i._setVars(),i._resetCols(),i._addClasses(),i._initItems(),i.$window.on("resize.shuffle."+i.unique,s),e=i.$container.css(["paddingLeft","paddingRight","position","width"]),"static"===e.position&&i.$container.css("position","relative"),i.offset={left:parseInt(e.paddingLeft,10)||0,top:parseInt(e.paddingTop,10)||0},i._setColumns(parseInt(e.width,10)),i.shuffle(i.group,r),i.supported&&setTimeout(function(){i._setTransitions(),i.$container[0].style[i.transitionName]="height "+i.speed+"ms "+i.easing},0)},_addClasses:function(){var t=this
return t.$container.addClass("shuffle"),t.$items.addClass("shuffle-item filtered"),t},_setVars:function(){var e=this
return e.$items=e._getItems(),e.transitionName=e.prefixed("transition"),e.transitionDelayName=e.prefixed("transitionDelay"),e.transitionDuration=e.prefixed("transitionDuration"),e.transform=e.getPrefixed("transform"),e.transitionend={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",msTransition:"MSTransitionEnd",transition:"transitionend"}[e.transitionName],e.isFluid=e.columnWidth&&"function"==typeof e.columnWidth,0===e.columnWidth&&null!==e.sizer&&(e.columnWidth=e.sizer),"string"==typeof e.columnWidth?e.$sizer=e.$container.find(e.columnWidth):e.columnWidth&&e.columnWidth.nodeType&&1===e.columnWidth.nodeType?e.$sizer=t(e.columnWidth):e.columnWidth&&e.columnWidth.jquery&&(e.$sizer=e.columnWidth),e.$sizer&&e.$sizer.length&&(e.useSizer=!0,e.sizer=e.$sizer[0]),e},_filter:function(e,n){var s=this,r=n!==i,o=r?n:s.$items,a=t()
return e=e||s.lastFilter,s._fire("filter"),t.isFunction(e)?o.each(function(){var i=t(this),n=e.call(i[0],i,s)
n&&(a=a.add(i))}):(s.group=e,"all"!==e?o.each(function(){var i=t(this),n=i.data("groups"),r=s.delimeter&&!t.isArray(n)?n.split(s.delimeter):n,o=t.inArray(e,r)>-1
o&&(a=a.add(i))}):a=o),s._toggleFilterClasses(o,a),o=null,n=null,a},_toggleFilterClasses:function(e,i){var n="concealed",s="filtered"
e.filter(i).each(function(){var e=t(this)
e.hasClass(n)&&e.removeClass(n),e.hasClass(s)||e.addClass(s)}),e.not(i).each(function(){var e=t(this)
e.hasClass(n)||e.addClass(n),e.hasClass(s)&&e.removeClass(s)})},_initItems:function(t){return t=t||this.$items,t.css(this.itemCss)},_updateItemCount:function(){return this.visibleItems=this.$items.filter(".filtered").length,this},_setTransition:function(t){var e=this
return t.style[e.transitionName]=e.transform+" "+e.speed+"ms "+e.easing+", opacity "+e.speed+"ms "+e.easing,t},_setTransitions:function(t){var e=this
return t=t||e.$items,t.each(function(){e._setTransition(this)}),e},_setSequentialDelay:function(e){var i=this
i.supported&&t.each(e,function(e){this.style[i.transitionDelayName]="0ms,"+(e+1)*i.sequentialFadeDelay+"ms",t(this).one(i.transitionend,function(){this.style[i.transitionDelayName]="0ms"})})},_getItems:function(){return this.$container.children(this.itemSelector)},_getPreciseDimension:function(e,i){var n
return n=window.getComputedStyle?window.getComputedStyle(e,null)[i]:t(e).css(i),parseFloat(n)},_setColumns:function(t){var e,i=this,n=t||i.$container.width(),s="function"==typeof i.gutterWidth?i.gutterWidth(n):i.useSizer?i._getPreciseDimension(i.sizer,"marginLeft"):i.gutterWidth
i.colWidth=i.isFluid?i.columnWidth(n):i.useSizer?i._getPreciseDimension(i.sizer,"width"):i.columnWidth||i.$items.outerWidth(!0)||n,i.colWidth=i.colWidth||n,i.colWidth+=s,e=(n+s)/i.colWidth,Math.ceil(e)-e<.01&&(e=Math.ceil(e)),i.cols=Math.floor(e),i.cols=Math.max(i.cols,1),i.containerWidth=n},_setContainerSize:function(){var t=this,e=Math.max.apply(Math,t.colYs)
t.$container.css("height",e+"px")},_fire:function(t,e){this.$container.trigger(t+".shuffle",e&&e.length?e:[this])},_layout:function(e,i,n,s){var r=this
i=i||r.filterEnd,r.layoutTransitionEnded=!1,t.each(e,function(o){var a=t(e[o]),l=Math.ceil(a.outerWidth(!0)/r.colWidth)
if(l=Math.min(l,r.cols),1===l)r._placeItem(a,r.colYs,i,n,s)
else{var u,d,c=r.cols+1-l,f=[]
for(d=0;c>d;d++)u=r.colYs.slice(d,d+l),f[d]=Math.max.apply(Math,u)
r._placeItem(a,f,i,n,s)}}),r._processStyleQueue(),r._setContainerSize()},_resetCols:function(){var t=this.cols
for(this.colYs=[];t--;)this.colYs.push(0)},_reLayout:function(t,e){var i=this
t=t||i.filterEnd,i._resetCols(),i.keepSorted&&i.lastSort?i.sort(i.lastSort,!0,e):i._layout(i.$items.filter(".filtered").get(),i.filterEnd,e)},_placeItem:function(t,e,i,n,s){for(var r=this,o=Math.min.apply(Math,e),a=0,l=0,u=e.length;u>l;l++)if(e[l]>=o-r.buffer&&e[l]<=o+r.buffer){a=l
break}var d=r.colWidth*a,c=o
d=Math.round(d+r.offset.left),c=Math.round(c+r.offset.top),t.data({x:d,y:c})
var f=o+t.outerHeight(!0),h=r.cols+1-u
for(l=0;h>l;l++)r.colYs[a+l]=f
var p={from:"layout",$this:t,x:d,y:c,scale:1}
n?p.skipTransition=!0:(p.opacity=1,p.callback=i),s&&(p.opacity=0),r.styleQueue.push(p)},_shrink:function(e,i){var n=this,s=e||n.$items.filter(".concealed"),r={},o=i||n.shrinkEnd
s.length&&(n._fire("shrink"),n.shrinkTransitionEnded=!1,s.each(function(){var e=t(this),i=e.data()
r={from:"shrink",$this:e,x:i.x,y:i.y,scale:.001,opacity:0,callback:o},n.styleQueue.push(r)}))},_onResize:function(){var t,e=this
e.enabled&&!e.destroyed&&(t=e.$container.width(),t!==e.containerWidth&&e.resized())},setPrefixedCss:function(t,e,i){t.css(this.prefixed(e),i)},getPrefixed:function(t){var e=this.prefixed(t)
return e?e.replace(/([A-Z])/g,function(t,e){return"-"+e.toLowerCase()}).replace(/^ms-/,"-ms-"):e},transition:function(e){var n,s=this,r=function(){s.layoutTransitionEnded||"layout"!==e.from?s.shrinkTransitionEnded||"shrink"!==e.from||(e.callback.call(s),s.shrinkTransitionEnded=!0):(s._fire("layout"),e.callback.call(s),s.layoutTransitionEnded=!0)}
if(e.callback=e.callback||t.noop,s.supported)e.scale===i&&(e.scale=1),n=s.threeD?"translate3d("+e.x+"px, "+e.y+"px, 0) scale3d("+e.scale+", "+e.scale+", 1)":"translate("+e.x+"px, "+e.y+"px) scale("+e.scale+", "+e.scale+")",e.x!==i&&s.setPrefixedCss(e.$this,"transform",n),e.opacity!==i&&e.$this.css("opacity",e.opacity),e.$this.one(s.transitionend,r)
else{var o={left:e.x,top:e.y,opacity:e.opacity}
e.$this.stop(!0).animate(o,s.speed,"swing",r)}},_processStyleQueue:function(){var e=this,i=e.styleQueue
t.each(i,function(t,i){i.skipTransition?e._skipTransition(i.$this[0],function(){e.transition(i)}):e.transition(i)}),e.styleQueue.length=0},shrinkEnd:function(){this._fire("shrunk")},filterEnd:function(){this._fire("filtered")},sortEnd:function(){this._fire("sorted")},_skipTransition:function(e,i,n){var s,r=this,o=r.transitionDuration,a=e.style[o]
e.style[o]="0ms",t.isFunction(i)?i():e.style[i]=n,s=e.offsetWidth,e.style[o]=a},_addItems:function(t,e,n){var s,r,o=this
o.supported||(e=!1),t.addClass("shuffle-item"),o._initItems(t),o._setTransitions(t),o.$items=o._getItems(),t.css("opacity",0),s=o._filter(i,t),r=s.get(),o._updateItemCount(),e?(o._layout(r,null,!0,!0),n&&o._setSequentialDelay(s),o._revealAppended(s)):o._layout(r)},_revealAppended:function(e){var i=this
setTimeout(function(){e.each(function(e,n){i.transition({from:"reveal",$this:t(n),opacity:1})})},i.revealAppendedDelay)},shuffle:function(t,e){var i=this
i.enabled&&(t||(t="all"),i._filter(t),i.lastFilter=t,i._updateItemCount(),i._resetCols(),i._shrink(),e&&(i.lastSort=e),i._reLayout())},sort:function(t,e,i){var n=this,s=n.$items.filter(".filtered").sorted(t)
e||n._resetCols(),n._layout(s,function(){e&&n.filterEnd(),n.sortEnd()},i),n.lastSort=t},resized:function(t){this.enabled&&(t||this._setColumns(),this._reLayout())},layout:function(){this.update(!0)},update:function(t){this.resized(t)},appended:function(t,e,i){e=e===!1?!1:!0,i=i===!1?!1:!0,this._addItems(t,e,i)},disable:function(){this.enabled=!1},enable:function(t){this.enabled=!0,t!==!1&&this.update()},remove:function(t){if(t.length&&t.jquery){var e=this
return e._shrink(t,function(){var e=this
t.remove(),setTimeout(function(){e.$items=e._getItems(),e.layout(),e._updateItemCount(),e._fire("removed",[t,e]),t=null},0)}),e._processStyleQueue(),e}},destroy:function(){var t=this
t.$window.off("."+t.unique),t.$container.removeClass("shuffle").removeAttr("style").removeData("shuffle"),t.$items.removeAttr("style").removeClass("concealed filtered shuffle-item"),t.destroyed=!0}},s.options={group:"all",speed:250,easing:"ease-out",itemSelector:"",sizer:null,gutterWidth:0,columnWidth:0,delimeter:null,buffer:0,initialSort:null,throttle:t.throttle||null,throttleTime:300,sequentialFadeDelay:150,supported:e.csstransforms&&e.csstransitions},s.settings={$sizer:null,useSizer:!1,itemCss:{position:"absolute",top:0,left:0},offset:{top:0,left:0},revealAppendedDelay:300,keepSorted:!0,enabled:!0,destroyed:!1,styleQueue:[],prefixed:e.prefixed,threeD:e.csstransforms3d},t.fn.shuffle=function(e){var i=Array.prototype.slice.call(arguments,1)
return this.each(function(){var n=t(this),r=n.data("shuffle")
r||(r=new s(n,e),n.data("shuffle",r)),"string"==typeof e&&r[e]&&r[e].apply(r,i)})}}(jQuery,Modernizr)

@ -0,0 +1,150 @@
window.Manipulator = (function($) {
'use strict';
var hasConsole = window.console && typeof window.console.log === 'function';
var Manipulator = function( element ) {
var self = this;
self.$el = $( element );
self.init();
};
Manipulator.prototype.init = function() {
var self = this;
self.initShuffle();
self.setupEvents();
};
// Column width and gutter width options can be functions
Manipulator.prototype.initShuffle = function() {
this.$el.shuffle({
itemSelector: '.box',
speed: 250,
easing: 'ease',
columnWidth: function( containerWidth ) {
// .box's have a width of 18%
return 0.18 * containerWidth;
},
gutterWidth: function( containerWidth ) {
// .box's have a margin-left of 2.5%
return 0.025 * containerWidth;
}
});
// Shuffle is stored in the elements data with jQuery.
// You can access the class instance here
this.shuffle = this.$el.data('shuffle');
};
Manipulator.prototype.setupEvents = function() {
var self = this;
$('#add').on('click', $.proxy( self.onAddClick, self ));
$('#randomize').on('click', $.proxy( self.onRandomize, self ));
$('#remove').on('click', $.proxy( self.onRemoveClick, self ));
// Show off some shuffle events
self.$el.on('removed.shuffle', function( evt, $collection, shuffle ) {
// Make sure logs work
if ( !hasConsole ) {
return;
}
console.log( this, evt, $collection, shuffle );
});
};
Manipulator.prototype.onAddClick = function() {
// Creating random elements. You could use an
// ajax request or clone elements instead
var self = this,
itemsToCreate = 5,
frag = document.createDocumentFragment(),
grid = self.$el[0],
items = [],
$items,
classes = ['w2', 'h2', 'w3'],
box, i, random, randomClass;
for (i = 0; i < itemsToCreate; i++) {
random = Math.random();
box = document.createElement('div');
box.className = 'box';
// Randomly add a class
if ( random > 0.8 ) {
randomClass = Math.floor( Math.random() * 3 );
box.className = box.className + ' ' + classes[ randomClass ];
}
items.push( box );
frag.appendChild( box );
}
grid.appendChild( frag );
$items = $(items);
// Tell shuffle items have been appended.
// It expects a jQuery object as the parameter.
self.shuffle.appended( $items );
// or
// self.$el.shuffle('appended', $items );
};
Manipulator.prototype.getRandomInt = function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
// Randomly choose some elements to remove
Manipulator.prototype.onRemoveClick = function() {
var self = this,
total = self.shuffle.visibleItems,
numberToRemove = Math.min( 3, total ),
indexesToRemove = [],
i = 0,
$collection = $();
// None left
if ( !total ) {
return;
}
// This has the possibility to choose the same index for more than
// one in the array, meaning sometimes less than 3 will be removed
for ( ; i < numberToRemove; i++ ) {
indexesToRemove.push( self.getRandomInt( 0, total - 1 ) );
}
// Make a jQuery collection out of the index selections
$.each(indexesToRemove, function(i, index) {
$collection = $collection.add( self.shuffle.$items.eq( index ) );
});
// Tell shuffle to remove them
self.shuffle.remove( $collection );
// or
// self.$el.shuffle('remove', $collection);
};
Manipulator.prototype.onRandomize = function() {
var self = this,
sortObj = {
randomize: true
};
self.shuffle.sort( sortObj );
// or
// self.$el.shuffle('sort', sortObj);
};
return Manipulator;
}(jQuery));
$(document).ready(function() {
new window.Manipulator( document.getElementById('my-shuffle') );
});

@ -0,0 +1,172 @@
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();
});

@ -0,0 +1,141 @@
var DEMO = (function( $ ) {
'use strict';
var $grid = $('#grid'),
$filterOptions = $('.filter-options'),
$sizer = $grid.find('.shuffle__sizer'),
init = function() {
// None of these need to be executed synchronously
setTimeout(function() {
listen();
setupFilters();
setupSorting();
setupSearching();
}, 100);
// instantiate the plugin
$grid.shuffle({
itemSelector: '.picture-item',
sizer: $sizer
});
// Destroy it! o_O
// $grid.shuffle('destroy');
// You can subscribe to custom events:
// shrink, shrunk, filter, filtered, sorted, load, done
// $grid.on('shrink.shuffle shrunk.shuffle filter.shuffle filtered.shuffle sorted.shuffle layout.shuffle', function(evt, shuffle) {
// if ( window.console ) {
// console.log(evt.type, shuffle, this);
// }
// });
},
// Set up button clicks
setupFilters = function() {
var $btns = $filterOptions.children();
$btns.on('click', function() {
var $this = $(this),
isActive = $this.hasClass( 'active' ),
group = isActive ? 'all' : $this.data('group');
// Hide current label, show current label in title
if ( !isActive ) {
$('.filter-options .active').removeClass('active');
}
$this.toggleClass('active');
// Filter elements
$grid.shuffle( 'shuffle', group );
});
$btns = null;
},
setupSorting = function() {
// Sorting options
$('.sort-options').on('change', function() {
var sort = this.value,
opts = {};
// We're given the element wrapped in jQuery
if ( sort === 'date-created' ) {
opts = {
reverse: true,
by: function($el) {
return $el.data('date-created');
}
};
} else if ( sort === 'title' ) {
opts = {
by: function($el) {
return $el.data('title').toLowerCase();
}
};
}
// Filter elements
$grid.shuffle('sort', opts);
});
},
setupSearching = function() {
// Advanced filtering
$('.js-shuffle-search').on('keyup change', function() {
var val = this.value.toLowerCase();
$grid.shuffle('shuffle', function($el, shuffle) {
// Only search elements in the current group
if (shuffle.group !== 'all' && $.inArray(shuffle.group, $el.data('groups')) === -1) {
return false;
}
var text = $.trim( $el.find('.picture-item__title').text() ).toLowerCase();
return text.indexOf(val) !== -1;
});
});
},
// Re layout shuffle when images load. This is only needed
// below 768 pixels because the .picture-item height is auto and therefore
// the height of the picture-item is dependent on the image
// I recommend using imagesloaded to determine when an image is loaded
// but that doesn't support IE7
listen = function() {
var debouncedLayout = $.throttle( 300, function() {
$grid.shuffle('update');
});
// Get all images inside shuffle
$grid.find('img').each(function() {
var proxyImage;
// Image already loaded
if ( this.complete && this.naturalWidth !== undefined ) {
return;
}
// If none of the checks above matched, simulate loading on detached element.
proxyImage = new Image();
$( proxyImage ).on('load', function() {
$(this).off('load');
debouncedLayout();
});
proxyImage.src = this.src;
});
};
return {
init: init
};
}( jQuery ));
$(document).ready(function() {
DEMO.init();
});

@ -0,0 +1,22 @@
var ImageDemo = (function( $ ) {
var $shuffle = $('.shuffle--images'),
sizer = document.getElementById('js-sizer'),
init = function() {
$shuffle.shuffle({
sizer: sizer,
itemSelector: '.js-item'
});
};
return {
init: init
};
}( jQuery ));
$(document).ready(function() {
ImageDemo.init();
});

@ -0,0 +1,54 @@
// For this demo, shuffle won't be initialized until
// all the images have finished loading.
// Another approach would be to initialize shuffle on document
// ready and as imagesLoaded reports back progress, call shuffle.layout()
// imagesLoade: https://github.com/desandro/imagesloaded
var ImageDemo = (function( $, imagesLoaded ) {
var $shuffle = $('.shuffle--images'),
$imgs = $shuffle.find('img'),
$loader = $('#loader'),
sizer = document.getElementById('js-sizer'),
imgLoad,
init = function() {
// Create a new imagesLoaded instance
imgLoad = new imagesLoaded( $imgs.get() );
// Listen for when all images are done
// will be executed even if some images fail
imgLoad.on( 'always', onAllImagesFinished );
},
onAllImagesFinished = function( instance ) {
if ( window.console && window.console.log ) {
console.log( instance );
}
// Hide loader
$loader.addClass('hidden');
// Adds visibility: visible;
$shuffle.addClass('images-loaded');
// Initialize shuffle
$shuffle.shuffle({
sizer: sizer,
itemSelector: '.js-item'
});
};
return {
init: init
};
}( jQuery, window.imagesLoaded ));
$(document).ready(function() {
ImageDemo.init();
});

8
js/html5shiv.js vendored

@ -0,0 +1,8 @@
/*
HTML5 Shiv v3.6.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}</style>";
c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video",version:"3.6.2",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment();
for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);

@ -0,0 +1,744 @@
/*!
* imagesLoaded PACKAGED v3.0.2
* JavaScript is all like "You images are done yet or what?"
*/
/*!
* EventEmitter v4.1.0 - git.io/ee
* Oliver Caldwell
* MIT license
* @preserve
*/
(function (exports) {
// Place the script in strict mode
'use strict';
/**
* Class for managing events.
* Can be extended to provide event functionality in other classes.
*
* @class Manages event registering and emitting.
*/
function EventEmitter() {}
// Shortcuts to improve speed and size
// Easy access to the prototype
var proto = EventEmitter.prototype,
nativeIndexOf = Array.prototype.indexOf ? true : false;
/**
* Finds the index of the listener for the event in it's storage array.
*
* @param {Function} listener Method to look for.
* @param {Function[]} listeners Array of listeners to search through.
* @return {Number} Index of the specified listener, -1 if not found
* @api private
*/
function indexOfListener(listener, listeners) {
// Return the index via the native method if possible
if (nativeIndexOf) {
return listeners.indexOf(listener);
}
// There is no native method
// Use a manual loop to find the index
var i = listeners.length;
while (i--) {
// If the listener matches, return it's index
if (listeners[i] === listener) {
return i;
}
}
// Default to returning -1
return -1;
}
/**
* Fetches the events object and creates one if required.
*
* @return {Object} The events storage object.
* @api private
*/
proto._getEvents = function () {
return this._events || (this._events = {});
};
/**
* Returns the listener array for the specified event.
* Will initialise the event object and listener arrays if required.
* Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
* Each property in the object response is an array of listener functions.
*
* @param {String|RegExp} evt Name of the event to return the listeners from.
* @return {Function[]|Object} All listener functions for the event.
*/
proto.getListeners = function (evt) {
// Create a shortcut to the storage object
// Initialise it if it does not exists yet
var events = this._getEvents(),
response,
key;
// Return a concatenated array of all matching events if
// the selector is a regular expression.
if (typeof evt === 'object') {
response = {};
for (key in events) {
if (events.hasOwnProperty(key) && evt.test(key)) {
response[key] = events[key];
}
}
}
else {
response = events[evt] || (events[evt] = []);
}
return response;
};
/**
* Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
*
* @param {String|RegExp} evt Name of the event to return the listeners from.
* @return {Object} All listener functions for an event in an object.
*/
proto.getListenersAsObject = function (evt) {
var listeners = this.getListeners(evt),
response;
if (listeners instanceof Array) {
response = {};
response[evt] = listeners;
}
return response || listeners;
};
/**
* Adds a listener function to the specified event.
* The listener will not be added if it is a duplicate.
* If the listener returns true then it will be removed after it is called.
* If you pass a regular expression as the event name then the listener will be added to all events that match it.
*
* @param {String|RegExp} evt Name of the event to attach the listener to.
* @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
* @return {Object} Current instance of EventEmitter for chaining.
*/
proto.addListener = function (evt, listener) {
var listeners = this.getListenersAsObject(evt),
key;
for (key in listeners) {
if (listeners.hasOwnProperty(key) &&
indexOfListener(listener, listeners[key]) === -1) {
listeners[key].push(listener);
}
}
// Return the instance of EventEmitter to allow chaining
return this;
};
/**
* Alias of addListener
*/
proto.on = proto.addListener;
/**
* Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
* You need to tell it what event names should be matched by a regex.
*
* @param {String} evt Name of the event to create.
* @return {Object} Current instance of EventEmitter for chaining.
*/
proto.defineEvent = function (evt) {
this.getListeners(evt);
return this;
};
/**
* Uses defineEvent to define multiple events.
*
* @param {String[]} evts An array of event names to define.
* @return {Object} Current instance of EventEmitter for chaining.
*/
proto.defineEvents = function (evts)
{
for (var i = 0; i < evts.length; i += 1) {
this.defineEvent(evts[i]);
}
return this;
};
/**
* Removes a listener function from the specified event.
* When passed a regular expression as the event name, it will remove the listener from all events that match it.
*
* @param {String|RegExp} evt Name of the event to remove the listener from.
* @param {Function} listener Method to remove from the event.
* @return {Object} Current instance of EventEmitter for chaining.
*/
proto.removeListener = function (evt, listener) {
var listeners = this.getListenersAsObject(evt),
index,
key;
for (key in listeners) {
if (listeners.hasOwnProperty(key)) {
index = indexOfListener(listener, listeners[key]);
if (index !== -1) {
listeners[key].splice(index, 1);
}
}
}
// Return the instance of EventEmitter to allow chaining
return this;
};
/**
* Alias of removeListener
*/
proto.off = proto.removeListener;
/**
* Adds listeners in bulk using the manipulateListeners method.
* If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
* You can also pass it a regular expression to add the array of listeners to all events that match it.
* Yeah, this function does quite a bit. That's probably a bad thing.
*
* @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
* @param {Function[]} [listeners] An optional array of listener functions to add.
* @return {Object} Current instance of EventEmitter for chaining.
*/
proto.addListeners = function (evt, listeners) {
// Pass through to manipulateListeners
return this.manipulateListeners(false, evt, listeners);
};
/**
* Removes listeners in bulk using the manipulateListeners method.
* If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
* You can also pass it an event name and an array of listeners to be removed.
* You can also pass it a regular expression to remove the listeners from all events that match it.
*
* @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
* @param {Function[]} [listeners] An optional array of listener functions to remove.
* @return {Object} Current instance of EventEmitter for chaining.
*/
proto.removeListeners = function (evt, listeners) {
// Pass through to manipulateListeners
return this.manipulateListeners(true, evt, listeners);
};
/**
* Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
* The first argument will determine if the listeners are removed (true) or added (false).
* If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
* You can also pass it an event name and an array of listeners to be added/removed.
* You can also pass it a regular expression to manipulate the listeners of all events that match it.
*
* @param {Boolean} remove True if you want to remove listeners, false if you want to add.
* @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
* @param {Function[]} [listeners] An optional array of listener functions to add/remove.
* @return {Object} Current instance of EventEmitter for chaining.
*/
proto.manipulateListeners = function (remove, evt, listeners) {
// Initialise any required variables
var i,
value,
single = remove ? this.removeListener : this.addListener,
multiple = remove ? this.removeListeners : this.addListeners;
// If evt is an object then pass each of it's properties to this method
if (typeof evt === 'object' && !(evt instanceof RegExp)) {
for (i in evt) {
if (evt.hasOwnProperty(i) && (value = evt[i])) {
// Pass the single listener straight through to the singular method
if (typeof value === 'function') {
single.call(this, i, value);
}
else {
// Otherwise pass back to the multiple function
multiple.call(this, i, value);
}
}
}
}
else {
// So evt must be a string
// And listeners must be an array of listeners
// Loop over it and pass each one to the multiple method
i = listeners.length;
while (i--) {
single.call(this, evt, listeners[i]);
}
}
// Return the instance of EventEmitter to allow chaining
return this;
};
/**
* Removes all listeners from a specified event.
* If you do not specify an event then all listeners will be removed.
* That means every event will be emptied.
* You can also pass a regex to remove all events that match it.
*
* @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
* @return {Object} Current instance of EventEmitter for chaining.
*/
proto.removeEvent = function (evt) {
var type = typeof evt,
events = this._getEvents(),
key;
// Remove different things depending on the state of evt
if (type === 'string') {
// Remove all listeners for the specified event
delete events[evt];
}
else if (type === 'object') {
// Remove all events matching the regex.
for (key in events) {
if (events.hasOwnProperty(key) && evt.test(key)) {
delete events[key];
}
}
}
else {
// Remove all listeners in all events
delete this._events;
}
// Return the instance of EventEmitter to allow chaining
return this;
};
/**
* Emits an event of your choice.
* When emitted, every listener attached to that event will be executed.
* If you pass the optional argument array then those arguments will be passed to every listener upon execution.
* Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
* So they will not arrive within the array on the other side, they will be separate.
* You can also pass a regular expression to emit to all events that match it.
*
* @param {String|RegExp} evt Name of the event to emit and execute listeners for.
* @param {Array} [args] Optional array of arguments to be passed to each listener.
* @return {Object} Current instance of EventEmitter for chaining.
*/
proto.emitEvent = function (evt, args) {
var listeners = this.getListenersAsObject(evt),
i,
key,
response;
for (key in listeners) {
if (listeners.hasOwnProperty(key)) {
i = listeners[key].length;
while (i--) {
// If the listener returns true then it shall be removed from the event
// The function is executed either with a basic call or an apply if there is an args array
response = args ? listeners[key][i].apply(null, args) : listeners[key][i]();
if (response === true) {
this.removeListener(evt, listeners[key][i]);
}
}
}
}
// Return the instance of EventEmitter to allow chaining
return this;
};
/**
* Alias of emitEvent
*/
proto.trigger = proto.emitEvent;
/**
* Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
* As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
*
* @param {String|RegExp} evt Name of the event to emit and execute listeners for.
* @param {...*} Optional additional arguments to be passed to each listener.
* @return {Object} Current instance of EventEmitter for chaining.
*/
proto.emit = function (evt) {
var args = Array.prototype.slice.call(arguments, 1);
return this.emitEvent(evt, args);
};
// Expose the class either via AMD or the global object
if (typeof define === 'function' && define.amd) {
define(function () {
return EventEmitter;
});
}
else {
exports.EventEmitter = EventEmitter;
}
}(this));
/*!
* eventie v1.0.3
* event binding helper
* eventie.bind( elem, 'click', myFn )
* eventie.unbind( elem, 'click', myFn )
*/
/*jshint browser: true, undef: true, unused: true */
/*global define: false */
( function( window ) {
'use strict';
var docElem = document.documentElement;
var bind = function() {};
if ( docElem.addEventListener ) {
bind = function( obj, type, fn ) {
obj.addEventListener( type, fn, false );
};
} else if ( docElem.attachEvent ) {
bind = function( obj, type, fn ) {
obj[ type + fn ] = fn.handleEvent ?
function() {
var event = window.event;
// add event.target
event.target = event.target || event.srcElement;
fn.handleEvent.call( fn, event );
} :
function() {
var event = window.event;
// add event.target
event.target = event.target || event.srcElement;
fn.call( obj, event );
};
obj.attachEvent( "on" + type, obj[ type + fn ] );
};
}
var unbind = function() {};
if ( docElem.removeEventListener ) {
unbind = function( obj, type, fn ) {
obj.removeEventListener( type, fn, false );
};
} else if ( docElem.detachEvent ) {
unbind = function( obj, type, fn ) {
obj.detachEvent( "on" + type, obj[ type + fn ] );
try {
delete obj[ type + fn ];
} catch ( err ) {
// can't delete window object properties
obj[ type + fn ] = undefined;
}
};
}
var eventie = {
bind: bind,
unbind: unbind
};
// transport
if ( typeof define === 'function' && define.amd ) {
// AMD
define( eventie );
} else {
// browser global
window.eventie = eventie;
}
})( this );
/*!
* imagesLoaded v3.0.2
* JavaScript is all like "You images are done yet or what?"
*/
( function( window ) {
'use strict';
var $ = window.jQuery;
var console = window.console;
var hasConsole = typeof console !== 'undefined';
// -------------------------- helpers -------------------------- //
// extend objects
function extend( a, b ) {
for ( var prop in b ) {
a[ prop ] = b[ prop ];
}
return a;
}
var objToString = Object.prototype.toString;
function isArray( obj ) {
return objToString.call( obj ) === '[object Array]';
}
// turn element or nodeList into an array
function makeArray( obj ) {
var ary = [];
if ( isArray( obj ) ) {
// use object if already an array
ary = obj;
} else if ( typeof obj.length === 'number' ) {
// convert nodeList to array
for ( var i=0, len = obj.length; i < len; i++ ) {
ary.push( obj[i] );
}
} else {
// array of single index
ary.push( obj );
}
return ary;
}
// -------------------------- -------------------------- //
function defineImagesLoaded( EventEmitter, eventie ) {
/**
* @param {Array, Element, NodeList, String} elem
* @param {Object or Function} options - if function, use as callback
* @param {Function} onAlways - callback function
*/
function ImagesLoaded( elem, options, onAlways ) {
// coerce ImagesLoaded() without new, to be new ImagesLoaded()
if ( !( this instanceof ImagesLoaded ) ) {
return new ImagesLoaded( elem, options );
}
// use elem as selector string
if ( typeof elem === 'string' ) {
elem = document.querySelectorAll( elem );
}
this.elements = makeArray( elem );
this.options = extend( {}, this.options );
if ( typeof options === 'function' ) {
onAlways = options;
} else {
extend( this.options, options );
}
if ( onAlways ) {
this.on( 'always', onAlways );
}
this.getImages();
if ( $ ) {
// add jQuery Deferred object
this.jqDeferred = new $.Deferred();
}
// HACK check async to allow time to bind listeners
var _this = this;
setTimeout( function() {
_this.check();
});
}
ImagesLoaded.prototype = new EventEmitter();
ImagesLoaded.prototype.options = {};
ImagesLoaded.prototype.getImages = function() {
this.images = [];
// filter & find items if we have an item selector
for ( var i=0, len = this.elements.length; i < len; i++ ) {
var elem = this.elements[i];
// filter siblings
if ( elem.nodeName === 'IMG' ) {
this.addImage( elem );
}
// find children
var childElems = elem.querySelectorAll('img');
// concat childElems to filterFound array
for ( var j=0, jLen = childElems.length; j < jLen; j++ ) {
var img = childElems[j];
this.addImage( img );
}
}
};
/**
* @param {Image} img
*/
ImagesLoaded.prototype.addImage = function( img ) {
var loadingImage = new LoadingImage( img );
this.images.push( loadingImage );
};
ImagesLoaded.prototype.check = function() {
var _this = this;
var checkedCount = 0;
var length = this.images.length;
this.hasAnyBroken = false;
// complete if no images
if ( !length ) {
this.complete();
return;
}
function onConfirm( image, message ) {
if ( _this.options.debug && hasConsole ) {
console.log( 'confirm', image, message );
}
_this.progress( image );
checkedCount++;
if ( checkedCount === length ) {
_this.complete();
}
return true; // bind once
}
for ( var i=0; i < length; i++ ) {
var loadingImage = this.images[i];
loadingImage.on( 'confirm', onConfirm );
loadingImage.check();
}
};
ImagesLoaded.prototype.progress = function( image ) {
this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
this.emit( 'progress', this, image );
if ( this.jqDeferred ) {
this.jqDeferred.notify( this, image );
}
};
ImagesLoaded.prototype.complete = function() {
var eventName = this.hasAnyBroken ? 'fail' : 'done';
this.isComplete = true;
this.emit( eventName, this );
this.emit( 'always', this );
if ( this.jqDeferred ) {
var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';
this.jqDeferred[ jqMethod ]( this );
}
};
// -------------------------- jquery -------------------------- //
if ( $ ) {
$.fn.imagesLoaded = function( options, callback ) {
var instance = new ImagesLoaded( this, options, callback );
return instance.jqDeferred.promise( $(this) );
};
}
// -------------------------- -------------------------- //
var cache = {};
function LoadingImage( img ) {
this.img = img;
}
LoadingImage.prototype = new EventEmitter();
LoadingImage.prototype.check = function() {
// first check cached any previous images that have same src
var cached = cache[ this.img.src ];
if ( cached ) {
this.useCached( cached );
return;
}
// add this to cache
cache[ this.img.src ] = this;
// If complete is true and browser supports natural sizes,
// try to check for image status manually.
if ( this.img.complete && this.img.naturalWidth !== undefined ) {
// report based on naturalWidth
this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
return;
}
// If none of the checks above matched, simulate loading on detached element.
var proxyImage = this.proxyImage = new Image();
eventie.bind( proxyImage, 'load', this );
eventie.bind( proxyImage, 'error', this );
proxyImage.src = this.img.src;
};
LoadingImage.prototype.useCached = function( cached ) {
if ( cached.isConfirmed ) {
this.confirm( cached.isLoaded, 'cached was confirmed' );
} else {
var _this = this;
cached.on( 'confirm', function( image ) {
_this.confirm( image.isLoaded, 'cache emitted confirmed' );
return true; // bind once
});
}
};
LoadingImage.prototype.confirm = function( isLoaded, message ) {
this.isConfirmed = true;
this.isLoaded = isLoaded;
this.emit( 'confirm', this, message );
};
// trigger specified handler for event type
LoadingImage.prototype.handleEvent = function( event ) {
var method = 'on' + event.type;
if ( this[ method ] ) {
this[ method ]( event );
}
};
LoadingImage.prototype.onload = function() {
this.confirm( true, 'onload' );
this.unbindProxyEvents();
};
LoadingImage.prototype.onerror = function() {
this.confirm( false, 'onerror' );
this.unbindProxyEvents();
};
LoadingImage.prototype.unbindProxyEvents = function() {
eventie.unbind( this.proxyImage, 'load', this );
eventie.unbind( this.proxyImage, 'error', this );
};
// ----- ----- //
return ImagesLoaded;
}
// -------------------------- transport -------------------------- //
if ( typeof define === 'function' && define.amd ) {
// AMD
define( [
'eventEmitter',
'eventie'
],
defineImagesLoaded );
} else {
// browser global
window.imagesLoaded = defineImagesLoaded(
window.EventEmitter,
window.eventie
);
}
})( window );

@ -0,0 +1,414 @@
/**
* @author Glen Cheney
* Debounce plugin is included in shuffle
*/
var Modules = {};
Modules.Support = (function( $ ) {
'use strict';
var self = {},
// some small (2x1 px) test images for each feature
webpImages = {
basic: 'data:image/webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA/v56QAAAAA==',
lossless: 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAQAAAAfQ//73v/+BiOh/AAA='
};
self.webp = function( feature ) {
var dfd = $.Deferred();
$('<img>')
.on('load', function() {
// the images should have these dimensions
if ( this.width === 2 && this.height === 1 ) {
dfd.resolve();
} else {
dfd.reject();
}
})
// Reject deferred on error
.on('error', function() {
dfd.reject();
})
// Set the image src
.attr('src', webpImages[ feature || 'basic' ]);
return dfd.promise();
};
// Fill rAF
var rAF = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
window.requestAnimationFrame = rAF;
return self;
}( jQuery ));
Modules.Polyfill = (function( $, Support ) {
'use strict';
var init = function() {
// If the deferred object in webp is rejected, call the webp polyfill function
Support.webp().fail( webp );
},
webp = function() {
$('img[src$=".webp"]').each(function() {
this.src = this.src.replace('.webp', '.jpg');
});
};
return {
init: init
};
}( jQuery, Modules.Support ));
Modules.Nav = (function( $ ) {
'use strict';
function NavTray( element ) {
this.$el = $( element );
this.init();
}
NavTray.prototype.init = function() {
this
.setVars()
.listen();
// Google web font loading affects this.
// I could use their loader, but don't really want their js too
// I've changed the fallback font to Verdana, sans-serif to better
// represent Ubuntu's wideness.
// Also this isn't needed on load and could be done on window load
setTimeout( $.proxy( this.saveHeight, this ), 100 );
};
NavTray.prototype.setVars = function() {
var self = this;
self.isOpen = false;
self.$window = $( window );
self.$trigger = self.$el.find('.js-nav-toggle');
self.$tray = self.$el.find('.js-tray');
self.$trigger.data( 'openLabel', self.$trigger.text() );
return self;
};
NavTray.prototype.saveHeight = function() {
var self = this,
height = self.$tray.children().first().outerHeight();
self.collapseHeight = height;
return height;
};
NavTray.prototype.listen = function() {
var self = this;
self.$trigger.on( 'click', $.proxy( self.toggle, self ) );
self.$window.on( 'resize', $.debounce( 250, $.proxy( self.onResize, self ) ) );
// This is a case for selectors level 4!
self.$el.find('.js-demos').on('mouseenter', '.js-demo', function( evt ) {
$( evt.currentTarget ).addClass('hovered');
});
self.$el.find('.js-demos').on('mouseleave', '.js-demo', function( evt ) {
$( evt.currentTarget ).removeClass('hovered');
});
return self;
};
NavTray.prototype.onResize = function() {
var self = this;
self.$tray.css( 'height', '' );
self.saveHeight();
if ( self.isOpen ) {
self.$tray.css( 'height', self.collapseHeight );
}
};
NavTray.prototype.toggle = function() {
var self = this;
self.toggleBtnText();
if ( self.isOpen ) {
self.close();
} else {
self.open();
}
return self;
};
NavTray.prototype.open = function() {
var self = this;
self.$el.removeClass('collapsed');
self.$tray.css( 'height', self.collapseHeight );
self.isOpen = true;
};
NavTray.prototype.close = function() {
var self = this;
self.$el.addClass('collapsed');
self.$tray.css( 'height', '' );
self.isOpen = false;
};
NavTray.prototype.toggleBtnText = function() {
var self = this,
key= self.isOpen ? 'openLabel' : 'closeLabel';
self.$trigger.text( self.$trigger.data( key ) );
return self;
};
return {
init: function() {
return new NavTray( document.getElementById('nav') );
}
};
}( jQuery ));
Modules.Favicon = (function( doc ) {
'use strict';
var Favicon = function( src, numFrames, framesPerAnimation, animationDelay ) {
var self = this;
// Variables based on params
self.src = src;
self.numFrames = numFrames;
self.framesPerAnimation = framesPerAnimation;
self.animationDelay = animationDelay;
// Elements
self.canvas = doc.createElement('canvas');
self.img = doc.createElement('img');
self.html = doc.documentElement;
// Calculations
self.size = window.devicePixelRatio > 1 ? 32 : 16;
// If it's not a data url, pick apart the filename and add @2x for retina
if ( !self.src.match(/data:/) && window.devicePixelRatio > 1 ) {
var dot = self.src.lastIndexOf('.');
self.src = self.src.substring( 0, dot ) + '@2x' + self.src.substring( dot );
}
self.currentFrame = 0;
// Chrome chokes on this. It looks like it can handle 4 frames per second
self.fps = 24;
self.init();
};
Favicon.prototype.init = function() {
var self = this;
// No #favicon element or browser doesn't support canvas or < IE9, stop
if ( !doc.getElementById('favicon') || !self.canvas.getContext || self.html.className.indexOf('lt-ie9') > -1 ) {
return;
}
// Save context
self.ctx = self.canvas.getContext('2d');
// Set canvas dimensions based on device DPI
self.canvas.height = self.canvas.width = self.size;
// Create a new sprite 32x32 size with 32x32 sprites
self.sprite = new Sprite( self.ctx, self.img, self.size );
// Bind the image load handler
self.img.onload = self.onSpriteLoaded.bind( self );
// Trigger image to load
self.img.src = self.src;
};
Favicon.prototype.getData = function() {
return this.canvas.toDataURL('image/png');
};
// Clone the current #favicon and replace it with a new element
// which has the updated data URI href
Favicon.prototype.setFavicon = function() {
var self = this,
data = self.getData(),
originalFavicon = doc.getElementById('favicon'),
clone = originalFavicon.cloneNode( true );
clone.setAttribute( 'href', data );
originalFavicon.parentNode.replaceChild( clone, originalFavicon );
};
// Request Animation Frame Loop
Favicon.prototype.loop = function( timestamp ) {
var self = this;
// If not enough time has elapse since the last call
// immediately call the next rAF
if ( timestamp - self.lastExecuted < self.timeToElapse ) {
return requestAnimationFrame( self.loop.bind( self ) );
}
// Increment current frame
self.currentFrame += 1;
if ( self.currentFrame === self.numFrames ) {
self.currentFrame = 0;
}
// Completed an animation state
self.timeToElapse = self.currentFrame % self.framesPerAnimation === 0 ?
self.animationDelay :
1000 / self.fps;
// Draw current frame from sprite
self.sprite.drawFrame( self.currentFrame );
// Swap <link>
self.setFavicon();
// Set a timeout to draw again
self.lastExecuted = timestamp;
// Continue loop
return requestAnimationFrame( self.loop.bind( self ) );
};
// Sprite loaded
Favicon.prototype.onSpriteLoaded = function() {
var self = this;
// Draw the first frame when the image loads
self.sprite.drawFrame( self.currentFrame );
// Swap <link>
self.setFavicon();
// Start loop
requestAnimationFrame( self.loop.bind( self ) );
};
var Sprite = function( context, img, size ) {
var self = this;
self.ctx = context;
self.img = img;
self.width = size;
self.height = size;
self.frameWidth = size;
self.frameHeight = size;
};
// Assuming horizontal sprite
Sprite.prototype.getFrame = function( frame ) {
return {
x: frame * this.frameWidth,
y: 0
};
};
Sprite.prototype.clearCanvas = function() {
this.ctx.clearRect( 0, 0, this.width, this.height );
};
Sprite.prototype.drawFrame = function( frameNumber ) {
var self = this;
var frame = self.getFrame( frameNumber );
// Clear out the last frame
self.clearCanvas();
// Draw to the context. This method is really confusing...
self.ctx.drawImage(
self.img,
frame.x,
frame.y,
self.width,
self.height,
0,
0,
self.width,
self.height
);
};
return Favicon;
}( document ));
// Analytics
var _gaq = [ ['_setAccount', 'UA-39355642-1'], ['_trackPageview'] ];
(function(doc, script) {
'use strict';
var js,
fjs = doc.scripts[0],
frag = doc.createDocumentFragment(),
add = function(url, id) {
if (doc.getElementById(id)) {return;}
js = doc.createElement(script);
js.src = url;
if ( id ) { js.id = id; }
frag.appendChild( js );
};
// Twitter SDK
// add('//platform.twitter.com/widgets.js', 'twitter-wjs');
// Load GA over http, we know it won't be over ssl
add('//www.google-analytics.com/ga.js');
fjs.parentNode.insertBefore(frag, fjs);
}(document, 'script'));
$(document).ready(function() {
'use strict';
Modules.Nav.init();
Modules.Polyfill.init();
var src = '/img/favicon-sprite.png';
new Modules.Favicon( src, 21, 7, 3000 * 1 );
});

@ -0,0 +1,11 @@
/**
* Prism: Lightweight, robust, elegant syntax highlighting
* MIT license http://www.opensource.org/licenses/mit-license.php/
* @author Lea Verou http://lea.verou.me
*/(function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var r={};for(var i in e)e.hasOwnProperty(i)&&(r[i]=t.util.clone(e[i]));return r;case"Array":return e.slice()}return e}},languages:{extend:function(e,n){var r=t.util.clone(t.languages[e]);for(var i in n)r[i]=n[i];return r},insertBefore:function(e,n,r,i){i=i||t.languages;var s=i[e],o={};for(var u in s)if(s.hasOwnProperty(u)){if(u==n)for(var a in r)r.hasOwnProperty(a)&&(o[a]=r[a]);o[u]=s[u]}return i[e]=o},DFS:function(e,n){for(var r in e){n.call(e,r,e[r]);t.util.type(e)==="Object"&&t.languages.DFS(e[r],n)}}},highlightAll:function(e,n){var r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');for(var i=0,s;s=r[i++];)t.highlightElement(s,e===!0,n)},highlightElement:function(r,i,s){var o,u,a=r;while(a&&!e.test(a.className))a=a.parentNode;if(a){o=(a.className.match(e)||[,""])[1];u=t.languages[o]}if(!u)return;r.className=r.className.replace(e,"").replace(/\s+/g," ")+" language-"+o;a=r.parentNode;/pre/i.test(a.nodeName)&&(a.className=a.className.replace(e,"").replace(/\s+/g," ")+" language-"+o);var f=r.textContent;if(!f)return;f=f.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\u00a0/g," ");var l={element:r,language:o,grammar:u,code:f};t.hooks.run("before-highlight",l);if(i&&self.Worker){var c=new Worker(t.filename);c.onmessage=function(e){l.highlightedCode=n.stringify(JSON.parse(e.data),o);l.element.innerHTML=l.highlightedCode;s&&s.call(l.element);t.hooks.run("after-highlight",l)};c.postMessage(JSON.stringify({language:l.language,code:l.code}))}else{l.highlightedCode=t.highlight(l.code,l.grammar,l.language);l.element.innerHTML=l.highlightedCode;s&&s.call(r);t.hooks.run("after-highlight",l)}},highlight:function(e,r,i){return n.stringify(t.tokenize(e,r),i)},tokenize:function(e,n,r){var i=t.Token,s=[e],o=n.rest;if(o){for(var u in o)n[u]=o[u];delete n.rest}e:for(var u in n){if(!n.hasOwnProperty(u)||!n[u])continue;var a=n[u],f=a.inside,l=!!a.lookbehind||0;a=a.pattern||a;for(var c=0;c<s.length;c++){var h=s[c];if(s.length>e.length)break e;if(h instanceof i)continue;a.lastIndex=0;var p=a.exec(h);if(p){l&&(l=p[1].length);var d=p.index-1+l,p=p[0].slice(l),v=p.length,m=d+v,g=h.slice(0,d+1),y=h.slice(m+1),b=[c,1];g&&b.push(g);var w=new i(u,f?t.tokenize(p,f):p);b.push(w);y&&b.push(y);Array.prototype.splice.apply(s,b)}}}return s},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[];r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(!r||!r.length)return;for(var i=0,s;s=r[i++];)s(n)}}},n=t.Token=function(e,t){this.type=e;this.content=t};n.stringify=function(e,r,i){if(typeof e=="string")return e;if(Object.prototype.toString.call(e)=="[object Array]")return e.map(function(t){return n.stringify(t,r,e)}).join("");var s={type:e.type,content:n.stringify(e.content,r,i),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:i};s.type=="comment"&&(s.attributes.spellcheck="true");t.hooks.run("wrap",s);var o="";for(var u in s.attributes)o+=u+'="'+(s.attributes[u]||"")+'"';return"<"+s.tag+' class="'+s.classes.join(" ")+'" '+o+">"+s.content+"</"+s.tag+">"};if(!self.document){self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,i=n.code;self.postMessage(JSON.stringify(t.tokenize(i,t.languages[r])));self.close()},!1);return}var r=document.getElementsByTagName("script");r=r[r.length-1];if(r){t.filename=r.src;document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)}})();;
Prism.languages.markup={comment:/&lt;!--[\w\W]*?--(&gt;|&gt;)/g,prolog:/&lt;\?.+?\?&gt;/,doctype:/&lt;!DOCTYPE.+?&gt;/,cdata:/&lt;!\[CDATA\[[\w\W]+?]]&gt;/i,tag:{pattern:/&lt;\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|\w+))?\s*)*\/?&gt;/gi,inside:{tag:{pattern:/^&lt;\/?[\w:-]+/i,inside:{punctuation:/^&lt;\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,inside:{punctuation:/=|&gt;|"/g}},punctuation:/\/?&gt;/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/&amp;#?[\da-z]{1,8};/gi};Prism.hooks.add("wrap",function(e){e.type==="entity"&&(e.attributes.title=e.content.replace(/&amp;/,"&"))});;
Prism.languages.css={comment:/\/\*[\w\W]*?\*\//g,atrule:/@[\w-]+?(\s+[^;{]+)?(?=\s*{|\s*;)/gi,url:/url\((["']?).*?\1\)/gi,selector:/[^\{\}\s][^\{\}]*(?=\s*\{)/g,property:/(\b|\B)[a-z-]+(?=\s*:)/ig,string:/("|')(\\?.)*?\1/g,important:/\B!important\b/gi,ignore:/&(lt|gt|amp);/gi,punctuation:/[\{\};:]/g};Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{style:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,inside:{tag:{pattern:/(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css}}});;
Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:class|interface|extends|implements|trait|instanceof|new)\s+)[a-z0-9_\.\\]+/ig,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/ig,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|=?&lt;|=?&gt;|={1,2}|(&amp;){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};;
Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(var|let|if|else|while|do|for|return|in|instanceof|function|new|with|typeof|try|catch|finally|null|break|continue)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g});Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}});Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,inside:{tag:{pattern:/(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});;
Prism.languages.scss=Prism.languages.extend("css",{comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|\/\/.*?(\r?\n|$))/g,lookbehind:!0},atrule:/@[\w-]+(?=\s+(\(|\{|;))/gi,url:/([-a-z]+-)*url(?=\()/gi,selector:/([^@;\{\}\(\)]?([^@;\{\}\(\)]|&amp;|\#\{\$[-_\w]+\})+)(?=\s*\{(\}|\s|[^\}]+(:|\{)[^\}]+))/gm});Prism.languages.insertBefore("scss","atrule",{keyword:/@(if|else if|else|for|each|while|import|extend|debug|warn|mixin|include|function|return)|(?=@for\s+\$[-_\w]+\s)+from/i});Prism.languages.insertBefore("scss","property",{variable:/((\$[-_\w]+)|(#\{\$[-_\w]+\}))/i});Prism.languages.insertBefore("scss","ignore",{placeholder:/%[-_\w]+/i,statement:/\B!(default|optional)\b/gi,"boolean":/\b(true|false)\b/g,"null":/\b(null)\b/g,operator:/\s+([-+]{1,2}|={1,2}|!=|\|?\||\?|\*|\/|\%)\s+/g});
;
Loading…
Cancel
Save