Browse Source

lazy commit of semantic module spec inside shape.. will edit out later

Former-commit-id: b7aa684d34
Former-commit-id: 7d07d34ddf
pull/258/head
Jack Lukic 11 years ago
parent
commit
efc8bdc920
7 changed files with 947 additions and 30 deletions
  1. 8
      examples/example.css
  2. 8
      examples/index.html
  3. 1
      examples/ui/table.css
  4. 270
      src/multiple.js
  5. 30
      src/shape.css
  6. 26
      src/shape.js
  7. 634
      src/single.js

8
examples/example.css

@ -62,6 +62,14 @@ a:hover {
}
#example pre {
background-color: #F0F0F0;
}
#example code {
background-color: #F0F0F0;
border: 1px solid #DDDDDD;
padding: 3px 5px;
}
#example pre code {
}
#example p {
margin: 10px 0px;

8
examples/index.html

@ -41,13 +41,13 @@
<h3>Regular Shape</h3>
<div class="demo square shape module">
<div class="shape">
<div class="active side">
<div class="active jira side">
<img src="images/jira.png">
</div>
<div class="side">
<div class="heroku side">
<img src="images/heroku.png">
</div>
<div class="side">
<div class="quirky side">
<img src="images/quirky.png">
</div>
</div>
@ -120,7 +120,7 @@
<thead>
<th>Setting Name</th>
<th>Default Value</th>
<td>Usage</th>
<th>Usage</th>
</thead>
<tr>
<td>moduleName</td>

1
examples/ui/table.css

@ -2,6 +2,7 @@
width: 100%;
border: 1px solid #F0F0F0;
border: 1px solid rgba(0, 0, 0, 0.1);
border-collapse: collapse;
font-size: 12px;
color: #555555;

270
src/multiple.js

@ -0,0 +1,270 @@
/* *******************************************************************************************
Example Boilerplate - Multiple Instances
Version 0.1
Author : Jack Lukic
Last revision : April 2013
********************************************************************************************* */
;(function ( $, window, document, undefined ) {
$.fn.example = function(parameters) {
var
// store a reference to the module group, this can be useful to refer to other modules inside each module
$allModules = $(this),
// extend settings to merge run time settings with defaults
settings = $.extend(true, {}, $.fn.example.settings, parameters),
// define namespaces for modules
eventNamespace = '.' + settings.namespace,
moduleNamespace = 'module-' + settings.namespace,
// preserve original arguments to determine if a method is being invoked
query = arguments[0],
methodInvoked = (typeof query == 'string'),
queryArguments = [].slice.call(arguments, 1),
invokedResponse
;
// iterate over all elements to initialize module
$allModules
.each(function() {
var
// cache selectors using selector definitions for access inside instance of module
$module = $(this),
$text = $module.find(settings.selector.text),
// define private variables which can be used to maintain internal state
foo = false,
// define variables used to track module state. In semantic modules default values are set using 'a || b' syntax
selector = $module.selector || '',
instance = $module.data(moduleNamespace),
element = this,
// alias settings object for convenience and performance
namespace = settings.namespace,
error = settings.error,
className = settings.className,
// you may also find it useful to alias your own settings
text = settings.text,
module
;
// define the entire module
module = {
// initialize attaches events and preserves each instance in html metadata
initialize: function() {
module.verbose('Initializing module for', element);
$module
.on('click' + eventNamespace, module.exampleBehavior)
;
// the instance is just a copy of the module definition, we store it in metadata so we can use it outside of scope, but also define it for immediate use
instance = module;
$module
.data(moduleNamespace, instance)
;
},
// destroy removes all events and the instance from metadata
destroy: function() {
module.verbose('Destroying previous module for', element);
$module
.removeData(moduleNamespace)
.off(eventNamespace)
;
},
// selectors are cached so we need a method to manually refresh the cache
refresh: function() {
module.verbose('Refreshing selector cache for', element);
$module = $(element);
$text = $(this).find(settings.selector.text);
},
exampleBehavior: function(event) {
},
// all of your module's specific behavior goes here. In this example our module can only get and set text of a child node
has: {
text: function(state) {
return (text[state] !== undefined);
}
},
set: {
text: function(state) {
if( module.has.text(state) ) {
$text
.text( text[state] )
;
}
}
},
// module settings can be read or set using this method
setting: function(name, value) {
if( $.isPlainObject(name) ) {
$.extend(true, settings, name);
}
else if(value === undefined) {
return settings[name];
}
else {
settings[name] = value;
}
},
// verbose allows for additional data to be logged by the module which can assist in debugging
verbose: function() {
if(settings.verbose) {
module.debug.apply(this, arguments);
}
},
// debug pushes arguments to the console formatted as a debug statement
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 allows for the module to report named error messages
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 is used to lookup and invoke a method or property by its dot notation string definition
invoke: function(query, passedArguments, context) {
var
maxDepth,
found
;
passedArguments = passedArguments || queryArguments;
context = element || context;
// invoke iterates through the module instance looking for methods or properties that match the requested query
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(error.method);
return false;
});
}
if ( $.isFunction( found ) ) {
module.verbose('Executing invoked function', found);
return found.apply(context, passedArguments);
}
// return retrieved variable or chain
return found || false;
}
};
// the module checks to see if you passed in a method name to call
if(methodInvoked) {
if(instance === undefined) {
module.initialize();
}
invokedResponse = module.invoke(query);
}
// if you didn't pass in anything it can assume you are initializing the module
else {
if(instance !== undefined) {
module.destroy();
}
module.initialize();
}
})
;
// if you called invoke, you may have a returned value which shoudl be returned, otherwise allow the call to chain
return (invokedResponse)
? invokedResponse
: this
;
};
// After you define your plugin, its necessary to include a settings object which specifies the defaults for your module
$.fn.example.settings = {
// used in debug statements to refer to the module itself
moduleName : 'Todo Module',
// whether debug content should be outputted to console
debug : true,
// whether extra debug content should be outputted
verbose : true,
// a unique identifier used to namespace events, and preserve the module instance
namespace : 'example',
// callbacks are often useful to include in your settings object
onChange : function() {},
// you may also want to include settings specific to your module's function
text: {
hover: 'You are hovering me now',
click: 'You clicked on me'
},
// error messages returned by the module
error: {
side : 'You tried to switch to a side that does not exist.',
method : 'The method you called is not defined'
},
// class names which your module refers to
className : {
active : 'active'
},
// metadata stored by your module
metadata: {
},
// selectors used by your module
selector : {
example : '.example'
}
};
})( jQuery, window , document );

