You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@edgent.apache.org by wc...@apache.org on 2016/03/18 19:56:38 UTC

[14/53] [abbrv] incubator-quarks-website git commit: Merged Jekyll repositories

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/fonts/glyphicons-halflings-regular.ttf
----------------------------------------------------------------------
diff --git a/site/fonts/glyphicons-halflings-regular.ttf b/site/fonts/glyphicons-halflings-regular.ttf
index 67fa00b..1413fc6 100755
Binary files a/site/fonts/glyphicons-halflings-regular.ttf and b/site/fonts/glyphicons-halflings-regular.ttf differ

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/fonts/glyphicons-halflings-regular.woff
----------------------------------------------------------------------
diff --git a/site/fonts/glyphicons-halflings-regular.woff b/site/fonts/glyphicons-halflings-regular.woff
index 8c54182..9e61285 100755
Binary files a/site/fonts/glyphicons-halflings-regular.woff and b/site/fonts/glyphicons-halflings-regular.woff differ

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/fonts/glyphicons-halflings-regular.woff2
----------------------------------------------------------------------
diff --git a/site/fonts/glyphicons-halflings-regular.woff2 b/site/fonts/glyphicons-halflings-regular.woff2
new file mode 100644
index 0000000..64539b5
Binary files /dev/null and b/site/fonts/glyphicons-halflings-regular.woff2 differ

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/index.html
----------------------------------------------------------------------
diff --git a/site/index.html b/site/index.html
index 61133e9..3305add 100644
--- a/site/index.html
+++ b/site/index.html
@@ -1,5 +1,5 @@
 ---
