I am trying to make a function to buy item but I dont want people to be able to gather more than 2 items at the same time.
I am looking for a condition that state something like.
if Axe + Sword = true then calling the function buyItem(Dagger) will say something like "You cant have more than 2 items".
But consider I want to add more items later.
var buyItem = function (name)
{
if (name === "Axe")
{
console.log("Axe");
}
else if (name === "Sword")
{
console.log("Sword");
}
else if (name === "Dagger")
{
console.log("Dagger");
}
};
Thank you :)
How about having a variable that keeps track of how many items you have?
int itemsHeld = 0;
When you acquire a new item use itemsHeld++; and when you lose one use itemsHeld--;
Now when trying to get a new item you can just ask if (itemsHeld < 2) getItem();
Store bought count as private variable
// store reference to your function returned from self invoking anonymous function enclosure (to prevent internal vairables from leaking into global scope)
var buyItem = (function(){
// store local reference to number of items already bought
var bought = 0;
// return the function to be assigned to buyItem
return function (name)
{
// if we reached the maximum, don't buy any more - just log a warning and return
if(bought >= 2){
console.log("your hands are full!!");
return;
} else {
// otherwise increment the bought counter
bought++;
};
if (name === "Axe")
{
console.log("Axe");
}
else if (name === "Sword")
{
console.log("Sword");
}
else if (name === "Dagger")
{
console.log("Dagger");
}
};
})();
// try it out
buyItem('Dagger');
buyItem('Sword');
buyItem('Axe');
Related
I'm trying to filter an array by a given ID in a function, but I don't know how to add the ID to the filter-method
function checkIdFilter(mediaObject, subCollectionId){
//mediaObject is allMedia[index??]
console.log("FILTERING ON " + subCollectionId);
return mediaObject.id == subCollectionId//check if mediaObject has certain ID here;
}
function searchMediaByCollection(subCollectionId) {
let filteredMedia = allMedia.filter(checkIdFilter);
// let filteredMedia = allMedia.filter(checkIdFilter(this.mo??, subCollectionId));
}
As you can see, I don't know how to correctly pass the Id to the checkIdFilter method, as it (I assume) iterates invisibly over the array.
A filter function takes only one parameter: the current object, so you have to wrap your function in another function, and use the closure to reach subCollectionId.
function checkIdFilter(mediaObject, subCollectionId){
//mediaObject is allMedia[index??]
console.log("FILTERING ON " + subCollectionId);
return mediaObject.id == subCollectionId//check if mediaObject has certain ID here;
}
function searchMediaByCollection(subCollectionId) {
let filteredMedia = allMedia.filter(media => checkIdFilter(media, subCollectionId);
}
or
function searchMediaByCollection(subCollectionId) {
let filteredMedia = allMedia.filter(function(media) {
return checkIdFilter(media, subCollectionId);
});
}
Don't hesitate to ask details if needed ;)
I am working through a code challenge and I need to return a string into a variable if the guess passed in attemptAnswer(guess) matches the answer property's value. My test is failing currently saying that the variable response is undefined.
Is this some sort of binding issue?
...curious how this problem could be resolved.
Thank you!
class Sphinx {
constructor() {
this.name = null;
this.riddles = [];
}
collectRiddle(riddle) {
this.riddles.push(riddle);
if (this.riddles.length > 3) { this.riddles.shift() };
}
attemptAnswer(guess) {
this.riddles.forEach( (element, index) => {
if (guess === element.answer) {
this.riddles.splice(index, 1);
return "That wasn't that hard, I bet you don't get the next one."
};
})
}
}
//test
const response = sphinx.attemptAnswer('short');
assert.equal(response, 'That wasn\'t that hard, I bet you don\'t get the next one');
When you return in attemptAnswer() you're actually retuning to the inner forEach callback function you defined: (element, index) => {..., not the outer attemptAnswer() method.
Instead of immediately returning within your forEach loop, you can set a variable outside this loop called result, and then return the result once your forEach loop is complete.
Also, currently, you're not creating a new instance of Sphinx, which means you don't have an object which can call the attemptAnswer() method. To fix this add new Sphinx() to create a new Sphinx object.
See example below:
class Sphinx {
constructor() {
this.name = null;
this.riddles = [{"answer":"short"}];
}
collectRiddle(riddle) {
this.riddles.push(riddle);
if (this.riddles.length > 3) {
this.riddles.shift()
};
}
attemptAnswer(guess) {
let res = "";
this.riddles.forEach((element, index) => {
if (guess === element.answer && !res) {
// no need for splice as it will skip an entry
res = "That wasn't that hard, I bet you don't get the next one.";
};
})
return res;
}
}
const response = new Sphinx();
response.collectRiddle({"answer":"short"});
console.log(response.attemptAnswer('short'));
you're never calling collectRiddle so this.riddles is always [] and the forEach block is never entered, therefore, not returning anything, so, the return value is undefined
you should have a variable called found right before the loop, if you find a match, set it to truethen return the string depending on the found variable :
note : the string inside the function is different from the one you're comparing it to (it has backslashes and ends with a dot) so the test will always be falsy
class Sphinx {
constructor() {
this.name = null;
this.riddles = [];
}
collectRiddle(riddle) {
this.riddles.push(riddle);
if (this.riddles.length > 3) {
this.riddles.shift()
};
}
attemptAnswer(guess) {
var found = false;
this.riddles.forEach((element, index) => {
if (guess === element.answer) {
found = true;
}
})
return found ? "Woohoo" : "That wasn't that hard, I bet you don't get the next one."
}
}
//test
const s = new Sphinx();
const response = s.attemptAnswer('short');
console.log(response === `That wasn't that hard, I bet you don't get the next one.`);
I assume you already did const sphynx = new Sphynx().
attemptAnswer() doesn't return anything, in Javascript, if you don't return anything, you basically return undefined. So it is normal that response is undefined.
In your case, I would use for-loop, instead of forEach.
attemptAnswer(guess) {
for (let i = 0; i < this.riddles.length; i++) {
if (guess === this.riddles[i].answer) {
this.riddles.splice(index, 1);
return "That wasn't that hard, I bet you don't get the next one.";
}
}
return "Not found";
}
Using .splice() inside forEach is not recommended
using forEach, will go through all the items inside the array, even if you already found your answer.
I'm having trouble with how member variables of objects work in javascript.
I have this function which finds a specific table in HTML and it seems to be working just fine. But it for some reason the member variables of the object associated with the table becomes null...
I tried debugging and here is what I got.
let tables;
function find_table(s) {
for(const table of tables){
if(table.prefix === s){
return table;
}
}
return null;
}
function search_table(table){
const tmp = find_table(table);
console.log(tmp.prefix); // debug0
tmp.search();
}
Inside the object called "table".
search(){
const search_text = $("#" + this.prefix + "_search_text").val().toLowerCase();
let item_count = 0;
$("#" + this.prefix +"_table tr").each(function () {
if (!$(this).hasClass("search_ignore")) {
let count = 0;
let show = false;
console.log(this.prefix); // debug1
for(const type of this.types){ // error here. this.types is undefined
const temp = $(this).find("td").eq(count).text().toLowerCase();
if(type === 0){
// 文字列検索
show = temp.includes(search_text)
}else if(type === 2){
...(the rest is probably irrelevant)...
So, I call the search_table() function so I can search for a table in tables with a string. The function find_table() seems to be working fine. The debug0 line returns "admin_account_list" properly. But after that when search() of table is called, the variable this.types has for some reason, turned into null. And the debug1 line also returns null.
I expected it to have the value I have assigned when the constructor was called.
I would greatly appreciate it if someone helped me understand what I did wrong here.
So, I have this little code in my js file:
window.onload = function Equal() {
var a = 'b1'
var b = 'box1'
var bookstorname = localStorage.getItem(a)
if (bookstorname == 1) {
document.getElementById(b).setAttribute('checked','checked');
}
if (bookstorname == 0) {
document.getElementById(b).removeAttribute('checked','checked');
}
var a = 'b2'
var b = 'box2'
var bookstorname = localStorage.getItem(a)
if (bookstorname == 1) {
document.getElementById(b).setAttribute('checked','checked');
}
if (bookstorname == 0) {
document.getElementById(b).removeAttribute('checked','checked');
}
}
The function itself is not important (it equals checkboxvalues set in the localstorage), but I execute it 2 times. First time with var a & b set to 'b1' & 'box1'. Then I run the script again (same script), but with var a & b set to 'b2' & 'box2'. Now, this code works, but my question is if there is a shorter way to write this? I can imagine some sort of array with a loop, but I could not get it to work for some reason. The 2 variables are pairs, and I know this might be a dumb question, but I can't find the answer anywhere.
You can use a second function which will accept the local storage key and the checkbox id like
window.onload = function Equal() {
setCheckboxState('box1', 'b1');
setCheckboxState('box2', 'b2');
}
function setCheckboxState(id, key) {
document.getElementById(id).checked = 1 == localStorage.getItem(key);
}
You might separate common logic into another function
window.onload = function Equal() {
function extractFromStorage(a, b) {
var bookstorname = localStorage.getItem(a)
if (bookstorname == 1) {
document.getElementById(b).setAttribute('checked','checked');
}
if (bookstorname == 0) {
document.getElementById(b).removeAttribute('checked','checked');
}
}
extractFromStorage('b1', 'box1');
extractFromStorage('b2', 'box2');
}
function doTheStuff(a, b) {
var bookstorname = localStorage.getItem(a)
if (bookstorname == 1) {
document.getElementById(b).setAttribute('checked','checked');
}
if (bookstorname == 0) {
document.getElementById(b).removeAttribute('checked','checked');
}
}
window.onload = function Equal() {
doTheStuff('b1', 'box1');
doTheStuff('b2', 'box2');
}
?
This is how I would do it.
There are several problems with your code.
You do not check that the element you are stetting an attribute to
exists. You do not check if the localStorage item you get is
defined.
You pollute the global name space with the function name Equal.
That function should not be named with a capital as it is not a Object generator.
There is no need to use setAttribute and removeAttribute, in
fact removeAttribute makes no sense in this case as you can not
remove the checked attribute from the element. BTW why use setAttribute here and not for window.onload?
The checked attribute is either true or false, it does not use the
string "checked"
Binding the load event via the onload attribute is not safe as you may
block 3rd party code, or worse 3rd party code may block you.
There is no error checking. DOM pages are dynamic environments, pages
have adverts and content from many places that can interfer with your
code. Always code with this in mind. Check for possible errors and deal with them in a friendly way for the end user. In this case I used an alert, not friendly for a normal user but for you the coder.
My solution.
// add an event listener rather than replace the event listener
window.addEventListener(
"load", // for the load event
function(){
// the update function that is called for each item;
var update = function(item){
// the right hand side equates to true if the localstorage
// is equal to "1". LocalStorage allways returns a string or
// undefined if the key is not defined.
item.element.checked = localStorage[item.storageName] === "1";
}
// safe element getter
var getElement = function(eId){
var e = document.getElementById(eId); // try and get the element
if(e === null){ // does it exist?
throw "Missing element:"+eId; // no then we can not continue
// the program stops here unless
// you catch the error and deal with
// it gracefully.
}
return e; //ok return the element.
}
// Item creator. This creates a new item.
// sName is the local storage name
// eId id the element ID
var item = function(sName, eId){
return {
storageName: sName, // set the loaclStorage name
element:getElement(eId); // get the element and check its safe
};
}
// make it all safe
try{
// create an array of items.
var items = [
item("b1","box1"),
item("b2","box2")
];
// for each item update the element status
items.forEach(update);
}catch(e){
alert("Could not update page?");
}
}
);
I'm not really sure why my code isn't running correctly.. what I'm trying to do is create a grocery list object that has a couple of functions to add and remove items..
I can instantiate the objects with new items but my functions don't seem to work for some reason.
If you could save me the few hairs left in my head and tell me where the issue is I would greatly appreciate it.
var groceryList = function(itemNames,quantity) {
if (Array.isArray(itemNames)) {
this.items = itemNames;
this.quantity = quantity
this.addItems = function(newItems){
if ( Array.isArray(newItems) ) {
this.items.concat(newItems);
} else {
console.log("Please enter the items in an array fashion!");
};
};
this.removeItem = function(name) {
var listSize = this.items.length;
for (var i = 0; i < listSize; i++) {
if (this.items[i] == name) {
this.items.splice(i,1);
break;
} else {
console.log("Please enter the items in an array fashion!")
};
};
};
} else {
console.log("Please enter the items in an array fashion!")
};
};
.concat() returns a new array so you have to assign the result back to your instance variable.
So this:
this.items.concat(newItems);
needs to be changed to this:
this.items = this.items.concat(newItems);
or, you could actually use this to append to the array directly:
this.items.push.apply(this.items, newItems);
Because .push() can take more than one argument.
Then, in your .removeItem() function, you need to remove the item you actually found by changing this:
this.items.splice(2,1);
to this:
this.items.splice(i,1);