Add files via upload

This commit is contained in:
Jessica Guarato 2022-09-18 18:19:13 -03:00 committed by GitHub
commit 1c99d6fbb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 1448 additions and 0 deletions

21
LICENSE.txt Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2022 by Jessica Guarato (https://codepen.io/jguarato/pen/PoRQPqG)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

4
README.md Normal file
View File

@ -0,0 +1,4 @@
# Solitaire (desktop browsers only)
A Pen created on CodePen.io. Original URL: [https://codepen.io/jguarato/pen/PoRQPqG](https://codepen.io/jguarato/pen/PoRQPqG).

49
dist/index.html vendored Normal file
View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>CodePen - Solitaire (desktop browsers only)</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- partial:index.partial.html -->
<div class="top-area">
<div class="container">
<div class="left-area">
<div id="deck" class="deck"></div>
<div id="top-cards" class="top-cards"></div>
</div>
<div class="right-area">
<div class="pile"><span id="spade-cards"></span></div>
<div class="pile"><span id="heart-cards"></span></div>
<div class="pile"><span id="diamond-cards"></span></div>
<div class="pile"><span id="club-cards"></span></div>
</div>
</div>
</div>
<div class="container">
<div class="bottom-area">
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
</div>
</div>
<footer>
<p>
Created by <a class="name-dark">jguarato</a>
<a href="https://codepen.io/jguarato" target="_blank">Check out my other Pens</a>
<a href="https://github.com/jguarato" target="_blank">Follow me on GitHub</a>
</p>
</footer>
<!-- partial -->
<script src="./script.js"></script>
</body>
</html>

414
dist/script.js vendored Normal file
View File

@ -0,0 +1,414 @@
function createCard(rank, suit, higher) {
let suitSymbol, cardColor;
switch (suit) {
case 'spade':
suitSymbol = '♠';
cardColor = 'black';
break;
case 'heart':
suitSymbol = '♥';
cardColor = 'red';
break;
case 'diamond':
suitSymbol = '♦';
cardColor = 'red';
break;
case 'club':
suitSymbol = '♣';
cardColor = 'black';
break;
default:
suitSymbol = '🃏';
cardColor = 'black';
break;
}
let frontInnerHTML = `<div class="inner-info card-rank">${rank}</div>`;
frontInnerHTML += `<div class="inner-info card-suit-small">${suitSymbol}</div>`;
frontInnerHTML += `<div class="inner-info card-suit-big">${suitSymbol}</div>`;
return {
rank,
higher,
inner: frontInnerHTML,
suit,
color: cardColor,
below: null
}
}
function createDeck() {
const cardRanking = ['A', '2', '3', '4', '5',
'6', '7', '8', '9', '10', 'J', 'Q', 'K'];
const cardSuits = ['spade', 'heart', 'diamond', 'club'];
const deck = [];
for (let i = 0; i < cardSuits.length; i++) {
for (let j = 0; j < cardRanking.length; j++) {
const higherRank = cardRanking[j + 1] ? cardRanking[j + 1] : null;
const newCard = createCard(cardRanking[j], cardSuits[i], higherRank);
deck.push(newCard);
}
}
return deck;
}
function shuffleCards(deck) {
return deck.sort(() => Math.random() - 0.5);
}
function putCardsInDeck(cards) {
const deck = document.getElementById('deck');
cards.forEach(() => {
deck.innerHTML += `<div class="card back"></div>`;
});
const cardsInDeck = deck.querySelectorAll('.card');
cards.forEach((card, index) => {
cardsInDeck[index].cardInfo = card;
});
}
function turnCard() {
const isLastCard = this === this.parentNode.lastElementChild;
const isCardVisible = this.style.visibility !== 'hidden';
const isCardFacingDown = this.classList.contains('back');
if (isLastCard && isCardVisible) {
if (isCardFacingDown) {
this.classList.remove('back');
this.classList.add(`${this.cardInfo.suit}`);
this.innerHTML = this.cardInfo.inner;
}
this.setAttribute('draggable', true);
}
}
function turnCardBack(card) {
card.classList.remove(`${card.cardInfo.suit}`);
card.classList.add('back');
card.innerHTML = '';
card.setAttribute('draggable', false);
}
function distributeCards() {
const piles = document.querySelectorAll('.row');
piles.forEach((pile, index) => {
for (let i = 0; i < index + 1; i++) {
const deck = document.getElementById('deck');
const topCard = deck.lastElementChild;
if (i === index) {
turnCard.apply(topCard);
}
deck.removeChild(topCard);
pile.append(topCard);
}
});
}
function showTopCard(topCards, deck, deckTopCard) {
if (deckTopCard.cardInfo) {
deck.removeChild(deckTopCard);
topCards.append(deckTopCard);
if (topCards.childElementCount > 1) {
topCards.childNodes[0].setAttribute('draggable', false);
}
if (topCards.childElementCount > 2) {
topCards.childNodes[1].setAttribute('draggable', false);
}
if (topCards.childElementCount > 3) {
topCards.childNodes[2].setAttribute('draggable', false);
const firstCard = topCards.firstElementChild;
turnCardBack(firstCard);
firstCard.style.visibility = 'hidden';
topCards.removeChild(firstCard);
deck.prepend(firstCard);
}
}
}
function returnCardsToDeck(topCards, deck) {
const cardsToDeck = [];
topCards.childNodes.forEach(card => {
turnCardBack(card);
card.style.visibility = 'hidden';
cardsToDeck.push(card);
});
cardsToDeck.forEach(card => {
deck.prepend(card);
});
topCards.innerHTML = '';
const cardsInDeck = deck.querySelectorAll('.card');
cardsInDeck.forEach(card => {
card.style.visibility = 'visible';
});
}
function checkDeckCards() {
const topCards = document.getElementById('top-cards');
const deck = document.getElementById('deck');
const deckTopCard = deck.lastElementChild;
if (!deckTopCard) {
returnCardsToDeck(topCards, deck);
} else if (deckTopCard.style.visibility === 'hidden') {
returnCardsToDeck(topCards, deck);
} else {
showTopCard(topCards, deck, deckTopCard);
}
}
function changeCardPosition(cardToDrop, dropSpot, checkCondition) {
if (checkCondition) {
const cardAbove = cardToDrop.previousSibling;
cardToDrop.parentNode.removeChild(cardToDrop);
dropSpot.append(cardToDrop);
if (cardToDrop.cardInfo.below) {
cardToDrop.cardInfo.below.forEach(card => dropSpot.append(card));
}
return cardAbove;
}
}
function dropInRow(cardToDrop, dropSpot) {
const cardToDropInfo = cardToDrop.cardInfo;
const lastCardInRow = dropSpot.lastElementChild;
if (lastCardInRow) {
const lastCardInfo = lastCardInRow.cardInfo;
if (lastCardInfo && lastCardInRow.draggable) {
const checkRank = lastCardInfo.rank === cardToDropInfo.higher;
const checkColor = lastCardInfo.color !== cardToDropInfo.color;
return changeCardPosition(cardToDrop, dropSpot, (checkRank && checkColor));
}
} else {
const checkRank = cardToDrop.cardInfo.rank === 'K';
return changeCardPosition(cardToDrop, dropSpot, checkRank);
}
}
function dropInPile(cardToDrop, dropSpot) {
const cardToDropInfo = cardToDrop.cardInfo;
const lastCardInPile = dropSpot.lastElementChild;
if (!cardToDropInfo.below) {
if (lastCardInPile) {
const lastCardInfo = lastCardInPile.cardInfo;
if (lastCardInfo) {
const checkRank = lastCardInfo.higher === cardToDropInfo.rank;
const checkSuit = lastCardInfo.suit === cardToDropInfo.suit;
if (checkRank && checkSuit) {
lastCardInPile.setAttribute('draggable', false);
}
return changeCardPosition(cardToDrop, dropSpot, (checkRank && checkSuit));
} else {
const checkRank = cardToDropInfo.rank === 'A';
const checkSuit = lastCardInPile.id.split('-')[0] === cardToDropInfo.suit;
return changeCardPosition(cardToDrop, dropSpot, (checkRank && checkSuit));
}
}
}
}
function dropCard(event, cardToDrop) {
const tgt = event.target;
const findSpot = function (element, htmlClass) {
const classList = element.classList;
if (classList) {
if (classList.contains(htmlClass)) {
return element;
} else {
return findSpot(element.parentNode, htmlClass);
}
}
return;
}
const dropSpot = findSpot(tgt, 'row') || findSpot(tgt, 'pile');
let cardAbove;
if (dropSpot) {
if (dropSpot.classList.contains('row')) {
cardAbove = dropInRow(cardToDrop, dropSpot);
} else if (dropSpot.classList.contains('pile')) {
cardAbove = dropInPile(cardToDrop, dropSpot);
}
}
if (cardAbove) {
turnCard.apply(cardAbove);
}
}
function checkGameOver() {
const piles = document.querySelectorAll('.pile');
let allPilesComplete = true;
piles.forEach(pile => {
allPilesComplete = allPilesComplete && (pile.childElementCount - 1) === 13;
});
if (allPilesComplete) {
alert('YOU WIN!');
}
}
function resetSelections(card) {
card.cardInfo.below = null;
card = null;
return card;
}
function dragRowCards(card) {
const cardParent = card.parentNode;
const isLastCard = card === cardParent.lastElementChild;
if (!isLastCard) {
card.cardInfo.below = [];
for (let i = cardParent.childElementCount - 1; i >= 0; i--) {
if (cardParent.childNodes[i] === card) {
return;
}
card.cardInfo.below.unshift(cardParent.childNodes[i]);
}
}
}
const globalDeck = createDeck();
const shuffledDeck = shuffleCards(globalDeck);
putCardsInDeck(shuffledDeck);
distributeCards();
const deck = document.getElementById('deck');
deck.addEventListener('click', checkDeckCards);
const cards = document.getElementsByClassName('card');
for (let i = 0; i < cards.length; i++) {
cards[i].addEventListener('click', turnCard);
}
let selectedCard = null;
document.addEventListener("dragstart", event => {
if (event.target.draggable) {
selectedCard = event.target;
dragRowCards(selectedCard);
}
});
document.addEventListener("dragover", event => {
event.preventDefault();
}, false);
document.addEventListener("drop", event => {
event.preventDefault();
dropCard(event, selectedCard);
selectedCard = resetSelections(selectedCard);
checkGameOver();
});

256
dist/style.css vendored Normal file
View File

@ -0,0 +1,256 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&family=Poppins:wght@300;400;500;600&display=swap');
html,
body {
width: 100%;
margin: 0;
padding: 0;
background-color: #f7f7f7;
background-color: #147246;
font: 400 1.2em sans-serif;
line-height: 1.2;
user-select: none;
}
.container {
width: fit-content;
height: 100%;
margin: 0 auto;
}
.card {
padding: 0;
margin: 2vmin;
width: 7.6vmin;
height: 11vmin;
box-shadow: inset 0px 0px 1vmin 0.2vmin #c3c6c6;
border-radius: 0.8vmin;
background-color: #f5f9fa;
font-family: Roboto;
}
.card-rank {
width: 48%;
float: left;
margin-left: 0.4vmin;
margin-right: 0.3vmin;
letter-spacing: -0.8vmin;
font-size: 4vmin;
font-weight: 500;
}
.card-suit-small {
width: 40%;
float: left;
font-size: 4vmin;
}
.card-suit-big {
width: 100%;
height: inherit;
line-height: 0.6;
font-size: 8vmin;
text-align: center;
}
@-moz-document url-prefix() {
.card-rank {
margin-right: 0.3vmin;
font-size: 4vmin;
}
.card-suit-small {
line-height: 1.6;
font-size: 3vmin;
}
.card-suit-big {
line-height: 0.8;
font-size: 7vmin;
}
}
.card.diamond .inner-info,
.card.heart .inner-info {
background: linear-gradient(to right, #c21f02, #ff2802, #c21f02, #ff2802, #c21f02);
-webkit-background-clip: text;
color: transparent;
}
.card.club .inner-info,
.card.spade .inner-info {
background: linear-gradient(to right, #242222, #534f51, #242222, #534f51, #242222);
-webkit-background-clip: text;
color: transparent;
}
.back {
box-shadow: inset 0px 0px 0.2vmin 0.2vmin #0a2f41;
background: linear-gradient(315deg, #242222, #534f51, #242222, #534f51, #242222);
background: linear-gradient(315deg, #0a3142, #104c66, #12506b, #1b7ca5, #2195ca);
}
.top-area {
padding-top: 2vmin;
width: 100vw;
height: 16vmin;
background-color: #1b4934;
}
.left-area,
.right-area {
display: flex;
place-content: center;
float: left;
}
.left-area {
width: 41vmin;
}
.right-area {
width: 57vmin;
}
.deck {
margin: 2vmin;
width: 7.6vmin;
height: 11vmin;
box-shadow: inset 0px 0px 0vmin 0.5vmin #c3c6c644;
border-radius: 0.8vmin;
background-color: #c3c6c60c;
position: relative;
}
.deck::before {
content: "⟲";
width: 100%;
height: inherit;
line-height: 1.6;
font-size: 7vmin;
text-align: center;
color: #c3c6c644;
position: absolute;
cursor: pointer;
}
.deck .card {
position: absolute;
transform: translateX(-2vmin) translateY(-2vmin);
cursor: pointer;
}
.top-cards {
width: 55%;
display: flex;
}
.top-cards .card {
margin-right: -5vmin;
}
.pile {
padding: 0;
margin: 2vmin;
width: 7.6vmin;
height: 11vmin;
box-shadow: inset 0px 0px 0vmin 0.5vmin #c3c6c644;
border-radius: 0.8vmin;
background-color: #c3c6c60c;
position: relative;
}
.pile span {
width: 100%;
height: inherit;
line-height: 1.4;
font-size: 8vmin;
text-align: center;
color: #c3c6c644;
position: absolute;
}
.pile .card {
position: absolute;
transform: translateX(-2vmin) translateY(-2vmin);
}
.bottom-area {
display: flex;
place-content: center;
width: 100vmin;
min-height: 100%;
height: fit-content;
padding-top: 4vmin;
padding-bottom: 10vmin;
}
.row {
display: grid;
margin-right: 1%;
width: 12%;
height: 100%;
position: relative;
}
.row::before {
content: "";
width: 7.6vmin;
height: 11vmin;
box-shadow: inset 0px 0px 0vmin 0.5vmin #c3c6c644;
border-radius: 0.8vmin;
background-color: #c3c6c60c;
transform: translateX(2vmin) translateY(2vmin);
position: absolute;
}
.row .card {
position: relative;
}
.row .card:not(:first-child) {
margin-top: -8vmin;
}
footer {
position: fixed;
bottom: 0;
width: 100%;
height: fit-content;
margin-top: 25vmin;
padding: 1vmin 0;
background-color: #1e1f26;
font-size: 1.6vmin;
}
footer p {
margin: 1vmin;
text-align: center;
color: #F5F5F5;
font-family: Poppins;
}
footer a:link {
color: #b3a290;
}
footer a:visited {
color: #91d4d0;
}
footer a:hover {
color: #ff3300;
}
footer a:active {
color: #ff3300;
}
.name-dark {
color: #91d4d0;
text-decoration: none;
background: linear-gradient(to right, #91d4d0 50%, #ff3300 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}

34
src/index.html Normal file
View File

@ -0,0 +1,34 @@
<div class="top-area">
<div class="container">
<div class="left-area">
<div id="deck" class="deck"></div>
<div id="top-cards" class="top-cards"></div>
</div>
<div class="right-area">
<div class="pile"><span id="spade-cards"></span></div>
<div class="pile"><span id="heart-cards"></span></div>
<div class="pile"><span id="diamond-cards"></span></div>
<div class="pile"><span id="club-cards"></span></div>
</div>
</div>
</div>
<div class="container">
<div class="bottom-area">
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
</div>
</div>
<footer>
<p>
Created by <a class="name-dark">jguarato</a>
<a href="https://codepen.io/jguarato" target="_blank">Check out my other Pens</a>
<a href="https://github.com/jguarato" target="_blank">Follow me on GitHub</a>
</p>
</footer>

414
src/script.js Normal file
View File

@ -0,0 +1,414 @@
function createCard(rank, suit, higher) {
let suitSymbol, cardColor;
switch (suit) {
case 'spade':
suitSymbol = '♠';
cardColor = 'black';
break;
case 'heart':
suitSymbol = '♥';
cardColor = 'red';
break;
case 'diamond':
suitSymbol = '♦';
cardColor = 'red';
break;
case 'club':
suitSymbol = '♣';
cardColor = 'black';
break;
default:
suitSymbol = '🃏';
cardColor = 'black';
break;
}
let frontInnerHTML = `<div class="inner-info card-rank">${rank}</div>`;
frontInnerHTML += `<div class="inner-info card-suit-small">${suitSymbol}</div>`;
frontInnerHTML += `<div class="inner-info card-suit-big">${suitSymbol}</div>`;
return {
rank,
higher,
inner: frontInnerHTML,
suit,
color: cardColor,
below: null
}
}
function createDeck() {
const cardRanking = ['A', '2', '3', '4', '5',
'6', '7', '8', '9', '10', 'J', 'Q', 'K'];
const cardSuits = ['spade', 'heart', 'diamond', 'club'];
const deck = [];
for (let i = 0; i < cardSuits.length; i++) {
for (let j = 0; j < cardRanking.length; j++) {
const higherRank = cardRanking[j + 1] ? cardRanking[j + 1] : null;
const newCard = createCard(cardRanking[j], cardSuits[i], higherRank);
deck.push(newCard);
}
}
return deck;
}
function shuffleCards(deck) {
return deck.sort(() => Math.random() - 0.5);
}
function putCardsInDeck(cards) {
const deck = document.getElementById('deck');
cards.forEach(() => {
deck.innerHTML += `<div class="card back"></div>`;
});
const cardsInDeck = deck.querySelectorAll('.card');
cards.forEach((card, index) => {
cardsInDeck[index].cardInfo = card;
});
}
function turnCard() {
const isLastCard = this === this.parentNode.lastElementChild;
const isCardVisible = this.style.visibility !== 'hidden';
const isCardFacingDown = this.classList.contains('back');
if (isLastCard && isCardVisible) {
if (isCardFacingDown) {
this.classList.remove('back');
this.classList.add(`${this.cardInfo.suit}`);
this.innerHTML = this.cardInfo.inner;
}
this.setAttribute('draggable', true);
}
}
function turnCardBack(card) {
card.classList.remove(`${card.cardInfo.suit}`);
card.classList.add('back');
card.innerHTML = '';
card.setAttribute('draggable', false);
}
function distributeCards() {
const piles = document.querySelectorAll('.row');
piles.forEach((pile, index) => {
for (let i = 0; i < index + 1; i++) {
const deck = document.getElementById('deck');
const topCard = deck.lastElementChild;
if (i === index) {
turnCard.apply(topCard);
}
deck.removeChild(topCard);
pile.append(topCard);
}
});
}
function showTopCard(topCards, deck, deckTopCard) {
if (deckTopCard.cardInfo) {
deck.removeChild(deckTopCard);
topCards.append(deckTopCard);
if (topCards.childElementCount > 1) {
topCards.childNodes[0].setAttribute('draggable', false);
}
if (topCards.childElementCount > 2) {
topCards.childNodes[1].setAttribute('draggable', false);
}
if (topCards.childElementCount > 3) {
topCards.childNodes[2].setAttribute('draggable', false);
const firstCard = topCards.firstElementChild;
turnCardBack(firstCard);
firstCard.style.visibility = 'hidden';
topCards.removeChild(firstCard);
deck.prepend(firstCard);
}
}
}
function returnCardsToDeck(topCards, deck) {
const cardsToDeck = [];
topCards.childNodes.forEach(card => {
turnCardBack(card);
card.style.visibility = 'hidden';
cardsToDeck.push(card);
});
cardsToDeck.forEach(card => {
deck.prepend(card);
});
topCards.innerHTML = '';
const cardsInDeck = deck.querySelectorAll('.card');
cardsInDeck.forEach(card => {
card.style.visibility = 'visible';
});
}
function checkDeckCards() {
const topCards = document.getElementById('top-cards');
const deck = document.getElementById('deck');
const deckTopCard = deck.lastElementChild;
if (!deckTopCard) {
returnCardsToDeck(topCards, deck);
} else if (deckTopCard.style.visibility === 'hidden') {
returnCardsToDeck(topCards, deck);
} else {
showTopCard(topCards, deck, deckTopCard);
}
}
function changeCardPosition(cardToDrop, dropSpot, checkCondition) {
if (checkCondition) {
const cardAbove = cardToDrop.previousSibling;
cardToDrop.parentNode.removeChild(cardToDrop);
dropSpot.append(cardToDrop);
if (cardToDrop.cardInfo.below) {
cardToDrop.cardInfo.below.forEach(card => dropSpot.append(card));
}
return cardAbove;
}
}
function dropInRow(cardToDrop, dropSpot) {
const cardToDropInfo = cardToDrop.cardInfo;
const lastCardInRow = dropSpot.lastElementChild;
if (lastCardInRow) {
const lastCardInfo = lastCardInRow.cardInfo;
if (lastCardInfo && lastCardInRow.draggable) {
const checkRank = lastCardInfo.rank === cardToDropInfo.higher;
const checkColor = lastCardInfo.color !== cardToDropInfo.color;
return changeCardPosition(cardToDrop, dropSpot, (checkRank && checkColor));
}
} else {
const checkRank = cardToDrop.cardInfo.rank === 'K';
return changeCardPosition(cardToDrop, dropSpot, checkRank);
}
}
function dropInPile(cardToDrop, dropSpot) {
const cardToDropInfo = cardToDrop.cardInfo;
const lastCardInPile = dropSpot.lastElementChild;
if (!cardToDropInfo.below) {
if (lastCardInPile) {
const lastCardInfo = lastCardInPile.cardInfo;
if (lastCardInfo) {
const checkRank = lastCardInfo.higher === cardToDropInfo.rank;
const checkSuit = lastCardInfo.suit === cardToDropInfo.suit;
if (checkRank && checkSuit) {
lastCardInPile.setAttribute('draggable', false);
}
return changeCardPosition(cardToDrop, dropSpot, (checkRank && checkSuit));
} else {
const checkRank = cardToDropInfo.rank === 'A';
const checkSuit = lastCardInPile.id.split('-')[0] === cardToDropInfo.suit;
return changeCardPosition(cardToDrop, dropSpot, (checkRank && checkSuit));
}
}
}
}
function dropCard(event, cardToDrop) {
const tgt = event.target;
const findSpot = function (element, htmlClass) {
const classList = element.classList;
if (classList) {
if (classList.contains(htmlClass)) {
return element;
} else {
return findSpot(element.parentNode, htmlClass);
}
}
return;
}
const dropSpot = findSpot(tgt, 'row') || findSpot(tgt, 'pile');
let cardAbove;
if (dropSpot) {
if (dropSpot.classList.contains('row')) {
cardAbove = dropInRow(cardToDrop, dropSpot);
} else if (dropSpot.classList.contains('pile')) {
cardAbove = dropInPile(cardToDrop, dropSpot);
}
}
if (cardAbove) {
turnCard.apply(cardAbove);
}
}
function checkGameOver() {
const piles = document.querySelectorAll('.pile');
let allPilesComplete = true;
piles.forEach(pile => {
allPilesComplete = allPilesComplete && (pile.childElementCount - 1) === 13;
});
if (allPilesComplete) {
alert('YOU WIN!');
}
}
function resetSelections(card) {
card.cardInfo.below = null;
card = null;
return card;
}
function dragRowCards(card) {
const cardParent = card.parentNode;
const isLastCard = card === cardParent.lastElementChild;
if (!isLastCard) {
card.cardInfo.below = [];
for (let i = cardParent.childElementCount - 1; i >= 0; i--) {
if (cardParent.childNodes[i] === card) {
return;
}
card.cardInfo.below.unshift(cardParent.childNodes[i]);
}
}
}
const globalDeck = createDeck();
const shuffledDeck = shuffleCards(globalDeck);
putCardsInDeck(shuffledDeck);
distributeCards();
const deck = document.getElementById('deck');
deck.addEventListener('click', checkDeckCards);
const cards = document.getElementsByClassName('card');
for (let i = 0; i < cards.length; i++) {
cards[i].addEventListener('click', turnCard);
}
let selectedCard = null;
document.addEventListener("dragstart", event => {
if (event.target.draggable) {
selectedCard = event.target;
dragRowCards(selectedCard);
}
});
document.addEventListener("dragover", event => {
event.preventDefault();
}, false);
document.addEventListener("drop", event => {
event.preventDefault();
dropCard(event, selectedCard);
selectedCard = resetSelections(selectedCard);
checkGameOver();
});

256
src/style.css Normal file
View File

@ -0,0 +1,256 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&family=Poppins:wght@300;400;500;600&display=swap');
html,
body {
width: 100%;
margin: 0;
padding: 0;
background-color: #f7f7f7;
background-color: #147246;
font: 400 1.2em sans-serif;
line-height: 1.2;
user-select: none;
}
.container {
width: fit-content;
height: 100%;
margin: 0 auto;
}
.card {
padding: 0;
margin: 2vmin;
width: 7.6vmin;
height: 11vmin;
box-shadow: inset 0px 0px 1vmin 0.2vmin #c3c6c6;
border-radius: 0.8vmin;
background-color: #f5f9fa;
font-family: Roboto;
}
.card-rank {
width: 48%;
float: left;
margin-left: 0.4vmin;
margin-right: 0.3vmin;
letter-spacing: -0.8vmin;
font-size: 4vmin;
font-weight: 500;
}
.card-suit-small {
width: 40%;
float: left;
font-size: 4vmin;
}
.card-suit-big {
width: 100%;
height: inherit;
line-height: 0.6;
font-size: 8vmin;
text-align: center;
}
@-moz-document url-prefix() {
.card-rank {
margin-right: 0.3vmin;
font-size: 4vmin;
}
.card-suit-small {
line-height: 1.6;
font-size: 3vmin;
}
.card-suit-big {
line-height: 0.8;
font-size: 7vmin;
}
}
.card.diamond .inner-info,
.card.heart .inner-info {
background: linear-gradient(to right, #c21f02, #ff2802, #c21f02, #ff2802, #c21f02);
-webkit-background-clip: text;
color: transparent;
}
.card.club .inner-info,
.card.spade .inner-info {
background: linear-gradient(to right, #242222, #534f51, #242222, #534f51, #242222);
-webkit-background-clip: text;
color: transparent;
}
.back {
box-shadow: inset 0px 0px 0.2vmin 0.2vmin #0a2f41;
background: linear-gradient(315deg, #242222, #534f51, #242222, #534f51, #242222);
background: linear-gradient(315deg, #0a3142, #104c66, #12506b, #1b7ca5, #2195ca);
}
.top-area {
padding-top: 2vmin;
width: 100vw;
height: 16vmin;
background-color: #1b4934;
}
.left-area,
.right-area {
display: flex;
place-content: center;
float: left;
}
.left-area {
width: 41vmin;
}
.right-area {
width: 57vmin;
}
.deck {
margin: 2vmin;
width: 7.6vmin;
height: 11vmin;
box-shadow: inset 0px 0px 0vmin 0.5vmin #c3c6c644;
border-radius: 0.8vmin;
background-color: #c3c6c60c;
position: relative;
}
.deck::before {
content: "⟲";
width: 100%;
height: inherit;
line-height: 1.6;
font-size: 7vmin;
text-align: center;
color: #c3c6c644;
position: absolute;
cursor: pointer;
}
.deck .card {
position: absolute;
transform: translateX(-2vmin) translateY(-2vmin);
cursor: pointer;
}
.top-cards {
width: 55%;
display: flex;
}
.top-cards .card {
margin-right: -5vmin;
}
.pile {
padding: 0;
margin: 2vmin;
width: 7.6vmin;
height: 11vmin;
box-shadow: inset 0px 0px 0vmin 0.5vmin #c3c6c644;
border-radius: 0.8vmin;
background-color: #c3c6c60c;
position: relative;
}
.pile span {
width: 100%;
height: inherit;
line-height: 1.4;
font-size: 8vmin;
text-align: center;
color: #c3c6c644;
position: absolute;
}
.pile .card {
position: absolute;
transform: translateX(-2vmin) translateY(-2vmin);
}
.bottom-area {
display: flex;
place-content: center;
width: 100vmin;
min-height: 100%;
height: fit-content;
padding-top: 4vmin;
padding-bottom: 10vmin;
}
.row {
display: grid;
margin-right: 1%;
width: 12%;
height: 100%;
position: relative;
}
.row::before {
content: "";
width: 7.6vmin;
height: 11vmin;
box-shadow: inset 0px 0px 0vmin 0.5vmin #c3c6c644;
border-radius: 0.8vmin;
background-color: #c3c6c60c;
transform: translateX(2vmin) translateY(2vmin);
position: absolute;
}
.row .card {
position: relative;
}
.row .card:not(:first-child) {
margin-top: -8vmin;
}
footer {
position: fixed;
bottom: 0;
width: 100%;
height: fit-content;
margin-top: 25vmin;
padding: 1vmin 0;
background-color: #1e1f26;
font-size: 1.6vmin;
}
footer p {
margin: 1vmin;
text-align: center;
color: #F5F5F5;
font-family: Poppins;
}
footer a:link {
color: #b3a290;
}
footer a:visited {
color: #91d4d0;
}
footer a:hover {
color: #ff3300;
}
footer a:active {
color: #ff3300;
}
.name-dark {
color: #91d4d0;
text-decoration: none;
background: linear-gradient(to right, #91d4d0 50%, #ff3300 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}