// Michael McElroy, MichaelMcElroy.NET // Copyrighted, 2007, All Rights Reserved var scaffoldPredicate = false; var Solitaire = function () { // Identity this . reference = null; this . ID = null; this . path_of_the_public_folder = null; // Settings this . rowQuantity = null; this . columnQuantity = null; this . rowLength = null; this . columnLength = null; this . pieceHeight = null; this . pieceWidth = null; this . dimpleHeight = null; this . dimpleWidth = null; this . rowOffset = null; this . columnOffset = null; this . boardTexture = null; this . pieceTexture = null; this . dimpleTexture = null; this . thunkAddress = null; // Status this . playablePredicate = null; this . selectedPiece = null; this . mask = null; this . occupations = null; // Graphics this . renderTarget = null; this . board = null; this . pieces = null; this . shadows = null; this . shadow = null; this . dimples = null; this . glass = null; this . resetButton = null; this . layerIndexes = null; // Delegates this . resetDelegate = null; this . selectPieceDelegate = null; this . movePieceDelegate = null; this . releasePieceDelegate = null; this . initialize = function (reference, ID, path_of_the_public_folder) { this . initializeIdentity (reference, ID, path_of_the_public_folder); this . initializeSettings (); this . initializeStatus (); this . initializeGraphics (); this . initializeDelegates (); this . render (); this . registerDelegates (); return; }; this . initializeIdentity = function (reference, ID, path_of_the_public_folder) { this . reference = reference; this . ID = ID; this . path_of_the_public_folder = path_of_the_public_folder; return; }; this . initializeSettings = function () { this . rowQuantity = 7; this . columnQuantity = 7; this . rowLength = 60; this . columnLength = 60; this . pieceHeight = 40; this . pieceWidth = 40; this . dimpleHeight = 22; this . dimpleWidth = 22; this . rowOffset = 50; this . columnOffset = 50; this . boardTexture = "board.jpg"; this . pieceTexture = "piece.png"; this . shadowTexture = "piece.shadow.near.png"; this . hoverTexture = "piece.shadow.far.png"; this . dimpleTexture = "dimple.png"; this . thunkAddress = "thunk.wav"; return; }; this . initializeStatus = function () { this . playablePredicate = true; this . selectedPiece = null; this . mask = new Array (); this . occupations = new Array (); for (var rowIndex = 0; rowIndex < this . rowQuantity; rowIndex = rowIndex + 1) { this . mask [rowIndex] = new Array (); this . occupations [rowIndex] = new Array (); for (var columnIndex = 0; columnIndex < this . columnQuantity; columnIndex = columnIndex + 1) { this . mask [rowIndex] [columnIndex] = false; this . occupations [rowIndex] [columnIndex] = false; } } this . mask [0] [2] = true; this . mask [0] [3] = true; this . mask [0] [4] = true; this . mask [1] [2] = true; this . mask [1] [3] = true; this . mask [1] [4] = true; this . mask [2] [0] = true; this . mask [2] [1] = true; this . mask [2] [2] = true; this . mask [2] [3] = true; this . mask [2] [4] = true; this . mask [2] [5] = true; this . mask [2] [6] = true; this . mask [3] [0] = true; this . mask [3] [1] = true; this . mask [3] [2] = true; this . mask [3] [3] = true; this . mask [3] [4] = true; this . mask [3] [5] = true; this . mask [3] [6] = true; this . mask [4] [0] = true; this . mask [4] [1] = true; this . mask [4] [2] = true; this . mask [4] [3] = true; this . mask [4] [4] = true; this . mask [4] [5] = true; this . mask [4] [6] = true; this . mask [5] [2] = true; this . mask [5] [3] = true; this . mask [5] [4] = true; this . mask [6] [2] = true; this . mask [6] [3] = true; this . mask [6] [4] = true; for (var rowIndex = 0; rowIndex < this . rowQuantity; rowIndex = rowIndex + 1) { for (var columnIndex = 0; columnIndex < this . columnQuantity; columnIndex = columnIndex + 1) { this . occupations [rowIndex] [columnIndex] = this . mask [rowIndex] [columnIndex]; } } this . occupations [3] [3] = false; return; }; this . initializeGraphics = function () { var piece; var dimple; // Layer Indexes this . layerIndexes = new Object (); this . layerIndexes . board = 0; this . layerIndexes . dimple = 1; this . layerIndexes . lowerShadow = 2; this . layerIndexes . lowerPiece = 3; this . layerIndexes . upperShadow = 4; this . layerIndexes . upperPiece = 5; this . layerIndexes . glass = 6; this . layerIndexes . resetButton = 7; // Render Target this . renderTarget = null; // Board this . board = document . createElement ("div"); this . board . style . zIndex = this . layerIndexes . board; this . board . style . position = "relative"; this . board . style . height = (this . rowOffset * 2 + this . rowLength * this . rowQuantity) + "px"; this . board . style . width = (this . columnOffset * 2 + this . columnLength * this . columnQuantity) + "px"; this . board . style . border = "#ecece2 0px solid"; this . board . style . backgroundColor = "#222222"; this . board . style . backgroundImage = "url('" + this . path_of_the_public_folder + "/pictures/" + this . boardTexture + "')"; // Pieces this . pieces = new Array (); for (var rowIndex = 0; rowIndex < this . rowQuantity; rowIndex = rowIndex + 1) { this . pieces [rowIndex] = new Array (); for (var columnIndex = 0; columnIndex < this . columnQuantity; columnIndex = columnIndex + 1) { piece = document . createElement ("div"); piece . style . zIndex = this . layerIndexes . lowerPiece; piece . style . position = "absolute"; piece . style . top = (this . rowOffset + this . rowLength * rowIndex + Math . floor ((this . rowLength - this . pieceHeight) / 2)) + "px"; piece . style . left = (this . columnOffset + this . columnLength * columnIndex + Math . floor ((this . columnLength - this . pieceWidth) / 2)) + "px"; piece . style . height = (this . pieceHeight) + "px"; piece . style . width = (this . pieceWidth) + "px"; piece . style . backgroundImage = "url('" + this . path_of_the_public_folder + "/pictures/" + this . pieceTexture + "')"; piece . style . backgroundRepeat = "no-repeat"; piece . rowIndex = rowIndex; piece . columnIndex = columnIndex; this . pieces [rowIndex] [columnIndex] = piece; this . board . appendChild (piece); } } // Shadows this . shadows = new Array (); for (var rowIndex = 0; rowIndex < this . rowQuantity; rowIndex = rowIndex + 1) { this . shadows [rowIndex] = new Array (); for (var columnIndex = 0; columnIndex < this . columnQuantity; columnIndex = columnIndex + 1) { shadow = document . createElement ("div"); shadow . style . zIndex = this . layerIndexes . lowerShadow; shadow . style . position = "absolute"; shadow . style . top = (this . rowOffset + this . rowLength * rowIndex + Math . floor ((this . rowLength - this . pieceHeight) / 2)) + "px"; shadow . style . left = (this . columnOffset + this . columnLength * columnIndex + Math . floor ((this . columnLength - this . pieceWidth) / 2)) - 15 + "px"; shadow . style . height = (this . pieceHeight * 1.5) + "px"; shadow . style . width = (this . pieceWidth * 1.5) + "px"; shadow . style . backgroundImage = "url('" + this . path_of_the_public_folder + "/pictures/" + this . shadowTexture + "')"; shadow . style . backgroundRepeat = "no-repeat"; shadow . rowIndex = rowIndex; shadow . columnIndex = columnIndex; this . shadows [rowIndex] [columnIndex] = shadow; this . board . appendChild (shadow); } } this . shadow = document . createElement ("div"); this . shadow . style . zIndex = this . layerIndexes . upperShadow; this . shadow . style . position = "absolute"; this . shadow . style . top = (5) + "px"; this . shadow . style . left = (-20) + "px"; this . shadow . style . height = (this . pieceHeight * 1.5) + "px"; this . shadow . style . width = (this . pieceWidth * 1.5) + "px"; this . shadow . style . backgroundImage = "url('" + this . path_of_the_public_folder + "/pictures/" + this . hoverTexture + "')"; this . shadow . style . backgroundRepeat = "no-repeat"; this . shadow . style . display = "none"; this . shadow . rowIndex = rowIndex; this . shadow . columnIndex = columnIndex; this . board . appendChild (this . shadow); // Dimples this . dimples = new Array (); for (var rowIndex = 0; rowIndex < this . rowQuantity; rowIndex = rowIndex + 1) { this . dimples [rowIndex] = new Array (); for (var columnIndex = 0; columnIndex < this . columnQuantity; columnIndex = columnIndex + 1) { dimple = document . createElement ("div"); dimple . style . zIndex = this . layerIndexes . dimple; dimple . style . position = "absolute"; dimple . style . top = (this . rowOffset + this . rowLength * rowIndex + Math . floor ((this . rowLength - this . dimpleHeight) / 2)) + "px"; dimple . style . left = (this . columnOffset + this . columnLength * columnIndex + Math . floor ((this . columnLength - this . dimpleWidth) / 2)) + "px"; dimple . style . height = (this . pieceHeight) + "px"; dimple . style . width = (this . pieceWidth) + "px"; dimple . style . backgroundImage = "url('" + this . path_of_the_public_folder + "/pictures/" + this . dimpleTexture + "')"; dimple . style . backgroundRepeat = "no-repeat"; dimple . rowIndex = rowIndex; dimple . columnIndex = columnIndex; this . dimples [rowIndex] [columnIndex] = dimple; this . board . appendChild (dimple); } } // Glass this . glass = document . createElement ("div"); this . glass . style . cursor = "pointer"; this . glass . style . zIndex = this . layerIndexes . glass; this . glass . style . position = "absolute"; this . glass . style . top = "0px"; this . glass . style . left = "0px"; this . glass . style . height = (this . rowOffset * 2 + this . rowLength * this . rowQuantity) + "px"; this . glass . style . width = (this . columnOffset * 2 + this . columnLength * this . columnQuantity) + "px"; this . board . appendChild (this . glass); // Reset Button this . resetButton = document . createElement ("div"); this . resetButton . style . zIndex = this . layerIndexes . resetButton; this . resetButton . style . position = "absolute"; this . resetButton . style . paddingTop = "8px"; this . resetButton . style . paddingBottom = "8px"; this . resetButton . style . paddingLeft = "16px"; this . resetButton . style . paddingRight = "16px"; this . resetButton . style . bottom = "20px"; this . resetButton . style . right = "20px"; this . resetButton . style . color = "#ffffff"; this . resetButton . style . backgroundColor = "#000000"; this . resetButton . style . cursor = "pointer"; this . resetButton . style . display = "none"; this . resetButton . appendChild (document . createTextNode ("Reset")); this . board . appendChild (this . resetButton); return; }; this . initializeDelegates = function () { var delegate; this . resetDelegate = new Delegate (); this . resetDelegate . initialize (); this . resetDelegate . setEntity (this); this . resetDelegate . setMethod (this . reset); this . selectPieceDelegate = new Delegate (); this . selectPieceDelegate . initialize (); this . selectPieceDelegate . setEntity (this); this . selectPieceDelegate . setMethod (this . selectPiece); this . movePieceDelegate = new Delegate (); this . movePieceDelegate . initialize (); this . movePieceDelegate . setEntity (this); this . movePieceDelegate . setMethod (this . movePiece); this . releasePieceDelegate = new Delegate (); this . releasePieceDelegate . initialize (); this . releasePieceDelegate . setEntity (this); this . releasePieceDelegate . setMethod (this . releasePiece); return; }; this . reset = function () { this . unregisterDelegates (); this . initializeStatus (); this . render (); this . registerDelegates (); return; }; this . selectPiece = function (cursorEvent) { var rowIndex; var columnIndex; rowIndex = this . getRowIndex (this . getRowCoordinate (cursorEvent)); columnIndex = this . getColumnIndex (this . getColumnCoordinate (cursorEvent)); if (rowIndex != null) if (columnIndex != null) if (this . mask [rowIndex] [columnIndex]) if (this . occupations [rowIndex] [columnIndex]) { this . selectedPiece = this . pieces [rowIndex] [columnIndex]; this . selectedPiece . style . zIndex = this . layerIndexes . upperPiece; this . shadow . style . top = (this . rowOffset + this . rowLength * rowIndex + Math . floor ((this . rowLength - this . pieceHeight) / 2)) + 5 + "px"; this . shadow . style . left = (this . columnOffset + this . columnLength * columnIndex + Math . floor ((this . columnLength - this . pieceWidth) / 2)) - 20 + "px"; this . shadow . style . display = "block"; this . shadows [rowIndex] [columnIndex] . style . display = "none"; } cursorEvent . stopPropagation (); cursorEvent . preventDefault (); return; }; this . movePiece = function (cursorEvent) { var rowCoordinate; var columnCoordinate; rowCoordinate = this . getRowCoordinate (cursorEvent); columnCoordinate = this . getColumnCoordinate (cursorEvent); if (this . selectedPiece != null) { this . selectedPiece . style . top = (rowCoordinate - Math . floor (this . pieceHeight / 2)) + "px"; this . selectedPiece . style . left = (columnCoordinate - Math . floor (this . pieceWidth / 2)) + "px"; this . shadow . style . top = (rowCoordinate - Math . floor (this . pieceHeight / 2)) + 5 + "px"; this . shadow . style . left = (columnCoordinate - Math . floor (this . pieceWidth / 2)) - 20 + "px"; } cursorEvent . stopPropagation (); cursorEvent . preventDefault (); return; }; this . releasePiece = function (cursorEvent) { var rowIndex; var columnIndex; this . shadow . style . display = "none"; if (this . selectedPiece != null) { rowIndex = this . getRowIndex (this . getRowCoordinate (cursorEvent)); columnIndex = this . getColumnIndex (this . getColumnCoordinate (cursorEvent)); if ((rowIndex != null) && (columnIndex != null)) { // Up if (((rowIndex - this . selectedPiece . rowIndex) == -2) && ((columnIndex - this . selectedPiece . columnIndex) == 0)) if (this . mask [rowIndex + 0] [columnIndex]) if (this . mask [rowIndex + 1] [columnIndex]) if (! this . occupations [rowIndex + 0] [columnIndex]) if (this . occupations [rowIndex + 1] [columnIndex]) { this . occupations [rowIndex + 0] [columnIndex] = true; this . occupations [rowIndex + 1] [columnIndex] = false; this . occupations [rowIndex + 2] [columnIndex] = false; } // Down if (((rowIndex - this . selectedPiece . rowIndex) == 2) && ((columnIndex - this . selectedPiece . columnIndex) == 0)) if (this . mask [rowIndex - 0] [columnIndex]) if (this . mask [rowIndex - 1] [columnIndex]) if (! this . occupations [rowIndex - 0] [columnIndex]) if (this . occupations [rowIndex - 1] [columnIndex]) { this . occupations [rowIndex - 0] [columnIndex] = true; this . occupations [rowIndex - 1] [columnIndex] = false; this . occupations [rowIndex - 2] [columnIndex] = false; } // Left if (((columnIndex - this . selectedPiece . columnIndex) == -2) && ((rowIndex - this . selectedPiece . rowIndex) == 0)) if (this . mask [rowIndex] [columnIndex + 0]) if (this . mask [rowIndex] [columnIndex + 1]) if (! this . occupations [rowIndex] [columnIndex + 0]) if (this . occupations [rowIndex] [columnIndex + 1]) { this . occupations [rowIndex] [columnIndex + 0] = true; this . occupations [rowIndex] [columnIndex + 1] = false; this . occupations [rowIndex] [columnIndex + 2] = false; } // Right if (((columnIndex - this . selectedPiece . columnIndex) == 2) && ((rowIndex - this . selectedPiece . rowIndex) == 0)) if (this . mask [rowIndex] [columnIndex - 0]) if (this . mask [rowIndex] [columnIndex - 1]) if (! this . occupations [rowIndex] [columnIndex - 0]) if (this . occupations [rowIndex] [columnIndex - 1]) { this . occupations [rowIndex] [columnIndex - 0] = true; this . occupations [rowIndex] [columnIndex - 1] = false; this . occupations [rowIndex] [columnIndex - 2] = false; } } this . selectedPiece . style . zIndex = this . layerIndexes . lowerPiece; this . selectedPiece = null; this . updatePlayablePredicate (); this . render (); } cursorEvent . stopPropagation (); cursorEvent . preventDefault (); return; }; this . updatePlayablePredicate = function () { this . playablePredicate = false; // Assume false and try to prove otherwise. for (var rowIndex = 0; rowIndex < this . rowQuantity; rowIndex = rowIndex + 1) { for (var columnIndex = 0; columnIndex < this . columnQuantity; columnIndex = columnIndex + 1) { if (this . occupations [rowIndex] [columnIndex]) { // Up if ((rowIndex - 2) >= 0) if (this . mask [rowIndex - 1] [columnIndex] == true) if (this . mask [rowIndex - 2] [columnIndex] == true) if (this . occupations [rowIndex - 1] [columnIndex] == true) if (this . occupations [rowIndex - 2] [columnIndex] == false) { this . playablePredicate = true; } // Down if ((rowIndex + 2) < this . rowQuantity) if (this . mask [rowIndex + 1] [columnIndex] == true) if (this . mask [rowIndex + 2] [columnIndex] == true) if (this . occupations [rowIndex + 1] [columnIndex] == true) if (this . occupations [rowIndex + 2] [columnIndex] == false) { this . playablePredicate = true; } // Left if ((columnIndex - 2) >= 0) if (this . mask [rowIndex] [columnIndex - 1] == true) if (this . mask [rowIndex] [columnIndex - 2] == true) if (this . occupations [rowIndex] [columnIndex - 1] == true) if (this . occupations [rowIndex] [columnIndex - 2] == false) { this . playablePredicate = true; } // Right if ((columnIndex + 2) < this . columnQuantity) if (this . mask [rowIndex] [columnIndex + 1] == true) if (this . mask [rowIndex] [columnIndex + 2] == true) if (this . occupations [rowIndex] [columnIndex + 1] == true) if (this . occupations [rowIndex] [columnIndex + 2] == false) { this . playablePredicate = true; } } } } return; } this . setRenderTarget = function (node) { this . renderTarget = node; this . renderTarget . appendChild (this . board); return; }; this . render = function () { var color; var value; if (this . playablePredicate) { this . resetButton . style . display = "none"; } else { this . resetButton . style . display = "block"; } for (var rowIndex = 0; rowIndex < this . rowQuantity; rowIndex = rowIndex + 1) for (var columnIndex = 0; columnIndex < this . columnQuantity; columnIndex = columnIndex + 1) { if (this . mask [rowIndex] [columnIndex] == true) { this . dimples [rowIndex] [columnIndex] . style . display = "block"; } else { this . dimples [rowIndex] [columnIndex] . style . display = "none"; } if (this . occupations [rowIndex] [columnIndex] == true) { this . pieces [rowIndex] [columnIndex] . style . display = "block"; this . shadows [rowIndex] [columnIndex] . style . display = "block"; } else { this . pieces [rowIndex] [columnIndex] . style . display = "none"; this . shadows [rowIndex] [columnIndex] . style . display = "none"; } this . pieces [rowIndex] [columnIndex] . style . top = (this . rowOffset + this . rowLength * this . pieces [rowIndex] [columnIndex] . rowIndex + Math . floor ((this . rowLength - this . pieceHeight) / 2)) + "px"; this . pieces [rowIndex] [columnIndex] . style . left = (this . columnOffset + this . columnLength * this . pieces [rowIndex] [columnIndex] . columnIndex + Math . floor ((this . columnLength - this . pieceWidth) / 2)) + "px"; } return; }; this . registerDelegates = function () { this . resetDelegate . register (this . resetButton, "mouseup"); this . selectPieceDelegate . register (this . glass, "mousedown"); this . movePieceDelegate . register (this . glass, "mousemove"); this . releasePieceDelegate . register (this . glass, "mouseup"); return; }; this . unregisterDelegates = function () { this . resetDelegate . unregister (this . resetButton, "mouseup"); this . selectPieceDelegate . unregister (this . glass, "mousedown"); this . movePieceDelegate . unregister (this . glass, "mousemove"); this . releasePieceDelegate . unregister (this . glass, "mouseup"); return; }; this . getRowIndex = function (rowCoordinate) { var rowIndex; rowIndex = null; if (typeof (rowCoordinate) != "undefined") if (rowCoordinate != null) if (rowCoordinate >= (this . rowOffset)) if (rowCoordinate <= (this . rowOffset * 2 + this . rowLength * this . rowQuantity)) if (((rowCoordinate - this . rowOffset) % (this . rowLength)) > (Math . floor ((this . rowLength - this . pieceHeight) / 2))) if (((rowCoordinate - this . rowOffset) % (this . rowLength)) < (Math . floor ((this . rowLength - this . pieceHeight) / 2) + this . pieceHeight)) { rowIndex = Math . floor ((rowCoordinate - this . rowOffset) / (this . rowLength)); } return (rowIndex); }; this . getColumnIndex = function (columnCoordinate) { var columnIndex; columnIndex = null; if (typeof (columnCoordinate) != "undefined") if (columnCoordinate != null) if (columnCoordinate >= (this . columnOffset)) if (columnCoordinate <= (this . columnOffset * 2 + this . columnLength * this . columnQuantity)) if (((columnCoordinate - this . columnOffset) % (this . columnLength)) > (Math . floor ((this . columnLength - this . pieceWidth) / 2))) if (((columnCoordinate - this . columnOffset) % (this . columnLength)) < (Math . floor ((this . columnLength - this . pieceWidth) / 2) + this . pieceWidth)) { columnIndex = Math . floor ((columnCoordinate - this . columnOffset) / (this . columnLength)); } return (columnIndex); }; this . getRowCoordinate = function (cursorEvent) { var rowCoordinate; rowCoordinate = null; if (typeof (event) != "undefined") if (typeof (event . offsetY) != "undefined") { rowCoordinate = event . offsetY; } if (typeof (cursorEvent) != "undefined") if (typeof (cursorEvent . layerY) != "undefined") { rowCoordinate = cursorEvent . layerY; } return (rowCoordinate); }; this . getColumnCoordinate = function (cursorEvent) { var columnCoordinate; columnCoordinate = null; if (typeof (event) != "undefined") if (typeof (event . offsetX) != "undefined") { columnCoordinate = event . offsetX; } if (typeof (cursorEvent) != "undefined") if (typeof (cursorEvent . layerX) != "undefined") { columnCoordinate = cursorEvent . layerX; } return (columnCoordinate); }; this . clearNodes = function (node) { while (node . hasChildNodes ()) { node . removeChild (node . firstChild); } return; }; }; // Entity function Entity () {} Entity . prototype . superclass = null; // Methods Entity . prototype . initialize = function () { return; }; Entity . prototype . graft = function (that) { var property; // Copy each property from 'this' to 'that'. for (property in this) { if (typeof (that [property]) == "undefined") { that [property] = this [property]; } } // Assign a superclass to each function in 'that'. for (property in that) { if (typeof (that [property]) == "function") { that [property] . superclass = this; } } return; }; // Delegate function Delegate () {} Delegate . prototype . superclass = Entity . prototype; // Members Delegate . prototype . proxy = null; Delegate . prototype . entity = null; Delegate . prototype . method = null; // Methods Delegate . prototype . act = function () { return (this . proxy . apply (this, arguments)); }; Delegate . prototype . getProxy = function () { return (this . proxy); }; Delegate . prototype . setEntity = function (entity) { this . entity = entity; this . updateProxy (); return; }; Delegate . prototype . setMethod = function (method) { this . method = method; this . updateProxy (); return; }; Delegate . prototype . updateProxy = function () { var entity; var method; entity = this . entity; method = this . method; if ((entity != null) && (method != null)) { this . proxy = function () {return (method . apply (entity, arguments));}; } else { this . proxy = function () {return;}; } return; }; Delegate . prototype . register = function (entity, event) { if (entity . addEventListener) { entity . addEventListener (event, this . getProxy (), false); } else if (entity . attachEvent) { entity . attachEvent ("on" + event, this . getProxy ()); } else { entity ["on" + event] = this . getProxy (); } return; }; Delegate . prototype . unregister = function (entity, event) { if (entity . removeEventListener) { entity . removeEventListener (event, this . getProxy (), false); } else if (entity . detatchEvent) { entity . detachEvent ("on" + entity, this . getProxy ()); } else if (entity ["on" + event] == this . getProxy ()) { entity ["on" + event] = null; } return; }; Delegate . prototype . superclass . graft (Delegate . prototype);