Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

- add unit test runner

- author tests
- fix copyright
- remake
  • Loading branch information...
commit a057abe8d108d86ff830fe4e03870f7143c9eeda 1 parent 84e4bda
@ded authored
View
3  .gitmodules
@@ -0,0 +1,3 @@
+[submodule "support/sink"]
+ path = support/sink
+ url = git://github.com/ded/sink-test.git
View
145 morpheus.js
@@ -1,14 +1,12 @@
/*!
- * Morpheus - An animation framework
- * copyright Dustin Diaz 2011
- * https://github.com/ded/morpheus
+ * Morpheus - A Brilliant Animator
+ * https://github.com/ded/morpheus - (c) Dustin Diaz 2011
* License MIT
*/
!function (context, doc) {
var ie = /msie/i.test(navigator.userAgent),
hex = "0123456789abcdef",
- digit = /^-?[\d\.]+$/,
px = 'px',
unitless = { lineHeight: 1, zoom: 1, zIndex: 1, opacity: 1 },
getStyle = doc.defaultView && doc.defaultView.getComputedStyle ?
@@ -39,66 +37,92 @@
function (el, property) {
return el.style[camelize(property)];
+ },
+ RGBtoHex = function () {
+ function hx(n) {
+ n = parseInt(n, 10);
+ if (n === 0 || isNaN(n)) {
+ return '00';
+ }
+ n = Math.max(0, n);
+ n = Math.min(n, 255);
+ n = Math.round(n);
+ return hex.charAt((n - n % 16) / 16) + hex.charAt(n % 16);
+ }
+ return function (r, g, b) {
+ return hx(r) + hx(g) + hx(b);
};
+ }(),
+ toHex = function (c) {
+ var m = /rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(c);
+ return (m ? '#' + RGBtoHex(m[1], m[2], m[3]) : c)
+ .replace(/#(\w)(\w)(\w)$/, '#$1$1$2$2$3$3'); // short to long
+ },
+ camelize = function (s) {
+ return s.replace(/-(.)/g, function (m, m1) {
+ return m1.toUpperCase();
+ });
+ };
- function toHex(c) {
- var m = /rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(c);
- return (m ? '#' + (m[1] << 16 | m[2] << 8 | m[3]).toString(16) : c)
- .replace(/#(\w)(\w)(\w)$/, '#$1$1$2$2$3$3'); // from short to long
- }
-
- function camelize(s) {
- return s.replace(/-(.)/g, function (m, m1) {
- return m1.toUpperCase();
- });
+ function tween(duration, fn, done, ease, from, to) {
+ ease = ease || function (t) {
+ return Math.sin(t * Math.PI / 2)
+ };
+ var self = this,
+ time = duration || 1000,
+ diff = to - from,
+ start = new Date(),
+ timer = setTimeout(run, 5);
+
+ function run() {
+ var delta = new Date() - start;
+ if (delta > time) {
+ fn(to || 1);
+ done && done();
+ timer = null;
+ return;
+ }
+ to ?
+ fn((diff * ease(delta / time)) + from) :
+ fn(ease(delta / time));
+ setTimeout(run, 5);
+ }
}
+ function nextColor(pos, start, finish) {
+ var r = [], i;
+ for (i = 0; i < 6; i++) {
+ from = hex.indexOf(start[i]);
+ to = hex.indexOf(finish[i]);
+ r[i] = hex[Math.floor((to - from) * pos + from)];
+ }
+ return '#' + r.join('');
+ }
- function tween(duration, fn, done, ease, from, to) {
- ease = ease || function (t) {
- return Math.sin(t * Math.PI / 2)
- };
- var self = this,
- time = duration || 1000,
- diff = to - from,
- start = new Date(),
- timer = setTimeout(run, 5);
-
- function run() {
- var delta = new Date() - start;
- if (delta > time) {
- fn(to || 1);
- done && done();
- timer = null;
- return;
- }
- to ?
- fn((diff * ease(delta / time)) + from) :
- fn(ease(delta / time));
- setTimeout(run, 5);
- }
- }
+ function getVal(pos, options, begin, end, k, i, v) {
+ if (typeof begin[i][k] == 'string') {
+ return nextColor(pos, begin[i][k], end[i][k]);
+ } else {
+ v = (end[i][k] - begin[i][k]) * pos + begin[i][k];
+ !(k in unitless) && (v += px);
+ return v;
+ }
+ }
- tween.color = function (duration, from, to, fn, done, ease) {
- var start = toHex(from).slice(1),
- finish = toHex(to).slice(1);
- tween(duration, function (pos) {
- var r = [], i;
- for (i = 0; i < 6; i++) {
- from = hex.indexOf(start[i]);
- to = hex.indexOf(finish[i]);
- r[i] = hex[Math.floor((to - from) * pos + from)];
- }
- fn('#' + r.join(''));
- }, done, ease);
- }
+ function by(val, start, m, r, i) {
+ return (m = /^([+\-])=([\d\.]+)/.exec(val)) ?
+ (i = parseInt(m[2], 10)) && (r = (start + i)) && m[1] == '+' ?
+ r : start - i :
+ parseInt(val, 10);
+ }
function morpheus(elements, options) {
var els = elements ? (els = isFinite(elements.length) ? elements : [elements]) : [], i,
complete = options.complete,
duration = options.duration,
ease = options.easing,
- begin = [];
+ begin = [],
+ end = [];
delete options.complete;
delete options.duration;
delete options.easing;
@@ -106,24 +130,25 @@
// record beginning "from" state
for (i = els.length; i--;) {
begin[i] = {};
+ end[i] = {};
for (var k in options) {
- var v = options[k];
- digit.test(v) && !(k in unitless) && (v += px);
- begin[i][k] = parseInt(getStyle(els[i], k), 10);
+ var v = getStyle(els[i], k);
+ begin[i][k] = typeof options[k] == 'string' && options[k][0] == '#' ? toHex(v).slice(1) : parseFloat(v, 10);
+ end[i][k] = typeof options[k] == 'string' && options[k][0] == '#' ? toHex(options[k]).slice(1) : by(options[k], parseFloat(v, 10));
}
}
- // (p = camelize(k)) && digit.test(v) && !(p in unitless) && (v += px);
// one tween to rule them all
- tween(duration, function (pos) {
+ tween(duration, function (pos, v) {
for (i = els.length; i--;) {
for (var k in options) {
- var val = (options[k] - begin[i][k]) * pos + begin[i][k];
- els[i].style[k] = val + 'px';
+ v = getVal(pos, options, begin, end, k, i);
+ ie && k == 'opacity' ?
+ (els[i].filter = 'alpha(opacity=' + (v * 100) + ')') :
+ (els[i].style[camelize(k)] = v);
}
}
}, complete, ease);
-
}
typeof module !== 'undefined' && module.exports &&
View
7 morpheus.min.js
@@ -1,7 +1,6 @@
/*!
- * Morpheus - An animation framework
- * copyright Dustin Diaz 2011
- * https://github.com/ded/morpheus
+ * Morpheus - A Brilliant Animator
+ * https://github.com/ded/morpheus - (c) Dustin Diaz 2011
* License MIT
*/
-!function(a,b){function l(a,b){var c=a?c=isFinite(a.length)?a:[a]:[],d,i=b.complete,j=b.duration,l=b.easing,m=[];delete b.complete,delete b.duration,delete b.easing;for(d=c.length;d--;){m[d]={};for(var n in b){var o=b[n];e.test(o)&&!(n in g)&&(o+=f),m[d][n]=parseInt(h(c[d],n),10)}}k(j,function(a){for(d=c.length;d--;)for(var e in b){var f=(b[e]-m[d][e])*a+m[d][e];c[d].style[e]=f+"px"}},i,l)}function k(a,b,c,d,e,f){function l(){var a=new Date-j;a>h?(b(f||1),c&&c(),k=null):(f?b(i*d(a/h)+e):b(d(a/h)),setTimeout(l,5))}d=d||function(a){return Math.sin(a*Math.PI/2)};var g=this,h=a||1e3,i=f-e,j=new Date,k=setTimeout(l,5)}function j(a){return a.replace(/-(.)/g,function(a,b){return b.toUpperCase()})}function i(a){var b=/rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(a);return(b?"#"+(b[1]<<16|b[2]<<8|b[3]).toString(16):a).replace(/#(\w)(\w)(\w)$/,"#$1$1$2$2$3$3")}var c=/msie/i.test(navigator.userAgent),d="0123456789abcdef",e=/^-?[\d\.]+$/,f="px",g={lineHeight:1,zoom:1,zIndex:1,opacity:1},h=b.defaultView&&b.defaultView.getComputedStyle?function(a,c){var d=null,e=b.defaultView.getComputedStyle(a,"");e&&(d=e[j(c)]);return a.style[c]||d}:c&&html.currentStyle?function(a,b){b=j(b);if(b=="opacity"){var c=100;try{c=a.filters["DXImageTransform.Microsoft.Alpha"].opacity}catch(d){try{c=a.filters("alpha").opacity}catch(e){}}return c/100}var f=a.currentStyle?a.currentStyle[b]:null;return a.style[b]||f}:function(a,b){return a.style[j(b)]};k.color=function(a,b,c,e,f,g){var h=i(b).slice(1),j=i(c).slice(1);k(a,function(a){var f=[],g;for(g=0;g<6;g++)b=d.indexOf(h[g]),c=d.indexOf(j[g]),f[g]=d[Math.floor((c-b)*a+b)];e("#"+f.join(""))},f,g)},typeof module!="undefined"&&module.exports&&(module.exports=l),a.morpheus=l}(this,document)
+!function(a,b){function o(a,b){var d=a?d=isFinite(a.length)?a:[a]:[],e,f=b.complete,h=b.duration,l=b.easing,o=[],p=[];delete b.complete,delete b.duration,delete b.easing;for(e=d.length;e--;){o[e]={},p[e]={};for(var q in b){var r=g(d[e],q);o[e][q]=typeof b[q]=="string"&&b[q][0]=="#"?i(r).slice(1):parseFloat(r,10),p[e][q]=typeof b[q]=="string"&&b[q][0]=="#"?i(b[q]).slice(1):n(b[q],parseFloat(r,10))}}k(h,function(a,f){for(e=d.length;e--;)for(var g in b)f=m(a,b,o,p,g,e),c&&g=="opacity"?d[e].filter="alpha(opacity="+f*100+")":d[e].style[j(g)]=f},f,l)}function n(a,b,c,d,e){return(c=/^([+\-])=([\d\.]+)/.exec(a))?(e=parseInt(c[2],10))&&(d=b+e)&&c[1]=="+"?d:b-e:parseInt(a,10)}function m(a,b,c,d,g,h,i){if(typeof c[h][g]=="string")return l(a,c[h][g],d[h][g]);i=(d[h][g]-c[h][g])*a+c[h][g],!(g in f)&&(i+=e);return i}function l(a,b,c){var e=[],f;for(f=0;f<6;f++)from=d.indexOf(b[f]),to=d.indexOf(c[f]),e[f]=d[Math.floor((to-from)*a+from)];return"#"+e.join("")}function k(a,b,c,d,e,f){function l(){var a=new Date-j;a>h?(b(f||1),c&&c(),k=null):(f?b(i*d(a/h)+e):b(d(a/h)),setTimeout(l,5))}d=d||function(a){return Math.sin(a*Math.PI/2)};var g=this,h=a||1e3,i=f-e,j=new Date,k=setTimeout(l,5)}var c=/msie/i.test(navigator.userAgent),d="0123456789abcdef",e="px",f={lineHeight:1,zoom:1,zIndex:1,opacity:1},g=b.defaultView&&b.defaultView.getComputedStyle?function(a,c){var d=null,e=b.defaultView.getComputedStyle(a,"");e&&(d=e[j(c)]);return a.style[c]||d}:c&&html.currentStyle?function(a,b){b=j(b);if(b=="opacity"){var c=100;try{c=a.filters["DXImageTransform.Microsoft.Alpha"].opacity}catch(d){try{c=a.filters("alpha").opacity}catch(e){}}return c/100}var f=a.currentStyle?a.currentStyle[b]:null;return a.style[b]||f}:function(a,b){return a.style[j(b)]},h=function(){function a(a){a=parseInt(a,10);if(a===0||isNaN(a))return"00";a=Math.max(0,a),a=Math.min(a,255),a=Math.round(a);return d.charAt((a-a%16)/16)+d.charAt(a%16)}return function(b,c,d){return a(b)+a(c)+a(d)}}(),i=function(a){var b=/rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(a);return(b?"#"+h(b[1],b[2],b[3]):a).replace(/#(\w)(\w)(\w)$/,"#$1$1$2$2$3$3")},j=function(a){return a.replace(/-(.)/g,function(a,b){return b.toUpperCase()})};typeof module!="undefined"&&module.exports&&(module.exports=o),a.morpheus=o}(this,document)
View
5 src/copyright.js
@@ -1,6 +1,5 @@
/*!
- * Morpheus - An animation framework
- * copyright Dustin Diaz 2011
- * https://github.com/ded/morpheus
+ * Morpheus - A Brilliant Animator
+ * https://github.com/ded/morpheus - (c) Dustin Diaz 2011
* License MIT
*/
View
76 src/morpheus.js
@@ -35,8 +35,10 @@
},
RGBtoHex = function () {
function hx(n) {
- n = parseInt(n);
- if (n == 0 || isNaN(n)) return '00';
+ n = parseInt(n, 10);
+ if (n === 0 || isNaN(n)) {
+ return '00';
+ }
n = Math.max(0, n);
n = Math.min(n, 255);
n = Math.round(n);
@@ -47,10 +49,10 @@
};
}(),
toHex = function (c) {
- var m = /rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(c);
- return (m ? '#' + RGBtoHex(m[1], m[2], m[3]) : c)
- .replace(/#(\w)(\w)(\w)$/, '#$1$1$2$2$3$3'); // short to long
- },
+ var m = /rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(c);
+ return (m ? '#' + RGBtoHex(m[1], m[2], m[3]) : c)
+ .replace(/#(\w)(\w)(\w)$/, '#$1$1$2$2$3$3'); // short to long
+ },
camelize = function (s) {
return s.replace(/-(.)/g, function (m, m1) {
return m1.toUpperCase();
@@ -58,38 +60,38 @@
};
function tween(duration, fn, done, ease, from, to) {
- ease = ease || function (t) {
- return Math.sin(t * Math.PI / 2)
- };
- var self = this,
- time = duration || 1000,
- diff = to - from,
- start = new Date(),
- timer = setTimeout(run, 5);
+ ease = ease || function (t) {
+ return Math.sin(t * Math.PI / 2)
+ };
+ var self = this,
+ time = duration || 1000,
+ diff = to - from,
+ start = new Date(),
+ timer = setTimeout(run, 5);
- function run() {
- var delta = new Date() - start;
- if (delta > time) {
- fn(to || 1);
- done && done();
- timer = null;
- return;
- }
- to ?
- fn((diff * ease(delta / time)) + from) :
- fn(ease(delta / time));
- setTimeout(run, 5);
- }
- }
+ function run() {
+ var delta = new Date() - start;
+ if (delta > time) {
+ fn(to || 1);
+ done && done();
+ timer = null;
+ return;
+ }
+ to ?
+ fn((diff * ease(delta / time)) + from) :
+ fn(ease(delta / time));
+ setTimeout(run, 5);
+ }
+ }
function nextColor(pos, start, finish) {
var r = [], i;
- for (i = 0; i < 6; i++) {
- from = hex.indexOf(start[i]);
- to = hex.indexOf(finish[i]);
- r[i] = hex[Math.floor((to - from) * pos + from)];
- }
- return '#' + r.join('');
+ for (i = 0; i < 6; i++) {
+ from = hex.indexOf(start[i]);
+ to = hex.indexOf(finish[i]);
+ r[i] = hex[Math.floor((to - from) * pos + from)];
+ }
+ return '#' + r.join('');
}
function getVal(pos, options, begin, end, k, i, v) {
@@ -103,7 +105,7 @@
}
function by(val, start, m, r, i) {
- return (m = /^([+-])=([\d\.]+)/.exec(val)) ?
+ return (m = /^([+\-])=([\d\.]+)/.exec(val)) ?
(i = parseInt(m[2], 10)) && (r = (start + i)) && m[1] == '+' ?
r : start - i :
parseInt(val, 10);
@@ -132,9 +134,9 @@
}
// one tween to rule them all
- tween(duration, function (pos, v, k) {
+ tween(duration, function (pos, v) {
for (i = els.length; i--;) {
- for (k in options) {
+ for (var k in options) {
v = getVal(pos, options, begin, end, k, i);
ie && k == 'opacity' ?
(els[i].filter = 'alpha(opacity=' + (v * 100) + ')') :
1  support/sink
@@ -0,0 +1 @@
+Subproject commit 5b82553c81a3561b6525e72468caeeb3557687d4
View
137 tests/tests.html
@@ -0,0 +1,137 @@
+<!DOCTYPE HTML>
+<html lang="en-us">
+ <head>
+ <title>Morpheus Tests</title>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+ <style type="text/css" media="screen">
+ #fixtures {
+ position: absolute;
+ top: -999px;
+ }
+ #test {
+ left: 5px;
+ top: 5px;
+ position: relative;
+ }
+ </style>
+ <link rel="stylesheet" href="../support/sink/src/sink.css" type="text/css">
+ <script src="../support/sink/src/sink.js"></script>
+ <script src="../src/morpheus.js" type="text/javascript"></script>
+ </head>
+ <body>
+ <h1>Morpheus Tests</h1>
+ <div id="fixtures">
+ <div id="test"></div>
+ </div>
+ <ol id="tests"></ol>
+
+ <script>
+ sink('Integers', function(test, ok, before, after) {
+ var el = document.getElementById('test');
+ before(function () {
+ el.style.left = 0;
+ el.style.top = '10px';
+ })
+ test('should accept non-pixel value', 1, function() {
+ morpheus(el, {
+ left: 5,
+ duration: 10,
+ complete: function () {
+ ok(el.style.left == '5px', 'el.style.left == "5px"');
+ }
+ })
+ })
+
+ test('should accept pixel value', 1, function () {
+ morpheus(el, {
+ left: '10px',
+ duration: 10,
+ complete: function () {
+ ok(el.style.left == '10px', 'el.style.left == "10px"');
+ }
+ })
+ })
+
+ test('should accept positive += offset', 2, function () {
+ morpheus(el, {
+ top: '+=10px',
+ left: '+=10',
+ duration: 10,
+ complete: function () {
+ ok(el.style.top == '20px', '10px +=10px == "20px"');
+ ok(el.style.left == '10px', '0 +=10 == "10px"');
+ }
+ })
+ })
+
+ test('should accept negative -= offset', 2, function () {
+ morpheus(el, {
+ top: '-=10px',
+ left: '-=10',
+ duration: 10,
+ complete: function () {
+ ok(el.style.top == '0px', '10px -=10px == "0px"');
+ ok(el.style.left == '-10px', '0 -=10 == "-10px"');
+ }
+ })
+ })
+
+ });
+
+ sink('Colors', function (test, ok) {
+
+ var el = document.getElementById('test');
+
+ test('should accept long hex', 1, function () {
+ morpheus(el, {
+ color: '#ff0000',
+ duration: 10,
+ complete: function () {
+ ok(el.style.color == 'rgb(255, 0, 0)', 'color is rgb(255, 0, 0)');
+ }
+ })
+ })
+
+ test('should accept short hex', 1, function () {
+ morpheus(el, {
+ color: '#f00',
+ duration: 10,
+ complete: function () {
+ ok(el.style.color == 'rgb(255, 0, 0)', 'color is rgb(255, 0, 0)');
+ }
+ })
+ })
+
+ });
+
+ sink('Syntax', function (test, ok) {
+
+ var el = document.getElementById('test');
+
+ test('should accept dashes in properties', 1, function () {
+ morpheus(el, {
+ 'font-size': 30,
+ duration: 10,
+ complete: function () {
+ ok(el.style.fontSize == '30px', 'el.style.fontSize == "30px"');
+ }
+ })
+ })
+
+ test('should accept camelCase in properties', 1, function () {
+ morpheus(el, {
+ fontSize: 50,
+ duration: 10,
+ complete: function () {
+ ok(el.style.fontSize == '50px', 'el.style.fontSize == "50px"');
+ }
+ })
+ })
+
+ })
+
+ start();
+ </script>
+
+ </body>
+</html>
Please sign in to comment.
Something went wrong with that request. Please try again.