30
src/shape.css

@ -54,34 +54,34 @@
/* css animation */
.shape.css.module {
-webkit-transition:
all 0.5s ease-in-out;
all 0.6s ease-in-out;
;
-moz-transition:
all 0.5s ease-in-out;
all 0.6s ease-in-out;
;
-o-transition:
all 0.5s ease-in-out;
all 0.6s ease-in-out;
;
-ms-transition:
all 0.5s ease-in-out;
all 0.6s ease-in-out;
;
transition:
all 0.5s ease-in-out;
all 0.6s ease-in-out;
;
}
.shape.css.module .shape {
-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;
-webkit-transition: all 0.6s ease-in-out;
-moz-transition: all 0.6s ease-in-out;
-o-transition: all 0.6s ease-in-out;
-ms-transition: all 0.6s ease-in-out;
transition: all 0.6s ease-in-out;
}
.shape.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;
-webkit-transition: opacity 0.6s ease-out;
-moz-transition: opacity 0.6s ease-out;
-o-transition: opacity 0.6s ease-out;
-ms-transition: opacity 0.6s ease-out;
transition: opacity 0.6s ease-out;
}
/* Active */

26
src/shape.js

@ -14,12 +14,17 @@
$.fn.shape = function(parameters) {
var
$allModules = $(this),
settings = $.extend(true, {}, $.fn.shape.settings, parameters),
// define namespaces for modules
eventNamespace = '.' + settings.namespace,
moduleNamespace = 'module-' + settings.namespace,
// allow methods to be queried directly
query = arguments[0],
queryArguments = [].slice.call(arguments, 1),
methodInvoked = (typeof query == 'string'),
invokedResponse
;
@ -34,15 +39,12 @@ $.fn.shape = function(parameters) {
// private variables
$activeSide,
$nextSide,
endTransition = 'transitionend msTransitionEnd oTransitionEnd',
// standard module
selector = $module.selector || '',
element = this,
moduleName = 'module-' + settings.namespace,
instance = $module.data(moduleName),
methodInvoked = (typeof query == 'string'),
instance = $module.data(moduleNamespace),
// internal aliases
namespace = settings.namespace,
@ -59,15 +61,15 @@ $.fn.shape = function(parameters) {
module.set.defaultSide();
instance = module;
$module
.data(moduleName, instance)
.data(moduleNamespace, instance)
;
},
destroy: function() {
module.verbose('Destroying previous module for', element);
$module
.removeData(moduleName)
.off('.' + namespace)
.removeData(moduleNamespace)
.off(eventNamespace)
;
},
@ -540,7 +542,6 @@ $.fn.shape = function(parameters) {
if(typeof query == 'string' && instance !== undefined) {
query = query.split('.');
maxDepth = query.length - 1;
console.log('found is ', query, instance, context, passedArguments, found);
$.each(query, function(depth, value) {
if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) {
instance = instance[value];
@ -559,12 +560,15 @@ $.fn.shape = function(parameters) {
return found.apply(context, passedArguments);
}
// return retrieved variable or chain
return found;
return found || false;
}
};
// check for invoking internal method
if(methodInvoked) {
if(instance === undefined) {
module.initialize();
}
invokedResponse = module.invoke(query);
}
// otherwise initialize
@ -577,7 +581,7 @@ $.fn.shape = function(parameters) {
})
;
// chain or return queried method
return (invokedResponse !== undefined)
return (invokedResponse)
? invokedResponse
: this
;

634
src/single.js

@ -0,0 +1,634 @@
/* *******************************************************************************************
Shape - A 3D Animation Plugin
Version 0.1
(built using Semantic module spec)
Author : Jack Lukic
Last revision : April 2013
********************************************************************************************* */
;(function ( $, window, document, undefined ) {
$.fn.shape = function(parameters) {
var
$allModules = $(this),
settings = $.extend(true, {}, $.fn.shape.settings, parameters),
// allow methods to be queried directly
query = arguments[0],
queryArguments = [].slice.call(arguments, 1),
invokedResponse
;
$allModules
.each(function() {
var
// selector cache
$module = $(this),
$shape = $module.find(settings.selector.shape),
$side = $module.find(settings.selector.side),
// private variables
$activeSide,
$nextSide,
endTransition = 'transitionend msTransitionEnd oTransitionEnd',
// standard module
selector = $module.selector || '',
element = this,
moduleName = 'module-' + settings.namespace,
instance = $module.data(moduleName),
methodInvoked = (typeof query == 'string'),
// internal aliases
namespace = settings.namespace,
error = settings.error,
className = settings.className,
module
;
module = {
initialize: function() {
module.verbose('Initializing module for', element);
module.set.defaultSide();
instance = module;
$module
.data(moduleName, instance)
;
},
destroy: function() {
module.verbose('Destroying previous module for', element);
$module
.removeData(moduleName)
.off('.' + namespace)
;
},
refresh: function() {
module.verbose('Refreshing selector cache for', element);
$module = $(element);
$shape = $(this).find(settings.selector.shape);
$side = $(this).find(settings.selector.side);
},
repaint: function() {
module.verbose('Forcing repaint event');
var
fakeAssignment = $shape.get(0).offsetWidth
;
},
animate: function(propertyObject, callback) {
module.verbose('Animating box with properties', propertyObject);
callback = callback || function() {
module.reset();
module.set.active();
module.queue.perform();
$.proxy(settings.onChange, $nextSide)();
};
if(settings.useCSS) {
module.verbose('Starting CSS animation');
$module
.addClass(className.animating)
;
module.set.stageSize();
module.repaint();
$module
.addClass(className.css)
;
$activeSide
.addClass(className.hidden)
;
$shape
.css(propertyObject)
.one(endTransition, callback)
;
}
else {
// not yet supported until .animate() is extended to allow RotateX/Y
module.verbose('Starting javascript animation');
$module
.addClass(className.animating)
.removeClass(className.css)
;
module.set.stageSize();
module.repaint();
$activeSide
.animate({
opacity: 0
}, settings.duration, settings.easing)
;
$shape
.animate(propertyObject, settings.duration, settings.easing, callback)
;
}
},
queue: function(method) {
module.debug('Queueing animation of', method);
$shape
.one(endTransition, function() {
$module.shape(method);
})
;
},
reset: function() {
module.verbose('Animating states reset');
$module
.removeClass(className.css)
.removeClass(className.animating)
.removeAttr('style')
;
$shape
.removeAttr('style')
;
$side
.removeAttr('style')
.removeClass(className.hidden)
;
$nextSide
.removeClass(className.animating)
.removeAttr('style')
;
},
is: {
animating: function() {
return $module.hasClass(className.animating);
}
},
get: {
nextSide: function() {
return ( $activeSide.next(settings.selector.side).size() > 0 )
? $activeSide.next(settings.selector.side)
: $module.find(settings.selector.side).first()
;
}
},
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() {
var
stage = {
width : $nextSide.outerWidth(),
height : $nextSide.outerHeight()
}
;
module.verbose('Resizing stage to fit new content', stage);
$module
.css({
width : stage.width,
height : stage.height
})
;
},
nextSide: function(selector) {
$nextSide = $module.find(selector);
if($nextSide.size() === 0) {
module.error(error.side);
}
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();
}
},
flip: {
up: function() {
module.debug('Flipping up', $nextSide);
if( !module.is.animating() ) {
module.stage.above();
module.animate( module.getTransform.up() );
}
else {
module.queue('flip.up');
}
},
down: function() {
module.debug('Flipping down', $nextSide);
if( !module.is.animating() ) {
module.stage.below();
module.animate( module.getTransform.down() );
}
else {
module.queue('flip.down');
}
},
left: function() {
module.debug('Flipping left', $nextSide);
if( !module.is.animating() ) {
module.stage.left();
module.animate(module.getTransform.left() );
}
else {
module.queue('flip.left');
}
},
right: function() {
module.debug('Flipping right', $nextSide);
if( !module.is.animating() ) {
module.stage.right();
module.animate(module.getTransform.right() );
}
else {
module.queue('flip.right');
}
},
over: function() {
module.debug('Flipping over', $nextSide);
if( !module.is.animating() ) {
module.stage.behind();
module.animate(module.getTransform.behind() );
}
else {
module.queue('flip.over');
}
}
},
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)'
};
},
behind: function() {
var
translate = {
x : -(($activeSide.outerWidth() - $nextSide.outerWidth()) / 2)
}
;
return {
transform: 'translateX(' + translate.x + 'px) rotateY(180deg)'
};
}
},
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)'
})
;
},
behind: 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 behind', $nextSide, box);
$activeSide
.css({
'transform' : 'rotateY(0deg)'
})
;
$nextSide
.addClass(className.animating)
.css({
'display' : 'block',
'left' : box.origin + 'px',
'transform' : 'rotateY(-180deg)'
})
;
}
},
/* standard module */
setting: function(name, value) {
if( $.isPlainObject(name) ) {
$.extend(true, settings, name);
}
else if(value === undefined) {
return settings[name];
}
else {
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, passedArguments, context) {
var
maxDepth,
found
;
passedArguments = passedArguments || queryArguments || [].slice.call( arguments, 2 );
context = element || context;
if(typeof query == 'string' && instance !== undefined) {
query = query.split('.');
maxDepth = query.length - 1;
console.log('found is ', query, instance, context, passedArguments, found);
$.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(error.method);
return false;
});
}
if ( $.isFunction( found ) ) {
module.verbose('Executing invoked function', found);
return found.apply(context, passedArguments);
}
// return retrieved variable or chain
return found;
}
};
// check for invoking internal method
if(methodInvoked) {
invokedResponse = module.invoke(query);
}
// otherwise initialize
else {
if(instance !== undefined) {
module.destroy();
}
module.initialize();
}
})
;
// chain or return queried method
return (invokedResponse !== undefined)
? invokedResponse
: this
;
};
$.fn.shape.settings = {
// module info
moduleName : 'Shape Module',
// debug content outputted to console
debug : true,
// verbose debug output
verbose : true,
// event namespace
namespace : 'shape',
// callback occurs on side change
beforeChange : function() {},
onChange : function() {},
// use css animation (currently only true is supported)
useCSS : true,
// animation duration (useful only with future js animations)
duration : 1000,
easing : 'easeInOutQuad',
// possible errors
error: {
side : 'You tried to switch to a side that does not exist.',
method : 'The method you called is not defined'
},
// classnames used
className : {
css : 'css',
animating : 'animating',
hidden : 'hidden',
active : 'active'
},
// selectors used
selector : {
shape : '.shape',
side : '.side'
}
};
})( jQuery, window , document );
Loading…
Cancel
Save