Browse Source

Origami: Initial commit of origami module

beta
Jack Lukic 12 years ago
commit
e7674226de
  1. 1
      build/origami.min.css
  2. 1
      build/origami.min.js
  3. 30
      component.json
  4. 551
      dependencies/transform2d.js
  5. 92
      dependencies/transform3d.js
  6. 114
      src/origami.css
  7. 502
      src/origami.js

1
build/origami.min.css

@ -0,0 +1 @@
.origami.module{position:relative;-webkit-perspective:2000px;-moz-perspective:2000px;-ms-perspective:2000px;perspective:2000px}.origami.module .box{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;transform-style:preserve-3d}.origami.module .side{display:none;opacity:1;width:100%;background-color:#fff;-moz-box-shadow:0 1px 3px rgba(0,0,0,0.3);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.3);box-shadow:0 1px 3px rgba(0,0,0,0.3);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.origami.module .handle{cursor:pointer;position:absolute;bottom:-28px;right:50%;margin-left:-22px;width:44px;height:44px;background:url(/images/modules/origami-handle.png) no-repeat 0 0}.origami.module .down.handle{background-position:0 -50px}.origami.module.animating .box{position:absolute}.origami.module .animating.side{position:absolute;width:100%;top:0;left:0;z-index:100}.origami.module .hidden.side{opacity:.5}.origami.css.module{-webkit-transition:all .5s ease-in-out;-moz-transition:all .5s ease-in-out;-o-transition:all .5s ease-in-out;-ms-transition:all .5s ease-in-out;transition:all .5s ease-in-out}.origami.css.module .box{-webkit-transition:all .5s ease-in-out;-moz-transition:all .5s ease-in-out;-o-transition:all .5s ease-in-out;-ms-transition:all .5s ease-in-out;transition:all .5s ease-in-out}.origami.css.module .side{-webkit-transition:opacity .5s ease-out;-moz-transition:opacity .5s ease-out;-o-transition:opacity .5s ease-out;-ms-transition:opacity .5s ease-out;transition:opacity .5s ease-out}.origami.module .active.side{display:block}

1
build/origami.min.js

File diff suppressed because one or more lines are too long

30
component.json

@ -0,0 +1,30 @@
{
"name" : "Origami",
"version" : "0.1",
"description" : "3D animation made easy, using the Semantic module spec.",
"homepage" : "https://github.com/quirkyinc/",
"author": {
"name" : "Jack Lukic",
"web" : "http://www.github.com/quirkyjack/"
},
"keywords": [
"origami",
"animation",
"css3"
],
"license" : [
"http://bartaz.mit-license.org/",
"http://www.gnu.org/licenses/"
],
"main": [
"./build/origami.js",
"./build/origami.css"
],
"dependencies": {
"jquery" : ">=1.8",
"transform2d" : "./dependencies/transform2d.js",
"transform3d" : "./dependencies/transform3d.js"
}
}

551
dependencies/transform2d.js

@ -0,0 +1,551 @@
/*
* transform: A jQuery cssHooks adding cross-browser 2d transform capabilities to $.fn.css() and $.fn.animate()
*
* limitations:
* - requires jQuery 1.4.3+
* - Should you use the *translate* property, then your elements need to be absolutely positionned in a relatively positionned wrapper **or it will fail in IE678**.
* - transformOrigin is not accessible
*
* latest version and complete README available on Github:
* https://github.com/louisremi/jquery.transform.js
*
* Copyright 2011 @louis_remi
* Licensed under the MIT license.
*
* This saved you an hour of work?
* Send me music http://www.amazon.co.uk/wishlist/HNTU0468LQON
*
*/
(function( $, window, document, Math, undefined ) {
/*
* Feature tests and global variables
*/
var div = document.createElement("div"),
divStyle = div.style,
suffix = "Transform",
testProperties = [
"O" + suffix,
"ms" + suffix,
"Webkit" + suffix,
"Moz" + suffix
],
i = testProperties.length,
supportProperty,
supportMatrixFilter,
supportFloat32Array = "Float32Array" in window,
propertyHook,
propertyGet,
rMatrix = /Matrix([^)]*)/,
rAffine = /^\s*matrix\(\s*1\s*,\s*0\s*,\s*0\s*,\s*1\s*(?:,\s*0(?:px)?\s*){2}\)\s*$/,
_transform = "transform",
_transformOrigin = "transformOrigin",
_translate = "translate",
_rotate = "rotate",
_scale = "scale",
_skew = "skew",
_matrix = "matrix";
// test different vendor prefixes of these properties
while ( i-- ) {
if ( testProperties[i] in divStyle ) {
$.support[_transform] = supportProperty = testProperties[i];
$.support[_transformOrigin] = supportProperty + "Origin";
continue;
}
}
// IE678 alternative
if ( !supportProperty ) {
$.support.matrixFilter = supportMatrixFilter = divStyle.filter === "";
}
// px isn't the default unit of these properties
$.cssNumber[_transform] = $.cssNumber[_transformOrigin] = true;
/*
* fn.css() hooks
*/
if ( supportProperty && supportProperty != _transform ) {
// Modern browsers can use jQuery.cssProps as a basic hook
$.cssProps[_transform] = supportProperty;
$.cssProps[_transformOrigin] = supportProperty + "Origin";
// Firefox needs a complete hook because it stuffs matrix with "px"
if ( supportProperty == "Moz" + suffix ) {
propertyHook = {
get: function( elem, computed ) {
return (computed ?
// remove "px" from the computed matrix
$.css( elem, supportProperty ).split("px").join(""):
elem.style[supportProperty]
);
},
set: function( elem, value ) {
// add "px" to matrices
elem.style[supportProperty] = /matrix\([^)p]*\)/.test(value) ?
value.replace(/matrix((?:[^,]*,){4})([^,]*),([^)]*)/, _matrix+"$1$2px,$3px"):
value;
}
};
/* Fix two jQuery bugs still present in 1.5.1
* - rupper is incompatible with IE9, see http://jqbug.com/8346
* - jQuery.css is not really jQuery.cssProps aware, see http://jqbug.com/8402
*/
} else if ( /^1\.[0-5](?:\.|$)/.test($.fn.jquery) ) {
propertyHook = {
get: function( elem, computed ) {
return (computed ?
$.css( elem, supportProperty.replace(/^ms/, "Ms") ):
elem.style[supportProperty]
);
}
};
}
/* TODO: leverage hardware acceleration of 3d transform in Webkit only
else if ( supportProperty == "Webkit" + suffix && support3dTransform ) {
propertyHook = {
set: function( elem, value ) {
elem.style[supportProperty] =
value.replace();
}
}
}*/
} else if ( supportMatrixFilter ) {
propertyHook = {
get: function( elem, computed, asArray ) {
var elemStyle = ( computed && elem.currentStyle ? elem.currentStyle : elem.style ),
matrix, data;
if ( elemStyle && rMatrix.test( elemStyle.filter ) ) {
matrix = RegExp.$1.split(",");
matrix = [
matrix[0].split("=")[1],
matrix[2].split("=")[1],
matrix[1].split("=")[1],
matrix[3].split("=")[1]
];
} else {
matrix = [1,0,0,1];
}
if ( ! $.cssHooks[_transformOrigin] ) {
matrix[4] = elemStyle ? parseInt(elemStyle.left, 10) || 0 : 0;
matrix[5] = elemStyle ? parseInt(elemStyle.top, 10) || 0 : 0;
} else {
data = $._data( elem, "transformTranslate", undefined );
matrix[4] = data ? data[0] : 0;
matrix[5] = data ? data[1] : 0;
}
return asArray ? matrix : _matrix+"(" + matrix + ")";
},
set: function( elem, value, animate ) {
var elemStyle = elem.style,
currentStyle,
Matrix,
filter,
centerOrigin;
if ( !animate ) {
elemStyle.zoom = 1;
}
value = matrix(value);
// rotate, scale and skew
Matrix = [
"Matrix("+
"M11="+value[0],
"M12="+value[2],
"M21="+value[1],
"M22="+value[3],
"SizingMethod='auto expand'"
].join();
filter = ( currentStyle = elem.currentStyle ) && currentStyle.filter || elemStyle.filter || "";
elemStyle.filter = rMatrix.test(filter) ?
filter.replace(rMatrix, Matrix) :
filter + " progid:DXImageTransform.Microsoft." + Matrix + ")";
if ( ! $.cssHooks[_transformOrigin] ) {
// center the transform origin, from pbakaus's Transformie http://github.com/pbakaus/transformie
if ( (centerOrigin = $.transform.centerOrigin) ) {
elemStyle[centerOrigin == "margin" ? "marginLeft" : "left"] = -(elem.offsetWidth/2) + (elem.clientWidth/2) + "px";
elemStyle[centerOrigin == "margin" ? "marginTop" : "top"] = -(elem.offsetHeight/2) + (elem.clientHeight/2) + "px";
}
// translate
// We assume that the elements are absolute positionned inside a relative positionned wrapper
elemStyle.left = value[4] + "px";
elemStyle.top = value[5] + "px";
} else {
$.cssHooks[_transformOrigin].set( elem, value );
}
}
};
}
// populate jQuery.cssHooks with the appropriate hook if necessary
if ( propertyHook ) {
$.cssHooks[_transform] = propertyHook;
}
// we need a unique setter for the animation logic
propertyGet = propertyHook && propertyHook.get || $.css;
/*
* fn.animate() hooks
*/
$.fx.step.transform = function( fx ) {
var elem = fx.elem,
start = fx.start,
end = fx.end,
pos = fx.pos,
transform = "",
precision = 1E5,
i, startVal, endVal, unit;
// fx.end and fx.start need to be converted to interpolation lists
if ( !start || typeof start === "string" ) {
// the following block can be commented out with jQuery 1.5.1+, see #7912
if ( !start ) {
start = propertyGet( elem, supportProperty );
}
// force layout only once per animation
if ( supportMatrixFilter ) {
elem.style.zoom = 1;
}
// replace "+=" in relative animations (-= is meaningless with transforms)
end = end.split("+=").join(start);
// parse both transform to generate interpolation list of same length
$.extend( fx, interpolationList( start, end ) );
start = fx.start;
end = fx.end;
}
i = start.length;
// interpolate functions of the list one by one
while ( i-- ) {
startVal = start[i];
endVal = end[i];
unit = +false;
switch ( startVal[0] ) {
case _translate:
unit = "px";
case _scale:
unit || ( unit = "");
transform = startVal[0] + "(" +
Math.round( (startVal[1][0] + (endVal[1][0] - startVal[1][0]) * pos) * precision ) / precision + unit +","+
Math.round( (startVal[1][1] + (endVal[1][1] - startVal[1][1]) * pos) * precision ) / precision + unit + ")"+
transform;
break;
case _skew + "X":
case _skew + "Y":
case _rotate:
transform = startVal[0] + "(" +
Math.round( (startVal[1] + (endVal[1] - startVal[1]) * pos) * precision ) / precision +"rad)"+
transform;
break;
}
}
fx.origin && ( transform = fx.origin + transform );
propertyHook && propertyHook.set ?
propertyHook.set( elem, transform, +true ):
elem.style[supportProperty] = transform;
};
/*
* Utility functions
*/
// turns a transform string into its "matrix(A,B,C,D,X,Y)" form (as an array, though)
function matrix( transform ) {
transform = transform.split(")");
var
trim = $.trim
, i = -1
// last element of the array is an empty string, get rid of it
, l = transform.length -1
, split, prop, val
, prev = supportFloat32Array ? new Float32Array(6) : []
, curr = supportFloat32Array ? new Float32Array(6) : []
, rslt = supportFloat32Array ? new Float32Array(6) : [1,0,0,1,0,0]
;
prev[0] = prev[3] = rslt[0] = rslt[3] = 1;
prev[1] = prev[2] = prev[4] = prev[5] = 0;
// Loop through the transform properties, parse and multiply them
while ( ++i < l ) {
split = transform[i].split("(");
prop = trim(split[0]);
val = split[1];
curr[0] = curr[3] = 1;
curr[1] = curr[2] = curr[4] = curr[5] = 0;
switch (prop) {
case _translate+"X":
curr[4] = parseInt(val, 10);
break;
case _translate+"Y":
curr[5] = parseInt(val, 10);
break;
case _translate:
val = val.split(",");
curr[4] = parseInt(val[0], 10);
curr[5] = parseInt(val[1] || 0, 10);
break;
case _rotate:
val = toRadian(val);
curr[0] = Math.cos(val);
curr[1] = Math.sin(val);
curr[2] = -Math.sin(val);
curr[3] = Math.cos(val);
break;
case _scale+"X":
curr[0] = +val;
break;
case _scale+"Y":
curr[3] = val;
break;
case _scale:
val = val.split(",");
curr[0] = val[0];
curr[3] = val.length>1 ? val[1] : val[0];
break;
case _skew+"X":
curr[2] = Math.tan(toRadian(val));
break;
case _skew+"Y":
curr[1] = Math.tan(toRadian(val));
break;
case _matrix:
val = val.split(",");
curr[0] = val[0];
curr[1] = val[1];
curr[2] = val[2];
curr[3] = val[3];
curr[4] = parseInt(val[4], 10);
curr[5] = parseInt(val[5], 10);
break;
}
// Matrix product (array in column-major order)
rslt[0] = prev[0] * curr[0] + prev[2] * curr[1];
rslt[1] = prev[1] * curr[0] + prev[3] * curr[1];
rslt[2] = prev[0] * curr[2] + prev[2] * curr[3];
rslt[3] = prev[1] * curr[2] + prev[3] * curr[3];
rslt[4] = prev[0] * curr[4] + prev[2] * curr[5] + prev[4];
rslt[5] = prev[1] * curr[4] + prev[3] * curr[5] + prev[5];
prev = [rslt[0],rslt[1],rslt[2],rslt[3],rslt[4],rslt[5]];
}
return rslt;
}
// turns a matrix into its rotate, scale and skew components
// algorithm from http://hg.mozilla.org/mozilla-central/file/7cb3e9795d04/layout/style/nsStyleAnimation.cpp
function unmatrix(matrix) {
var
scaleX
, scaleY
, skew
, A = matrix[0]
, B = matrix[1]
, C = matrix[2]
, D = matrix[3]
;
// Make sure matrix is not singular
if ( A * D - B * C ) {
// step (3)
scaleX = Math.sqrt( A * A + B * B );
A /= scaleX;
B /= scaleX;
// step (4)
skew = A * C + B * D;
C -= A * skew;
D -= B * skew;
// step (5)
scaleY = Math.sqrt( C * C + D * D );
C /= scaleY;
D /= scaleY;
skew /= scaleY;
// step (6)
if ( A * D < B * C ) {
A = -A;
B = -B;
skew = -skew;
scaleX = -scaleX;
}
// matrix is singular and cannot be interpolated
} else {
// In this case the elem shouldn't be rendered, hence scale == 0
scaleX = scaleY = skew = 0;
}
// The recomposition order is very important
// see http://hg.mozilla.org/mozilla-central/file/7cb3e9795d04/layout/style/nsStyleAnimation.cpp#l971
return [
[_translate, [+matrix[4], +matrix[5]]],
[_rotate, Math.atan2(B, A)],
[_skew + "X", Math.atan(skew)],
[_scale, [scaleX, scaleY]]
];
}
// build the list of transform functions to interpolate
// use the algorithm described at http://dev.w3.org/csswg/css3-2d-transforms/#animation
function interpolationList( start, end ) {
var list = {
start: [],
end: []
},
i = -1, l,
currStart, currEnd, currType;
// get rid of affine transform matrix
( start == "none" || isAffine( start ) ) && ( start = "" );
( end == "none" || isAffine( end ) ) && ( end = "" );
// if end starts with the current computed style, this is a relative animation
// store computed style as the origin, remove it from start and end
if ( start && end && !end.indexOf("matrix") && toArray( start ).join() == toArray( end.split(")")[0] ).join() ) {
list.origin = start;
start = "";
end = end.slice( end.indexOf(")") +1 );
}
if ( !start && !end ) { return; }
// start or end are affine, or list of transform functions are identical
// => functions will be interpolated individually
if ( !start || !end || functionList(start) == functionList(end) ) {
start && ( start = start.split(")") ) && ( l = start.length );
end && ( end = end.split(")") ) && ( l = end.length );
while ( ++i < l-1 ) {
start[i] && ( currStart = start[i].split("(") );
end[i] && ( currEnd = end[i].split("(") );
currType = $.trim( ( currStart || currEnd )[0] );
append( list.start, parseFunction( currType, currStart ? currStart[1] : 0 ) );
append( list.end, parseFunction( currType, currEnd ? currEnd[1] : 0 ) );
}
// otherwise, functions will be composed to a single matrix
} else {
list.start = unmatrix(matrix(start));
list.end = unmatrix(matrix(end))
}
return list;
}
function parseFunction( type, value ) {
var
// default value is 1 for scale, 0 otherwise
defaultValue = +(!type.indexOf(_scale)),
scaleX,
// remove X/Y from scaleX/Y & translateX/Y, not from skew
cat = type.replace( /e[XY]/, "e" );
switch ( type ) {
case _translate+"Y":
case _scale+"Y":
value = [
defaultValue,
value ?
parseFloat( value ):
defaultValue
];
break;
case _translate+"X":
case _translate:
case _scale+"X":
scaleX = 1;
case _scale:
value = value ?
( value = value.split(",") ) && [
parseFloat( value[0] ),
parseFloat( value.length>1 ? value[1] : type == _scale ? scaleX || value[0] : defaultValue+"" )
]:
[defaultValue, defaultValue];
break;
case _skew+"X":
case _skew+"Y":
case _rotate:
value = value ? toRadian( value ) : 0;
break;
case _matrix:
return unmatrix( value ? toArray(value) : [1,0,0,1,0,0] );
break;
}
return [[ cat, value ]];
}
function isAffine( matrix ) {
return rAffine.test(matrix);
}
function functionList( transform ) {
return transform.replace(/(?:\([^)]*\))|\s/g, "");
}
function append( arr1, arr2, value ) {
while ( value = arr2.shift() ) {
arr1.push( value );
}
}
// converts an angle string in any unit to a radian Float
function toRadian(value) {
return ~value.indexOf("deg") ?
parseInt(value,10) * (Math.PI * 2 / 360):
~value.indexOf("grad") ?
parseInt(value,10) * (Math.PI/200):
parseFloat(value);
}
// Converts "matrix(A,B,C,D,X,Y)" to [A,B,C,D,X,Y]
function toArray(matrix) {
// remove the unit of X and Y for Firefox
matrix = /([^,]*),([^,]*),([^,]*),([^,]*),([^,p]*)(?:px)?,([^)p]*)(?:px)?/.exec(matrix);
return [matrix[1], matrix[2], matrix[3], matrix[4], matrix[5], matrix[6]];
}
$.transform = {
centerOrigin: "margin"
};
})( jQuery, window, document, Math );

