function Board(options) {
//PRIVATE INSTANCE VARIABLES
options = options || {};
var __MY_ROOT = options.rootId || "BoardRoot";
var __HAND_HOLDER = options.handId || "HandRoot";
var __DECK_OPACITY = options.cardOpacity || .9;
var __EXTENSION_TYPE = options.extensionType || "gif";
var __IMAGES_DIRECTORY = options.imagesDirectory || "images/";
var __CARD_WIDTH = options.cardWidth || 73;
var __CARD_HEIGHT = options.cardHeight || 102;
var __DECK_HEIGHT = options.deckHeight || 204;
var __MAGICAL_UNIT_X = options.magicalX || 150;
var __MAGICAL_UNIT_Y = options.magicalY || 220;
var __HAND_WIDTH = options.handWidth || 500;
var __MULTI_DRAG = (options.multiDrag===false) ? false : true;
var handHolder=$("#"+__HAND_HOLDER);
handHolder.addClass("board");
var root=$("#"+__MY_ROOT);
root.addClass("board");
var decks = new Array();
var appendString = options.appendString || "cardHolder";
var counter = 0;
var cardHash = {};
var maxX = 0;
var maxY = 0;
//PUBLIC TYPE PROPERTIES
/**
* creates a vertical offset deck for decks (relative to the deck size and the deckHeight option) and a horizontal one for hands
*/
this.defaultType = function(deck) {
var isHand = isNaN(deck.getX());
//the offset for hands is proportional to the size of the hand
var minOverlapX = __CARD_WIDTH / 2;
var maxOverlapX = ((__HAND_WIDTH - __CARD_WIDTH) / deck.getSize());
var overlapX = (minOverlapX < maxOverlapX) ? minOverlapX : maxOverlapX;
var offsetX = isHand ? overlapX : 0;
//the offset for decks is proportional to the size of the deck
var minOverlap = __CARD_HEIGHT / 5;
var maxOverlap = ((__DECK_HEIGHT - __CARD_HEIGHT) / deck.getSize());
var overlap = (minOverlap < maxOverlap) ? minOverlap : maxOverlap;
var offsetY = isHand ? 0 : overlap;
return [offsetX, offsetY];
};
/**
* creates a deck with no offset so that all cards are stacked directly on top of each other
*/
this.collapsedType = function(deck) {
return [0,0];
};
/**
* creates a deck that has horizontal offset relative to the size of the deck and the handWidth option
*/
this.horizontalType = function(deck) {
//the offset for hands is proportional to the size of the hand
var minOverlapX = __CARD_WIDTH / 2;
var maxOverlapX = ((__HAND_WIDTH - __CARD_WIDTH) / deck.getSize());
var overlapX = (minOverlapX < maxOverlapX) ? minOverlapX : maxOverlapX;
var offsetX = overlapX;
var offsetY = 0;
return [offsetX, offsetY];
};
//PRIVATE FUNCTIONS
function createDeck(deck) {
//observe events
deck.observe(function() {
for(var i = 0; i < decks.length; i++) {
if(deck == decks[i][0]) {
return reDrawDeck(decks[i]);
}
}
return null;
});
var isHand = isNaN(deck.getX());
//add ui
var div = $("
");
div.droppable({
accept : function(el) {
var cards=getCards(el[0]);
return deck.getFilter()(cards[cards.length-1],getDeck(el[0]),cards.length);
},
drop : function(event, ui) {
var srcDeck=event.srcElement.parentElement;
var cards=getCards(srcDeck);
for(var i=cards.length-1;i>=0;i--) {
try {
console.log(cards[i]);
getDeck(srcDeck).remove(cards[i]);
deck.addTop(cards[i]);
} catch(e) {
continue;
}
}
reDrawDeck([getDeck(srcDeck), div]);
reDrawDeck([deck, $(event.target)]);
}
});
div.addClass(isHand ? "hand" : "deck");
if(isHand&&deck.isActive()) {
handHolder.append(div);
} else if(!isHand) {
root.append(div);
}
return reDrawDeck([deck, div]);
}
function getSuitName(card) {
var suit=card.getSuit().toUpperCase();
switch(suit) {
case "H":
suit="of hearts";
break;
case "D":
suit="of diamonds";
break;
case "C":
suit="of clubs";
break;
case "S":
suit="of spades";
break;
}
return suit;
}
function getOffsetByType(deck) {
return deck.getType()(deck);
}
function getCard(element) {
return cardHash[element.id][1];
}
function getCards(element) {
var cards=[];
if(__MULTI_DRAG) {
var children=$(element).children(".card");
if(children) {
for(var i = 0; i < children.length; i++) {
cards.push(getCard(children[i]));
}
}
}
cards.push(getCard(element));
return cards;
}
function getDeck(element) {
return cardHash[element.id][0];
}
function reDrawDeck(deckArr) {
var deck = deckArr[0];
var div = deckArr[1];
div[0].onclick=deck.getAction();
maxX = deck.getX() > maxX ? deck.getX() : maxX;
maxY = deck.getY() > maxY ? deck.getY() : maxY;
root.css("width",((maxX+1)*__MAGICAL_UNIT_X)+"px");
root.css("height",((maxY+1)*__MAGICAL_UNIT_Y)+"px");
div.empty();
var isHand = isNaN(deck.getX());
if(!isHand) {
div.css("left", deck.getX()*__MAGICAL_UNIT_X);
div.css("top", deck.getY()*__MAGICAL_UNIT_Y);
}
var offsets=getOffsetByType(deck);
var offsetX=offsets[0];
var offsetY=offsets[1];
var cards = deck.getCards();
var soFar=new Array();
for(var i = cards.length - 1; i >= 0; i--) {
var newDiv=(function (stack,i) {
var card = cards[i];
var holder = $("
");
cardHash[appendString+counter]=[deck,card];
holder.attr("id", appendString+(counter++));
holder.css("z-index",i+deck.getzOffset());
if(card.isFaceUp()&&deck.isDraggable()) {
holder.draggable({
revert : "invalid",
start : function(event, ui) {
holder.css("z-index",99+deck.getzOffset());
if(__MULTI_DRAG) {
for(var j = 0; j < stack.length; j++) {
stack[j][1].detach();
holder.append(stack[j][1]);
}
}
},
stop : function(event, ui) {
var srcDeck=event.srcElement.parentElement;
holder.css("z-index",i+deck.getzOffset());
reDrawDeck([getDeck(srcDeck),div]);
}
});
}
holder.addClass("card");
holder.css("left", (offsetX * i)+"px");
holder.css("top", (offsetY * i)+"px");
holder.css("position", "absolute");
var img = $("
![]()
");
if(card.isFaceUp()) {
img.attr("alt", card.getRankAsString()+" "+getSuitName(card));
img.attr("title", card.getRankAsString()+" "+getSuitName(card));
}
img.attr("src", card.isFaceUp() ? (__IMAGES_DIRECTORY+card.getRank()+card.getSuit()+"."+__EXTENSION_TYPE) : (__IMAGES_DIRECTORY+"back."+__EXTENSION_TYPE));
img.css("opacity", __DECK_OPACITY);
holder.append(img);
div.append(holder);
return holder;
})(soFar.concat(),i);
soFar.push([cards[i],newDiv]);
}
div.css("width",((cards.length)*offsetX)+__CARD_WIDTH);
div.css("height",((cards.length)*offsetY)+__CARD_HEIGHT);
return div;
}
//PUBLIC FUNCTIONS
/**
* Adds a deck to the Board, this adds a div that contains the view of the deck and specifies event listeners to update the deck
*/
this.addDeck = function (deck) {
return decks.push([deck, createDeck(deck)]);
};
/**
* returns an array of all decks attached to this board
*/
this.getDecks = function() {
return decks;
};
}