blob: d332f21f6aa675d91fc98cc91f01519110189035 [file]
var svgns = "http://www.w3.org/2000/svg";
var xlinkns = "http://www.w3.org/1999/xlink";
function Pile(board, x, y, w, h, dx, dy, pdx, pdy) {
this.board = board;
this.doc = board.doc;
this.index = board.thePiles.length;
board.thePiles.push(this);
this.g = this.doc.createElementNS(svgns, "g");
this.g.setAttribute("id", "pile-"+this.index);
this.g.addEventListener("mousedown", new PileMouseDownHandler(this), false);
this.g.addEventListener("click", new PileClickHandler(this), false);
this.base = this.doc.createElementNS(svgns, "rect");
this.base.setAttribute("x", ""+x);
this.base.setAttribute("y", ""+y);
this.base.setAttribute("width", ""+w);
this.base.setAttribute("height", ""+h);
this.base.setAttribute("style", "visibility:hidden; pointer-events:fill");
this.g.appendChild(this.base);
board.boardGroup.appendChild(this.g);
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.dx = dx;
this.dy = dy;
this.pdx = pdx;
this.pdy = pdy;
this.cards = new Array();
var me = this;
}
Pile.prototype.addCard = function(card) {
if (card.pile) {
card.pile.removeCard(card);
}
var len = this.cards.length;
if ((this.pdx != 0) || (this.pdy !=0)) {
for (var i=0; i<len; i++) {
this.cards[i].setPos(this.x+this.pdx*len+this.dx*i,
this.y+this.pdy*len+this.dy*i);
}
}
card.pile = this;
this.cards[len] = card;
card.rect.style.setProperty("pointer-events", "fill", "");
card.setPos(this.x+this.pdx*len+this.dx*len,
this.y+this.pdy*len+this.dy*len);
this.g.appendChild(card.getElem());
}
Pile.prototype.removeCard = function(card) {
if (this != card.pile) return;
var len = this.cards.length;
for (var i=len-1; i>=0; i--) {
var c = this.cards[i];
if (c == card) {
this.cards.splice(i, 1);
len = this.cards.length;
for (var j=i; j<len; j++) {
c = this.cards[j];
c.setPos(this.x+this.dx*j, this.y+this.dy*j);
}
card.pile = null;
break;
}
}
if ((this.pdx != 0) || (this.pdy !=0)) {
var len = this.cards.length;
var x = this.x+this.pdx*(len-1);
var y = this.y+this.pdy*(len-1);
for (var i=0; i<len; i++) {
this.cards[i].setPos(x+this.dx*i, y+this.dy*i);
}
}
}
Pile.prototype.moveCardTo = function(card, step) {
if (card.pile) {
card.pile.removeCard(card);
}
var len = this.cards.length;
card.pile = this;
this.cards.push(card);
card.rect.style.setProperty("pointer-events", "fill", "");
this.board.moveGroup.appendChild(card.getElem());
var x = this.x+this.pdx*len;
var y = this.y+this.pdy*len;
card.moveTo(x+this.dx*len, y+this.dy*len, step);
}
Pile.prototype.moveCardsTo = function(cards, step) {
var xlocs = new Array();
var ylocs = new Array();
for (var i=0; i<cards.length; i++) {
xlocs[i] = cards[i].x;
ylocs[i] = cards[i].y;
}
for (var i=0; i<cards.length; i++) {
var card = cards[i];
if (card.pile) {
card.pile.removeCard(card);
}
card.setPos(xlocs[i], ylocs[i]);
var len = this.cards.length;
card.pile = this;
this.cards.push(card);
card.rect.style.setProperty("pointer-events", "fill", "");
this.board.moveGroup.appendChild(card.getElem());
var x = this.x+this.pdx*len;
var y = this.y+this.pdy*len;
card.moveTo(x+this.dx*len, y+this.dy*len, step);
this.moveCardTo(card, step);
}
}
function moveCardsToPiles(cards, piles, step) {
var xlocs = new Array();
var ylocs = new Array();
for (var i=0; i<cards.length; i++) {
xlocs[i] = cards[i].x;
ylocs[i] = cards[i].y;
}
for (var i=0; i<cards.length; i++) {
var card = cards[i];
var pile = piles[i];
if (card.pile) {
card.pile.removeCard(card);
}
card.setPos(xlocs[i], ylocs[i]);
var len = pile.cards.length;
card.pile = pile;
pile.cards.push(card);
card.rect.style.setProperty("pointer-events", "fill", "");
pile.board.moveGroup.appendChild(card.getElem());
var x = pile.x+pile.pdx*len;
var y = pile.y+pile.pdy*len;
card.moveTo(x+pile.dx*len, y+pile.dy*len, step);
pile.moveCardTo(card, step);
}
}
Pile.prototype.size = function() {
return this.cards.length;
}
Pile.prototype.getTopCard = function() {
if (this.cards.length == 0) return null;
var c = this.cards.pop();
c.pile = null;
if ((this.pdx != 0) || (this.pdy !=0)) {
var len = this.cards.length;
var x = this.x+this.pdx*(len-1);
var y = this.y+this.pdy*(len-1);
for (var i=0; i<len; i++) {
this.cards[i].setPos(x+this.dx*i, y+this.dy*i);
}
}
return c;
}
Pile.prototype.checkTopCard = function() {
if (this.cards.length == 0) return null;
return this.cards[this.cards.length-1];
}
Pile.prototype.checkCard = function(index) {
return this.cards[index];
}
Pile.prototype.nextCard = function(card) {
var sz = this.cards.length-1;
for (var i=0; i<sz; i++) {
if (this.cards[i] == card)
return this.cards[i+1];
}
return null;
}
Pile.prototype.setDragCheck = function(dragCheck) {
this.dragCheck = dragCheck;
}
Pile.prototype.setDropCheck = function(dropCheck) {
this.dropCheck = dropCheck;
}
Pile.prototype.setClick = function(click) {
this.click = click;
}
Pile.prototype.setDoubleClick = function(doubleClick) {
this.doubleClick = doubleClick;
}
function PileClickHandler(pile) {
this.pile = pile;
this.tgt = null;
this.clickX =0;
this.clickY =0;
this.clickCnt =0;
}
PileClickHandler.prototype.handleEvent = function(evt) {
if (this.tgt != evt.target) {
this.tgt = evt.target;
this.clickX = evt.clientX;
this.clickY = evt.clientY;
this.clickCnt = 1;
if (this.pile.click)
this.pile.click(this.pile, evt);
return;
}
var dx = evt.clientX-this.clickX;
var dy = evt.clientY-this.clickY;
if (dx*dx+dy*dy > 9) {
this.clickX = evt.clientX;
this.clickY = evt.clientY;
this.clickCnt = 1;
if (this.pile.click)
this.pile.click(this.pile, evt);
return;
}
this.clickX = evt.clientX;
this.clickY = evt.clientY;
this.clickCnt++;
if (this.clickCnt > 2) {
this.clickCnt = 1;
if (this.pile.click)
this.pile.click(this.pile, evt);
return;
}
if (this.pile.doubleClick) {
this.pile.doubleClick(this.pile, evt);
}
};
function PileMouseDownHandler(pile) {
this.pile = pile;
}
PileMouseDownHandler.prototype.handleEvent = function(evt) {
if (!this.pile.dragCheck) return;
var tgt = evt.target;
var e = tgt;
var p = e.parentNode;
while (p && (p != this.pile.g)) {
e = p;
p = e.parentNode;
}
if (!p) return;
var c, i;
var num = this.pile.cards.length;
for (i=num-1; i>=0; i--) {
c = this.pile.cards[i];
if (e == c.elem)
break;
c = null;
}
if (!c) return;
var g = this.pile.dragCheck(this.pile, c, i);
if (!g) return;
var cards = this.pile.cards.splice(i, num-i);
new CardMoveManager(g, this.pile, cards,
evt.clientX, evt.clientY);
}
/**
* Finds the pile associated with elem, if any.
* returns null if elem is not associated with a pile.
* otherwise it returns the associated Pile object.
*/
function findPile(board, elem) {
var root = document.getRootElement();
var tgt = elem
var destPile = null;
while (tgt != root) {
var id;
try { id = tgt.getAttribute("id"); } catch (x) { break; }
if (id && id.substring(0, 5) == "pile-") {
var idx = parseFloat(id.substring(5));
destPile = board.thePiles[idx];
break;
}
tgt = tgt.parentNode;
}
return destPile;
}
function CardMoveManager(group, pile, cards, x, y) {
this.pile = pile;
this.board = pile.board;
this.cards = cards;
this.group = group;
this.parent = group.parentNode;
this.root = this.group.getOwnerDocument().getRootElement();
this.startPt = localPt(this.parent, x, y);
this.fmm = new ForwardMouseMove(this);
this.fmu = new ForwardMouseUp(this);
this.root.addEventListener("mousemove", this.fmm, false);
this.root.addEventListener("mouseup", this.fmu, false);
this.moved = false;
};
CardMoveManager.prototype.mousemove = function(evt) {
var pt = localPt(this.parent, evt.clientX, evt.clientY);
var dx = pt.x-this.startPt.x;
var dy = pt.y-this.startPt.y;
if (!this.moved && ((dx*dx+dy*dy) < 4))
return;
if (!this.moved) {
this.moved = true;
// Now move cards
for (var i=0; i<this.cards.length; i++) {
this.cards[i].pile = null;
this.cards[i].rect.style.removeProperty("pointer-events");
this.group.appendChild(this.cards[i].elem);
}
}
this.group.setAttribute("transform", "translate(" + dx + ", " + dy + ")");
};
CardMoveManager.prototype.mouseup = function(evt) {
this.root.removeEventListener("mousemove", this.fmm, false);
this.root.removeEventListener("mouseup", this.fmu, false);
this.group.setAttribute("transform","");
if (!this.moved) {
for (var i=0; i<this.cards.length; i++) {
this.pile.cards.push(this.cards[i]);
}
return;
}
var pt = localPt(this.parent, evt.clientX, evt.clientY);
var dx = pt.x-this.startPt.x;
var dy = pt.y-this.startPt.y;
var moveInfo = false;
var destPile = findPile(this.board, evt.target);
if (destPile && destPile.dropCheck) {
moveInfo = destPile.dropCheck(this.pile, destPile, this.cards);
}
switch(moveInfo) {
case true:
// Drop succeeded but no move info.
this.pile.board.notifyMoveDone();
return;
case false:
// Drop failed move back to original.
for (var i=0; i<this.cards.length; i++) {
var c = this.cards[i];
c.setPos(c.x+dx, c.y+dy);
}
this.pile.moveCardsTo(this.cards, 40);
return;
default:
// Drop succeed record move info.
this.pile.board.saveMove(moveInfo);
this.pile.board.notifyMoveDone();
return;
}
};