92
dependencies/transform3d.js

@ -0,0 +1,92 @@
/*
* transform: A jQuery cssHooks adding 2D/3D transform capabilities to $.fn.css() and $.fn.animate()
*
* Requirements:
* - jQuery 1.5.1+
* - jquery.transition.js for animations
* - browser implementing W3C's CSS 2DTransforms for 2D tranform
* - browser implementing W3C's CSS 3DTransforms for 3D tranform
*
* latest version and complete README available on Github:
* https://github.com/louisremi/jquery.transform.js
*
* Copyright 2011 @louis_remi
* Licensed under the MIT license.
*
* This saved you an hour of work?
* Send me music http://www.amazon.co.uk/wishlist/HNTU0468LQON
*
*/
(function( $, window, document ) {
"use strict";
var div = document.createElement("div"),
divStyle = div.style,
prefixes = [
"O",
"ms",
"Webkit",
"Moz"
],
prefix,
i = prefixes.length,
properties = [
"transform",
"transformOrigin",
"transformStyle",
"perspective",
"perspectiveOrigin",
"backfaceVisibility"
],
property,
j = prefixes.length;
// Find the right prefix
while ( i-- ) {
if ( prefixes[i] + leadingUppercase( properties[0] ) in divStyle ) {
prefix = prefixes[i];
continue;
}
}
// This browser is not compatible with transforms
if ( !prefix ) { return; }
// Build cssHooks for each property
while ( j-- ) {
property = prefix + leadingUppercase( properties[j] );
if ( property in divStyle ) {
// px isn't the default unit of this property
$.cssNumber[ properties[j] ] = true;
// populate cssProps
$.cssProps[ properties[j] ] = property;
// MozTranform requires a complete hook because "px" is required in translate
property === "MozTransform" && ($.cssHooks[ properties[j] ] = {
get: function( elem, computed ) {
return (computed ?
// remove "px" from the computed matrix
$.css( elem, property ).split("px").join(""):
elem.style[property]
);
},
set: function( elem, value ) {
// add "px" to matrices
/matrix\([^)p]*\)/.test(value) && (
value = value.replace(/matrix((?:[^,]*,){4})([^,]*),([^)]*)/, "matrix$1$2px,$3px")
);
elem.style[property] = value;
}
});
}
}
function leadingUppercase( word ) {
return word.slice(0,1).toUpperCase() + word.slice(1);
}
})( jQuery, window, document );

