2017-09-18 12:04:55 -04:00
|
|
|
let deckName, deckJSON, cardCount, deckWidth, deckHeight,
|
|
|
|
piles = {'deck': [], discard: []};
|
|
|
|
|
|
|
|
window.addEventListener('load', () => {
|
|
|
|
let xhr = new XMLHttpRequest();
|
|
|
|
xhr.addEventListener("load", () => {
|
|
|
|
deckJSON = JSON.parse(xhr.responseText);
|
2017-09-20 22:36:06 -04:00
|
|
|
piles.deck = deckJSON.ObjectStates[0].DeckIDs.map(c => c - 100);
|
2017-09-18 12:04:55 -04:00
|
|
|
cardCount = piles['deck'].length;
|
|
|
|
shuffle(piles['deck']);
|
|
|
|
deckWidth = deckJSON.ObjectStates[0].CustomDeck["1"].NumWidth;
|
|
|
|
deckHeight = deckJSON.ObjectStates[0].CustomDeck["1"].NumHeight;
|
|
|
|
console.log(deckName);
|
|
|
|
});
|
2017-09-20 18:10:37 -04:00
|
|
|
deckName = document.querySelector('#card-container').getAttribute("data-deckName");
|
|
|
|
xhr.open("GET", "/deck/" + deckName + "/deck.json");
|
2017-09-18 12:04:55 -04:00
|
|
|
xhr.send();
|
2017-09-21 12:00:50 -04:00
|
|
|
|
|
|
|
window.addEventListener("contextmenu", event => event.preventDefault());
|
2017-09-18 12:04:55 -04:00
|
|
|
});
|
|
|
|
|
2017-09-20 22:35:31 -04:00
|
|
|
let cardInteract = interact('.card', {ignoreFrom: '.in-list'})
|
2017-09-18 12:04:55 -04:00
|
|
|
.draggable({
|
|
|
|
restrict: {
|
|
|
|
restriction: "parent",
|
|
|
|
endOnly: true,
|
|
|
|
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
|
|
|
|
},
|
|
|
|
|
|
|
|
snap: {
|
|
|
|
targets: [() => {
|
|
|
|
// TODO: maybe change to dropzone?
|
|
|
|
let pos = document.body.getBoundingClientRect(),
|
2017-09-20 22:36:06 -04:00
|
|
|
hand = document.getElementById('hand'),
|
2017-09-18 12:04:55 -04:00
|
|
|
style = window.getComputedStyle(hand),
|
|
|
|
handHeight = parseInt(style.getPropertyValue("height"));
|
|
|
|
return {y: pos.bottom,
|
|
|
|
range: handHeight/2};
|
|
|
|
}],
|
|
|
|
relativePoints: [{x: 0.5 , y: 1}]
|
|
|
|
},
|
|
|
|
|
|
|
|
onmove: dragMoveListener
|
|
|
|
})
|
2017-09-21 12:03:43 -04:00
|
|
|
.on('doubletap', event => {
|
|
|
|
let scale = parseFloat(event.target.getAttribute('data-scale')) === 2 ? 1 : 2;
|
|
|
|
event.target.setAttribute('data-scale', scale);
|
|
|
|
dragMoveListener({target: event.target, dx: 0, dy: 0});
|
2017-09-18 12:04:55 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
interact('.card-pile')
|
|
|
|
.dropzone({
|
|
|
|
accept: '.card',
|
|
|
|
ondrop: event => {
|
2017-09-20 18:12:16 -04:00
|
|
|
let pileName = event.target.getAttribute('data-pile');
|
|
|
|
piles[pileName].push(event.relatedTarget.getAttribute('data-num'));
|
2017-09-18 12:04:55 -04:00
|
|
|
event.relatedTarget.parentElement.removeChild(event.relatedTarget);
|
|
|
|
|
|
|
|
// update deck text
|
2017-09-20 18:12:16 -04:00
|
|
|
event.target.innerHTML = `${pileName.toUpperCase()}<br>${piles[pileName].length}/${cardCount}`;
|
2017-09-18 12:04:55 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.draggable({manualStart: true})
|
|
|
|
.on('move', event => {
|
|
|
|
let interaction = event.interaction;
|
2017-09-20 18:12:16 -04:00
|
|
|
let pileName = event.target.getAttribute('data-pile');
|
|
|
|
let pile = piles[pileName];
|
2017-09-18 12:04:55 -04:00
|
|
|
|
|
|
|
// if the pointer was moved while being held down
|
|
|
|
// and an interaction hasn't started yet
|
2017-09-20 22:35:31 -04:00
|
|
|
// and there are cards in the pile
|
2017-09-18 12:04:55 -04:00
|
|
|
if (interaction.pointerIsDown &&
|
|
|
|
!interaction.interacting() &&
|
|
|
|
pile.length > 0) {
|
|
|
|
// draw a new card
|
2017-09-20 22:35:31 -04:00
|
|
|
let newCard = makeCard(pile.pop());
|
|
|
|
newCard.style.position = "fixed";
|
|
|
|
newCard.style.top = event.pageY;
|
|
|
|
newCard.style.left = event.pageX;
|
2017-09-20 18:38:01 -04:00
|
|
|
// insert the card to the page
|
|
|
|
document.querySelector("#card-container").appendChild(newCard);
|
|
|
|
|
2017-09-18 12:04:55 -04:00
|
|
|
// update deck text
|
2017-09-20 18:12:16 -04:00
|
|
|
event.target.innerHTML = `${pileName.toUpperCase()}<br>${pile.length}/${cardCount}`;
|
2017-09-18 12:04:55 -04:00
|
|
|
|
|
|
|
// start a drag interaction targeting the clone
|
|
|
|
interaction.start({name: 'drag'}, cardInteract, newCard);
|
|
|
|
}
|
2017-09-20 22:35:31 -04:00
|
|
|
})
|
|
|
|
.on('hold', event => {
|
|
|
|
let pile = piles[event.target.getAttribute('data-pile')];
|
2017-09-21 13:10:00 -04:00
|
|
|
let searchBox = document.createElement('input');
|
|
|
|
let container = document.createElement('div');
|
2017-09-20 22:35:31 -04:00
|
|
|
let cardList = document.createElement('div');
|
2017-09-21 13:10:00 -04:00
|
|
|
searchBox.setAttribute('type', 'search');
|
|
|
|
searchBox.setAttribute('placeholder', 'Filter');
|
|
|
|
searchBox.addEventListener('input', event => {
|
|
|
|
for (var ii = 0; ii < cardList.children.length; ii++) {
|
|
|
|
let input = event.target.value;
|
|
|
|
let cardNum = parseInt(cardList.children[ii].getAttribute('data-num'));
|
|
|
|
let cardData = deckJSON.ObjectStates[0].ContainedObjects.find(c => c.CardID === (cardNum + 100));
|
|
|
|
cardList.children[ii].style.display =
|
|
|
|
(cardData.Nickname.toLowerCase().includes(input.toLowerCase()) ||
|
|
|
|
cardData.Description.toLowerCase().includes(input.toLowerCase())) ?
|
|
|
|
"": "none";
|
|
|
|
}
|
|
|
|
});
|
|
|
|
container.appendChild(searchBox);
|
|
|
|
|
2017-09-20 22:35:31 -04:00
|
|
|
pile.forEach(cardNum => {
|
|
|
|
let newCard = makeCard(cardNum);
|
|
|
|
newCard.classList.add('in-list');
|
|
|
|
newCard.addEventListener('click', event => {
|
|
|
|
// re-parent
|
|
|
|
event.target.parentElement.removeChild(event.target);
|
|
|
|
document.querySelector("#card-container").appendChild(event.target);
|
|
|
|
|
|
|
|
// remove list class
|
|
|
|
event.target.classList.remove('in-list');
|
|
|
|
|
|
|
|
// fix position
|
|
|
|
newCard.style.position = "fixed";
|
|
|
|
|
|
|
|
// remove from source pile
|
|
|
|
let cardNum = parseInt(event.target.getAttribute('data-num'));
|
|
|
|
let index = pile.indexOf(cardNum);
|
|
|
|
if (index > -1) {
|
|
|
|
pile.splice(index, 1);
|
|
|
|
}
|
|
|
|
}, {once: true});
|
|
|
|
cardList.appendChild(newCard);
|
|
|
|
});
|
2017-09-21 13:10:00 -04:00
|
|
|
container.appendChild(cardList);
|
|
|
|
showModal(container);
|
2017-09-21 02:42:09 -04:00
|
|
|
})
|
|
|
|
.on('tap', event => shuffle(piles[event.target.getAttribute('data-pile')]));
|
2017-09-18 12:04:55 -04:00
|
|
|
|
2017-09-20 22:35:31 -04:00
|
|
|
function makeCard(cardNum) {
|
|
|
|
// draw a new card
|
|
|
|
let card = document.createElement('div');
|
|
|
|
card.className = "card";
|
|
|
|
|
|
|
|
// temporary add so getComputedStyle works on Chrome
|
|
|
|
document.body.appendChild(card);
|
|
|
|
let style = window.getComputedStyle(card);
|
|
|
|
card.setAttribute('data-num', cardNum);
|
|
|
|
card.style.backgroundPositionX =
|
|
|
|
-(cardNum % deckWidth) * parseInt(style.getPropertyValue("width")) + "px";
|
|
|
|
card.style.backgroundPositionY =
|
|
|
|
-Math.floor(cardNum/deckHeight) * parseInt(style.getPropertyValue("height")) + "px";
|
|
|
|
card.style.backgroundImage = "url('deck.png')";
|
|
|
|
card.style.backgroundSize = `${deckWidth * 100}% ${deckHeight * 100}%`;
|
|
|
|
document.body.removeChild(card);
|
|
|
|
|
|
|
|
return card;
|
|
|
|
}
|
|
|
|
|
|
|
|
function showModal(content) {
|
|
|
|
let shade = document.createElement('div');
|
|
|
|
shade.id = "shade";
|
|
|
|
shade.className = "modal";
|
|
|
|
shade.addEventListener('click', hideModal);
|
|
|
|
document.body.appendChild(shade);
|
|
|
|
|
|
|
|
let modal = document.createElement('div');
|
|
|
|
modal.id = "modal-content";
|
|
|
|
modal.className = "modal";
|
|
|
|
modal.appendChild(content);
|
|
|
|
document.body.appendChild(modal);
|
|
|
|
}
|
|
|
|
|
|
|
|
function hideModal() {
|
|
|
|
document.querySelectorAll('.modal').forEach(
|
|
|
|
e => e.parentElement.removeChild(e));
|
|
|
|
}
|
|
|
|
|
2017-09-18 12:04:55 -04:00
|
|
|
// Fisher-Yates shuffle from https://bost.ocks.org/mike/shuffle/
|
|
|
|
function shuffle(array) {
|
|
|
|
let m = array.length, t, i;
|
|
|
|
|
|
|
|
// While there remain elements to shuffle…
|
|
|
|
while (m) {
|
|
|
|
// Pick a remaining element…
|
|
|
|
i = Math.floor(Math.random() * m--);
|
|
|
|
|
|
|
|
// And swap it with the current element.
|
|
|
|
t = array[m];
|
|
|
|
array[m] = array[i];
|
|
|
|
array[i] = t;
|
|
|
|
}
|
|
|
|
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
function dragMoveListener (event) {
|
|
|
|
let target = event.target,
|
|
|
|
// keep the dragged position in the data-x/data-y attributes
|
|
|
|
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
|
|
|
|
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
|
2017-09-21 12:03:43 -04:00
|
|
|
scale = (parseFloat(target.getAttribute('data-scale')) || 1);
|
2017-09-18 12:04:55 -04:00
|
|
|
|
2017-09-21 12:03:43 -04:00
|
|
|
// translate and scale the element
|
2017-09-18 12:04:55 -04:00
|
|
|
target.style.webkitTransform =
|
|
|
|
target.style.transform =
|
2017-09-21 12:03:43 -04:00
|
|
|
'translate(' + x + 'px, ' + y + 'px) scale(' + scale + ')';
|
2017-09-18 12:04:55 -04:00
|
|
|
|
|
|
|
// raise to top
|
|
|
|
target.parentElement.removeChild(target);
|
|
|
|
document.querySelector("#card-container").appendChild(target);
|
|
|
|
|
|
|
|
// update the posiion attributes
|
|
|
|
target.setAttribute('data-x', x);
|
|
|
|
target.setAttribute('data-y', y);
|
|
|
|
}
|
|
|
|
|