-layout: default
+layout: default_orig
 title: Quarks
 subTitle: A Community for <br>Accelerating Analytics at the Edge
 ---

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/js/customscripts.js
----------------------------------------------------------------------
diff --git a/site/js/customscripts.js b/site/js/customscripts.js
new file mode 100644
index 0000000..8c9fb4c
--- /dev/null
+++ b/site/js/customscripts.js
@@ -0,0 +1,55 @@
+
+$('#mysidebar').height($(".nav").height());
+
+
+$( document ).ready(function() {
+
+    //this script says, if the height of the viewport is greater than 800px, then insert affix class, which makes the nav bar float in a fixed
+    // position as your scroll. if you have a lot of nav items, this height may not work for you.
+    var h = $(window).height();
+    //console.log (h);
+    if (h > 800) {
+        $( "#mysidebar" ).attr("class", "nav affix");
+    }
+    // activate tooltips. although this is a bootstrap js function, it must be activated this way in your theme.
+    $('[data-toggle="tooltip"]').tooltip({
+        placement : 'top'
+    });
+
+    /**
+     * AnchorJS
+     */
+    anchors.add('h2,h3,h4,h5');
+
+});
+
+// needed for nav tabs on pages. See Formatting > Nav tabs for more details.
+// script from http://stackoverflow.com/questions/10523433/how-do-i-keep-the-current-tab-active-with-twitter-bootstrap-after-a-page-reload
+$(function() {
+    var json, tabsState;
+    $('a[data-toggle="pill"], a[data-toggle="tab"]').on('shown.bs.tab', function(e) {
+        var href, json, parentId, tabsState;
+
+        tabsState = localStorage.getItem("tabs-state");
+        json = JSON.parse(tabsState || "{}");
+        parentId = $(e.target).parents("ul.nav.nav-pills, ul.nav.nav-tabs").attr("id");
+        href = $(e.target).attr('href');
+        json[parentId] = href;
+
+        return localStorage.setItem("tabs-state", JSON.stringify(json));
+    });
+
+    tabsState = localStorage.getItem("tabs-state");
+    json = JSON.parse(tabsState || "{}");
+
+    $.each(json, function(containerId, href) {
+        return $("#" + containerId + " a[href=" + href + "]").tab('show');
+    });
+
+    $("ul.nav.nav-pills, ul.nav.nav-tabs").each(function() {
+        var $this = $(this);
+        if (!json[$this.attr("id")]) {
+            return $this.find("a[data-toggle=tab]:first, a[data-toggle=pill]:first").tab("show");
+        }
+    });
+});

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/js/jekyll-search.js
----------------------------------------------------------------------
diff --git a/site/js/jekyll-search.js b/site/js/jekyll-search.js
new file mode 100644
index 0000000..04d6a0d
--- /dev/null
+++ b/site/js/jekyll-search.js
@@ -0,0 +1 @@
+!function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module){module.exports=function(){function receivedResponse(xhr){return 200==xhr.status&&4==xhr.readyState}function handleResponse(xhr,callback){xhr.onreadystatechange=function(){if(receivedResponse(xhr))try{callback(null,JSON.parse(xhr.responseText))}catch(err){callback(err,null)}}}var self=this;self.load=function(location,callback){var xhr=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");xhr.open("GET",location,!0),handleResponse(xhr,callback),xhr.send()}}},{}],2:[function(require,module){function FuzzySearchStrategy(){function creat
 eFuzzyRegExpFromString(string){return new RegExp(string.split("").join(".*?"),"gi")}var self=this;self.matches=function(string,crit){return"string"!=typeof string?!1:(string=string.trim(),!!string.match(createFuzzyRegExpFromString(crit)))}}module.exports=new FuzzySearchStrategy},{}],3:[function(require,module){function LiteralSearchStrategy(){function doMatch(string,crit){return string.toLowerCase().indexOf(crit.toLowerCase())>=0}var self=this;self.matches=function(string,crit){return"string"!=typeof string?!1:(string=string.trim(),doMatch(string,crit))}}module.exports=new LiteralSearchStrategy},{}],4:[function(require,module){module.exports=function(){function findMatches(store,crit,strategy){for(var data=store.get(),i=0;i<data.length&&matches.length<limit;i++)findMatchesInObject(data[i],crit,strategy);return matches}function findMatchesInObject(obj,crit,strategy){for(var key in obj)if(strategy.matches(obj[key],crit)){matches.push(obj);break}}function getSearchStrategy(){return fuz
 zy?fuzzySearchStrategy:literalSearchStrategy}var self=this,matches=[],fuzzy=!1,limit=10,fuzzySearchStrategy=require("./SearchStrategies/fuzzy"),literalSearchStrategy=require("./SearchStrategies/literal");self.setFuzzy=function(_fuzzy){fuzzy=!!_fuzzy},self.setLimit=function(_limit){limit=parseInt(_limit,10)||limit},self.search=function(data,crit){return crit?(matches.length=0,findMatches(data,crit,getSearchStrategy())):[]}}},{"./SearchStrategies/fuzzy":2,"./SearchStrategies/literal":3}],5:[function(require,module){module.exports=function(_store){function isObject(obj){return!!obj&&"[object Object]"==Object.prototype.toString.call(obj)}function isArray(obj){return!!obj&&"[object Array]"==Object.prototype.toString.call(obj)}function addObject(data){return store.push(data),data}function addArray(data){for(var added=[],i=0;i<data.length;i++)isObject(data[i])&&added.push(addObject(data[i]));return added}var self=this,store=[];isArray(_store)&&addArray(_store),self.clear=function(){return 
 store.length=0,store},self.get=function(){return store},self.put=function(data){return isObject(data)?addObject(data):isArray(data)?addArray(data):void 0}}},{}],6:[function(require,module){module.exports=function(){var self=this,templatePattern=/\{(.*?)\}/g;self.setTemplatePattern=function(newTemplatePattern){templatePattern=newTemplatePattern},self.render=function(t,data){return t.replace(templatePattern,function(match,prop){return data[prop]||match})}}},{}],7:[function(require){!function(window){"use strict";function SimpleJekyllSearch(){function initWithJSON(){store.put(opt.dataSource),registerInput()}function initWithURL(url){jsonLoader.load(url,function(err,json){err?throwError("failed to get JSON ("+url+")"):(store.put(json),registerInput())})}function throwError(message){throw new Error("SimpleJekyllSearch --- "+message)}function validateOptions(_opt){for(var i=0;i<requiredOptions.length;i++){var req=requiredOptions[i];_opt[req]||throwError("You must specify a "+req)}}functio
 n assignOptions(_opt){for(var option in opt)opt[option]=_opt[option]||opt[option]}function isJSON(json){try{return json instanceof Object&&JSON.parse(JSON.stringify(json))}catch(e){return!1}}function emptyResultsContainer(){opt.resultsContainer.innerHTML=""}function appendToResultsContainer(text){opt.resultsContainer.innerHTML+=text}function registerInput(){opt.searchInput.addEventListener("keyup",function(e){return 0==e.target.value.length?void emptyResultsContainer():void render(searcher.search(store,e.target.value))})}function render(results){if(emptyResultsContainer(),0==results.length)return appendToResultsContainer(opt.noResultsText);for(var i=0;i<results.length;i++)appendToResultsContainer(templater.render(opt.searchResultTemplate,results[i]))}var self=this,requiredOptions=["searchInput","resultsContainer","dataSource"],opt={searchInput:null,resultsContainer:null,dataSource:[],searchResultTemplate:'<li><a href="{url}" title="{desc}">{title}</a></li>',noResultsText:"No results
  found",limit:10,fuzzy:!1};self.init=function(_opt){validateOptions(_opt),assignOptions(_opt),isJSON(opt.dataSource)?initWithJSON(opt.dataSource):initWithURL(opt.dataSource)}}var Searcher=require("./Searcher"),Templater=require("./Templater"),Store=require("./Store"),JSONLoader=require("./JSONLoader"),searcher=new Searcher,templater=new Templater,store=new Store,jsonLoader=new JSONLoader;window.SimpleJekyllSearch=new SimpleJekyllSearch}(window,document)},{"./JSONLoader":1,"./Searcher":4,"./Store":5,"./Templater":6}]},{},[7]);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/js/jquery.ba-throttle-debounce.min.js
----------------------------------------------------------------------
diff --git a/site/js/jquery.ba-throttle-debounce.min.js b/site/js/jquery.ba-throttle-debounce.min.js
new file mode 100644
index 0000000..0720550
--- /dev/null
+++ b/site/js/jquery.ba-throttle-debounce.min.js
@@ -0,0 +1,9 @@
+/*
+ * 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);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/js/jquery.localScroll.min.js
----------------------------------------------------------------------
diff --git a/site/js/jquery.localScroll.min.js b/site/js/jquery.localScroll.min.js
new file mode 100644
index 0000000..48a6e16
--- /dev/null
+++ b/site/js/jquery.localScroll.min.js
@@ -0,0 +1,7 @@
+/**
+ * Copyright (c) 2007-2014 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com
+ * Licensed under MIT
+ * @author Ariel Flesler
+ * @version 1.3.5
+ */
+;(function(a){if(typeof define==='function'&&define.amd){define(['jquery'],a)}else{a(jQuery)}}(function($){var g=location.href.replace(/#.*/,'');var h=$.localScroll=function(a){$('body').localScroll(a)};h.defaults={duration:1000,axis:'y',event:'click',stop:true,target:window};$.fn.localScroll=function(a){a=$.extend({},h.defaults,a);if(a.hash&&location.hash){if(a.target)window.scrollTo(0,0);scroll(0,location,a)}return a.lazy?this.on(a.event,'a,area',function(e){if(filter.call(this)){scroll(e,this,a)}}):this.find('a,area').filter(filter).bind(a.event,function(e){scroll(e,this,a)}).end().end();function filter(){return!!this.href&&!!this.hash&&this.href.replace(this.hash,'')==g&&(!a.filter||$(this).is(a.filter))}};h.hash=function(){};function scroll(e,a,b){var c=a.hash.slice(1),elem=document.getElementById(c)||document.getElementsByName(c)[0];if(!elem)return;if(e)e.preventDefault();var d=$(b.target);if(b.lock&&d.is(':animated')||b.onBefore&&b.onBefore(e,elem,d)===false)return;if(b.stop)
 d._scrollable().stop(true);if(b.hash){var f=elem.id===c?'id':'name',$a=$('<a> </a>').attr(f,c).css({position:'absolute',top:$(window).scrollTop(),left:$(window).scrollLeft()});elem[f]='';$('body').prepend($a);location.hash=a.hash;$a.remove();elem[f]=c}d.scrollTo(elem,b).trigger('notify.serialScroll',[elem])};return h}));
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/js/jquery.navgoco.min.js
----------------------------------------------------------------------
diff --git a/site/js/jquery.navgoco.min.js b/site/js/jquery.navgoco.min.js
new file mode 100644
index 0000000..4ba4475
--- /dev/null
+++ b/site/js/jquery.navgoco.min.js
@@ -0,0 +1,8 @@
+/*
+ * jQuery Navgoco Menus Plugin v0.2.1 (2014-04-11)
+ * https://github.com/tefra/navgoco
+ *
+ * Copyright (c) 2014 Chris T (@tefra)
+ * BSD - https://github.com/tefra/navgoco/blob/master/LICENSE-BSD
+ */
+!function(a){"use strict";var b=function(b,c,d){return this.el=b,this.$el=a(b),this.options=c,this.uuid=this.$el.attr("id")?this.$el.attr("id"):d,this.state={},this.init(),this};b.prototype={init:function(){var b=this;b._load(),b.$el.find("ul").each(function(c){var d=a(this);d.attr("data-index",c),b.options.save&&b.state.hasOwnProperty(c)?(d.parent().addClass(b.options.openClass),d.show()):d.parent().hasClass(b.options.openClass)?(d.show(),b.state[c]=1):d.hide()});var c=a("<span></span>").prepend(b.options.caretHtml),d=b.$el.find("li > a");b._trigger(c,!1),b._trigger(d,!0),b.$el.find("li:has(ul) > a").prepend(c)},_trigger:function(b,c){var d=this;b.on("click",function(b){b.stopPropagation();var e=c?a(this).next():a(this).parent().next(),f=!1;if(c){var g=a(this).attr("href");f=void 0===g||""===g||"#"===g}if(e=e.length>0?e:!1,d.options.onClickBefore.call(this,b,e),!c||e&&f)b.preventDefault(),d._toggle(e,e.is(":hidden")),d._save();else if(d.options.accordion){var h=d.state=d._parents(a
 (this));d.$el.find("ul").filter(":visible").each(function(){var b=a(this),c=b.attr("data-index");h.hasOwnProperty(c)||d._toggle(b,!1)}),d._save()}d.options.onClickAfter.call(this,b,e)})},_toggle:function(b,c){var d=this,e=b.attr("data-index"),f=b.parent();if(d.options.onToggleBefore.call(this,b,c),c){if(f.addClass(d.options.openClass),b.slideDown(d.options.slide),d.state[e]=1,d.options.accordion){var g=d.state=d._parents(b);g[e]=d.state[e]=1,d.$el.find("ul").filter(":visible").each(function(){var b=a(this),c=b.attr("data-index");g.hasOwnProperty(c)||d._toggle(b,!1)})}}else f.removeClass(d.options.openClass),b.slideUp(d.options.slide),d.state[e]=0;d.options.onToggleAfter.call(this,b,c)},_parents:function(b,c){var d={},e=b.parent(),f=e.parents("ul");return f.each(function(){var b=a(this),e=b.attr("data-index");return e?void(d[e]=c?b:1):!1}),d},_save:function(){if(this.options.save){var b={};for(var d in this.state)1===this.state[d]&&(b[d]=1);c[this.uuid]=this.state=b,a.cookie(this.opt
 ions.cookie.name,JSON.stringify(c),this.options.cookie)}},_load:function(){if(this.options.save){if(null===c){var b=a.cookie(this.options.cookie.name);c=b?JSON.parse(b):{}}this.state=c.hasOwnProperty(this.uuid)?c[this.uuid]:{}}},toggle:function(b){var c=this,d=arguments.length;if(1>=d)c.$el.find("ul").each(function(){var d=a(this);c._toggle(d,b)});else{var e,f={},g=Array.prototype.slice.call(arguments,1);d--;for(var h=0;d>h;h++){e=g[h];var i=c.$el.find('ul[data-index="'+e+'"]').first();if(i&&(f[e]=i,b)){var j=c._parents(i,!0);for(var k in j)f.hasOwnProperty(k)||(f[k]=j[k])}}for(e in f)c._toggle(f[e],b)}c._save()},destroy:function(){a.removeData(this.$el),this.$el.find("li:has(ul) > a").unbind("click"),this.$el.find("li:has(ul) > a > span").unbind("click")}},a.fn.navgoco=function(c){if("string"==typeof c&&"_"!==c.charAt(0)&&"init"!==c)var d=!0,e=Array.prototype.slice.call(arguments,1);else c=a.extend({},a.fn.navgoco.defaults,c||{}),a.cookie||(c.save=!1);return this.each(function(f){v
 ar g=a(this),h=g.data("navgoco");h||(h=new b(this,d?a.fn.navgoco.defaults:c,f),g.data("navgoco",h)),d&&h[c].apply(h,e)})};var c=null;a.fn.navgoco.defaults={caretHtml:"",accordion:!1,openClass:"open",save:!0,cookie:{name:"navgoco",expires:!1,path:"/"},slide:{duration:400,easing:"swing"},onClickBefore:a.noop,onClickAfter:a.noop,onToggleBefore:a.noop,onToggleAfter:a.noop}}(jQuery);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/js/jquery.scrollTo.min.js
----------------------------------------------------------------------
diff --git a/site/js/jquery.scrollTo.min.js b/site/js/jquery.scrollTo.min.js
new file mode 100644
index 0000000..d9f9b15
--- /dev/null
+++ b/site/js/jquery.scrollTo.min.js
@@ -0,0 +1,7 @@
+/**
+ * Copyright (c) 2007-2014 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com
+ * Licensed under MIT
+ * @author Ariel Flesler
+ * @version 1.4.14
+ */
+;(function(k){'use strict';k(['jquery'],function($){var j=$.scrollTo=function(a,b,c){return $(window).scrollTo(a,b,c)};j.defaults={axis:'xy',duration:0,limit:!0};j.window=function(a){return $(window)._scrollable()};$.fn._scrollable=function(){return this.map(function(){var a=this,isWin=!a.nodeName||$.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!isWin)return a;var b=(a.contentWindow||a).document||a.ownerDocument||a;return/webkit/i.test(navigator.userAgent)||b.compatMode=='BackCompat'?b.body:b.documentElement})};$.fn.scrollTo=function(f,g,h){if(typeof g=='object'){h=g;g=0}if(typeof h=='function')h={onAfter:h};if(f=='max')f=9e9;h=$.extend({},j.defaults,h);g=g||h.duration;h.queue=h.queue&&h.axis.length>1;if(h.queue)g/=2;h.offset=both(h.offset);h.over=both(h.over);return this._scrollable().each(function(){if(f==null)return;var d=this,$elem=$(d),targ=f,toff,attr={},win=$elem.is('html,body');switch(typeof targ){case'number':case'string':if(/^([+-]=?)?\d+(\
 .\d+)?(px|%)?$/.test(targ)){targ=both(targ);break}targ=win?$(targ):$(targ,this);if(!targ.length)return;case'object':if(targ.is||targ.style)toff=(targ=$(targ)).offset()}var e=$.isFunction(h.offset)&&h.offset(d,targ)||h.offset;$.each(h.axis.split(''),function(i,a){var b=a=='x'?'Left':'Top',pos=b.toLowerCase(),key='scroll'+b,old=d[key],max=j.max(d,a);if(toff){attr[key]=toff[pos]+(win?0:old-$elem.offset()[pos]);if(h.margin){attr[key]-=parseInt(targ.css('margin'+b))||0;attr[key]-=parseInt(targ.css('border'+b+'Width'))||0}attr[key]+=e[pos]||0;if(h.over[pos])attr[key]+=targ[a=='x'?'width':'height']()*h.over[pos]}else{var c=targ[pos];attr[key]=c.slice&&c.slice(-1)=='%'?parseFloat(c)/100*max:c}if(h.limit&&/^\d+$/.test(attr[key]))attr[key]=attr[key]<=0?0:Math.min(attr[key],max);if(!i&&h.queue){if(old!=attr[key])animate(h.onAfterFirst);delete attr[key]}});animate(h.onAfter);function animate(a){$elem.animate(attr,g,h.easing,a&&function(){a.call(this,targ,h)})}}).end()};j.max=function(a,b){var c
 =b=='x'?'Width':'Height',scroll='scroll'+c;if(!$(a).is('html,body'))return a[scroll]-$(a)[c.toLowerCase()]();var d='client'+c,html=a.ownerDocument.documentElement,body=a.ownerDocument.body;return Math.max(html[scroll],body[scroll])-Math.min(html[d],body[d])};function both(a){return $.isFunction(a)||$.isPlainObject(a)?a:{top:a,left:a}}return j})}(typeof define==='function'&&define.amd?define:function(a,b){if(typeof module!=='undefined'&&module.exports){module.exports=b(require('jquery'))}else{b(jQuery)}}));
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/js/jquery.shuffle.min.js
----------------------------------------------------------------------
diff --git a/site/js/jquery.shuffle.min.js b/site/js/jquery.shuffle.min.js
new file mode 100644
index 0000000..d103127
--- /dev/null
+++ b/site/js/jquery.shuffle.min.js
@@ -0,0 +1,1588 @@
+/*!
+ * Shuffle.js by @Vestride
+ * Categorize, sort, and filter a responsive grid of items.
+ * Dependencies: jQuery 1.9+, Modernizr 2.6.2+
+ * @license MIT license
+ * @version 3.0.0
+ */
+
+/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
+ * Build: http://modernizr.com/download/#-csstransforms-csstransforms3d-csstransitions-cssclasses-prefixed-teststyles-testprop-testallprops-prefixes-domprefixes
+ */
+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&&"webkitPerspec
 tive"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);
+
+(function (factory) {
+  if (typeof define === 'function' && define.amd) {
+    define(['jquery', 'modernizr'], factory);
+  } else {
+    window.Shuffle = factory(window.jQuery, window.Modernizr);
+  }
+})(function($, Modernizr, undefined) {
+
+'use strict';
+
+
+// Validate Modernizr exists.
+// Shuffle requires `csstransitions`, `csstransforms`, `csstransforms3d`,
+// and `prefixed` to exist on the Modernizr object.
+if (typeof Modernizr !== 'object') {
+  throw new Error('Shuffle.js requires Modernizr.\n' +
+      'http://vestride.github.io/Shuffle/#dependencies');
+}
+
+
+/**
+ * Returns css prefixed properties like `-webkit-transition` or `box-sizing`
+ * from `transition` or `boxSizing`, respectively.
+ * @param {(string|boolean)} prop Property to be prefixed.
+ * @return {string} The prefixed css property.
+ */
+function dashify( prop ) {
+  if (!prop) {
+    return '';
+  }
+
+  // Replace upper case with dash-lowercase,
+  // then fix ms- prefixes because they're not capitalized.
+  return prop.replace(/([A-Z])/g, function( str, m1 ) {
+    return '-' + m1.toLowerCase();
+  }).replace(/^ms-/,'-ms-');
+}
+
+// Constant, prefixed variables.
+var TRANSITION = Modernizr.prefixed('transition');
+var TRANSITION_DELAY = Modernizr.prefixed('transitionDelay');
+var TRANSITION_DURATION = Modernizr.prefixed('transitionDuration');
+
+// Note(glen): Stock Android 4.1.x browser will fail here because it wrongly
+// says it supports non-prefixed transitions.
+// https://github.com/Modernizr/Modernizr/issues/897
+var TRANSITIONEND = {
+  'WebkitTransition' : 'webkitTransitionEnd',
+  'transition' : 'transitionend'
+}[ TRANSITION ];
+
+var TRANSFORM = Modernizr.prefixed('transform');
+var CSS_TRANSFORM = dashify(TRANSFORM);
+
+// Constants
+var CAN_TRANSITION_TRANSFORMS = Modernizr.csstransforms && Modernizr.csstransitions;
+var HAS_TRANSFORMS_3D = Modernizr.csstransforms3d;
+var SHUFFLE = 'shuffle';
+var COLUMN_THRESHOLD = 0.3;
+
+// Configurable. You can change these constants to fit your application.
+// The default scale and concealed scale, however, have to be different values.
+var ALL_ITEMS = 'all';
+var FILTER_ATTRIBUTE_KEY = 'groups';
+var DEFAULT_SCALE = 1;
+var CONCEALED_SCALE = 0.001;
+
+
+// Underscore's throttle function.
+function throttle(func, wait, options) {
+  var context, args, result;
+  var timeout = null;
+  var previous = 0;
+  options = options || {};
+  var later = function() {
+    previous = options.leading === false ? 0 : $.now();
+    timeout = null;
+    result = func.apply(context, args);
+    context = args = null;
+  };
+  return function() {
+    var now = $.now();
+    if (!previous && options.leading === false) {
+      previous = now;
+    }
+    var remaining = wait - (now - previous);
+    context = this;
+    args = arguments;
+    if (remaining <= 0 || remaining > wait) {
+      clearTimeout(timeout);
+      timeout = null;
+      previous = now;
+      result = func.apply(context, args);
+      context = args = null;
+    } else if (!timeout && options.trailing !== false) {
+      timeout = setTimeout(later, remaining);
+    }
+    return result;
+  };
+}
+
+function each(obj, iterator, context) {
+  for (var i = 0, length = obj.length; i < length; i++) {
+    if (iterator.call(context, obj[i], i, obj) === {}) {
+      return;
+    }
+  }
+}
+
+function defer(fn, context, wait) {
+  return setTimeout( $.proxy( fn, context ), wait );
+}
+
+function arrayMax( array ) {
+  return Math.max.apply( Math, array );
+}
+
+function arrayMin( array ) {
+  return Math.min.apply( Math, array );
+}
+
+
+/**
+ * Always returns a numeric value, given a value.
+ * @param {*} value Possibly numeric value.
+ * @return {number} `value` or zero if `value` isn't numeric.
+ * @private
+ */
+function getNumber(value) {
+  return $.isNumeric(value) ? value : 0;
+}
+
+
+/**
+ * Represents a coordinate pair.
+ * @param {number} [x=0] X.
+ * @param {number} [y=0] Y.
+ */
+var Point = function(x, y) {
+  this.x = getNumber( x );
+  this.y = getNumber( y );
+};
+
+
+/**
+ * Whether two points are equal.
+ * @param {Point} a Point A.
+ * @param {Point} b Point B.
+ * @return {boolean}
+ */
+Point.equals = function(a, b) {
+  return a.x === b.x && a.y === b.y;
+};
+
+
+// Used for unique instance variables
+var id = 0;
+var $window = $( window );
+
+
+/**
+ * Categorize, sort, and filter a responsive grid of items.
+ *
+ * @param {Element} element An element which is the parent container for the grid items.
+ * @param {Object} [options=Shuffle.options] Options object.
+ * @constructor
+ */
+var Shuffle = function( element, options ) {
+  options = options || {};
+  $.extend( this, Shuffle.options, options, Shuffle.settings );
+
+  this.$el = $(element);
+  this.element = element;
+  this.unique = 'shuffle_' + id++;
+
+  this._fire( Shuffle.EventType.LOADING );
+  this._init();
+
+  // Dispatch the done event asynchronously so that people can bind to it after
+  // Shuffle has been initialized.
+  defer(function() {
+    this.initialized = true;
+    this._fire( Shuffle.EventType.DONE );
+  }, this, 16);
+};
+
+
+/**
+ * Events the container element emits with the .shuffle namespace.
+ * For example, "done.shuffle".
+ * @enum {string}
+ */
+Shuffle.EventType = {
+  LOADING: 'loading',
+  DONE: 'done',
+  LAYOUT: 'layout',
+  REMOVED: 'removed'
+};
+
+
+/** @enum {string} */
+Shuffle.ClassName = {
+  BASE: SHUFFLE,
+  SHUFFLE_ITEM: 'shuffle-item',
+  FILTERED: 'filtered',
+  CONCEALED: 'concealed'
+};
+
+
+// Overrideable options
+Shuffle.options = {
+  group: ALL_ITEMS, // Initial 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. Use an element to determine the size of columns and gutters.
+  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, // By default, shuffle will throttle resize events. This can be changed or removed.
+  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: CAN_TRANSITION_TRANSFORMS // Whether to use transforms or absolute positioning.
+};
+
+
+// Not overrideable
+Shuffle.settings = {
+  useSizer: false,
+  itemCss : { // default CSS for each item
+    position: 'absolute',
+    top: 0,
+    left: 0,
+    visibility: 'visible'
+  },
+  revealAppendedDelay: 300,
+  lastSort: {},
+  lastFilter: ALL_ITEMS,
+  enabled: true,
+  destroyed: false,
+  initialized: false,
+  _animations: [],
+  styleQueue: []
+};
+
+
+// Expose for testing.
+Shuffle.Point = Point;
+
+
+/**
+ * Static methods.
+ */
+
+/**
+ * If the browser has 3d transforms available, build a string with those,
+ * otherwise use 2d transforms.
+ * @param {Point} point X and Y positions.
+ * @param {number} scale Scale amount.
+ * @return {string} A normalized string which can be used with the transform style.
+ * @private
+ */
+Shuffle._getItemTransformString = function(point, scale) {
+  if ( HAS_TRANSFORMS_3D ) {
+    return 'translate3d(' + point.x + 'px, ' + point.y + 'px, 0) scale3d(' + scale + ', ' + scale + ', 1)';
+  } else {
+    return 'translate(' + point.x + 'px, ' + point.y + 'px) scale(' + scale + ')';
+  }
+};
+
+
+/**
+ * Retrieve the computed style for an element, parsed as a float. This should
+ * not be used for width or height values because jQuery mangles them and they
+ * are not precise enough.
+ * @param {Element} element Element to get style for.
+ * @param {string} style Style property.
+ * @return {number} The parsed computed value or zero if that fails because IE
+ *     will return 'auto' when the element doesn't have margins instead of
+ *     the computed style.
+ * @private
+ */
+Shuffle._getNumberStyle = function( element, style ) {
+  return Shuffle._getFloat( $( element ).css( style )  );
+};
+
+
+/**
+ * Parse a string as an integer.
+ * @param {string} value String integer.
+ * @return {number} The string as an integer or zero.
+ * @private
+ */
+Shuffle._getInt = function(value) {
+  return getNumber( parseInt( value, 10 ) );
+};
+
+/**
+ * Parse a string as an float.
+ * @param {string} value String float.
+ * @return {number} The string as an float or zero.
+ * @private
+ */
+Shuffle._getFloat = function(value) {
+  return getNumber( parseFloat( value ) );
+};
+
+
+/**
+ * Returns the outer width of an element, optionally including its margins.
+ * The `offsetWidth` property must be used because having a scale transform
+ * on the element affects the bounding box. Sadly, Firefox doesn't return an
+ * integer value for offsetWidth (yet).
+ * @param {Element} element The element.
+ * @param {boolean} [includeMargins] Whether to include margins. Default is false.
+ * @return {number} The width.
+ */
+Shuffle._getOuterWidth = function( element, includeMargins ) {
+  var width = element.offsetWidth;
+
+  // Use jQuery here because it uses getComputedStyle internally and is
+  // cross-browser. Using the style property of the element will only work
+  // if there are inline styles.
+  if ( includeMargins ) {
+    var marginLeft = Shuffle._getNumberStyle( element, 'marginLeft');
+    var marginRight = Shuffle._getNumberStyle( element, 'marginRight');
+    width += marginLeft + marginRight;
+  }
+
+  return width;
+};
+
+
+/**
+ * Returns the outer height of an element, optionally including its margins.
+ * @param {Element} element The element.
+ * @param {boolean} [includeMargins] Whether to include margins. Default is false.
+ * @return {number} The height.
+ */
+Shuffle._getOuterHeight = function( element, includeMargins ) {
+  var height = element.offsetHeight;
+
+  if ( includeMargins ) {
+    var marginTop = Shuffle._getNumberStyle( element, 'marginTop');
+    var marginBottom = Shuffle._getNumberStyle( element, 'marginBottom');
+    height += marginTop + marginBottom;
+  }
+
+  return height;
+};
+
+
+/**
+ * Change a property or execute a function which will not have a transition
+ * @param {Element} element DOM element that won't be transitioned
+ * @param {Function} callback A function which will be called while transition
+ *     is set to 0ms.
+ * @param {Object} [context] Optional context for the callback function.
+ * @private
+ */
+Shuffle._skipTransition = function( element, callback, context ) {
+  var duration = element.style[ TRANSITION_DURATION ];
+
+  // Set the duration to zero so it happens immediately
+  element.style[ TRANSITION_DURATION ] = '0ms'; // ms needed for firefox!
+
+  callback.call( context );
+
+  // Force reflow
+  var reflow = element.offsetWidth;
+  // Avoid jshint warnings: unused variables and expressions.
+  reflow = null;
+
+  // Put the duration back
+  element.style[ TRANSITION_DURATION ] = duration;
+};
+
+
+/**
+ * Instance methods.
+ */
+
+Shuffle.prototype._init = function() {
+  this.$items = this._getItems();
+
+  this.sizer = this._getElementOption( this.sizer );
+
+  if ( this.sizer ) {
+    this.useSizer = true;
+  }
+
+  // Add class and invalidate styles
+  this.$el.addClass( Shuffle.ClassName.BASE );
+
+  // Set initial css for each item
+  this._initItems();
+
+  // Bind resize events
+  // http://stackoverflow.com/questions/1852751/window-resize-event-firing-in-internet-explorer
+  $window.on('resize.' + SHUFFLE + '.' + this.unique, this._getResizeFunction());
+
+  // Get container css all in one request. Causes reflow
+  var containerCSS = this.$el.css(['position', 'overflow']);
+  var containerWidth = Shuffle._getOuterWidth( this.element );
+
+  // Add styles to the container if it doesn't have them.
+  this._validateStyles( containerCSS );
+
+  // We already got the container's width above, no need to cause another reflow getting it again...
+  // Calculate the number of columns there will be
+  this._setColumns( containerWidth );
+
+  // Kick off!
+  this.shuffle( this.group, this.initialSort );
+
+  // The shuffle items haven't had transitions set on them yet
+  // so the user doesn't see the first layout. Set them now that the first layout is done.
+  if ( this.supported ) {
+    defer(function() {
+      this._setTransitions();
+      this.element.style[ TRANSITION ] = 'height ' + this.speed + 'ms ' + this.easing;
+    }, this);
+  }
+};
+
+
+/**
+ * Returns a throttled and proxied function for the resize handler.
+ * @return {Function}
+ * @private
+ */
+Shuffle.prototype._getResizeFunction = function() {
+  var resizeFunction = $.proxy( this._onResize, this );
+  return this.throttle ?
+      this.throttle( resizeFunction, this.throttleTime ) :
+      resizeFunction;
+};
+
+
+/**
+ * Retrieve an element from an option.
+ * @param {string|jQuery|Element} option The option to check.
+ * @return {?Element} The plain element or null.
+ * @private
+ */
+Shuffle.prototype._getElementOption = function( option ) {
+  // If column width is a string, treat is as a selector and search for the
+  // sizer element within the outermost container
+  if ( typeof option === 'string' ) {
+    return this.$el.find( option )[0] || null;
+
+  // Check for an element
+  } else if ( option && option.nodeType && option.nodeType === 1 ) {
+    return option;
+
+  // Check for jQuery object
+  } else if ( option && option.jquery ) {
+    return option[0];
+  }
+
+  return null;
+};
+
+
+/**
+ * Ensures the shuffle container has the css styles it needs applied to it.
+ * @param {Object} styles Key value pairs for position and overflow.
+ * @private
+ */
+Shuffle.prototype._validateStyles = function(styles) {
+  // Position cannot be static.
+  if ( styles.position === 'static' ) {
+    this.element.style.position = 'relative';
+  }
+
+  // Overflow has to be hidden
+  if ( styles.overflow !== 'hidden' ) {
+    this.element.style.overflow = 'hidden';
+  }
+};
+
+
+/**
+ * Filter the elements by a category.
+ * @param {string} [category] Category to filter by. If it's given, the last
+ *     category will be used to filter the items.
+ * @param {ArrayLike} [$collection] Optionally filter a collection. Defaults to
+ *     all the items.
+ * @return {jQuery} Filtered items.
+ * @private
+ */
+Shuffle.prototype._filter = function( category, $collection ) {
+  category = category || this.lastFilter;
+  $collection = $collection || this.$items;
+
+  var set = this._getFilteredSets( category, $collection );
+
+  // Individually add/remove concealed/filtered classes
+  this._toggleFilterClasses( set.filtered, set.concealed );
+
+  // Save the last filter in case elements are appended.
+  this.lastFilter = category;
+
+  // This is saved mainly because providing a filter function (like searching)
+  // will overwrite the `lastFilter` property every time its called.
+  if ( typeof category === 'string' ) {
+    this.group = category;
+  }
+
+  return set.filtered;
+};
+
+
+/**
+ * Returns an object containing the filtered and concealed elements.
+ * @param {string|Function} category Category or function to filter by.
+ * @param {ArrayLike.<Element>} $items A collection of items to filter.
+ * @return {!{filtered: jQuery, concealed: jQuery}}
+ * @private
+ */
+Shuffle.prototype._getFilteredSets = function( category, $items ) {
+  var $filtered = $();
+  var $concealed = $();
+
+  // category === 'all', add filtered class to everything
+  if ( category === ALL_ITEMS ) {
+    $filtered = $items;
+
+  // Loop through each item and use provided function to determine
+  // whether to hide it or not.
+  } else {
+    each($items, function( el ) {
+      var $item = $(el);
+      if ( this._doesPassFilter( category, $item ) ) {
+        $filtered = $filtered.add( $item );
+      } else {
+        $concealed = $concealed.add( $item );
+      }
+    }, this);
+  }
+
+  return {
+    filtered: $filtered,
+    concealed: $concealed
+  };
+};
+
+
+/**
+ * Test an item to see if it passes a category.
+ * @param {string|Function} category Category or function to filter by.
+ * @param {jQuery} $item A single item, wrapped with jQuery.
+ * @return {boolean} Whether it passes the category/filter.
+ * @private
+ */
+Shuffle.prototype._doesPassFilter = function( category, $item ) {
+  if ( $.isFunction( category ) ) {
+    return category.call( $item[0], $item, this );
+
+  // Check each element's data-groups attribute against the given category.
+  } else {
+    var groups = $item.data( FILTER_ATTRIBUTE_KEY );
+    var keys = this.delimeter && !$.isArray( groups ) ?
+        groups.split( this.delimeter ) :
+        groups;
+    return $.inArray(category, keys) > -1;
+  }
+};
+
+
+/**
+ * Toggles the filtered and concealed class names.
+ * @param {jQuery} $filtered Filtered set.
+ * @param {jQuery} $concealed Concealed set.
+ * @private
+ */
+Shuffle.prototype._toggleFilterClasses = function( $filtered, $concealed ) {
+  $filtered
+    .removeClass( Shuffle.ClassName.CONCEALED )
+    .addClass( Shuffle.ClassName.FILTERED );
+  $concealed
+    .removeClass( Shuffle.ClassName.FILTERED )
+    .addClass( Shuffle.ClassName.CONCEALED );
+};
+
+
+/**
+ * Set the initial css for each item
+ * @param {jQuery} [$items] Optionally specifiy at set to initialize
+ */
+Shuffle.prototype._initItems = function( $items ) {
+  $items = $items || this.$items;
+  $items.addClass([
+    Shuffle.ClassName.SHUFFLE_ITEM,
+    Shuffle.ClassName.FILTERED
+  ].join(' '));
+  $items.css( this.itemCss ).data('point', new Point()).data('scale', DEFAULT_SCALE);
+};
+
+
+/**
+ * Updates the filtered item count.
+ * @private
+ */
+Shuffle.prototype._updateItemCount = function() {
+  this.visibleItems = this._getFilteredItems().length;
+};
+
+
+/**
+ * Sets css transform transition on a an element.
+ * @param {Element} element Element to set transition on.
+ * @private
+ */
+Shuffle.prototype._setTransition = function( element ) {
+  element.style[ TRANSITION ] = CSS_TRANSFORM + ' ' + this.speed + 'ms ' +
+    this.easing + ', opacity ' + this.speed + 'ms ' + this.easing;
+};
+
+
+/**
+ * Sets css transform transition on a group of elements.
+ * @param {ArrayLike.<Element>} $items Elements to set transitions on.
+ * @private
+ */
+Shuffle.prototype._setTransitions = function( $items ) {
+  $items = $items || this.$items;
+  each($items, function( el ) {
+    this._setTransition( el );
+  }, this);
+};
+
+
+/**
+ * Sets a transition delay on a collection of elements, making each delay
+ * greater than the last.
+ * @param {ArrayLike.<Element>} $collection Array to iterate over.
+ */
+Shuffle.prototype._setSequentialDelay = function( $collection ) {
+  if ( !this.supported ) {
+    return;
+  }
+
+  // $collection can be an array of dom elements or jquery object
+  each($collection, function( el, i ) {
+    // This works because the transition-property: transform, opacity;
+    el.style[ TRANSITION_DELAY ] = '0ms,' + ((i + 1) * this.sequentialFadeDelay) + 'ms';
+  }, this);
+};
+
+
+Shuffle.prototype._getItems = function() {
+  return this.$el.children( this.itemSelector );
+};
+
+
+Shuffle.prototype._getFilteredItems = function() {
+  return this.$items.filter('.' + Shuffle.ClassName.FILTERED);
+};
+
+
+Shuffle.prototype._getConcealedItems = function() {
+  return this.$items.filter('.' + Shuffle.ClassName.CONCEALED);
+};
+
+
+/**
+ * Returns the column size, based on column width and sizer options.
+ * @param {number} containerWidth Size of the parent container.
+ * @param {number} gutterSize Size of the gutters.
+ * @return {number}
+ * @private
+ */
+Shuffle.prototype._getColumnSize = function( containerWidth, gutterSize ) {
+  var size;
+
+  // If the columnWidth property is a function, then the grid is fluid
+  if ( $.isFunction( this.columnWidth ) ) {
+    size = this.columnWidth(containerWidth);
+
+  // columnWidth option isn't a function, are they using a sizing element?
+  } else if ( this.useSizer ) {
+    size = Shuffle._getOuterWidth(this.sizer);
+
+  // if not, how about the explicitly set option?
+  } else if ( this.columnWidth ) {
+    size = this.columnWidth;
+
+  // or use the size of the first item
+  } else if ( this.$items.length > 0 ) {
+    size = Shuffle._getOuterWidth(this.$items[0], true);
+
+  // if there's no items, use size of container
+  } else {
+    size = containerWidth;
+  }
+
+  // Don't let them set a column width of zero.
+  if ( size === 0 ) {
+    size = containerWidth;
+  }
+
+  return size + gutterSize;
+};
+
+
+/**
+ * Returns the gutter size, based on gutter width and sizer options.
+ * @param {number} containerWidth Size of the parent container.
+ * @return {number}
+ * @private
+ */
+Shuffle.prototype._getGutterSize = function( containerWidth ) {
+  var size;
+  if ( $.isFunction( this.gutterWidth ) ) {
+    size = this.gutterWidth(containerWidth);
+  } else if ( this.useSizer ) {
+    size = Shuffle._getNumberStyle(this.sizer, 'marginLeft');
+  } else {
+    size = this.gutterWidth;
+  }
+
+  return size;
+};
+
+
+/**
+ * Calculate the number of columns to be used. Gets css if using sizer element.
+ * @param {number} [theContainerWidth] Optionally specify a container width if it's already available.
+ */
+Shuffle.prototype._setColumns = function( theContainerWidth ) {
+  var containerWidth = theContainerWidth || Shuffle._getOuterWidth( this.element );
+  var gutter = this._getGutterSize( containerWidth );
+  var columnWidth = this._getColumnSize( containerWidth, gutter );
+  var calculatedColumns = (containerWidth + gutter) / columnWidth;
+
+  // Widths given from getComputedStyle are not precise enough...
+  if ( Math.abs(Math.round(calculatedColumns) - calculatedColumns) < COLUMN_THRESHOLD ) {
+    // e.g. calculatedColumns = 11.998876
+    calculatedColumns = Math.round( calculatedColumns );
+  }
+
+  this.cols = Math.max( Math.floor(calculatedColumns), 1 );
+  this.containerWidth = containerWidth;
+  this.colWidth = columnWidth;
+};
+
+/**
+ * Adjust the height of the grid
+ */
+Shuffle.prototype._setContainerSize = function() {
+  this.$el.css( 'height', this._getContainerSize() );
+};
+
+
+/**
+ * Based on the column heights, it returns the biggest one.
+ * @return {number}
+ * @private
+ */
+Shuffle.prototype._getContainerSize = function() {
+  return arrayMax( this.positions );
+};
+
+
+/**
+ * Fire events with .shuffle namespace
+ */
+Shuffle.prototype._fire = function( name, args ) {
+  this.$el.trigger( name + '.' + SHUFFLE, args && args.length ? args : [ this ] );
+};
+
+
+/**
+ * Zeros out the y columns array, which is used to determine item placement.
+ * @private
+ */
+Shuffle.prototype._resetCols = function() {
+  var i = this.cols;
+  this.positions = [];
+  while (i--) {
+    this.positions.push( 0 );
+  }
+};
+
+
+/**
+ * Loops through each item that should be shown and calculates the x, y position.
+ * @param {Array.<Element>} items Array of items that will be shown/layed out in order in their array.
+ *     Because jQuery collection are always ordered in DOM order, we can't pass a jq collection.
+ * @param {boolean} [isOnlyPosition=false] If true this will position the items with zero opacity.
+ */
+Shuffle.prototype._layout = function( items, isOnlyPosition ) {
+  each(items, function( item ) {
+    this._layoutItem( item, !!isOnlyPosition );
+  }, this);
+
+  // `_layout` always happens after `_shrink`, so it's safe to process the style
+  // queue here with styles from the shrink method.
+  this._processStyleQueue();
+
+  // Adjust the height of the container.
+  this._setContainerSize();
+};
+
+
+/**
+ * Calculates the position of the item and pushes it onto the style queue.
+ * @param {Element} item Element which is being positioned.
+ * @param {boolean} isOnlyPosition Whether to position the item, but with zero
+ *     opacity so that it can fade in later.
+ * @private
+ */
+Shuffle.prototype._layoutItem = function( item, isOnlyPosition ) {
+  var $item = $(item);
+  var itemData = $item.data();
+  var currPos = itemData.point;
+  var currScale = itemData.scale;
+  var itemSize = {
+    width: Shuffle._getOuterWidth( item, true ),
+    height: Shuffle._getOuterHeight( item, true )
+  };
+  var pos = this._getItemPosition( itemSize );
+
+  // If the item will not change its position, do not add it to the render
+  // queue. Transitions don't fire when setting a property to the same value.
+  if ( Point.equals(currPos, pos) && currScale === DEFAULT_SCALE ) {
+    return;
+  }
+
+  // Save data for shrink
+  itemData.point = pos;
+  itemData.scale = DEFAULT_SCALE;
+
+  this.styleQueue.push({
+    $item: $item,
+    point: pos,
+    scale: DEFAULT_SCALE,
+    opacity: isOnlyPosition ? 0 : 1,
+    skipTransition: isOnlyPosition,
+    callfront: function() {
+      if ( !isOnlyPosition ) {
+        $item.css( 'visibility', 'visible' );
+      }
+    },
+    callback: function() {
+      if ( isOnlyPosition ) {
+        $item.css( 'visibility', 'hidden' );
+      }
+    }
+  });
+};
+
+
+/**
+ * Determine the location of the next item, based on its size.
+ * @param {{width: number, height: number}} itemSize Object with width and height.
+ * @return {Point}
+ * @private
+ */
+Shuffle.prototype._getItemPosition = function( itemSize ) {
+  var columnSpan = this._getColumnSpan( itemSize.width, this.colWidth, this.cols );
+
+  var setY = this._getColumnSet( columnSpan, this.cols );
+
+  // Finds the index of the smallest number in the set.
+  var shortColumnIndex = this._getShortColumn( setY, this.buffer );
+
+  // Position the item
+  var point = new Point(
+    Math.round( this.colWidth * shortColumnIndex ),
+    Math.round( setY[shortColumnIndex] ));
+
+  // Update the columns array with the new values for each column.
+  // e.g. before the update the columns could be [250, 0, 0, 0] for an item
+  // which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0].
+  var setHeight = setY[shortColumnIndex] + itemSize.height;
+  var setSpan = this.cols + 1 - setY.length;
+  for ( var i = 0; i < setSpan; i++ ) {
+    this.positions[ shortColumnIndex + i ] = setHeight;
+  }
+
+  return point;
+};
+
+
+/**
+ * Determine the number of columns an items spans.
+ * @param {number} itemWidth Width of the item.
+ * @param {number} columnWidth Width of the column (includes gutter).
+ * @param {number} columns Total number of columns
+ * @return {number}
+ * @private
+ */
+Shuffle.prototype._getColumnSpan = function( itemWidth, columnWidth, columns ) {
+  var columnSpan = itemWidth / columnWidth;
+
+  // If the difference between the rounded column span number and the
+  // calculated column span number is really small, round the number to
+  // make it fit.
+  if ( Math.abs(Math.round( columnSpan ) - columnSpan ) < COLUMN_THRESHOLD ) {
+    // e.g. columnSpan = 4.0089945390298745
+    columnSpan = Math.round( columnSpan );
+  }
+
+  // Ensure the column span is not more than the amount of columns in the whole layout.
+  return Math.min( Math.ceil( columnSpan ), columns );
+};
+
+
+/**
+ * Retrieves the column set to use for placement.
+ * @param {number} columnSpan The number of columns this current item spans.
+ * @param {number} columns The total columns in the grid.
+ * @return {Array.<number>} An array of numbers represeting the column set.
+ * @private
+ */
+Shuffle.prototype._getColumnSet = function( columnSpan, columns ) {
+  // The item spans only one column.
+  if ( columnSpan === 1 ) {
+    return this.positions;
+
+  // The item spans more than one column, figure out how many different
+  // places it could fit horizontally.
+  // The group count is the number of places within the positions this block
+  // could fit, ignoring the current positions of items.
+  // Imagine a 2 column brick as the second item in a 4 column grid with
+  // 10px height each. Find the places it would fit:
+  // [10, 0, 0, 0]
+  //  |   |  |
+  //  *   *  *
+  //
+  // Then take the places which fit and get the bigger of the two:
+  // max([10, 0]), max([0, 0]), max([0, 0]) = [10, 0, 0]
+  //
+  // Next, find the first smallest number (the short column).
+  // [10, 0, 0]
+  //      |
+  //      *
+  //
+  // And that's where it should be placed!
+  } else {
+    var groupCount = columns + 1 - columnSpan;
+    var groupY = [];
+
+    // For how many possible positions for this item there are.
+    for ( var i = 0; i < groupCount; i++ ) {
+      // Find the bigger value for each place it could fit.
+      groupY[i] = arrayMax( this.positions.slice( i, i + columnSpan ) );
+    }
+
+    return groupY;
+  }
+};
+
+
+/**
+ * Find index of short column, the first from the left where this item will go.
+ *
+ * @param {Array.<number>} positions The array to search for the smallest number.
+ * @param {number} buffer Optional buffer which is very useful when the height
+ *     is a percentage of the width.
+ * @return {number} Index of the short column.
+ * @private
+ */
+Shuffle.prototype._getShortColumn = function( positions, buffer ) {
+  var minPosition = arrayMin( positions );
+  for (var i = 0, len = positions.length; i < len; i++) {
+    if ( positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer ) {
+      return i;
+    }
+  }
+  return 0;
+};
+
+
+/**
+ * Hides the elements that don't match our filter.
+ * @param {jQuery} $collection jQuery collection to shrink.
+ * @private
+ */
+Shuffle.prototype._shrink = function( $collection ) {
+  var $concealed = $collection || this._getConcealedItems();
+
+  each($concealed, function( item ) {
+    var $item = $(item);
+    var itemData = $item.data();
+
+    // Continuing would add a transitionend event listener to the element, but
+    // that listener would not execute because the transform and opacity would
+    // stay the same.
+    if ( itemData.scale === CONCEALED_SCALE ) {
+      return;
+    }
+
+    itemData.scale = CONCEALED_SCALE;
+
+    this.styleQueue.push({
+      $item: $item,
+      point: itemData.point,
+      scale : CONCEALED_SCALE,
+      opacity: 0,
+      callback: function() {
+        $item.css( 'visibility', 'hidden' );
+      }
+    });
+  }, this);
+};
+
+
+/**
+ * Resize handler.
+ * @private
+ */
+Shuffle.prototype._onResize = function() {
+  // If shuffle is disabled, destroyed, don't do anything
+  if ( !this.enabled || this.destroyed || this.isTransitioning ) {
+    return;
+  }
+
+  // Will need to check height in the future if it's layed out horizontaly
+  var containerWidth = Shuffle._getOuterWidth( this.element );
+
+  // containerWidth hasn't changed, don't do anything
+  if ( containerWidth === this.containerWidth ) {
+    return;
+  }
+
+  this.update();
+};
+
+
+/**
+ * Returns styles for either jQuery animate or transition.
+ * @param {Object} opts Transition options.
+ * @return {!Object} Transforms for transitions, left/top for animate.
+ * @private
+ */
+Shuffle.prototype._getStylesForTransition = function( opts ) {
+  var styles = {
+    opacity: opts.opacity
+  };
+
+  if ( this.supported ) {
+    styles[ TRANSFORM ] = Shuffle._getItemTransformString( opts.point, opts.scale );
+  } else {
+    styles.left = opts.point.x;
+    styles.top = opts.point.y;
+  }
+
+  return styles;
+};
+
+
+/**
+ * Transitions an item in the grid
+ *
+ * @param {Object} opts options.
+ * @param {jQuery} opts.$item jQuery object representing the current item.
+ * @param {Point} opts.point A point object with the x and y coordinates.
+ * @param {number} opts.scale Amount to scale the item.
+ * @param {number} opts.opacity Opacity of the item.
+ * @param {Function} opts.callback Complete function for the animation.
+ * @param {Function} opts.callfront Function to call before transitioning.
+ * @private
+ */
+Shuffle.prototype._transition = function( opts ) {
+  var styles = this._getStylesForTransition( opts );
+  this._startItemAnimation( opts.$item, styles, opts.callfront || $.noop, opts.callback || $.noop );
+};
+
+
+Shuffle.prototype._startItemAnimation = function( $item, styles, callfront, callback ) {
+  // Transition end handler removes its listener.
+  function handleTransitionEnd( evt ) {
+    // Make sure this event handler has not bubbled up from a child.
+    if ( evt.target === evt.currentTarget ) {
+      $( evt.target ).off( TRANSITIONEND, handleTransitionEnd );
+      callback();
+    }
+  }
+
+  callfront();
+
+  // Transitions are not set until shuffle has loaded to avoid the initial transition.
+  if ( !this.initialized ) {
+    $item.css( styles );
+    callback();
+    return;
+  }
+
+  // Use CSS Transforms if we have them
+  if ( this.supported ) {
+    $item.css( styles );
+    $item.on( TRANSITIONEND, handleTransitionEnd );
+
+  // Use jQuery to animate left/top
+  } else {
+    // Save the deferred object which jQuery returns.
+    var anim = $item.stop( true ).animate( styles, this.speed, 'swing', callback );
+    // Push the animation to the list of pending animations.
+    this._animations.push( anim.promise() );
+  }
+};
+
+
+/**
+ * Execute the styles gathered in the style queue. This applies styles to elements,
+ * triggering transitions.
+ * @param {boolean} noLayout Whether to trigger a layout event.
+ * @private
+ */
+Shuffle.prototype._processStyleQueue = function( noLayout ) {
+  var $transitions = $();
+
+  // Iterate over the queue and keep track of ones that use transitions.
+  each(this.styleQueue, function( transitionObj ) {
+    if ( transitionObj.skipTransition ) {
+      this._styleImmediately( transitionObj );
+    } else {
+      $transitions = $transitions.add( transitionObj.$item );
+      this._transition( transitionObj );
+    }
+  }, this);
+
+
+  if ( $transitions.length > 0 && this.initialized ) {
+    // Set flag that shuffle is currently in motion.
+    this.isTransitioning = true;
+
+    if ( this.supported ) {
+      this._whenCollectionDone( $transitions, TRANSITIONEND, this._movementFinished );
+
+    // The _transition function appends a promise to the animations array.
+    // When they're all complete, do things.
+    } else {
+      this._whenAnimationsDone( this._movementFinished );
+    }
+
+  // A call to layout happened, but none of the newly filtered items will
+  // change position. Asynchronously fire the callback here.
+  } else if ( !noLayout ) {
+    defer( this._layoutEnd, this );
+  }
+
+  // Remove everything in the style queue
+  this.styleQueue.length = 0;
+};
+
+
+/**
+ * Apply styles without a transition.
+ * @param {Object} opts Transitions options object.
+ * @private
+ */
+Shuffle.prototype._styleImmediately = function( opts ) {
+  Shuffle._skipTransition(opts.$item[0], function() {
+    opts.$item.css( this._getStylesForTransition( opts ) );
+  }, this);
+};
+
+Shuffle.prototype._movementFinished = function() {
+  this.isTransitioning = false;
+  this._layoutEnd();
+};
+
+Shuffle.prototype._layoutEnd = function() {
+  this._fire( Shuffle.EventType.LAYOUT );
+};
+
+Shuffle.prototype._addItems = function( $newItems, addToEnd, isSequential ) {
+  // Add classes and set initial positions.
+  this._initItems( $newItems );
+
+  // Add transition to each item.
+  this._setTransitions( $newItems );
+
+  // Update the list of
+  this.$items = this._getItems();
+
+  // Shrink all items (without transitions).
+  this._shrink( $newItems );
+  each(this.styleQueue, function( transitionObj ) {
+    transitionObj.skipTransition = true;
+  });
+
+  // Apply shrink positions, but do not cause a layout event.
+  this._processStyleQueue( true );
+
+  if ( addToEnd ) {
+    this._addItemsToEnd( $newItems, isSequential );
+  } else {
+    this.shuffle( this.lastFilter );
+  }
+};
+
+
+Shuffle.prototype._addItemsToEnd = function( $newItems, isSequential ) {
+  // Get ones that passed the current filter
+  var $passed = this._filter( null, $newItems );
+  var passed = $passed.get();
+
+  // How many filtered elements?
+  this._updateItemCount();
+
+  this._layout( passed, true );
+
+  if ( isSequential && this.supported ) {
+    this._setSequentialDelay( passed );
+  }
+
+  this._revealAppended( passed );
+};
+
+
+/**
+ * Triggers appended elements to fade in.
+ * @param {ArrayLike.<Element>} $newFilteredItems Collection of elements.
+ * @private
+ */
+Shuffle.prototype._revealAppended = function( newFilteredItems ) {
+  defer(function() {
+    each(newFilteredItems, function( el ) {
+      var $item = $( el );
+      this._transition({
+        $item: $item,
+        opacity: 1,
+        point: $item.data('point'),
+        scale: DEFAULT_SCALE
+      });
+    }, this);
+
+    this._whenCollectionDone($(newFilteredItems), TRANSITIONEND, function() {
+      $(newFilteredItems).css( TRANSITION_DELAY, '0ms' );
+      this._movementFinished();
+    });
+  }, this, this.revealAppendedDelay);
+};
+
+
+/**
+ * Execute a function when an event has been triggered for every item in a collection.
+ * @param {jQuery} $collection Collection of elements.
+ * @param {string} eventName Event to listen for.
+ * @param {Function} callback Callback to execute when they're done.
+ * @private
+ */
+Shuffle.prototype._whenCollectionDone = function( $collection, eventName, callback ) {
+  var done = 0;
+  var items = $collection.length;
+  var self = this;
+
+  function handleEventName( evt ) {
+    if ( evt.target === evt.currentTarget ) {
+      $( evt.target ).off( eventName, handleEventName );
+      done++;
+
+      // Execute callback if all items have emitted the correct event.
+      if ( done === items ) {
+        callback.call( self );
+      }
+    }
+  }
+
+  // Bind the event to all items.
+  $collection.on( eventName, handleEventName );
+};
+
+
+/**
+ * Execute a callback after jQuery `animate` for a collection has finished.
+ * @param {Function} callback Callback to execute when they're done.
+ * @private
+ */
+Shuffle.prototype._whenAnimationsDone = function( callback ) {
+  $.when.apply( null, this._animations ).always( $.proxy( function() {
+    this._animations.length = 0;
+    callback.call( this );
+  }, this ));
+};
+
+
+/**
+ * Public Methods
+ */
+
+/**
+ * The magic. This is what makes the plugin 'shuffle'
+ * @param {string|Function} [category] Category to filter by. Can be a function
+ * @param {Object} [sortObj] A sort object which can sort the filtered set
+ */
+Shuffle.prototype.shuffle = function( category, sortObj ) {
+  if ( !this.enabled || this.isTransitioning ) {
+    return;
+  }
+
+  if ( !category ) {
+    category = ALL_ITEMS;
+  }
+
+  this._filter( category );
+
+  // How many filtered elements?
+  this._updateItemCount();
+
+  // Shrink each concealed item
+  this._shrink();
+
+  // Update transforms on .filtered elements so they will animate to their new positions
+  this.sort( sortObj );
+};
+
+
+/**
+ * Gets the .filtered elements, sorts them, and passes them to layout.
+ * @param {Object} opts the options object for the sorted plugin
+ */
+Shuffle.prototype.sort = function( opts ) {
+  if ( this.enabled && !this.isTransitioning ) {
+    this._resetCols();
+
+    var sortOptions = opts || this.lastSort;
+    var items = this._getFilteredItems().sorted( sortOptions );
+
+    this._layout( items );
+
+    this.lastSort = sortOptions;
+  }
+};
+
+
+/**
+ * Reposition everything.
+ * @param {boolean} isOnlyLayout If true, column and gutter widths won't be
+ *     recalculated.
+ */
+Shuffle.prototype.update = function( isOnlyLayout ) {
+  if ( this.enabled && !this.isTransitioning ) {
+
+    if ( !isOnlyLayout ) {
+      // Get updated colCount
+      this._setColumns();
+    }
+
+    // Layout items
+    this.sort();
+  }
+};
+
+
+/**
+ * Use this instead of `update()` if you don't need the columns and gutters updated
+ * Maybe an image inside `shuffle` loaded (and now has a height), which means calculations
+ * could be off.
+ */
+Shuffle.prototype.layout = function() {
+  this.update( true );
+};
+
+
+/**
+ * New items have been appended to shuffle. Fade them in sequentially
+ * @param {jQuery} $newItems jQuery collection of new items
+ * @param {boolean} [addToEnd=false] If true, new items will be added to the end / bottom
+ *     of the items. If not true, items will be mixed in with the current sort order.
+ * @param {boolean} [isSequential=true] If false, new items won't sequentially fade in
+ */
+Shuffle.prototype.appended = function( $newItems, addToEnd, isSequential ) {
+  this._addItems( $newItems, addToEnd === true, isSequential !== false );
+};
+
+
+/**
+ * Disables shuffle from updating dimensions and layout on resize
+ */
+Shuffle.prototype.disable = function() {
+  this.enabled = false;
+};
+
+
+/**
+ * Enables shuffle again
+ * @param {boolean} [isUpdateLayout=true] if undefined, shuffle will update columns and gutters
+ */
+Shuffle.prototype.enable = function( isUpdateLayout ) {
+  this.enabled = true;
+  if ( isUpdateLayout !== false ) {
+    this.update();
+  }
+};
+
+
+/**
+ * Remove 1 or more shuffle items
+ * @param {jQuery} $collection A jQuery object containing one or more element in shuffle
+ * @return {Shuffle} The shuffle object
+ */
+Shuffle.prototype.remove = function( $collection ) {
+
+  // If this isn't a jquery object, exit
+  if ( !$collection.length || !$collection.jquery ) {
+    return;
+  }
+
+  function handleRemoved() {
+    // Remove the collection in the callback
+    $collection.remove();
+
+    // Update things now that elements have been removed.
+    this.$items = this._getItems();
+    this._updateItemCount();
+
+    this._fire( Shuffle.EventType.REMOVED, [ $collection, this ] );
+
+    // Let it get garbage collected
+    $collection = null;
+  }
+
+  // Hide collection first.
+  this._toggleFilterClasses( $(), $collection );
+  this._shrink( $collection );
+
+  this.sort();
+
+  this.$el.one( Shuffle.EventType.LAYOUT + '.' + SHUFFLE, $.proxy( handleRemoved, this ) );
+};
+
+
+/**
+ * Destroys shuffle, removes events, styles, and classes
+ */
+Shuffle.prototype.destroy = function() {
+  // If there is more than one shuffle instance on the page,
+  // removing the resize handler from the window would remove them
+  // all. This is why a unique value is needed.
+  $window.off('.' + this.unique);
+
+  // Reset container styles
+  this.$el
+      .removeClass( SHUFFLE )
+      .removeAttr('style')
+      .removeData( SHUFFLE );
+
+  // Reset individual item styles
+  this.$items
+      .removeAttr('style')
+      .removeData('point')
+      .removeData('scale')
+      .removeClass([
+        Shuffle.ClassName.CONCEALED,
+        Shuffle.ClassName.FILTERED,
+        Shuffle.ClassName.SHUFFLE_ITEM
+      ].join(' '));
+
+  // Null DOM references
+  this.$items = null;
+  this.$el = null;
+  this.sizer = null;
+  this.element = null;
+
+  // Set a flag so if a debounced resize has been triggered,
+  // it can first check if it is actually destroyed and not doing anything
+  this.destroyed = true;
+};
+
+
+// Plugin definition
+$.fn.shuffle = function( opts ) {
+  var args = Array.prototype.slice.call( arguments, 1 );
+  return this.each(function() {
+    var $this = $( this );
+    var shuffle = $this.data( SHUFFLE );
+
+    // If we don't have a stored shuffle, make a new one and save it
+    if ( !shuffle ) {
+      shuffle = new Shuffle( this, opts );
+      $this.data( SHUFFLE, shuffle );
+    } else if ( typeof opts === 'string' && shuffle[ opts ] ) {
+      shuffle[ opts ].apply( shuffle, args );
+    }
+  });
+};
+
+
+// http://stackoverflow.com/a/962890/373422
+function randomize( array ) {
+  var tmp, current;
+  var top = array.length;
+
+  if ( !top ) {
+    return array;
+  }
+
+  while ( --top ) {
+    current = Math.floor( Math.random() * (top + 1) );
+    tmp = array[ current ];
+    array[ current ] = array[ top ];
+    array[ top ] = tmp;
+  }
+
+  return array;
+}
+
+
+// You can return `undefined` from the `by` function to revert to DOM order
+// This plugin does NOT return a jQuery object. It returns a plain array because
+// jQuery sorts everything in DOM order.
+$.fn.sorted = function(options) {
+  var opts = $.extend({}, $.fn.sorted.defaults, options);
+  var arr = this.get();
+  var revert = false;
+
+  if ( !arr.length ) {
+    return [];
+  }
+
+  if ( opts.randomize ) {
+    return randomize( arr );
+  }
+
+  // Sort the elements by the opts.by function.
+  // If we don't have opts.by, default to DOM order
+  if ( $.isFunction( opts.by ) ) {
+    arr.sort(function(a, b) {
+
+      // Exit early if we already know we want to revert
+      if ( revert ) {
+        return 0;
+      }
+
+      var valA = opts.by($(a));
+      var valB = opts.by($(b));
+
+      // If both values are undefined, use the DOM order
+      if ( valA === undefined && valB === undefined ) {
+        revert = true;
+        return 0;
+      }
+
+      if ( valA < valB || valA === 'sortFirst' || valB === 'sortLast' ) {
+        return -1;
+      }
+
+      if ( valA > valB || valA === 'sortLast' || valB === 'sortFirst' ) {
+        return 1;
+      }
+
+      return 0;
+    });
+  }
+
+  // Revert to the original array if necessary
+  if ( revert ) {
+    return this.get();
+  }
+
+  if ( opts.reverse ) {
+    arr.reverse();
+  }
+
+  return arr;
+};
+
+
+$.fn.sorted.defaults = {
+  reverse: false, // Use array.reverse() to reverse the results
+  by: null, // Sorting function
+  randomize: false // If true, this will skip the sorting and return a randomized order in the array
+};
+
+return Shuffle;
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/js/toc.js
----------------------------------------------------------------------
diff --git a/site/js/toc.js b/site/js/toc.js
new file mode 100644
index 0000000..a54d172
--- /dev/null
+++ b/site/js/toc.js
@@ -0,0 +1,82 @@
+// https://github.com/ghiculescu/jekyll-table-of-contents
+(function($){
+  $.fn.toc = function(options) {
+    var defaults = {
+      noBackToTopLinks: false,
+      title: '',
+      minimumHeaders: 3,
+      headers: 'h1, h2, h3, h4',
+      listType: 'ol', // values: [ol|ul]
+      showEffect: 'show', // values: [show|slideDown|fadeIn|none]
+      showSpeed: 'slow' // set to 0 to deactivate effect
+    },
+    settings = $.extend(defaults, options);
+
+    var headers = $(settings.headers).filter(function() {
+      // get all headers with an ID
+      var previousSiblingName = $(this).prev().attr( "name" );
+      if (!this.id && previousSiblingName) {
+        this.id = $(this).attr( "id", previousSiblingName.replace(/\./g, "-") );
+      }
+      return this.id;
+    }), output = $(this);
+    if (!headers.length || headers.length < settings.minimumHeaders || !output.length) {
+      return;
+    }
+
+    if (0 === settings.showSpeed) {
+      settings.showEffect = 'none';
+    }
+
+    var render = {
+      show: function() { output.hide().html(html).show(settings.showSpeed); },
+      slideDown: function() { output.hide().html(html).slideDown(settings.showSpeed); },
+      fadeIn: function() { output.hide().html(html).fadeIn(settings.showSpeed); },
+      none: function() { output.html(html); }
+    };
+
+    var get_level = function(ele) { return parseInt(ele.nodeName.replace("H", ""), 10); }
+    var highest_level = headers.map(function(_, ele) { return get_level(ele); }).get().sort()[0];
+    var return_to_top = '<i class="icon-arrow-up back-to-top"> </i>';
+
+    var level = get_level(headers[0]),
+      this_level,
+      html = settings.title + " <"+settings.listType+">";
+    headers.on('click', function() {
+      if (!settings.noBackToTopLinks) {
+        window.location.hash = this.id;
+      }
+    })
+    .addClass('clickable-header')
+    .each(function(_, header) {
+      this_level = get_level(header);
+      if (!settings.noBackToTopLinks && this_level === highest_level) {
+        $(header).addClass('top-level-header').after(return_to_top);
+      }
+      if (this_level === level) // same level as before; same indenting
+        html += "<li><a href='#" + header.id + "'>" + header.innerHTML + "</a>";
+      else if (this_level <= level){ // higher level than before; end parent ol
+        for(i = this_level; i < level; i++) {
+          html += "</li></"+settings.listType+">"
+        }
+        html += "<li><a href='#" + header.id + "'>" + header.innerHTML + "</a>";
+      }
+      else if (this_level > level) { // lower level than before; expand the previous to contain a ol
+        for(i = this_level; i > level; i--) {
+          html += "<"+settings.listType+"><li>"
+        }
+        html += "<a href='#" + header.id + "'>" + header.innerHTML + "</a>";
+      }
+      level = this_level; // update for the next one
+    });
+    html += "</"+settings.listType+">";
+    if (!settings.noBackToTopLinks) {
+      $(document).on('click', '.back-to-top', function() {
+        $(window).scrollTop(0);
+        window.location.hash = '';
+      });
+    }
+
+    render[settings.showEffect]();
+  };
+})(jQuery);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/mydoc/committers.md
----------------------------------------------------------------------
diff --git a/site/mydoc/committers.md b/site/mydoc/committers.md
new file mode 100644
index 0000000..8f190c4
--- /dev/null
+++ b/site/mydoc/committers.md
@@ -0,0 +1,18 @@
+---
+title: Committers  
+description: Commit Activity and How to Become a Committer
+---
+
+# Commit Activity
+
+To see commit activity for Quarks, click [here](https://github.com/quarks-edge/quarks/pulse).
+
+# How to Become a Committer
+
+You can become a committer by contributing to Quarks. Qualifications for a new committer include:
+
+* **Sustained Contributions**: Potential committers should have a history of contributions to Quarks. They will create pull requests over a period of time.  
+
+* **Quality of Contributions**: Potential committers should submit code that adds value to Quarks, including tests and documentation as needed. They should comment in a positive way on issues and pull requests, providing guidance and input to improve Quarks.
+
+* **Community Involvement**: Committers should participate in discussions in a positive way, triage and fix bugs, and interact with users who submit questions. They will remain courteous, and helpful, and encourage new members to join the Quarks community.

http://git-wip-us.apache.org/repos/asf/incubator-quarks-website/blob/9d3aa00d/site/mydoc/common-quarks-operations.md
----------------------------------------------------------------------
diff --git a/site/mydoc/common-quarks-operations.md b/site/mydoc/common-quarks-operations.md
new file mode 100644
index 0000000..5f2f466
--- /dev/null
+++ b/site/mydoc/common-quarks-operations.md
@@ -0,0 +1,68 @@
+---
+title: Common Quarks Operations
+---
+
+# Common Quarks Operations
+In the first [getting started guide](quarks-getting-started), we covered a "hello world" Quarks application where we read from a device's simulated temperature sensor. Yet Quarks supports more operations than simple filtering. Data analysis and streaming require a suite of functionality, the most important components of which will be outlined below.
+
+## TStream.map()
+TStream.map() is arguably the most used method in the Quarks API. Its two main purposes are to perform stateful or stateless operations on a stream's tuples, and to produce a TStream with tuples of a different type from that of the calling stream.
+
+<br>
+
+#### Changing a TStream's Tuple Type
+In addition to filtering tuples, TStreams support operations that *transform* tuples from one Java type to another by invoking the TStream.map() method.
+
+<img src="images/Map_Type_Change.jpg" style="width:750px;height:150px;">
+
+This is useful in cases such as calculating the floating point average of a list of Integers, or tokenizing a Java String into a list of Strings. To demonstrate this, let's say we have a TStream which contains a few lines, each of which contains multiple words:
+
+```java
+    TStream<String> lines = topology.strings(
+            "this is a line",
+            "this is another line",
+            "there are three lines now",
+            "and now four"
+        );
+```
+
+We then want to print the third word in each line. The best way to do this is to convert each line to a list of Strings by tokenizing them. We can do this in one line of code with the TStream.map() method:
+
+```java
+    TStream<List<String> > wordsInLine = lines.map(tuple -> Arrays.asList(tuple.split(" ")));
+```
+
+Since each tuple is now a list of strings, the *wordsInLine* stream is of type List<String>. As you can see, the map() method has the ability to change the type of the TStream. Finally, we can use the *wordsInLine* stream to print the third word in each line.
+
+```java
+    wordsInLine.sink(list -> System.out.println(list.get(2)));
+```
+
+As mentioned in the [getting started guide](quarks-getting-started), a TStream can be parameterized to any serializable Java type, including ones created by the user.
+
+<br>
+
+
+#### Performing Stateful Operations
+
+In all previous examples, the operations performed on a TStream have been stateless; keeping track of information over multiple invocations of the same operation has not been necessary. What if we want to keep track of the number of Strings sent over a stream? To do this, we need our TStream.map() method to contain a counter as state.
+
+<img src="images/Map_Stateful.jpg" style="width:750px;height:150px;">
+
+This can be achieved by creating an anonymous Function class, and giving it the required fields.
+
+```java
+	TStream<String> streamOfStrings = ...;
+    TStream<Integer> counts = streamOfStrings.map(new Function<String, Integer>(){
+            int count = 0;
+            @Override
+            public Integer apply(String arg0) {
+                count = count + 1;
+                return count;
+            }
+        });
+```
+
+The *count* field will now contain the number of Strings which were sent over streamOfStrings. Although this is a simple example, the anonymous Function passed to TStream.map() can contain any kind of state! This could be a HashMap<K, T>, a running list of tuples, or any serializable Java type. The state will be maintained throughout the entire runtime of your application.
+
+<br>