114
src/origami.css

@ -0,0 +1,114 @@
/*******************************
Origami Module
*******************************/
.origami.module {
position: relative;
-webkit-perspective: 2000px;
-moz-perspective: 2000px;
-ms-perspective: 2000px;
perspective: 2000px;
}
.origami.module .box {
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.origami.module .side {
display: none;
opacity: 1;
width: 100%;
background-color: #FFFFFF;
-moz-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.3);
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.3);
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
backface-visibility: hidden;
}
/* Handle (Stubbed as image will fix) */
.origami.module .handle {
cursor: pointer;
position: absolute;
bottom: -28px;
right: 50%;
margin-left: -22px;
width: 44px;
height: 44px;
background: url(/images/modules/origami-handle.png) no-repeat 0px 0px;
}
.origami.module .down.handle {
background-position: 0px -50px;
}
/*---------------
States
----------------*/
/* Animating */
.origami.module.animating .box {
position: absolute;
}
.origami.module .animating.side {
position: absolute;
width: 100%;
top: 0px;
left: 0px;
z-index: 100;
}
.origami.module .hidden.side {
opacity: 0.5;
}
/* Animate using CSS */
.origami.css.module {
-webkit-transition:
all 0.5s ease-in-out;
;
-moz-transition:
all 0.5s ease-in-out;
;
-o-transition:
all 0.5s ease-in-out;
;
-ms-transition:
all 0.5s ease-in-out;
;
transition:
all 0.5s ease-in-out;
;
}
.origami.css.module .box {
-webkit-transition: all 0.5s ease-in-out;
-moz-transition: all 0.5s ease-in-out;
-o-transition: all 0.5s ease-in-out;
-ms-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;
}
.origami.css.module .side {
-webkit-transition: opacity 0.5s ease-out;
-moz-transition: opacity 0.5s ease-out;
-o-transition: opacity 0.5s ease-out;
-ms-transition: opacity 0.5s ease-out;
transition: opacity 0.5s ease-out;
}
/* Active */
.origami.module .active.side {
display: block;
}

