META-INF.resources.bower_components.isotope.jquery.isotope.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jwebmp-jqui-vertical-timeline Show documentation
Show all versions of jwebmp-jqui-vertical-timeline Show documentation
The JWebSwing JQuery Vertical Timeline
/**
* Isotope v1.5.26
* An exquisite jQuery plugin for magical layouts
* http://isotope.metafizzy.co
*
* Commercial use requires one-time purchase of a commercial license
* http://isotope.metafizzy.co/docs/license.html
*
* Non-commercial use is licensed under the MIT License
*
* Copyright 2014 Metafizzy
*/
/*jshint asi: true, browser: true, curly: true, eqeqeq: true, forin: false, immed: false, newcap: true, noempty: true, strict: true, undef: true */
/*global jQuery: false */
(function (window, $, undefined) {
'use strict';
// get global vars
var document = window.document;
var docElem = document.documentElement;
var Modernizr = window.Modernizr;
// helper function
var capitalize = function (str) {
return str.charAt(0).toUpperCase() + str.slice(1);
};
// ========================= getStyleProperty by kangax ===============================
// http://perfectionkills.com/feature-testing-css-properties/
var prefixes = 'Moz Webkit O Ms'.split(' ');
var getStyleProperty = function (propName) {
var style = docElem.style,
prefixed;
// test standard property first
if (typeof style[propName] === 'string') {
return propName;
}
// capitalize
propName = capitalize(propName);
// test vendor specific properties
for (var i = 0, len = prefixes.length; i < len; i++) {
prefixed = prefixes[i] + propName;
if (typeof style[prefixed] === 'string') {
return prefixed;
}
}
};
var transformProp = getStyleProperty('transform'),
transitionProp = getStyleProperty('transitionProperty');
// ========================= miniModernizr ===============================
// <3<3<3 and thanks to Faruk and Paul for doing the heavy lifting
/*!
* Modernizr v1.6ish: miniModernizr for Isotope
* http://www.modernizr.com
*
* Developed by:
* - Faruk Ates http://farukat.es/
* - Paul Irish http://paulirish.com/
*
* Copyright (c) 2009-2010
* Dual-licensed under the BSD or MIT licenses.
* http://www.modernizr.com/license/
*/
/*
* This version whittles down the script just to check support for
* CSS transitions, transforms, and 3D transforms.
*/
var tests = {
csstransforms: function () {
return !!transformProp;
},
csstransforms3d: function () {
var test = !!getStyleProperty('perspective');
// double check for Chrome's false positive
if (test && 'webkitPerspective' in docElem.style) {
var $style = $('').appendTo('head'),
$div = $('').appendTo('html');
test = $div.height() === 3;
$div.remove();
$style.remove();
}
return test;
},
csstransitions: function () {
return !!transitionProp;
}
};
var testName;
if (Modernizr) {
// if there's a previous Modernzir, check if there are necessary tests
for (testName in tests) {
if (!Modernizr.hasOwnProperty(testName)) {
// if test hasn't been run, use addTest to run it
Modernizr.addTest(testName, tests[testName]);
}
}
} else {
// or create new mini Modernizr that just has the 3 tests
Modernizr = window.Modernizr = {
_version: '1.6ish: miniModernizr for Isotope'
};
var classes = ' ';
var result;
// Run through tests
for (testName in tests) {
result = tests[testName]();
Modernizr[testName] = result;
classes += ' ' + ( result ? '' : 'no-' ) + testName;
}
// Add the new classes to the element.
$('html').addClass(classes);
}
// ========================= isoTransform ===============================
/**
* provides hooks for .css({ scale: value, translate: [x, y] })
* Progressively enhanced CSS transforms
* Uses hardware accelerated 3D transforms for Safari
* or falls back to 2D transforms.
*/
if (Modernizr.csstransforms) {
// i.e. transformFnNotations.scale(0.5) >> 'scale3d( 0.5, 0.5, 1)'
var transformFnNotations = Modernizr.csstransforms3d ?
{ // 3D transform functions
translate: function (position) {
return 'translate3d(' + position[0] + 'px, ' + position[1] + 'px, 0) ';
},
scale: function (scale) {
return 'scale3d(' + scale + ', ' + scale + ', 1) ';
}
} :
{ // 2D transform functions
translate: function (position) {
return 'translate(' + position[0] + 'px, ' + position[1] + 'px) ';
},
scale: function (scale) {
return 'scale(' + scale + ') ';
}
}
;
var setIsoTransform = function (elem, name, value) {
// unpack current transform data
var data = $.data(elem, 'isoTransform') || {},
newData = {},
fnName,
transformObj = {},
transformValue;
// i.e. newData.scale = 0.5
newData[name] = value;
// extend new value over current data
$.extend(data, newData);
for (fnName in data) {
transformValue = data[fnName];
transformObj[fnName] = transformFnNotations[fnName](transformValue);
}
// get proper order
// ideally, we could loop through this give an array, but since we only have
// a couple transforms we're keeping track of, we'll do it like so
var translateFn = transformObj.translate || '',
scaleFn = transformObj.scale || '',
// sorting so translate always comes first
valueFns = translateFn + scaleFn;
// set data back in elem
$.data(elem, 'isoTransform', data);
// set name to vendor specific property
elem.style[transformProp] = valueFns;
};
// ==================== scale ===================
$.cssNumber.scale = true;
$.cssHooks.scale = {
set: function (elem, value) {
// uncomment this bit if you want to properly parse strings
// if ( typeof value === 'string' ) {
// value = parseFloat( value );
// }
setIsoTransform(elem, 'scale', value);
},
get: function (elem, computed) {
var transform = $.data(elem, 'isoTransform');
return transform && transform.scale ? transform.scale : 1;
}
};
$.fx.step.scale = function (fx) {
$.cssHooks.scale.set(fx.elem, fx.now + fx.unit);
};
// ==================== translate ===================
$.cssNumber.translate = true;
$.cssHooks.translate = {
set: function (elem, value) {
// uncomment this bit if you want to properly parse strings
// if ( typeof value === 'string' ) {
// value = value.split(' ');
// }
//
// var i, val;
// for ( i = 0; i < 2; i++ ) {
// val = value[i];
// if ( typeof val === 'string' ) {
// val = parseInt( val );
// }
// }
setIsoTransform(elem, 'translate', value);
},
get: function (elem, computed) {
var transform = $.data(elem, 'isoTransform');
return transform && transform.translate ? transform.translate : [0, 0];
}
};
}
// ========================= get transition-end event ===============================
var transitionEndEvent, transitionDurProp;
if (Modernizr.csstransitions) {
transitionEndEvent = {
WebkitTransitionProperty: 'webkitTransitionEnd', // webkit
MozTransitionProperty: 'transitionend',
OTransitionProperty: 'oTransitionEnd otransitionend',
transitionProperty: 'transitionend'
}[transitionProp];
transitionDurProp = getStyleProperty('transitionDuration');
}
// ========================= smartresize ===============================
/*
* smartresize: debounced resize event for jQuery
*
* latest version and complete README available on Github:
* https://github.com/louisremi/jquery.smartresize.js
*
* Copyright 2011 @louis_remi
* Licensed under the MIT license.
*/
var $event = $.event,
dispatchMethod = $.event.handle ? 'handle' : 'dispatch',
resizeTimeout;
$event.special.smartresize = {
setup: function () {
$(this).bind("resize", $event.special.smartresize.handler);
},
teardown: function () {
$(this).unbind("resize", $event.special.smartresize.handler);
},
handler: function (event, execAsap) {
// Save the context
var context = this,
args = arguments;
// set correct event type
event.type = "smartresize";
if (resizeTimeout) {
clearTimeout(resizeTimeout);
}
resizeTimeout = setTimeout(function () {
$event[dispatchMethod].apply(context, args);
}, execAsap === "execAsap" ? 0 : 100);
}
};
$.fn.smartresize = function (fn) {
return fn ? this.bind("smartresize", fn) : this.trigger("smartresize", ["execAsap"]);
};
// ========================= Isotope ===============================
// our "Widget" object constructor
$.Isotope = function (options, element, callback) {
this.element = $(element);
this._create(options);
this._init(callback);
};
// styles of container element we want to keep track of
var isoContainerStyles = ['width', 'height'];
var $window = $(window);
$.Isotope.settings = {
resizable: true,
layoutMode: 'masonry',
containerClass: 'isotope',
itemClass: 'isotope-item',
hiddenClass: 'isotope-hidden',
hiddenStyle: {opacity: 0, scale: 0.001},
visibleStyle: {opacity: 1, scale: 1},
containerStyle: {
position: 'relative',
overflow: 'hidden'
},
animationEngine: 'best-available',
animationOptions: {
queue: false,
duration: 800
},
sortBy: 'original-order',
sortAscending: true,
resizesContainer: true,
transformsEnabled: true,
itemPositionDataEnabled: false
};
$.Isotope.prototype = {
// sets up widget
_create: function (options) {
this.options = $.extend({}, $.Isotope.settings, options);
this.styleQueue = [];
this.elemCount = 0;
// get original styles in case we re-apply them in .destroy()
var elemStyle = this.element[0].style;
this.originalStyle = {};
// keep track of container styles
var containerStyles = isoContainerStyles.slice(0);
for (var prop in this.options.containerStyle) {
containerStyles.push(prop);
}
for (var i = 0, len = containerStyles.length; i < len; i++) {
prop = containerStyles[i];
this.originalStyle[prop] = elemStyle[prop] || '';
}
// apply container style from options
this.element.css(this.options.containerStyle);
this._updateAnimationEngine();
this._updateUsingTransforms();
// sorting
var originalOrderSorter = {
'original-order': function ($elem, instance) {
instance.elemCount++;
return instance.elemCount;
},
random: function () {
return Math.random();
}
};
this.options.getSortData = $.extend(this.options.getSortData, originalOrderSorter);
// need to get atoms
this.reloadItems();
// get top left position of where the bricks should be
this.offset = {
left: parseInt(( this.element.css('padding-left') || 0 ), 10),
top: parseInt(( this.element.css('padding-top') || 0 ), 10)
};
// add isotope class first time around
var instance = this;
setTimeout(function () {
instance.element.addClass(instance.options.containerClass);
}, 0);
// bind resize method
if (this.options.resizable) {
$window.bind('smartresize.isotope', function () {
instance.resize();
});
}
// dismiss all click events from hidden events
this.element.delegate('.' + this.options.hiddenClass, 'click', function () {
return false;
});
},
_getAtoms: function ($elems) {
var selector = this.options.itemSelector,
// filter & find
$atoms = selector ? $elems.filter(selector).add($elems.find(selector)) : $elems,
// base style for atoms
atomStyle = {position: 'absolute'};
// filter out text nodes
$atoms = $atoms.filter(function (i, atom) {
return atom.nodeType === 1;
});
if (this.usingTransforms) {
atomStyle.left = 0;
atomStyle.top = 0;
}
$atoms.css(atomStyle).addClass(this.options.itemClass);
this.updateSortData($atoms, true);
return $atoms;
},
// _init fires when your instance is first created
// (from the constructor above), and when you
// attempt to initialize the widget again (by the bridge)
// after it has already been initialized.
_init: function (callback) {
this.$filteredAtoms = this._filter(this.$allAtoms);
this._sort();
this.reLayout(callback);
},
option: function (opts) {
// change options AFTER initialization:
// signature: $('#foo').bar({ cool:false });
if ($.isPlainObject(opts)) {
this.options = $.extend(true, this.options, opts);
// trigger _updateOptionName if it exists
var updateOptionFn;
for (var optionName in opts) {
updateOptionFn = '_update' + capitalize(optionName);
if (this[updateOptionFn]) {
this[updateOptionFn]();
}
}
}
},
// ====================== updaters ====================== //
// kind of like setters
_updateAnimationEngine: function () {
var animationEngine = this.options.animationEngine.toLowerCase().replace(/[ _\-]/g, '');
var isUsingJQueryAnimation;
// set applyStyleFnName
switch (animationEngine) {
case 'css' :
case 'none' :
isUsingJQueryAnimation = false;
break;
case 'jquery' :
isUsingJQueryAnimation = true;
break;
default : // best available
isUsingJQueryAnimation = !Modernizr.csstransitions;
}
this.isUsingJQueryAnimation = isUsingJQueryAnimation;
this._updateUsingTransforms();
},
_updateTransformsEnabled: function () {
this._updateUsingTransforms();
},
_updateUsingTransforms: function () {
var usingTransforms = this.usingTransforms = this.options.transformsEnabled &&
Modernizr.csstransforms && Modernizr.csstransitions && !this.isUsingJQueryAnimation;
// prevent scales when transforms are disabled
if (!usingTransforms) {
delete this.options.hiddenStyle.scale;
delete this.options.visibleStyle.scale;
}
this.getPositionStyles = usingTransforms ? this._translate : this._positionAbs;
},
// ====================== Filtering ======================
_filter: function ($atoms) {
var filter = this.options.filter === '' ? '*' : this.options.filter;
if (!filter) {
return $atoms;
}
var hiddenClass = this.options.hiddenClass,
hiddenSelector = '.' + hiddenClass,
$hiddenAtoms = $atoms.filter(hiddenSelector),
$atomsToShow = $hiddenAtoms;
if (filter !== '*') {
$atomsToShow = $hiddenAtoms.filter(filter);
var $atomsToHide = $atoms.not(hiddenSelector).not(filter).addClass(hiddenClass);
this.styleQueue.push({$el: $atomsToHide, style: this.options.hiddenStyle});
}
this.styleQueue.push({$el: $atomsToShow, style: this.options.visibleStyle});
$atomsToShow.removeClass(hiddenClass);
return $atoms.filter(filter);
},
// ====================== Sorting ======================
updateSortData: function ($atoms, isIncrementingElemCount) {
var instance = this,
getSortData = this.options.getSortData,
$this, sortData;
$atoms.each(function () {
$this = $(this);
sortData = {};
// get value for sort data based on fn( $elem ) passed in
for (var key in getSortData) {
if (!isIncrementingElemCount && key === 'original-order') {
// keep original order original
sortData[key] = $.data(this, 'isotope-sort-data')[key];
} else {
sortData[key] = getSortData[key]($this, instance);
}
}
// apply sort data to element
$.data(this, 'isotope-sort-data', sortData);
});
},
// used on all the filtered atoms
_sort: function () {
var sortBy = this.options.sortBy,
getSorter = this._getSorter,
sortDir = this.options.sortAscending ? 1 : -1,
sortFn = function (alpha, beta) {
var a = getSorter(alpha, sortBy),
b = getSorter(beta, sortBy);
// fall back to original order if data matches
if (a === b && sortBy !== 'original-order') {
a = getSorter(alpha, 'original-order');
b = getSorter(beta, 'original-order');
}
return ( ( a > b ) ? 1 : ( a < b ) ? -1 : 0 ) * sortDir;
};
this.$filteredAtoms.sort(sortFn);
},
_getSorter: function (elem, sortBy) {
return $.data(elem, 'isotope-sort-data')[sortBy];
},
// ====================== Layout Helpers ======================
_translate: function (x, y) {
return {translate: [x, y]};
},
_positionAbs: function (x, y) {
return {left: x, top: y};
},
_pushPosition: function ($elem, x, y) {
x = Math.round(x + this.offset.left);
y = Math.round(y + this.offset.top);
var position = this.getPositionStyles(x, y);
this.styleQueue.push({$el: $elem, style: position});
if (this.options.itemPositionDataEnabled) {
$elem.data('isotope-item-position', {x: x, y: y});
}
},
// ====================== General Layout ======================
// used on collection of atoms (should be filtered, and sorted before )
// accepts atoms-to-be-laid-out to start with
layout: function ($elems, callback) {
var layoutMode = this.options.layoutMode;
// layout logic
this['_' + layoutMode + 'Layout']($elems);
// set the size of the container
if (this.options.resizesContainer) {
var containerStyle = this['_' + layoutMode + 'GetContainerSize']();
this.styleQueue.push({$el: this.element, style: containerStyle});
}
this._processStyleQueue($elems, callback);
this.isLaidOut = true;
},
_processStyleQueue: function ($elems, callback) {
// are we animating the layout arrangement?
// use plugin-ish syntax for css or animate
var styleFn = !this.isLaidOut ? 'css' : (
this.isUsingJQueryAnimation ? 'animate' : 'css'
),
animOpts = this.options.animationOptions,
onLayout = this.options.onLayout,
objStyleFn, processor,
triggerCallbackNow, callbackFn;
// default styleQueue processor, may be overwritten down below
processor = function (i, obj) {
obj.$el[styleFn](obj.style, animOpts);
};
if (this._isInserting && this.isUsingJQueryAnimation) {
// if using styleQueue to insert items
processor = function (i, obj) {
// only animate if it not being inserted
objStyleFn = obj.$el.hasClass('no-transition') ? 'css' : styleFn;
obj.$el[objStyleFn](obj.style, animOpts);
};
} else if (callback || onLayout || animOpts.complete) {
// has callback
var isCallbackTriggered = false,
// array of possible callbacks to trigger
callbacks = [callback, onLayout, animOpts.complete],
instance = this;
triggerCallbackNow = true;
// trigger callback only once
callbackFn = function () {
if (isCallbackTriggered) {
return;
}
var hollaback;
for (var i = 0, len = callbacks.length; i < len; i++) {
hollaback = callbacks[i];
if (typeof hollaback === 'function') {
hollaback.call(instance.element, $elems, instance);
}
}
isCallbackTriggered = true;
};
if (this.isUsingJQueryAnimation && styleFn === 'animate') {
// add callback to animation options
animOpts.complete = callbackFn;
triggerCallbackNow = false;
} else if (Modernizr.csstransitions) {
// detect if first item has transition
var i = 0,
firstItem = this.styleQueue[0],
testElem = firstItem && firstItem.$el,
styleObj;
// get first non-empty jQ object
while (!testElem || !testElem.length) {
styleObj = this.styleQueue[i++];
// HACK: sometimes styleQueue[i] is undefined
if (!styleObj) {
return;
}
testElem = styleObj.$el;
}
// get transition duration of the first element in that object
// yeah, this is inexact
var duration = parseFloat(getComputedStyle(testElem[0])[transitionDurProp]);
if (duration > 0) {
processor = function (i, obj) {
obj.$el[styleFn](obj.style, animOpts)
// trigger callback at transition end
.one(transitionEndEvent, callbackFn);
};
triggerCallbackNow = false;
}
}
}
// process styleQueue
$.each(this.styleQueue, processor);
if (triggerCallbackNow) {
callbackFn();
}
// clear out queue for next time
this.styleQueue = [];
},
resize: function () {
if (this['_' + this.options.layoutMode + 'ResizeChanged']()) {
this.reLayout();
}
},
reLayout: function (callback) {
this['_' + this.options.layoutMode + 'Reset']();
this.layout(this.$filteredAtoms, callback);
},
// ====================== Convenience methods ======================
// ====================== Adding items ======================
// adds a jQuery object of items to a isotope container
addItems: function ($content, callback) {
var $newAtoms = this._getAtoms($content);
// add new atoms to atoms pools
this.$allAtoms = this.$allAtoms.add($newAtoms);
if (callback) {
callback($newAtoms);
}
},
// convienence method for adding elements properly to any layout
// positions items, hides them, then animates them back in <--- very sezzy
insert: function ($content, callback) {
// position items
this.element.append($content);
var instance = this;
this.addItems($content, function ($newAtoms) {
var $newFilteredAtoms = instance._filter($newAtoms);
instance._addHideAppended($newFilteredAtoms);
instance._sort();
instance.reLayout();
instance._revealAppended($newFilteredAtoms, callback);
});
},
// convienence method for working with Infinite Scroll
appended: function ($content, callback) {
var instance = this;
this.addItems($content, function ($newAtoms) {
instance._addHideAppended($newAtoms);
instance.layout($newAtoms);
instance._revealAppended($newAtoms, callback);
});
},
// adds new atoms, then hides them before positioning
_addHideAppended: function ($newAtoms) {
this.$filteredAtoms = this.$filteredAtoms.add($newAtoms);
$newAtoms.addClass('no-transition');
this._isInserting = true;
// apply hidden styles
this.styleQueue.push({$el: $newAtoms, style: this.options.hiddenStyle});
},
// sets visible style on new atoms
_revealAppended: function ($newAtoms, callback) {
var instance = this;
// apply visible style after a sec
setTimeout(function () {
// enable animation
$newAtoms.removeClass('no-transition');
// reveal newly inserted filtered elements
instance.styleQueue.push({$el: $newAtoms, style: instance.options.visibleStyle});
instance._isInserting = false;
instance._processStyleQueue($newAtoms, callback);
}, 10);
},
// gathers all atoms
reloadItems: function () {
this.$allAtoms = this._getAtoms(this.element.children());
},
// removes elements from Isotope widget
remove: function ($content, callback) {
// remove elements immediately from Isotope instance
this.$allAtoms = this.$allAtoms.not($content);
this.$filteredAtoms = this.$filteredAtoms.not($content);
// remove() as a callback, for after transition / animation
var instance = this;
var removeContent = function () {
$content.remove();
if (callback) {
callback.call(instance.element);
}
};
if ($content.filter(':not(.' + this.options.hiddenClass + ')').length) {
// if any non-hidden content needs to be removed
this.styleQueue.push({$el: $content, style: this.options.hiddenStyle});
this._sort();
this.reLayout(removeContent);
} else {
// remove it now
removeContent();
}
},
shuffle: function (callback) {
this.updateSortData(this.$allAtoms);
this.options.sortBy = 'random';
this._sort();
this.reLayout(callback);
},
// destroys widget, returns elements and container back (close) to original style
destroy: function () {
var usingTransforms = this.usingTransforms;
var options = this.options;
this.$allAtoms
.removeClass(options.hiddenClass + ' ' + options.itemClass)
.each(function () {
var style = this.style;
style.position = '';
style.top = '';
style.left = '';
style.opacity = '';
if (usingTransforms) {
style[transformProp] = '';
}
});
// re-apply
var elemStyle = this.element[0].style;
for (var prop in this.originalStyle) {
elemStyle[prop] = this.originalStyle[prop];
}
this.element
.unbind('.isotope')
.undelegate('.' + options.hiddenClass, 'click')
.removeClass(options.containerClass)
.removeData('isotope');
$window.unbind('.isotope');
},
// ====================== LAYOUTS ======================
// calculates number of rows or columns
// requires columnWidth or rowHeight to be set on namespaced object
// i.e. this.masonry.columnWidth = 200
_getSegments: function (isRows) {
var namespace = this.options.layoutMode,
measure = isRows ? 'rowHeight' : 'columnWidth',
size = isRows ? 'height' : 'width',
segmentsName = isRows ? 'rows' : 'cols',
containerSize = this.element[size](),
segments,
// i.e. options.masonry && options.masonry.columnWidth
segmentSize = this.options[namespace] && this.options[namespace][measure] ||
// or use the size of the first item, i.e. outerWidth
this.$filteredAtoms['outer' + capitalize(size)](true) ||
// if there's no items, use size of container
containerSize;
segments = Math.floor(containerSize / segmentSize);
segments = Math.max(segments, 1);
// i.e. this.masonry.cols = ....
this[namespace][segmentsName] = segments;
// i.e. this.masonry.columnWidth = ...
this[namespace][measure] = segmentSize;
},
_checkIfSegmentsChanged: function (isRows) {
var namespace = this.options.layoutMode,
segmentsName = isRows ? 'rows' : 'cols',
prevSegments = this[namespace][segmentsName];
// update cols/rows
this._getSegments(isRows);
// return if updated cols/rows is not equal to previous
return ( this[namespace][segmentsName] !== prevSegments );
},
// ====================== Masonry ======================
_masonryReset: function () {
// layout-specific props
this.masonry = {};
// FIXME shouldn't have to call this again
this._getSegments();
var i = this.masonry.cols;
this.masonry.colYs = [];
while (i--) {
this.masonry.colYs.push(0);
}
},
_masonryLayout: function ($elems) {
var instance = this,
props = instance.masonry;
$elems.each(function () {
var $this = $(this),
//how many columns does this brick span
colSpan = Math.ceil($this.outerWidth(true) / props.columnWidth);
colSpan = Math.min(colSpan, props.cols);
if (colSpan === 1) {
// if brick spans only one column, just like singleMode
instance._masonryPlaceBrick($this, props.colYs);
} else {
// brick spans more than one column
// how many different places could this brick fit horizontally
var groupCount = props.cols + 1 - colSpan,
groupY = [],
groupColY,
i;
// for each group potential horizontal position
for (i = 0; i < groupCount; i++) {
// make an array of colY values for that one group
groupColY = props.colYs.slice(i, i + colSpan);
// and get the max value of the array
groupY[i] = Math.max.apply(Math, groupColY);
}
instance._masonryPlaceBrick($this, groupY);
}
});
},
// worker method that places brick in the columnSet
// with the the minY
_masonryPlaceBrick: function ($brick, setY) {
// get the minimum Y value from the columns
var minimumY = Math.min.apply(Math, setY),
shortCol = 0;
// Find index of short column, the first from the left
for (var i = 0, len = setY.length; i < len; i++) {
if (setY[i] === minimumY) {
shortCol = i;
break;
}
}
// position the brick
var x = this.masonry.columnWidth * shortCol,
y = minimumY;
this._pushPosition($brick, x, y);
// apply setHeight to necessary columns
var setHeight = minimumY + $brick.outerHeight(true),
setSpan = this.masonry.cols + 1 - len;
for (i = 0; i < setSpan; i++) {
this.masonry.colYs[shortCol + i] = setHeight;
}
},
_masonryGetContainerSize: function () {
var containerHeight = Math.max.apply(Math, this.masonry.colYs);
return {height: containerHeight};
},
_masonryResizeChanged: function () {
return this._checkIfSegmentsChanged();
},
// ====================== fitRows ======================
_fitRowsReset: function () {
this.fitRows = {
x: 0,
y: 0,
height: 0
};
},
_fitRowsLayout: function ($elems) {
var instance = this,
containerWidth = this.element.width(),
props = this.fitRows;
$elems.each(function () {
var $this = $(this),
atomW = $this.outerWidth(true),
atomH = $this.outerHeight(true);
if (props.x !== 0 && atomW + props.x > containerWidth) {
// if this element cannot fit in the current row
props.x = 0;
props.y = props.height;
}
// position the atom
instance._pushPosition($this, props.x, props.y);
props.height = Math.max(props.y + atomH, props.height);
props.x += atomW;
});
},
_fitRowsGetContainerSize: function () {
return {height: this.fitRows.height};
},
_fitRowsResizeChanged: function () {
return true;
},
// ====================== cellsByRow ======================
_cellsByRowReset: function () {
this.cellsByRow = {
index: 0
};
// get this.cellsByRow.columnWidth
this._getSegments();
// get this.cellsByRow.rowHeight
this._getSegments(true);
},
_cellsByRowLayout: function ($elems) {
var instance = this,
props = this.cellsByRow;
$elems.each(function () {
var $this = $(this),
col = props.index % props.cols,
row = Math.floor(props.index / props.cols),
x = ( col + 0.5 ) * props.columnWidth - $this.outerWidth(true) / 2,
y = ( row + 0.5 ) * props.rowHeight - $this.outerHeight(true) / 2;
instance._pushPosition($this, x, y);
props.index++;
});
},
_cellsByRowGetContainerSize: function () {
return {height: Math.ceil(this.$filteredAtoms.length / this.cellsByRow.cols) * this.cellsByRow.rowHeight + this.offset.top};
},
_cellsByRowResizeChanged: function () {
return this._checkIfSegmentsChanged();
},
// ====================== straightDown ======================
_straightDownReset: function () {
this.straightDown = {
y: 0
};
},
_straightDownLayout: function ($elems) {
var instance = this;
$elems.each(function (i) {
var $this = $(this);
instance._pushPosition($this, 0, instance.straightDown.y);
instance.straightDown.y += $this.outerHeight(true);
});
},
_straightDownGetContainerSize: function () {
return {height: this.straightDown.y};
},
_straightDownResizeChanged: function () {
return true;
},
// ====================== masonryHorizontal ======================
_masonryHorizontalReset: function () {
// layout-specific props
this.masonryHorizontal = {};
// FIXME shouldn't have to call this again
this._getSegments(true);
var i = this.masonryHorizontal.rows;
this.masonryHorizontal.rowXs = [];
while (i--) {
this.masonryHorizontal.rowXs.push(0);
}
},
_masonryHorizontalLayout: function ($elems) {
var instance = this,
props = instance.masonryHorizontal;
$elems.each(function () {
var $this = $(this),
//how many rows does this brick span
rowSpan = Math.ceil($this.outerHeight(true) / props.rowHeight);
rowSpan = Math.min(rowSpan, props.rows);
if (rowSpan === 1) {
// if brick spans only one column, just like singleMode
instance._masonryHorizontalPlaceBrick($this, props.rowXs);
} else {
// brick spans more than one row
// how many different places could this brick fit horizontally
var groupCount = props.rows + 1 - rowSpan,
groupX = [],
groupRowX, i;
// for each group potential horizontal position
for (i = 0; i < groupCount; i++) {
// make an array of colY values for that one group
groupRowX = props.rowXs.slice(i, i + rowSpan);
// and get the max value of the array
groupX[i] = Math.max.apply(Math, groupRowX);
}
instance._masonryHorizontalPlaceBrick($this, groupX);
}
});
},
_masonryHorizontalPlaceBrick: function ($brick, setX) {
// get the minimum Y value from the columns
var minimumX = Math.min.apply(Math, setX),
smallRow = 0;
// Find index of smallest row, the first from the top
for (var i = 0, len = setX.length; i < len; i++) {
if (setX[i] === minimumX) {
smallRow = i;
break;
}
}
// position the brick
var x = minimumX,
y = this.masonryHorizontal.rowHeight * smallRow;
this._pushPosition($brick, x, y);
// apply setHeight to necessary columns
var setWidth = minimumX + $brick.outerWidth(true),
setSpan = this.masonryHorizontal.rows + 1 - len;
for (i = 0; i < setSpan; i++) {
this.masonryHorizontal.rowXs[smallRow + i] = setWidth;
}
},
_masonryHorizontalGetContainerSize: function () {
var containerWidth = Math.max.apply(Math, this.masonryHorizontal.rowXs);
return {width: containerWidth};
},
_masonryHorizontalResizeChanged: function () {
return this._checkIfSegmentsChanged(true);
},
// ====================== fitColumns ======================
_fitColumnsReset: function () {
this.fitColumns = {
x: 0,
y: 0,
width: 0
};
},
_fitColumnsLayout: function ($elems) {
var instance = this,
containerHeight = this.element.height(),
props = this.fitColumns;
$elems.each(function () {
var $this = $(this),
atomW = $this.outerWidth(true),
atomH = $this.outerHeight(true);
if (props.y !== 0 && atomH + props.y > containerHeight) {
// if this element cannot fit in the current column
props.x = props.width;
props.y = 0;
}
// position the atom
instance._pushPosition($this, props.x, props.y);
props.width = Math.max(props.x + atomW, props.width);
props.y += atomH;
});
},
_fitColumnsGetContainerSize: function () {
return {width: this.fitColumns.width};
},
_fitColumnsResizeChanged: function () {
return true;
},
// ====================== cellsByColumn ======================
_cellsByColumnReset: function () {
this.cellsByColumn = {
index: 0
};
// get this.cellsByColumn.columnWidth
this._getSegments();
// get this.cellsByColumn.rowHeight
this._getSegments(true);
},
_cellsByColumnLayout: function ($elems) {
var instance = this,
props = this.cellsByColumn;
$elems.each(function () {
var $this = $(this),
col = Math.floor(props.index / props.rows),
row = props.index % props.rows,
x = ( col + 0.5 ) * props.columnWidth - $this.outerWidth(true) / 2,
y = ( row + 0.5 ) * props.rowHeight - $this.outerHeight(true) / 2;
instance._pushPosition($this, x, y);
props.index++;
});
},
_cellsByColumnGetContainerSize: function () {
return {width: Math.ceil(this.$filteredAtoms.length / this.cellsByColumn.rows) * this.cellsByColumn.columnWidth};
},
_cellsByColumnResizeChanged: function () {
return this._checkIfSegmentsChanged(true);
},
// ====================== straightAcross ======================
_straightAcrossReset: function () {
this.straightAcross = {
x: 0
};
},
_straightAcrossLayout: function ($elems) {
var instance = this;
$elems.each(function (i) {
var $this = $(this);
instance._pushPosition($this, instance.straightAcross.x, 0);
instance.straightAcross.x += $this.outerWidth(true);
});
},
_straightAcrossGetContainerSize: function () {
return {width: this.straightAcross.x};
},
_straightAcrossResizeChanged: function () {
return true;
}
};
// ======================= imagesLoaded Plugin ===============================
/*!
* jQuery imagesLoaded plugin v1.1.0
* http://github.com/desandro/imagesloaded
*
* MIT License. by Paul Irish et al.
*/
// $('#my-container').imagesLoaded(myFunction)
// or
// $('img').imagesLoaded(myFunction)
// execute a callback when all images have loaded.
// needed because .load() doesn't work on cached images
// callback function gets image collection as argument
// `this` is the container
$.fn.imagesLoaded = function (callback) {
var $this = this,
$images = $this.find('img').add($this.filter('img')),
len = $images.length,
blank = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==',
loaded = [];
function triggerCallback() {
callback.call($this, $images);
}
function imgLoaded(event) {
var img = event.target;
if (img.src !== blank && $.inArray(img, loaded) === -1) {
loaded.push(img);
if (--len <= 0) {
setTimeout(triggerCallback);
$images.unbind('.imagesLoaded', imgLoaded);
}
}
}
// if no images, trigger immediately
if (!len) {
triggerCallback();
}
$images.bind('load.imagesLoaded error.imagesLoaded', imgLoaded).each(function () {
// cached images don't fire load sometimes, so we reset src.
var src = this.src;
// webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
// data uri bypasses webkit log warning (thx doug jones)
this.src = blank;
this.src = src;
});
return $this;
};
// helper function for logging errors
// $.error breaks jQuery chaining
var logError = function (message) {
if (window.console) {
window.console.error(message);
}
};
// ======================= Plugin bridge ===============================
// leverages data method to either create or return $.Isotope constructor
// A bit from jQuery UI
// https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
// A bit from jcarousel
// https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js
$.fn.isotope = function (options, callback) {
if (typeof options === 'string') {
// call method
var args = Array.prototype.slice.call(arguments, 1);
this.each(function () {
var instance = $.data(this, 'isotope');
if (!instance) {
logError("cannot call methods on isotope prior to initialization; " +
"attempted to call method '" + options + "'");
return;
}
if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
logError("no such method '" + options + "' for isotope instance");
return;
}
// apply method
instance[options].apply(instance, args);
});
} else {
this.each(function () {
var instance = $.data(this, 'isotope');
if (instance) {
// apply options & init
instance.option(options);
instance._init(callback);
} else {
// initialize new instance
$.data(this, 'isotope', new $.Isotope(options, this, callback));
}
});
}
// return jQuery object
// so plugin methods do not have to
return this;
};
})(window, jQuery);
© 2015 - 2025 Weber Informatics LLC | Privacy Policy