Team:WHU-China/bill.js

From 2011.igem.org

(Difference between revisions)
(Created page with "// ====================================================================== // script by Gerard Ferrandez | February, 2010 // ----------------------------------------------------...")
 
Line 1: Line 1:
-
// ======================================================================  
+
// ================================
-
// script by Gerard Ferrandez | February, 2010
+
// DHTML mini library
-
// --------------------------------------------------------------------
+
// Gerard Ferrandez - January 2007
-
// http://www.dhteumeuleu.com | http://www.twitter.com/ge1doot
+
// http://www.dhteumeuleu.com
-
// Javascript code licensed under CC-BY-NC - Do not remove this notice
+
// ================================
-
// ======================================================================  
+
 
-
+
id = function(o) {
-
var res = function () {  
+
return document.getElementById(o);
-
// ---- private vars ----
+
}
-
var scr, a0, a1,
+
 
-
divs  = new Array(),
+
px = function (x) {
-
moves  = new Array(),
+
return ''.concat(Math.round(x), 'px');
-
idle = false,
+
}
-
nw, nh, wu, hu,
+
 
-
mx = [1,0,-1,0,2,0,-2,0,3,0,-3,0,4,0,-4,0],
+
pxLeft = function(o) {
-
my = [0,1,0,-1,0,2,0,-2,0,3,0,-3,0,4,0,-4],
+
for (var x = 0; o != null; o = o.offsetParent) x += o.offsetLeft;
-
bw = 10;
+
return x;
-
+
}
-
////////////////////////////////////////////////////////////////////////////
+
 
-
// ============== grid class =============
+
pxTop = function(o) {
-
var grid = {
+
for (var x = 0; o != null; o = o.offsetParent) x += o.offsetTop;
-
// ===== calculate grid =====
+
return x;
-
calc : function () {
+
}
-
// ---- empty grid ----
+
 
-
this.grid = new Array(24);
+
/* ==== DOM 2 add event ==== */
-
for (var i = 0; i < 24; i++)
+
addEvent = function (o, e, f) {
-
this.grid[i] = 0;
+
var r = false;
-
// ---- load grid ----
+
if (window.addEventListener) {
-
var i = 0, o;
+
o.addEventListener(e, f, false);
-
while ( o = divs[i++] )
+
r = true;
-
this.add(o);  
+
} else if (window.attachEvent) {
-
},
+
r = o.attachEvent('on' + e, f);
-
// ===== return cell value =====
+
}
-
cell : function (x, y) {  
+
return r;
-
return this.grid[x * 4 + y];
+
}
-
},
+
-
// ===== area weight =====
+
-
weight : function (x, y, w, h) {
+
-
var gw = 0;
+
-
for(var i = 0; i < w; i++)
+
-
for(var j = 0; j < h; j++)
+
-
gw += this.cell(i + x, j + y);  
+
-
return gw;
+
-
},
+
-
// ===== add div =====
+
-
add : function (o) {  
+
-
for(var i = 0; i < o.w; i++)
+
-
for(var j = 0; j < o.h; j++)  
+
-
this.grid[(i + o.x) * 4 + (j + o.y)] += o.f ? 20 : 1;  
+
-
}
+
-
}
+
-
+
-
////////////////////////////////////////////////////////////////////////////
+
-
// ============== tween class =============
+
-
var tween = {
+
-
// ===== tween stack =====
+
-
divs : new Array(),
+
-
// ===== create tween object =====
+
-
tween : function (o, x, y, w, h) {
+
-
return {
+
-
div : o,
+
-
x : x,
+
-
y : y,
+
-
w : w,
+
-
h : h
+
-
};  
+
-
},
+
-
// ===== add new tween =====
+
-
add : function (o, x, y, w, h) {  
+
-
if (o == true) return false;
+
-
// ---- consolidate with last move ----
+
-
var t = this.divs.length - 1;
+
-
if (t >= 0 && this.divs[t].div == o)
+
-
this.divs[t] = this.tween(o, x, y, w, h);
+
-
else {
+
-
// ---- push tween ----
+
-
this.divs.push(
+
-
this.tween(o, x, y, w, h)
+
-
);
+
-
}
+
-
},
+
-
// ======== start next tween =========
+
-
next : function () {
+
-
if (this.divs.length) {
+
-
var t = this.divs[0];  
+
-
var o = t.div;  
+
-
o.dx = t.x - o.xc;
+
-
o.dy = t.y - o.yc;
+
-
o.dw = t.w - o.wc;
+
-
o.dh = t.h - o.hc;
+
-
o.s = 1;
+
-
o.p = 0;
+
-
return o;
+
-
} else return false;
+
-
}
+
-
}
+
-
////////////////////////////////////////////////////////////////////////////
+
-
// =============== Div constructor ===============
+
-
var Frame = function (i, div) {
+
-
// ---- random position ----
+
-
do {
+
-
this.x = this.x0 = Math.floor(Math.random() * 6);
+
-
this.y = this.y0 = Math.floor(Math.random() * 4);
+
-
} while (moves[this.x * 4 + this.y]);
+
-
moves[this.x * 4 + this.y] = true;
+
-
// ---- dimensions ----
+
-
var img = div.getElementsByTagName("img")[0];
+
-
var wh = img.alt.split(",");
+
-
img.alt = "";
+
-
this.w = 1;
+
-
this.h = 1;
+
-
this.xc = this.x + .5;
+
-
this.yc = this.y + .5;
+
-
this.wc = 0;
+
-
this.hc = 0;
+
-
this.w1 = wh[0] * 1;
+
-
this.h1 = wh[1] * 1;
+
-
this.i = i;
+
-
this.s = 0;
+
-
div.parent = this;
+
-
div.onclick = function () { this.parent.click(); }
+
-
this.css = div.style;
+
-
// ---- push tween ----
+
-
tween.add(this, this.x, this.y, 1, 1);  
+
-
}
+
-
+
-
// ========== calculate moving cost ===========
+
-
Frame.prototype.costMove = function (m) {
+
-
// ---- what direction ----
+
-
var sx = mx[m] > 0 ? 1 : mx[m] < 0 ? -1 : 0,
+
-
    sy = my[m] > 0 ? 1 : my[m] < 0 ? -1 : 0,
+
-
    cm = 0;
+
-
// ---- horizontal ----
+
-
if (sx != 0) {
+
-
for (var i = this.x; i != this.x + mx[m]; i += sx)
+
-
cm += grid.weight(i, this.y, this.w, this.h);
+
-
// ---- vertical ----
+
-
} else if (sy != 0) {
+
-
for (var i = this.y; i != this.y + my[m]; i += sy)
+
-
cm += grid.weight(this.x, i, this.w, this.h);
+
-
}
+
-
// ---- return cost ----
+
-
return cm;
+
-
}
+
-
+
-
// ============ determine moving direction =============
+
-
Frame.prototype.findMove = function () {
+
-
var d = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+
-
    mx = 1000,
+
-
    cm, m;
+
-
// =========== loop distance ============
+
-
for (var p = 0; p < 4 && mx >= 20; p++) {
+
-
// ======== vertical neighbors weights ========
+
-
for (var i = 0; i < this.w; i++) {
+
-
// ---- up ----
+
-
if (this.y - p > 0)
+
-
d[3 + p * 4] += grid.cell(this.x + i, this.y - (p + 1));
+
-
else
+
-
// ---- border ----
+
-
d[3 + p * 4] = 100;
+
-
// ---- bottom ----
+
-
if (this.y + p + this.h < 4)
+
-
d[1 + p * 4] += grid.cell(this.x + i, this.y + this.h + p);
+
-
else
+
-
// ---- border ----
+
-
d[1 + p * 4] = 100;
+
-
}
+
-
// ======== horizontal neighbors weights ========
+
-
for (var j = 0; j < this.h; j++) {
+
-
// ---- left ----
+
-
if (this.x - p > 0)
+
-
d[2 + p * 4] += grid.cell(this.x - (p + 1), this.y + j);
+
-
else
+
-
// ---- border ----
+
-
d[2 + p * 4] = 100;
+
-
// ---- right ----
+
-
if (this.x + this.w + p < 6)
+
-
d[0 + p * 4] += grid.cell(this.x + this.w + p, this.y + j);
+
-
else
+
-
// ---- border ----
+
-
d[0 + p * 4] = 100;
+
-
}
+
-
// =============== find direction to the weakest neighbor ================
+
-
mx = 1000;
+
-
for (var i = 0; i < 4 * (p + 1); i++) {
+
-
if ( d[i] < mx) {
+
-
// ---- store min values ----
+
-
mx = d[i];
+
-
m = i;
+
-
cm = this.costMove(i);
+
-
// ---- equality case ----
+
-
} else if ( d[i] == mx) {
+
-
// ---- less costly move ----
+
-
var cmm = this.costMove(i);
+
-
if (cmm < cm) {
+
-
cm = cmm;
+
-
m = i;
+
-
mx = d[i];
+
-
}
+
-
}
+
-
}
+
-
}
+
-
// ====== return direction [0 = right, 1 = bottom, 2 = left, 3 = up] ======
+
-
return m;
+
-
}
+
-
+
-
// ============ HTML rendering =============
+
-
Frame.prototype.paint = function () {
+
-
this.css.left  = Math.round(bw + this.xc * wu) + "px";
+
-
this.css.top    = Math.round(bw + this.yc * hu) + "px";
+
-
this.css.width  = Math.round(Math.max(0, this.wc * wu - bw)) + "px";
+
-
this.css.height = Math.round(Math.max(0, this.hc * hu - bw)) + "px";
+
-
}
+
-
+
-
// ========== easing function ==============
+
-
Frame.prototype.tween = function () {  
+
-
if (this.s != 0) {
+
-
// ---- easing ----
+
-
this.p += this.s;
+
-
this.xc += this.dx * this.p * .01;
+
-
this.yc += this.dy * this.p * .01;
+
-
this.wc += this.dw * this.p * .01;
+
-
this.hc += this.dh * this.p * .01;
+
-
// ---- HTML rendering ----
+
-
this.paint();
+
-
// ---- percentage steps [1+2+3+4+5+6+7+8+9+10+9+8+7+6+5+4+3+2+1=100] ----
+
-
if (this.p == 10)
+
-
// ---- reverse acceleration
+
-
this.s = -1;
+
-
else if (this.p == 0)
+
-
// ---- moving end
+
-
this.s = false;
+
-
}
+
-
return this.s;
+
-
}
+
-
+
-
// ============= Main IA function for moving divs ===============
+
-
Frame.prototype.click = function () {
+
-
if (moves.length) {
+
-
var i = 0, o;
+
-
while ( o = moves[i++] ) {
+
-
o.f = false;  
+
-
// ---- zoom out ----
+
-
if (o.w != 1 || o.h != 1) {  
+
-
o.w = 1;
+
-
o.h = 1;
+
-
tween.add(o, o.x, o.y, o.w, o.h);
+
-
}
+
-
}
+
-
}
+
-
// ---- stop here if same div ----
+
-
if (moves[0] == this)
+
-
moves = new Array();
+
-
else {
+
-
// ---- init grid weights ----
+
-
moves = new Array();
+
-
grid.calc();
+
-
// =========== find the best place for the zoomed div ===========
+
-
var mvx = 0,
+
-
    mvy = 0;
+
-
// ---- right border limit ----
+
-
if (this.y + this.h1 > 3)
+
-
this.y -= this.y + this.h1 - 4;
+
-
else {
+
-
// ---- vertical backward move ----
+
-
for (var i = this.y - 1; i > this.y - this.h - 1; i--)
+
-
if (i >= 0 && grid.weight(this.x, i, this.w1, 1) == 0)
+
-
mvy++;
+
-
}
+
-
// ---- bottom border limit ----
+
-
if (this.x + this.w1 > 5)
+
-
this.x -= this.x + this.w1 - 6;
+
-
else if (!mvy) {
+
-
// ---- horizontal backward move ----
+
-
for (var i = this.x - 1; i > this.x - this.w - 1; i--)
+
-
if (i >= 0 && grid.weight(i, this.y, 1, this.h1) == 0)
+
-
mvx++;
+
-
}
+
-
// ============ move zoomed div =============
+
-
this.x -= mvx;
+
-
this.y -= mvy;
+
-
this.w = this.w1;
+
-
this.h = this.h1;
+
-
this.f = true;
+
-
this.findMove();
+
-
grid.add(this);
+
-
moves.push(this);
+
-
// ========= cascading child moves ==========
+
-
var k = 0, o;
+
-
// ---- loop through all divs ----
+
-
while ( o = divs[k++] ) {
+
-
// ---- skip frozen div ----
+
-
if (o.f != true) {
+
-
// ---- loop through all cells ----
+
-
for (var i = 0; i < o.w; i++) {
+
-
for (var j = 0; j < o.h; j++) {
+
-
// ---- collision (non empty cell) ----
+
-
if (grid.cell(i + o.x, j + o.y) > 1) {
+
-
// ---- move to a better place ----
+
-
var m = o.findMove();
+
-
o.x += mx[m];
+
-
o.y += my[m];
+
-
// ---- not inside another one ? ----
+
-
if (grid.weight(o.x, o.y, o.w, o.h) < 20) {
+
-
// ---- freeze div and push move ----
+
-
o.f = true;
+
-
grid.add(o);
+
-
moves.push(o);
+
-
// ---- reset main loop and exit ----
+
-
k = 0;
+
-
break;
+
-
}
+
-
}
+
-
}
+
-
if (o.f) break;
+
-
}
+
-
}
+
-
}
+
-
// ========= push moves in reverse order =========
+
-
var i = moves.length, o;
+
-
while ( o = moves[--i] )
+
-
tween.add(o, o.x, o.y, o.w, o.h);  
+
-
}
+
-
// ---- start tweens engine ----
+
-
a0 = tween.next();  
+
-
if (idle) {
+
-
idle = false;
+
-
run();
+
-
}
+
-
}  
+
-
+
-
// ============== main loop ================
+
-
var run = function () {
+
-
// ---- first tween ----
+
-
if (a0) {
+
-
a0.tween();
+
-
if (a0.p == 10) {  
+
-
// ---- next ----
+
-
a1 = a0;
+
-
tween.divs.splice(0,1);
+
-
a0 = tween.next();
+
-
}
+
-
}
+
-
// ---- second tween ----
+
-
if (a1) {
+
-
a1.tween();
+
-
// ---- end anim ----
+
-
if (a1.s === false)
+
-
a1 = false;
+
-
}
+
-
// ---- loop ----
+
-
if (a0 || a1) setTimeout(run, 32);
+
-
else idle = true;
+
-
}
+
-
// ============== init script ==============
+
-
var init = function () {
+
-
// ---- init container ----
+
-
scr = document.getElementById('screen');
+
-
// ---- load divs ----
+
-
var k = 0, o;
+
-
while ( o = scr.getElementsByTagName("div")[k++] )
+
-
divs.push(
+
-
new Frame(k, o)
+
-
);
+
-
// ---- ajust dimensions ----
+
-
nw = scr.offsetWidth - bw;
+
-
nh = scr.offsetHeight - bw;
+
-
wu = nw / 6;
+
-
hu = nh / 4;
+
-
// ---- start animation -----
+
-
a0 = tween.next();
+
-
run();  
+
-
}  
+
-
return {
+
-
// ==== public bloc ====
+
-
init : init
+
-
}  
+
-
}();
+

Latest revision as of 18:15, 2 October 2011

// ================================ // DHTML mini library // Gerard Ferrandez - January 2007 // http://www.dhteumeuleu.com // ================================

id = function(o) { return document.getElementById(o); }

px = function (x) { return .concat(Math.round(x), 'px'); }

pxLeft = function(o) { for (var x = 0; o != null; o = o.offsetParent) x += o.offsetLeft; return x; }

pxTop = function(o) { for (var x = 0; o != null; o = o.offsetParent) x += o.offsetTop; return x; }

/* ==== DOM 2 add event ==== */ addEvent = function (o, e, f) { var r = false; if (window.addEventListener) { o.addEventListener(e, f, false); r = true; } else if (window.attachEvent) { r = o.attachEvent('on' + e, f); } return r; }