2012-02-06 22:00:24 +00:00
|
|
|
/*
|
2012-02-02 22:47:23 +00:00
|
|
|
* Copyright (c) 2012, Andy Janata
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
|
|
|
* provided that the following conditions are met:
|
|
|
|
*
|
|
|
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions
|
|
|
|
* and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of
|
|
|
|
* conditions and the following disclaimer in the documentation and/or other materials provided
|
|
|
|
* with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
|
|
|
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2012-01-20 05:19:55 +00:00
|
|
|
/**
|
2012-02-06 22:00:24 +00:00
|
|
|
* Card objects. There is a base class, and individual classes for White and Black cards. This could
|
|
|
|
* probably stand to be split up into 3 files.
|
2012-01-20 05:19:55 +00:00
|
|
|
*
|
2012-02-06 22:00:24 +00:00
|
|
|
* @author Andy Janata (ajanata@socialgamer.net)
|
2012-01-20 05:19:55 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
cah.card = {};
|
2012-02-06 22:00:24 +00:00
|
|
|
/**
|
|
|
|
* Serial number to use in card div IDs. This possibly isn't needed.
|
|
|
|
*
|
|
|
|
* @type {Number}
|
|
|
|
*/
|
2012-01-20 05:19:55 +00:00
|
|
|
cah.card.serial = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Base class for cards.
|
|
|
|
*
|
2012-01-21 03:11:39 +00:00
|
|
|
* @param {boolean}
|
2012-01-20 05:19:55 +00:00
|
|
|
* opt_faceUp True if this card is initially face-up.
|
2012-01-21 03:11:39 +00:00
|
|
|
* @param {number}
|
2012-01-20 05:19:55 +00:00
|
|
|
* opt_id The id of this card, for server communication purposes.
|
|
|
|
* @constructor
|
|
|
|
*/
|
|
|
|
cah.card.BaseCard = function(opt_faceUp, opt_id) {
|
|
|
|
/**
|
|
|
|
* The id to use for html elements for this card.
|
|
|
|
*
|
|
|
|
* @type {number}
|
|
|
|
* @protected
|
|
|
|
*/
|
|
|
|
this.id_ = cah.card.serial++;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The id of this card, for server communication purposes.
|
|
|
|
*
|
|
|
|
* @type {?number}
|
|
|
|
* @protected
|
|
|
|
*/
|
|
|
|
this.serverId_ = opt_id;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether this card is currently face-up.
|
|
|
|
*
|
|
|
|
* @type {boolean}
|
|
|
|
* @protected
|
|
|
|
*/
|
|
|
|
this.faceUp_ = !!opt_faceUp;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Element for face-down version of this card. Lazily loaded.
|
|
|
|
*
|
|
|
|
* @type {HTMLDivElement}
|
|
|
|
* @protected
|
|
|
|
*/
|
|
|
|
this.faceDownElem_ = undefined;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Element for face-up version of this card. Lazily loaded.
|
|
|
|
*
|
|
|
|
* @type {HTMLDivElement}
|
|
|
|
* @protected
|
|
|
|
*/
|
|
|
|
this.faceUpElem_ = undefined;
|
|
|
|
|
2013-04-20 20:21:28 +01:00
|
|
|
this.element_ = $('<div id="card_' + this.id_ + '" class="card_holder"><br/></div>')[0];
|
2012-01-20 05:19:55 +00:00
|
|
|
if (this.faceUp_) {
|
|
|
|
this.turnFaceUp();
|
|
|
|
} else {
|
|
|
|
this.turnFaceDown();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replaces this card with its face-up version. If no text has been set on this card, it will need
|
|
|
|
* to be set!
|
|
|
|
*/
|
|
|
|
cah.card.BaseCard.prototype.turnFaceUp = function() {
|
|
|
|
this.ensureFaceUpElement_();
|
|
|
|
$(this.element_).empty().append(this.faceUpElem_);
|
|
|
|
this.faceUp_ = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replaces this card with its face-down version. If text has been set on this card, it will still
|
|
|
|
* be resident in the object, but the user would have seen the card face-up already anyway.
|
|
|
|
*/
|
|
|
|
cah.card.BaseCard.prototype.turnFaceDown = function() {
|
|
|
|
this.ensureFaceDownElement_();
|
|
|
|
$(this.element_).empty().append(this.faceDownElem_);
|
|
|
|
this.faceUp_ = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the face-down version of this card.
|
|
|
|
*
|
|
|
|
* @protected
|
|
|
|
* @abstract
|
|
|
|
* @returns {HTMLDivElement} Face-down card element.
|
|
|
|
*/
|
|
|
|
cah.card.BaseCard.prototype.getFaceDown_ = function() {
|
|
|
|
throw "Abstract method invoked.";
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the face-up version of this card.
|
|
|
|
*
|
|
|
|
* @protected
|
|
|
|
* @abstract
|
|
|
|
* @returns {HTMLDivElement} Face-up card element.
|
|
|
|
*/
|
|
|
|
cah.card.BaseCard.prototype.getFaceUp_ = function() {
|
|
|
|
throw "Abstract method invoked.";
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2013-03-27 01:07:09 +00:00
|
|
|
* Set the visible text on a card. It matters not if the card is face-up or face-down. HTML is
|
|
|
|
* allowed and entities are required.
|
2012-01-20 05:19:55 +00:00
|
|
|
*
|
|
|
|
* @param {string}
|
2013-03-27 01:07:09 +00:00
|
|
|
* text HTML to display on the card.
|
2012-01-20 05:19:55 +00:00
|
|
|
*/
|
|
|
|
cah.card.BaseCard.prototype.setText = function(text) {
|
|
|
|
this.ensureFaceUpElement_();
|
2013-04-20 20:21:28 +01:00
|
|
|
$(".card_text", this.faceUpElem_).html(text);
|
|
|
|
// TODO do this better
|
|
|
|
$(".card_text", this.faceUpElem_).attr(
|
|
|
|
"aria-label",
|
|
|
|
text.replace("____", "blank").replace("™", "").replace("®", "").replace("&",
|
|
|
|
"and"));
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the screen reader text from this card.
|
|
|
|
*/
|
|
|
|
cah.card.BaseCard.prototype.getAriaText = function() {
|
|
|
|
return $(".card_text", this.faceUpElem_).attr("aria-label");
|
2012-01-20 05:19:55 +00:00
|
|
|
};
|
|
|
|
|
2012-07-07 23:01:33 +01:00
|
|
|
/**
|
|
|
|
* Set the "watermark" on the logo on the card. It matters not if the card is face-up or face-down.
|
|
|
|
*
|
|
|
|
* @param {String}
|
|
|
|
* watermark Watermark to display on the card.
|
|
|
|
*/
|
|
|
|
cah.card.BaseCard.prototype.setWatermark = function(watermark) {
|
|
|
|
this.ensureFaceUpElement_();
|
|
|
|
$(".watermark", this.faceUpElem_).text(watermark);
|
|
|
|
};
|
|
|
|
|
2012-01-20 05:19:55 +00:00
|
|
|
/**
|
|
|
|
* Ensure this card has a face-up element, creating one if needed.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
cah.card.BaseCard.prototype.ensureFaceUpElement_ = function() {
|
|
|
|
if (!this.faceUpElem_) {
|
|
|
|
this.faceUpElem_ = this.getFaceUp_();
|
2012-02-06 22:00:24 +00:00
|
|
|
// TODO move the logo stuff out to static css instead of doing it for every card...
|
2012-02-01 04:22:07 +00:00
|
|
|
$(".logo_1", this.faceUpElem_).animate({
|
|
|
|
rotate : "-13deg",
|
|
|
|
}, {
|
|
|
|
duration : 0,
|
|
|
|
queue : false,
|
|
|
|
});
|
|
|
|
$(".logo_3", this.faceUpElem_).animate({
|
|
|
|
rotate : "13deg",
|
|
|
|
}, {
|
|
|
|
duration : 0,
|
|
|
|
queue : false,
|
|
|
|
});
|
2012-01-20 05:19:55 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Ensure this card has a face-down element, creating one if needed.
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
cah.card.BaseCard.prototype.ensureFaceDownElement_ = function() {
|
|
|
|
if (!this.faceDownElem_) {
|
|
|
|
this.faceDownElem_ = this.getFaceDown_();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2012-02-06 22:00:24 +00:00
|
|
|
* @return {?number} The server ID of this card, if one was specified at creation.
|
2012-01-20 05:19:55 +00:00
|
|
|
*/
|
|
|
|
cah.card.BaseCard.prototype.getServerId = function() {
|
|
|
|
return this.serverId_;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return {HTMLElement} The element for this card.
|
|
|
|
*/
|
|
|
|
cah.card.BaseCard.prototype.getElement = function() {
|
|
|
|
return this.element_;
|
|
|
|
};
|
|
|
|
|
|
|
|
// ///////////////////////////////////////////////
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Black card definition.
|
|
|
|
*
|
2012-01-21 03:11:39 +00:00
|
|
|
* @param {boolean}
|
2012-01-20 05:19:55 +00:00
|
|
|
* opt_faceUp True if this card is initially face-up.
|
2012-01-21 03:11:39 +00:00
|
|
|
* @param {number}
|
2012-01-20 05:19:55 +00:00
|
|
|
* opt_id The id of this card, for server communication purposes.
|
|
|
|
* @extends cah.card.BaseCard
|
|
|
|
* @constructor
|
|
|
|
*/
|
|
|
|
cah.card.BlackCard = function(opt_faceUp, opt_id) {
|
|
|
|
cah.card.BaseCard.call(this, opt_faceUp, opt_id);
|
2012-02-01 04:22:07 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* The number of white cards to draw when this is the active black card.
|
|
|
|
*
|
|
|
|
* @type {number}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this.draw_ = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The number of white cards to play for this black card.
|
|
|
|
*
|
|
|
|
* @type {number}
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
this.pick_ = 1;
|
2012-01-20 05:19:55 +00:00
|
|
|
};
|
|
|
|
cah.inherits(cah.card.BlackCard, cah.card.BaseCard);
|
|
|
|
|
2012-02-06 22:00:24 +00:00
|
|
|
/**
|
|
|
|
* @override
|
|
|
|
*/
|
2012-01-20 05:19:55 +00:00
|
|
|
cah.card.BlackCard.prototype.getFaceDown_ = function() {
|
|
|
|
var temp = $("#black_down_template").clone()[0];
|
|
|
|
temp.id = "black_down_" + this.id_;
|
2012-01-23 07:58:36 +00:00
|
|
|
$(temp).removeClass("hide");
|
2012-01-20 05:19:55 +00:00
|
|
|
return temp;
|
|
|
|
};
|
|
|
|
|
2012-02-06 22:00:24 +00:00
|
|
|
/**
|
|
|
|
* @override
|
|
|
|
*/
|
2012-01-20 05:19:55 +00:00
|
|
|
cah.card.BlackCard.prototype.getFaceUp_ = function() {
|
|
|
|
var temp = $("#black_up_template").clone()[0];
|
|
|
|
temp.id = "black_up_" + this.id_;
|
2012-01-23 07:58:36 +00:00
|
|
|
$(temp).removeClass("hide");
|
2012-01-20 05:19:55 +00:00
|
|
|
return temp;
|
|
|
|
};
|
|
|
|
|
2012-02-01 04:22:07 +00:00
|
|
|
/**
|
|
|
|
* @param {number}
|
|
|
|
* draw The number of white cards to draw when this black card is played.
|
|
|
|
*/
|
|
|
|
cah.card.BlackCard.prototype.setDraw = function(draw) {
|
|
|
|
this.draw_ = draw;
|
|
|
|
this.updateCardInfo_();
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {number}
|
|
|
|
* pick The number of white cards to play for this black card.
|
|
|
|
*/
|
|
|
|
cah.card.BlackCard.prototype.setPick = function(pick) {
|
|
|
|
this.pick_ = pick;
|
|
|
|
this.updateCardInfo_();
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Update the pick and draw displays on this card, and potentially change the game name to or from
|
|
|
|
* "CAH".
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
cah.card.BlackCard.prototype.updateCardInfo_ = function() {
|
|
|
|
if (this.draw_ != 0 || this.pick_ != 1) {
|
2012-03-17 00:00:01 +00:00
|
|
|
$(".logo_text", this.faceUpElem_).text("PYX");
|
2012-02-01 04:22:07 +00:00
|
|
|
if (this.draw_ != 0) {
|
|
|
|
$(".draw .card_number", this.faceUpElem_).text(this.draw_);
|
|
|
|
$(".draw", this.faceUpElem_).removeClass("hide");
|
|
|
|
} else {
|
|
|
|
$(".draw", this.faceUpElem_).addClass("hide");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.pick_ != 1) {
|
|
|
|
$(".pick .card_number", this.faceUpElem_).text(this.pick_);
|
|
|
|
$(".pick", this.faceUpElem_).removeClass("hide");
|
|
|
|
} else {
|
|
|
|
$(".pick", this.faceUpElem_).addClass("hide");
|
|
|
|
}
|
|
|
|
} else {
|
2012-03-15 17:14:32 +00:00
|
|
|
$(".logo_text", this.faceUpElem_).text("Pretend You're Xyzzy");
|
2012-02-01 04:22:07 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-01-20 05:19:55 +00:00
|
|
|
// ///////////////////////////////////////////////
|
|
|
|
|
|
|
|
/**
|
|
|
|
* White card definition.
|
|
|
|
*
|
2012-01-21 03:11:39 +00:00
|
|
|
* @param {boolean}
|
2012-01-20 05:19:55 +00:00
|
|
|
* opt_faceUp True if this card is initially face-up.
|
2012-01-21 03:11:39 +00:00
|
|
|
* @param {number}
|
2012-01-20 05:19:55 +00:00
|
|
|
* opt_id The id of this card, for server communication purposes.
|
|
|
|
* @extends cah.card.BaseCard
|
|
|
|
* @constructor
|
|
|
|
*/
|
|
|
|
cah.card.WhiteCard = function(opt_faceUp, opt_id) {
|
|
|
|
cah.card.BaseCard.call(this, opt_faceUp, opt_id);
|
2014-07-20 00:19:08 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether this is a fill-in blank card or not.
|
|
|
|
*
|
|
|
|
* @type {boolean}
|
|
|
|
*/
|
|
|
|
this.isBlankCard_ = false;
|
2012-01-20 05:19:55 +00:00
|
|
|
};
|
|
|
|
cah.inherits(cah.card.WhiteCard, cah.card.BaseCard);
|
|
|
|
|
2014-07-20 00:19:08 +01:00
|
|
|
/**
|
|
|
|
* Set this card's flag indicating if it is a fill-in blank card.
|
|
|
|
*
|
|
|
|
* @param {boolean}
|
|
|
|
* blank Whether this is a fill-in blank card or not.
|
|
|
|
*/
|
|
|
|
cah.card.WhiteCard.prototype.setIsBlankCard = function(blank) {
|
|
|
|
this.isBlankCard_ = blank;
|
|
|
|
};
|
|
|
|
|
2013-06-19 13:23:10 +01:00
|
|
|
/**
|
|
|
|
* Checks if this is a blank card.
|
|
|
|
*
|
|
|
|
* @returns True if this is a blank card.
|
|
|
|
*/
|
|
|
|
cah.card.WhiteCard.prototype.isBlankCard = function() {
|
2014-07-20 00:19:08 +01:00
|
|
|
return this.isBlankCard_;
|
2013-06-19 13:23:10 +01:00
|
|
|
};
|
|
|
|
|
2012-02-06 22:00:24 +00:00
|
|
|
/**
|
|
|
|
* @override
|
|
|
|
*/
|
2012-01-20 05:19:55 +00:00
|
|
|
cah.card.WhiteCard.prototype.getFaceDown_ = function() {
|
|
|
|
var temp = $("#white_down_template").clone()[0];
|
|
|
|
temp.id = "white_down_" + this.id_;
|
2012-01-23 07:58:36 +00:00
|
|
|
$(temp).removeClass("hide");
|
2012-01-20 05:19:55 +00:00
|
|
|
return temp;
|
|
|
|
};
|
|
|
|
|
2012-02-06 22:00:24 +00:00
|
|
|
/**
|
|
|
|
* @override
|
|
|
|
*/
|
2012-01-20 05:19:55 +00:00
|
|
|
cah.card.WhiteCard.prototype.getFaceUp_ = function() {
|
|
|
|
var temp = $("#white_up_template").clone()[0];
|
|
|
|
temp.id = "white_up_" + this.id_;
|
2012-01-23 07:58:36 +00:00
|
|
|
$(temp).removeClass("hide");
|
2012-01-20 05:19:55 +00:00
|
|
|
return temp;
|
|
|
|
};
|