Last active
February 23, 2016 16:13
-
-
Save dougwollison/c21f05eac188f20863dc to your computer and use it in GitHub Desktop.
jQuery cssAnimate and cssTransition plugins.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function( $ ) { | |
// Convert a className string into a classList array | |
function makeList( string ) { | |
// trim whitespace | |
string = ( string || '' ).replace( /^\s+|\s+$/g,'' ); | |
if ( string ) { | |
return string.split( /\s+/ ); | |
} else { | |
return []; | |
} | |
} | |
// Return entries from the second list that show up in the first | |
function matchList( list1, list2 ) { | |
var diff = []; | |
for ( var i in list2 ) { | |
if ( $.inArray( list2[ i ], list1 ) !== -1 ) { | |
diff.push( list2[ i ] ); | |
} | |
} | |
return diff; | |
} | |
// Return entries from the second list that DO NOT show up in the first | |
function diffList( list1, list2 ) { | |
var diff = []; | |
for ( var i in list2 ) { | |
if ( $.inArray( list2[ i ], list1 ) === -1 ) { | |
diff.push( list2[ i ] ); | |
} | |
} | |
return diff; | |
} | |
// CSS Property tester adapted from https://gist.github.com/jackfuchs/556448 | |
function cssSupports( property ) { | |
var style = document.createElement( 'div' ).style; | |
// Ensure CSS is supported at all | |
if ( typeof style === 'undefined' ) { | |
return false; | |
} | |
// Test for standard version of property | |
if ( typeof style[ property ] === 'string' ) { | |
return true; | |
} | |
// Test for vendor specific version of property | |
var vendors = [ 'Moz', 'Webkit', 'Khtml', 'O', 'ms', 'Icab' ]; | |
property = property.charAt( 0 ).toUpperCase() + property.substr( 1 ); // Capitalize | |
for ( var i in vendors ) { | |
if ( typeof style[ vendors[ i ] + property ] === 'string' ) { | |
// Return the matched prefix | |
return vendors[ i ]; | |
} | |
} | |
// Otherwise return false | |
return false; | |
} | |
// CSS End Event guesser | |
function cssEndEvent( property, supported ) { | |
var prefixes = { | |
Moz: 'moz', | |
Webkit: 'webkit', | |
O: 'o', | |
ms: 'MS', | |
}; | |
var event = property + 'end'; | |
if(typeof supported === 'string' && typeof prefixes[ supported ] === 'string' ) { | |
event = prefixes[ supported ] + property.charAt( 0 ).toUpperCase() + property.substr( 1 ) + 'End'; | |
} | |
return event; | |
} | |
var supports = { | |
animation: cssSupports( 'animation' ), | |
transition: cssSupports( 'transition' ) | |
}; | |
var endEvents = { | |
animation: cssEndEvent( 'animation', supports.animation ), | |
transition: cssEndEvent( 'transition', supports.transition ) | |
}; | |
function cssAnimateOrTransition( method, args ) { | |
var addClasses = '', removeClasses = '', endCallback; | |
if ( args.length === 0 ) { | |
// Abort | |
return; | |
} | |
// Check if first argument is the callback or the classes to add | |
if ( typeof args[0] === 'function' ) { | |
endCallback = args[0]; | |
} else { | |
addClasses = args[0]; | |
} | |
// Check if second argument exists and if it's the callback or the classes to remove | |
if ( args.length >= 2 ) { | |
if ( typeof args[1] === 'function' ) { | |
endCallback = args[1]; | |
} else { | |
removeClasses = args[1]; | |
} | |
} | |
// Check if third argument exists and if it's the callback | |
if ( args.length === 3 && typeof args[ 2 ] === 'function' ) { | |
endCallback = args[ 2 ]; | |
} | |
// Get the support result and end event | |
var supported = supports[ method ] !== false; | |
var endEvent = endEvents[ method ]; | |
return $( this ).each(function() { | |
// Get the current class list | |
var classList = this.classList || makeList( this.className ); | |
var addList = makeList( addClasses ); | |
var removeList = makeList( removeClasses ); | |
// Check that at least one of the classes being added doesn't exist yet | |
var toAdd = diffList( classList, addList ); | |
// Check that at least one of the classes being removed already exists | |
var toRemove = matchList( classList, removeList ); | |
var doEvent = supported && ( toAdd.length > 0 || toRemove.length > 0 ); | |
// Setup a onetime callback if supported, assuming there are classes to add/remove | |
if ( doEvent && endCallback ) { | |
$( this ).one( endEvent, endCallback ); | |
} | |
// Add/Remove the desired classes | |
$( this ).addClass( addClasses ).removeClass( removeClasses ); | |
// Fallback, trigger the callback now that the classes have been added | |
if ( ! doEvent && endCallback ) { | |
endCallback.apply( this ); | |
} | |
}); | |
} | |
$.fn.cssAnimate = function(){ | |
return cssAnimateOrTransition.call( this, 'animation', arguments ); | |
}; | |
$.fn.cssTransition = function(){ | |
return cssAnimateOrTransition.call( this, 'transition', arguments ); | |
}; | |
})( jQuery ); | |
/* | |
Examples | |
======== | |
// Trigger out animation on div1, then in animation on div2 | |
$('#div1').cssAnimate('out', function(){ | |
$('#div2').cssAnimate('in'); | |
}); | |
// Remove class to trigger transition | |
$('#mydiv').cssTransition(null, 'active', function(){ | |
// Do something | |
}); | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment