@ -72,7 +72,7 @@
// need to get atoms
this . atoms . $all = this . $elem . children ( ) . molequul ( '_filterFind' , this . options . itemSelector ) ;
console . log ( 'all atoms' , this . atoms . $all . length )
// console.log( 'all atoms', this.atoms.$all.length )
this . $elem . css ( {
overflow : 'hidden' ,
@ -169,6 +169,525 @@
} ,
isNewProp : function ( property , props ) {
if ( ! props . initialized ) {
return true ;
}
var previousProp = props . prevOpts [ property ] ;
return ( props . opts [ property ] !== previousProp ) ;
} ,
// ====================== Adding ======================
addSortData : function ( props ) {
return this . each ( function ( ) {
var $this = $ ( this ) ,
sortData = { } ,
getSortData = props . opts . getSortData ,
key ;
// get value for sort data based on fn( $elem ) passed in
for ( key in getSortData ) {
sortData [ key ] = getSortData [ key ] ( $this ) ;
}
// apply sort data to $element
$this . data ( 'molequul-sort-data' , sortData ) ;
// increment element count
props . elemCount ++ ;
} ) ;
} ,
setupAtoms : function ( props ) {
// base style for atoms
var atomStyle = { position : 'absolute' } ;
if ( props . usingTransforms ) {
atomStyle . left = 0 ;
atomStyle . top = 0 ;
}
// add sort data to each elem
return this . molequul ( 'addSortData' , props ) . css ( atomStyle ) ;
} ,
// ====================== Filtering ======================
filter : function ( $atoms ) {
var props = this . data ( 'molequul' ) ,
filter = props . opts . filter === '' ? '*' : props . opts . filter ;
if ( ! filter ) {
props . atoms . $filtered = $atoms ;
} else {
var hiddenClass = props . opts . hiddenClass ,
hiddenSelector = '.' + hiddenClass ,
$visibleAtoms = $atoms . not ( hiddenSelector ) ,
$hiddenAtoms = $atoms . filter ( hiddenSelector ) ,
$atomsToShow = $hiddenAtoms ;
props . atoms . $filtered = $atoms . filter ( filter ) ;
if ( filter !== '*' ) {
$atomsToShow = $hiddenAtoms . filter ( filter ) ;
var $atomsToHide = $visibleAtoms . not ( filter ) . toggleClass ( hiddenClass ) ;
$atomsToHide . addClass ( hiddenClass ) ;
props . styleQueue . push ( { $el : $atomsToHide , style : props . opts . hiddenStyle } ) ;
}
props . styleQueue . push ( { $el : $atomsToShow , style : props . opts . visibleStyle } ) ;
$atomsToShow . removeClass ( hiddenClass ) ;
}
return this ;
} ,
// ====================== Sorting ======================
getSortFn : function ( sortBy , sortDir ) {
var getSorter = function ( elem ) {
return $ ( elem ) . data ( 'molequul-sort-data' ) [ sortBy ] ;
} ;
return function ( alpha , beta ) {
var a = getSorter ( alpha ) ,
b = getSorter ( beta ) ;
return ( ( a > b ) ? 1 : ( a < b ) ? - 1 : 0 ) * sortDir ;
} ;
} ,
randomSortFn : function ( ) {
return Math . random ( ) > 5 ? 1 : - 1 ;
} ,
// used on all the filtered atoms, $atoms.filtered
sort : function ( props ) {
var sortFn = props . opts . sortBy === 'random' ? $ . molequul . randomSortFn :
$ . molequul . getSortFn ( props . opts . sortBy , props . opts . sortDir ) ;
props . atoms . $filtered . sort ( sortFn ) ;
return this ;
} ,
// ====================== Layout ======================
translate : function ( x , y ) {
return { translate : [ x , y ] } ;
} ,
positionAbs : function ( x , y ) {
return { left : x , top : y } ;
} ,
pushPosition : function ( x , y , props ) {
var position = props . positionFn ( x , y ) ;
props . styleQueue . push ( { $el : this , style : position } ) ;
return this ;
} ,
// ====================== masonry ======================
placeBrick : function ( setCount , setY , props ) {
// here, `this` refers to a child element or "brick"
// get the minimum Y value from the columns
var minimumY = Math . min . apply ( Math , setY ) ,
setHeight = minimumY + this . outerHeight ( true ) ,
i = setY . length ,
shortCol = i ,
setSpan = props . colCount + 1 - i ,
x , y ;
// Which column has the minY value, closest to the left
while ( i -- ) {
if ( setY [ i ] === minimumY ) {
shortCol = i ;
}
}
// position the brick
x = props . colW * shortCol + props . posLeft ;
y = minimumY ;
this . molequul ( 'pushPosition' , x , y , props ) ;
// apply setHeight to necessary columns
for ( i = 0 ; i < setSpan ; i ++ ) {
props . colYs [ shortCol + i ] = setHeight ;
}
return this ;
} ,
masonrySingleColumn : function ( props ) {
return this . each ( function ( ) {
$ ( this ) . molequul ( 'placeBrick' , props . colCount , props . colYs , props ) ;
} ) ;
} ,
masonryMultiColumn : function ( props ) {
return this . each ( function ( ) {
var $this = $ ( this ) ,
//how many columns does this brick span
colSpan = Math . ceil ( $this . outerWidth ( true ) / props . colW ) ;
colSpan = Math . min ( colSpan , props . colCount ) ;
if ( colSpan === 1 ) {
// if brick spans only one column, just like singleMode
$this . molequul ( 'placeBrick' , props . colCount , props . colYs , props ) ;
} else {
// brick spans more than one column
// how many different places could this brick fit horizontally
var groupCount = props . colCount + 1 - colSpan ,
groupY = [ ] ,
groupColY ;
// for each group potential horizontal position
for ( var 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 ) ;
}
$this . molequul ( 'placeBrick' , groupCount , groupY , props ) ;
}
} ) ;
} ,
getMasonryColCount : function ( props ) {
props . colW = props . opts . columnWidth || props . atoms . $all . outerWidth ( true ) ;
// if colW == 0, back out before divide by zero
if ( ! props . colW ) {
window . console && console . error ( 'Column width calculated to be zero. Stopping Molequul plugin before divide by zero. Check that the width of first child inside the molequul container is not zero.' ) ;
return this ;
}
props . width = this . width ( ) ;
props . colCount = Math . floor ( props . width / props . colW ) ;
props . colCount = Math . max ( props . colCount , 1 ) ;
return this ;
} ,
masonryResetLayoutProps : function ( props ) {
var i = props . colCount ;
props . colYs = [ ] ;
while ( i -- ) {
props . colYs . push ( props . posTop ) ;
}
return this ;
} ,
masonryResize : function ( props ) {
var prevColCount = props . colCount ;
// get updated colCount
this . molequul ( 'getMasonryColCount' , props ) ;
if ( props . colCount !== prevColCount ) {
// if column count has changed, do a new column cound
this . molequul ( 'reLayout' , props ) ;
}
return this ;
} ,
masonryMeasureContainerHeight : function ( props ) {
props . containerHeight = Math . max . apply ( Math , props . colYs ) - props . posTop ;
return this ;
} ,
masonrySetup : function ( props ) {
this . molequul ( 'getMasonryColCount' , props ) ;
return this ;
} ,
// ====================== ClearFloat ======================
clearFloat : function ( props ) {
return this . each ( function ( ) {
var $this = $ ( this ) ,
atomW = $this . outerWidth ( true ) ,
atomH = $this . outerHeight ( true ) ,
x , y ;
if ( props . clearFloat . x !== 0 && atomW + props . clearFloat . x > props . width ) {
// if this element cannot fit in the current row
props . clearFloat . x = 0 ;
props . clearFloat . y = props . clearFloat . height ;
}
// position the atom
x = props . clearFloat . x + props . posLeft ;
y = props . clearFloat . y + props . posTop ;
$this . molequul ( 'pushPosition' , x , y , props ) ;
props . clearFloat . height = Math . max ( props . clearFloat . y + atomH , props . clearFloat . height ) ;
props . clearFloat . x += atomW ;
} ) ;
} ,
clearFloatSetup : function ( props ) {
props . width = this . width ( ) ;
return this ;
} ,
clearFloatResetLayoutProps : function ( props ) {
props . clearFloat = {
x : 0 ,
y : 0 ,
height : 0
} ;
return this ;
} ,
clearFloatMeasureContainerHeight : function ( props ) {
props . containerHeight = props . clearFloat . height ;
return this ;
} ,
clearFloatResize : function ( props ) {
props . width = this . width ( ) ;
return this . molequul ( 'reLayout' , props ) ;
} ,
// ====================== 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 props = this . data ( 'molequul' ) ,
layoutMode = props . opts . layoutMode ,
layoutMethod = layoutMode ;
// layout logic
if ( layoutMethod === 'masonry' ) {
layoutMethod = props . opts . masonrySingleMode ? 'masonrySingleColumn' : 'masonryMultiColumn' ;
}
$elems . molequul ( layoutMethod , props ) ;
// set the height of the container to the tallest column
this . molequul ( layoutMode + 'MeasureContainerHeight' , props ) ;
var containerStyle = { height : props . containerHeight } ;
props . styleQueue . push ( { $el : this , style : containerStyle } ) ;
// are we animating the layout arrangement?
// use plugin-ish syntax for css or animate
var styleFn = ( props . applyStyleFnName === 'animate' && ! props . initialized ) ?
'css' : props . applyStyleFnName ,
animOpts = props . opts . animationOptions ;
// process styleQueue
$ . each ( props . styleQueue , function ( i , obj ) {
// have to extend animation to play nice with jQuery
obj . $el [ styleFn ] ( obj . style , $ . extend ( { } , animOpts ) ) ;
} ) ;
// clear out queue for next time
props . styleQueue = [ ] ;
// provide $elems as context for the callback
if ( callback ) {
callback . call ( $elems ) ;
}
return this ;
} ,
resize : function ( ) {
var props = this . data ( 'molequul' ) ;
return this . molequul ( props . opts . layoutMode + 'Resize' , props ) ;
} ,
reLayout : function ( props ) {
props = props || this . data ( 'molequul' ) ;
props . initialized = true ;
return this
. molequul ( props . opts . layoutMode + 'ResetLayoutProps' , props )
. molequul ( 'layout' , props . atoms . $filtered ) ;
} ,
// ====================== Setup and Init ======================
// only run though on initial init
setup : function ( props ) {
props . atoms = { } ;
props . isNew = { } ;
props . styleQueue = [ ] ;
props . elemCount = 0 ;
// need to get atoms
props . atoms . $all = props . opts . selector ?
this . find ( props . opts . selector ) :
this . children ( ) ;
this . css ( {
overflow : 'hidden' ,
position : 'relative'
} ) ;
var jQueryAnimation = false ;
// get applyStyleFnName
switch ( props . opts . animationEngine . toLowerCase ( ) . replace ( /[ _\-]/g , '' ) ) {
case 'none' :
props . applyStyleFnName = 'css' ;
break ;
case 'jquery' :
props . applyStyleFnName = 'animate' ;
jQueryAnimation = true ;
break ;
case 'bestavailable' :
default :
props . applyStyleFnName = Modernizr . csstransitions ? 'css' : 'animate' ;
}
props . usingTransforms = Modernizr . csstransforms && Modernizr . csstransitions && ! jQueryAnimation ;
props . positionFn = props . usingTransforms ? $ . molequul . translate : $ . molequul . positionAbs ;
// sorting
var originalOrderSorter = {
'original-order' : function ( $elem ) {
return props . elemCount ;
}
} ;
props . opts . getSortData = $ . extend ( originalOrderSorter , props . opts . getSortData ) ;
props . atoms . $all . molequul ( 'setupAtoms' , props ) ;
// get top left position of where the bricks should be
var $cursor = $ ( document . createElement ( 'div' ) ) ;
this . prepend ( $cursor ) ;
props . posTop = Math . round ( $cursor . position ( ) . top ) ;
props . posLeft = Math . round ( $cursor . position ( ) . left ) ;
$cursor . remove ( ) ;
// add molequul class first time around
var $container = this ;
setTimeout ( function ( ) {
$container . addClass ( props . opts . containerClass ) ;
} , 1 ) ;
// do any layout-specific setup
this . molequul ( props . opts . layoutMode + 'Setup' , props ) ;
// save data
this . data ( 'molequul' , props ) ;
return this ;
} ,
watchedProps : [ 'filter' , 'sortBy' , 'sortDir' , 'layoutMode' ] ,
init : function ( options , callback ) {
return this . each ( function ( ) {
var $this = $ ( this ) ,
data = $this . data ( 'molequul' ) ,
props = data || { } ;
// checks if molquul has been called before on this object
props . initialized = ! ! data ;
props . prevOpts = props . initialized ? data . opts : { } ;
props . opts = $ . extend (
{ } ,
$ . molequul . defaults ,
props . prevOpts ,
options
) ;
if ( ! props . initialized ) {
$this . molequul ( 'setup' , props ) ;
}
// check if watched properties are new
$ . each ( $ . molequul . watchedProps , function ( i , propName ) {
props . isNew [ propName ] = $ . molequul . isNewProp ( propName , props ) ;
} ) ;
if ( props . isNew . layoutMode ) {
$this . molequul ( props . opts . layoutMode + 'Setup' , props ) ;
}
if ( props . isNew . filter || props . appending ) {
$this . molequul ( 'filter' , props . atoms . $all ) ;
}
if ( props . isNew . filter || props . isNew . sortBy || props . isNew . sortDir || props . appending ) {
$this . molequul ( 'sort' , props ) ;
}
$this . molequul ( props . opts . layoutMode + 'ResetLayoutProps' , props )
. molequul ( 'layout' , props . atoms . $filtered , callback ) ;
// binding window resizing
if ( props . opts . resizeable ) {
$ ( window ) . bind ( 'smartresize.molequul' , function ( ) { $this . molequul ( 'resize' ) ; } ) ;
} else if ( ! props . opts . resizeable && ! ! props . prevOpts . resizeable ) {
$ ( window ) . unbind ( 'smartresize.molequul' ) ;
}
// reset this prop for next time
props . appending = false ;
// set all data so we can retrieve it for appended appendedContent
// or anyone else's crazy jquery fun
$this . data ( 'molequul' , props ) ;
} ) ;
} ,
// ====================== Convenience methods ======================
// adds a jQuery object of items to a molequul container
add : function ( $content ) {
var props = this . data ( 'molequul' ) ,
$newAtoms = props . opts . selector ? $content . filter ( props . opts . selector ) : $content ;
$newAtoms . molequul ( 'setupAtoms' , props )
// add new atoms to atoms pools
props . atoms . $all = props . atoms . $all . add ( $newAtoms ) ;
props . atoms . $filtered = props . atoms . $filtered . add ( $newAtoms ) ;
props . appending = true ;
return this ;
} ,
// convienence method for adding elements properly to any layout
insert : function ( $content ) {
return this . append ( $content ) . molequul ( 'add' , $content ) . molequul ( 'init' ) ;
} ,
// convienence method for working with Infinite Scroll
appended : function ( $content ) {
return this . molequul ( 'add' , $content ) . molequul ( 'layout' , $content ) ;
}
// publicFn: function(){ // notice no underscore
// return "public method";