502
src/origami.js

@ -0,0 +1,502 @@
/* ******************************
Module
Origami
Author: Jack Lukic
Created: Mar 28, 2013
Last revision: Mar 2013
Creates a cube which can be rotated
Usage:
$origami
.origami()
;
$origami
.origami('flip.up')
;
****************************** */
;(function ( $, window, document, undefined ) {
$.fn.origami = function(parameters) {
var
$allModules = $(this),
settings = $.extend(true, {}, $.fn.origami.settings, parameters),
// make arguments available
query = arguments[0],
passedArguments = [].slice.call(arguments, 1),
invokedResponse
;
$allModules
.each(function() {
var
// selector cache
$module = $(this),
$box = $module.find(settings.selector.box),
$side = $module.find(settings.selector.side),
$activeSide,
$nextSide,
// private variables
selector = $module.selector || '',
element = this,
instance = $module.data('module-' + settings.namespace),
methodInvoked = (typeof query == 'string'),
endTransition = 'transitionend msTransitionEnd oTransitionEnd',
// shortcuts
namespace = settings.namespace,
metadata = settings.metadata,
className = settings.className,
module
;
module = {
initialize: function() {
module.verbose('Initializing module for', element);
module.set.defaultSide();
$module
.data('module-' + namespace, module)
;
},
destroy: function() {
module.verbose('Destroying previous module for', element);
$module
.off('.' + namespace)
;
},
refresh: function() {
module.verbose('Refreshing selector cache for', element);
$module = $(element);
$box = $(this).find(settings.selector.box);
$side = $(this).find(settings.selector.side);
},
repaint: function() {
var
fakeAssignment = $module.get(0).offsetWidth
;
},
animate: function(propertyObject) {
module.verbose('Animating box with properties', propertyObject);
var
callback = function() {
module.reset();
module.set.active();
}
;
if(settings.useCSS) {
module.verbose('Using CSS transitions to animate');
$module
.addClass(className.animating)
;
module.set.stageSize();
module.repaint();
$module
.addClass(className.css)
;
$activeSide
.addClass(className.hidden)
;
$box
.css(propertyObject)
.one(endTransition, callback)
;
}
else {
// not yet supported until .animate() is extended to allow RotateX/Y
module.verbose('Using javascript to animate');
$module
.addClass(className.animating)
.removeClass(className.css)
;
module.set.stageSize();
module.repaint();
$activeSide
.animate({
opacity: 0
}, settings.duration, settings.easing)
;
$box
.animate(propertyObject, settings.duration, settings.easing, callback)
;
}
},
reset: function() {
module.verbose('Animating states reset');
$module
.removeClass(className.css)
.removeClass(className.animating)
.removeAttr('style')
;
$box
.removeAttr('style')
;
$side
.removeAttr('style')
.removeClass(className.hidden)
;
$nextSide
.removeClass(className.animating)
.removeAttr('style')
;
},
set: {
defaultSide: function() {
$activeSide = $module.find('.' + settings.className.active);
$nextSide = ( $activeSide.next(settings.selector.side).size() > 0 )
? $activeSide.next(settings.selector.side)
: $module.find(settings.selector.side).first()
;
module.verbose('Active side set to', $activeSide);
module.verbose('Next side set to', $nextSide);
},
stageSize: function() {
$module
.css({
width : $nextSide.outerWidth(),
height : $nextSide.outerHeight()
})
;
},
nextSide: function(selector) {
$nextSide = $module.find(selector);
module.verbose('Next side manually set to', $nextSide);
},
active: function() {
module.verbose('Setting new side to active', $nextSide);
$side
.removeClass(className.active)
;
$nextSide
.addClass(className.active)
;
module.set.defaultSide();
}
},
getTransform: {
up: function() {
var
translate = {
y: -(($activeSide.outerHeight() - $nextSide.outerHeight()) / 2),
z: -($activeSide.outerHeight() / 2)
}
;
return {
transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(-90deg)'
};
},
down: function() {
var
translate = {
y: -(($activeSide.outerHeight() - $nextSide.outerHeight()) / 2),
z: -($activeSide.outerHeight() / 2)
}
;
return {
transform: 'translateY(' + translate.y + 'px) translateZ('+ translate.z + 'px) rotateX(90deg)'
};
},
left: function() {
var
translate = {
x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2),
z : -($activeSide.outerWidth() / 2)
}
;
return {
transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(90deg)'
};
},
right: function() {
var
translate = {
x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2),
z : -($activeSide.outerWidth() / 2)
}
;
return {
transform: 'translateX(' + translate.x + 'px) translateZ(' + translate.z + 'px) rotateY(-90deg)'
};
}
},
stage: {
above: function() {
var
box = {
origin : (($activeSide.outerHeight() - $nextSide.outerHeight()) / 2),
depth : {
active : ($nextSide.outerHeight() / 2),
next : ($activeSide.outerHeight() / 2)
}
}
;
module.verbose('Setting the initial animation position as above', $nextSide, box);
$activeSide
.css({
'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
})
;
$nextSide
.addClass(className.animating)
.css({
'display' : 'block',
'top' : box.origin + 'px',
'transform' : 'rotateX(90deg) translateZ(' + box.depth.next + 'px)'
})
;
},
below: function() {
var
box = {
origin : (($activeSide.outerHeight() - $nextSide.outerHeight()) / 2),
depth : {
active : ($nextSide.outerHeight() / 2),
next : ($activeSide.outerHeight() / 2)
}
}
;
module.verbose('Setting the initial animation position as below', $nextSide, box);
$activeSide
.css({
'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
})
;
$nextSide
.addClass(className.animating)
.css({
'display' : 'block',
'top' : box.origin + 'px',
'transform' : 'rotateX(-90deg) translateZ(' + box.depth.next + 'px)'
})
;
},
left: function() {
var
box = {
origin : ( ( $activeSide.outerWidth() - $nextSide.outerWidth() ) / 2),
depth : {
active : ($nextSide.outerWidth() / 2),
next : ($activeSide.outerWidth() / 2)
}
}
;
module.verbose('Setting the initial animation position as left', $nextSide, box);
$activeSide
.css({
'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
})
;
$nextSide
.addClass(className.animating)
.css({
'display' : 'block',
'left' : box.origin + 'px',
'transform' : 'rotateY(-90deg) translateZ(' + box.depth.next + 'px)'
})
;
},
right: function() {
var
box = {
origin : ( ( $activeSide.outerWidth() - $nextSide.outerWidth() ) / 2),
depth : {
active : ($nextSide.outerWidth() / 2),
next : ($activeSide.outerWidth() / 2)
}
}
;
module.verbose('Setting the initial animation position as left', $nextSide, box);
$activeSide
.css({
'transform' : 'rotateY(0deg) translateZ(' + box.depth.active + 'px)'
})
;
$nextSide
.addClass(className.animating)
.css({
'display' : 'block',
'left' : box.origin + 'px',
'transform' : 'rotateY(90deg) translateZ(' + box.depth.next + 'px)'
})
;
}
},
flip: {
up: function() {
module.debug('Flipping up', $nextSide);
module.stage.above();
module.animate( module.getTransform.up(), element);
},
down: function() {
module.debug('Flipping down', $nextSide);
module.stage.below();
module.animate( module.getTransform.down(), element);
},
left: function() {
module.debug('Flipping left', $nextSide);
module.stage.left();
module.animate(module.getTransform.left(), element);
},
right: function() {
module.debug('Flipping right', $nextSide);
module.stage.right();
module.animate(module.getTransform.right(), element);
}
},
/* standard module */
setting: function(name, value) {
if(value === undefined) {
return settings[name];
}
settings[name] = value;
},
verbose: function() {
if(settings.verbose) {
module.debug.apply(this, arguments);
}
},
debug: function() {
var
output = [],
message = settings.moduleName + ': ' + arguments[0],
variables = [].slice.call( arguments, 1 ),
log = console.info || console.log || function(){}
;
log = Function.prototype.bind.call(log, console);
if(settings.debug) {
output.push(message);
log.apply(console, output.concat(variables) );
}
},
error: function() {
var
output = [],
errorMessage = settings.moduleName + ': ' + arguments[0],
variables = [].slice.call( arguments, 1 ),
log = console.warn || console.log || function(){}
;
log = Function.prototype.bind.call(log, console);
if(settings.debug) {
output.push(errorMessage);
output.concat(variables);
log.apply(console, output.concat(variables) );
}
},
invoke: function(query, context, passedArguments) {
var
maxDepth,
found
;
passedArguments = passedArguments || [].slice.call( arguments, 2 );
if(typeof query == 'string' && instance !== undefined) {
query = query.split('.');
maxDepth = query.length - 1;
$.each(query, function(depth, value) {
if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) {
instance = instance[value];
return true;
}
else if( instance[value] !== undefined ) {
found = instance[value];
return true;
}
module.error(settings.errors.method);
return false;
});
}
if ( $.isFunction( found ) ) {
return found.apply(context, passedArguments);
}
// return retrieved variable or chain
return found;
}
};
// check for invoking internal method
if(methodInvoked) {
invokedResponse = module.invoke(query, this, passedArguments);
}
// otherwise initialize
else {
if(instance !== undefined) {
module.destroy();
}
module.initialize();
}
})
;
// chain or return queried method
return (invokedResponse !== undefined)
? invokedResponse
: this
;
};
$.fn.origami.settings = {
// module info
moduleName : 'Origami Module',
// debug output
debug : true,
// verbose debug output
verbose : true,
namespace : 'origami',
// callback occurs on side change
onChange : function() {},
useCSS : true,
duration : 1000,
easing : 'easeInOutQuad',
errors: {
api : 'You tried to switch to a side that does not exist.',
method : 'The method you called is not defined'
},
metadata : {
},
className : {
css : 'css',
animating : 'animating',
hidden : 'hidden',
active : 'active'
},
selector : {
box : '.box',
side : '.side'
}
};
})( jQuery, window , document );
Loading…
Cancel
Save