Solution to this question: Render items into DOM from array and changing value for each on click
I have been developing a JavaScript game which is based on DOM manipulation using jQuery.
The feature I want to simplify is clicking the item to buy it from one location in the HTML that is #store
and moving it in an other location that is #inventory
. Clicking the inventory item to equip it will move it to #room
. Clicking the item in #room
will move it back to #inventory
.
When you click an item in the shop to buy it, the owned
variable changes from 0
to 1
. When you click the item in your inventory to equip it, it changes from 1
to 2
. When you click the item when it's equipped, it changes from 2
to 1
to move locations.
My setup for this now is unowned item.owned=0
, owned item.owned=1
, and equipped item.owned=2
.
The reason for the owned variable is to set/get it in localStorage
to save the items current position.
I have just hard coded the script and repeated myself to get desired results. But it's really bloating the files.
Here is my old solution:
HTML (class="dn" is display: none)
<body class="bg-near-black near-white sans-serif">
<main class="mw6 center">
<div class="ma3" id="shop">
<h3>shop</h3>
<div id="item1" class="item">
<p class="name-item1"></p>
<p class="cost-item1"></p>
<p class="desc-item1"></p>
</div>
<div id="item2" class="item">
<p class="name-item2"></p>
<p class="cost-item2"></p>
<p class="desc-item2"></p>
</div>
<div id="item3" class="item">
<p class="name-item3"></p>
<p class="cost-item3"></p>
<p class="desc-item3"></p>
</div>
</div>
<div class="ma3" id="inventory">
<h3>inventory</h3>
<div id="item1" class="item dn">
<p class="name-item1"></p>
<p class="desc-item1"></p>
</div>
<div id="item2" class="item dn">
<p class="name-item2"></p>
<p class="desc-item2"></p>
</div>
<div id="item3" class="item dn">
<p class="name-item3"></p>
<p class="desc-item3"></p>
</div>
</div>
<div class="ma3" id="room">
<h3>room</h3>
<div id="item1" class="item dn">
<p class="name-item1"></p>
</div>
<div id="item2" class="item dn">
<p class="name-item2"></p>
</div>
<div id="item3" class="item dn">
<p class="name-item3"></p>
</div>
</div>
</main>
<script src="js/jquery.min.js"></script>
<script src="js/script.js"></script>
</body>
JavaScript
$(document).ready(function() {
let items = {
item1: {
cost: 100,
owned: 0,
name: "Item | 1",
desc: "This is item 1.",
img: "img/item-1.gif"
}
};
// Render item info
$(".name-item1").each(function(){$(this).text(items.item1.name)});
$(".cost-item1").each(function(){$(this).text(items.item1.cost)});
$(".desc-item1").each(function(){$(this).text(items.item1.desc)});
// Render items
function drawitems() {
if (items.item1.owned==0) {
$("#shop #item1").show();
$("#inventory #item1").hide();
$("#room #item1").hide();
}
if (items.item1.owned==1) {
$("#shop #item1").hide();
$("#inventory #item1").show();
$("#room #item1").hide();
}
if (items.item1.owned==2) {
$("#shop #item1").hide();
$("#inventory #item1").hide();
$("#room #item1").show();
}
}
// Change item data
// Display item in inventory (Buy)
$("#shop").on("click","#item1",function(){
items.item1.owned=1
drawitems();
});
// Display item in room (Equip)
$("#inventory").on("click","#item1",function(){
items.item1.owned=2
drawitems();
});
// Display item in inventory (Unequip)
$("#room").on("click","#item1",function(){
items.item1.owned=1
drawitems();
});
// Save and load item data
$("#save").click(function(){
var save = {
"owneditem1": items.item1.owned,
};
localStorage.setItem("save",JSON.stringify(save));
});
function loadprogress() {
if (localStorage.getItem("save") !== null) {
var progress = JSON.parse(localStorage.getItem("save"));
items.item1.owned = progress["owneditem1"];
drawitems();
}
};
loadprogress();
});
I have been looking for easier and cleaner ways to do this and rendering the items to the <div>
ID-s using the .each()
function was a good start. But now I'm running into issues with changing the owned
data on click for each <div>
I want to render the items to and re-render the DOM to put the items in their right <div>
without changing the owned
data on ALL items.
My new solution in progress:
HTML
<body class="bg-near-black near-white sans-serif">
<main class="mw6 center">
<div class="ma3" id="shop">
<h3>shop</h3>
</div>
<div class="ma3" id="inventory">
<h3>inventory</h3>
</div>
<div class="ma3" id="room">
<h3>room</h3>
</div>
</main>
<script src="js/jquery.min.js"></script>
<script src="js/script.js"></script>
</body>
JavaScript
items = {
item1: {
cost: 100,
owned: 0,
name: "Item | 1",
desc: "This is item 1.",
img: "img/item-1.gif",
},
item2: {
cost: 200,
owned: 0,
name: "Item | 2",
desc: "This is item 2.",
img: "img/item-2.gif",
},
item3: {
cost: 300,
owned: 0,
name: "Item | 3",
desc: "This is item 3.",
img: "img/item-3.gif",
}
};
// Render items in their respective DIVs based on owned data
$.each(items, function(key,val) {
if (items[key].owned==0) { //Render name, cost and desc
$('#shop').append('<div class="item"><div style="background-image:url(' + items[key].img + ')"></div><span>'+ items[key].name +'</span><span>Price: '+ items[key].cost +'</span><span>'+ items[key].desc +'</span></div>');
} else if (items[key].owned==1) { // Render name and desc
$('#inventory').append('<div class="item"><div style="background-image:url(' + items[key].img + ')"></div><span>'+ items[key].name +'</span><span>'+ items[key].desc +'</span></div>');
} else if (items[key].owned==2) { // Render name
$('#room').append('<div class="item"><div style="background-image:url(' + items[key].img + ')"></div><span>'+ items[key].name +'</span></div>');
}
});
$('#shop').on('click', '.item', function() {
//How do I set item owned to 1 here?
});
$('#inventory').on('click', '.item', function() {
//How do I set item owned to 2 here?
});
$('#room').on('click', '.item', function() {
//How do I set item owned to 1 here?
});
setInterval(function(){
var save = {
"owneditem1": items.item1.owned,
"owneditem2": items.item2.owned,
"owneditem3": items.item3.owned,
};
localStorage.setItem("save",JSON.stringify(save));
}, 10000);
function loadprogress() {
if (localStorage.getItem("save") !== null) {
var progress = JSON.parse(localStorage.getItem("save"));
items.item1.owned = progress["owneditem1"];
items.item2.owned = progress["owneditem2"];
items.item3.owned = progress["owneditem3"];
};
};
This is how far I've gotten in the new version of my script. I want an easier way to change the states and display them accordingly in the HTML sections while localStorage is included without listing all the items in their own separate functions.