Една от многото интересни задачи в курса по JavaScript е свързана с упражняването на Drag and Drop техниката , а също така и използването на Local storage за съхраняване на информация.
За целта създавам игра, в която играчът събира разхвърлени торби с боклук и ги изхвърля в приготвена за целта кофа. При поднасяне на торба над кофата, капака на кофата се отваря. Също така се отчита времето за събиране на всички торби и се прави класиране. След края на всяка игра резултата на играча се записва Local storage. Веднага след това всички резултати се изчитат от Local storage, сортират се и имената на петте най-добри играчи се показват на екрана.
1.Drag and drop.
За да изпълня Drag and drop техниката съм подходил по следния начин:
- При създаването на кофата за боклук съм прикачил към нея два event-а. Първият слуша дали има изпуснат боклук в кофата (ondrop) и извиква функцията drop(ev), която измества торбата с боклук в кофата. Вторият слуша дали има провлачване на боклук върху кофата (ondragover) и съответно извиква функцията allowDrop(ev), която да отвори капака на кофата.
function createTrashCan() { var trashCan = document.createElement("div"); trashCan.id = "trashCan"; trashCan.addEventListener("drop", drop, false); trashCan.addEventListener("dragover", allowDrop, false); document.body.appendChild(trashCan); } - При създаването на площа, върху която е разпилян боклука прикачам към нея event, който слуша дали има провлачване на боклук върху тази площ (ondragover) и съответно извиква функцията closeTrashCan(), която да затвори капака на кофата.
function createTrashArea() { var trashArea = document.createElement("div"); trashArea.id = "trashArea"; trashArea.addEventListener("dragover", closeTrashCan, false); document.body.appendChild(trashArea); createRandomBags(); } - При създаването на всяка от торбите с боклук (функциите createBags() -> createDivElements()) поставям атрибута на „div“ контейнера й draggable = „true“. Също така прикачам към него event, който слуша дали провлачване е започнало (ondragstart) и съответно извиква функцията drag(ev), която записва ID-to на съответната торба с боклук в специален dataTransfer обект. Така, когато пуснем дадената торба и извикаме функцията drop(ev) може да вземем информацията за ID-то на торбата обратно от същия обект. Използват се двете функции dataTransfer.setData и dataTransfer.getData, съответно за записване и прочитане на информация от обекта.
2.Local storage.
Резултата от всяка игра се записва в Local storage-a -> localStorage.setItem(playerName, seconds). Веднага след записа всички резултати се прочитат обратно от Local storage, сортират се и първите пет се изкарват на екран – loadLocalStorageOnScoreBoard().
function savePlayerScore() {
localStorage.setItem(playerName, seconds);
loadLocalStorageOnScoreBoard();
}
function loadLocalStorageOnScoreBoard() {
if (!localStorage.length || localStorage.length == 0) {
return;
}
var sorterItems = sortLocalStorage();
var resultHTML = "<ul>";
if (localStorage.length > 5) {
var numberOfItemsInScoreBoard = 5;
}
else {
numberOfItemsInScoreBoard = localStorage.length;
}
for (var i = 0; i < numberOfItemsInScoreBoard; i++) {
var playerName = sorterItems[i].key;
var playerValue = sorterItems[i].value;
resultHTML +=
'<li>' +
(i + 1) + ". " + playerName + " : " + playerValue + 's'
'</li>';
}
resultHTML += "</ul>";
document.getElementById("scoreBoard").innerHTML = resultHTML;
}
function sortLocalStorage() {
if (localStorage.length > 0) {
var localStorageArray = new Array();
for (i = 0; i < localStorage.length; i++) {
localStorageArray[i] = new LocalStorageItem(
localStorage.key(i),
localStorage.getItem(localStorage.key(i))
);
}
}
var sortedArray = localStorageArray.sort(comparator);
return sortedArray;
}
Използвал съм отделна функция comparator() за сортиране на информацията в Local storage. Така направена функцията comparator(a,b) и подадена на array.sort() ще сортира масива от обекти (LocalStorageItem(key, value)) в низходящ ред според резултата на играча.
function comparator(a, b) {
return parseInt(a.value) - parseInt(b.value);
}
//Class that represents Local storage item
function LocalStorageItem(key, value)
{
this.key = key;
this.value = value;
}
Пълният javascript код следва, а тук може да изпробвате демото на играта -> DEMO.
function renderPlaygroud() {
playerName = document.getElementById("playerName").value;
removeInitialInfo();
createTrashCan();
createTrashArea();
createScoreBoard()
createTimer();
}
function removeInitialInfo() {
var initialInfo = document.getElementById("initialInfo");
document.body.removeChild(initialInfo);
}
function createTrashCan() {
var trashCan = document.createElement("div");
trashCan.id = "trashCan";
trashCan.addEventListener("drop", drop, false);
trashCan.addEventListener("dragover", allowDrop, false);
document.body.appendChild(trashCan);
}
function createTrashArea() {
var trashArea = document.createElement("div");
trashArea.id = "trashArea";
trashArea.addEventListener("dragover", closeTrashCan, false);
document.body.appendChild(trashArea);
createBags();
}
function createScoreBoard() {
var scoreBoard = document.createElement("div");
scoreBoard.id = "scoreBoard";
document.body.appendChild(scoreBoard);
loadLocalStorageOnScoreBoard();
}
function createBags() {
var numberBags = 10;
var docFragment = document.createDocumentFragment();
for (var i = 0; i < numberBags; i++) {
var divElement = createDivElement(i);
docFragment.appendChild(divElement);
}
var trashArea = document.getElementById("trashArea");
trashArea.appendChild(docFragment);
}
function createDivElement(number) {
var divElement = document.createElement("div");
//Add inline styles
divElement.id = "div" + number;
divElement.style.width = "76px";
divElement.style.height = "118px";
divElement.style.backgroundImage = "url('pictures/trash.png')";
divElement.style.position = "absolute";
divElement.style.top = generateRandomNumberFromInterval(0, 480) + "px";
divElement.style.left = generateRandomNumberFromInterval(0, 800) + "px";
divElement.draggable = "true";
divElement.addEventListener("dragstart", drag, false);
return divElement;
}
function generateRandomNumberFromInterval(from, to) {
return Math.floor(Math.random() * (to - from + 1) + from);
}
function createTimer() {
timer = document.createElement("div");
timer.id = "timer";
document.body.appendChild(timer);
seconds = 0;
updateTimer();
window.setTimeout("tick()", 1000);
}
function tick() {
seconds += 1;
updateTimer();
window.setTimeout("tick()", 1000);
}
function updateTimer() {
var timeString = playerName + " : " + seconds + "s";
timer.innerHTML = timeString;
}
function allowDrop(ev) {
openTrashCan();
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("dragged-id", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("dragged-id");
var element = document.getElementById(data);
element.parentNode.removeChild(element);
closeTrashCan();
var numberOfBags = document.getElementById("trashArea").childNodes.length;
if (numberOfBags == 0) {
savePlayerScore(playerName, seconds);
hidePlayGround();
var message = document.createElement('p');
message.innerHTML =
"Congratulations! You have managed to clean the trash for " + seconds + 's';
document.body.appendChild(message);
createResetButton();
}
}
function hidePlayGround() {
var trashCan = document.getElementById("trashCan");
trashCan.parentNode.removeChild(trashCan);
var trashArea = document.getElementById("trashArea");
trashArea.parentNode.removeChild(trashArea);
var timer = document.getElementById("timer");
timer.style.display = "none";
}
function createResetButton() {
var button = document.createElement("input");
button.type = "button";
button.value = "Restart Game";
button.addEventListener("click", function () { document.location.reload(true) }, false);
document.body.appendChild(button);
}
function openTrashCan() {
var trashCan = document.getElementById("trashCan");
trashCan.style.backgroundImage = "url('pictures/opened.png')"
}
function closeTrashCan() {
var trashCan = document.getElementById("trashCan");
trashCan.style.backgroundImage = "url('pictures/closed.png')"
}
function loadLocalStorageOnScoreBoard() {
if (!localStorage.length || localStorage.length == 0) {
return;
}
var sorterItems = sortLocalStorage();
var resultHTML = "<ul>";
if (localStorage.length > 5) {
var numberOfItemsInScoreBoard = 5;
}
else {
numberOfItemsInScoreBoard = localStorage.length;
}
for (var i = 0; i < numberOfItemsInScoreBoard; i++) {
var playerName = sorterItems[i].key;
var playerValue = sorterItems[i].value;
resultHTML +=
'<li>' +
(i + 1) + ". " + playerName + " : " + playerValue + 's'
'</li>';
}
resultHTML += "</ul>";
document.getElementById("scoreBoard").innerHTML = resultHTML;
}
function sortLocalStorage() {
if (localStorage.length > 0) {
var localStorageArray = new Array();
for (i = 0; i < localStorage.length; i++) {
localStorageArray[i] = new LocalStorageItem(
localStorage.key(i),
localStorage.getItem(localStorage.key(i))
);
}
}
var sortedArray = localStorageArray.sort(comparator);
return sortedArray;
}
function comparator(a, b) {
return parseInt(a.value) - parseInt(b.value);
}
//Class that represents Local storage item
function LocalStorageItem(key, value)
{
this.key = key;
this.value = value;
}
function savePlayerScore() {
localStorage.setItem(playerName, seconds);
loadLocalStorageOnScoreBoard();
}
