Една от многото интересни задачи в курса по 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(); }