У меня есть:
Как я могу сравнить значения, которые я получаю от функции, которая проверяет, какие флажки отмечены, со значениями в строковом объекте JSON и отображать их в выходном DIV? Скажем, я проверяю поля «Сыр» и «Чеснок» и ожидаю получить следующий результат:
HTML:
<form action = "" method = "">
<input type = "checkbox" value = "Cheese">Cheese<br>
<input type = "checkbox" value = "Tomato">Tomato<br>
<input type = "checkbox" value = "Garlic">Garlic<br>
<input type = "checkbox" value = "Bacon">Bacon<br>
<input type = "checkbox" value = "Paprika">Paprika<br>
<input type = "checkbox" value = "Onion">Onion<br>
<input type = "checkbox" value = "Potato">Potato<br>
<input type = "checkbox" value = "Mayo">Mayo<br>
<input type = "checkbox" value = "Beef">Beef<br>
<input type = "checkbox" value = "Garlic">Garlic<br>
<input type = "checkbox" value = "Butter">Butter<br>
<input type = "button" value = "Get recipes" id = "getRecipesButton">
</form>
<div id = "output">The results end up here</div>
JS:
//Recipes JSON-string:
var recipes = [
{
name:"recipe1",
ingredients:
[
{ingredient:"Cheese"},
{ingredient:"Tomato"},
{ingredient:"Garlic"}
]
},
{
name:"recipe2",
ingredients:
[
{ingredient:"Cheese"},
{ingredient:"Bacon"},
{ingredient:"Paprika"},
{ingredient:"Onion"}
]
},
{
name:"recipe3",
ingredients:
[
{ingredient:"Cheese"},
{ingredient:"Potato"},
{ingredient:"Mayo"},
{ingredient:"Beef"},
{ingredient:"Garlic"},
{ingredient:"Butter"}
]
}
];
//Test to retrieve single, specific entries:
// console.info(recipes[1].ingredients[0].ingredient);
//Test to get/return the checked values of the checkboxes:
function selectedBoxes(form) {
let selectedBoxesArr = [];
let inputFields = form.getElementsByTagName('input');
let inputFieldsNumber = inputFields.length;
for(let i=0; i<inputFieldsNumber; i++) {
if (
inputFields[i].type == 'checkbox' &&
inputFields[i].checked == true
) selectedBoxesArr.push(inputFields[i].value);
}
return selectedBoxesArr;
}
var getRecipesButton = document.getElementById('getRecipesButton');
getRecipesButton.addEventListener("click", function(){
let selectedCheckBoxes = selectedBoxes(this.form);
alert(selectedCheckBoxes);
});



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вот как вы можете установить значения на основе вашей текущей структуры. Имейте в виду, что неясно, какой рецепт вы хотели бы применить в любой момент времени, поэтому приведенный ниже код применит к форме первый рецепт.
//Recipes JSON-string:
var recipes = [{
name: "recipe1",
ingredients: [{
ingredient: "Cheese"
},
{
ingredient: "Tomato"
},
{
ingredient: "Garlic"
}
]
},
{
name: "recipe2",
ingredients: [{
ingredient: "Cheese"
},
{
ingredient: "Bacon"
},
{
ingredient: "Paprika"
},
{
ingredient: "Onion"
}
]
},
{
name: "recipe3",
ingredients: [{
ingredient: "Cheese"
},
{
ingredient: "Potato"
},
{
ingredient: "Mayo"
},
{
ingredient: "Beef"
},
{
ingredient: "Garlic"
},
{
ingredient: "Butter"
}
]
}
];
var getRecipesButton = document.getElementById('getRecipesButton');
getRecipesButton.addEventListener("click", function() {
for (let ingredient of recipes[0].ingredients) {
document.querySelector(`input[value='${ingredient.ingredient}']`).setAttribute('checked', true);
}
});<form action = "" method = "">
<input type = "checkbox" value = "Cheese">Cheese<br>
<input type = "checkbox" value = "Tomato">Tomato<br>
<input type = "checkbox" value = "Garlic">Garlic<br>
<input type = "checkbox" value = "Bacon">Bacon<br>
<input type = "checkbox" value = "Paprika">Paprika<br>
<input type = "checkbox" value = "Onion">Onion<br>
<input type = "checkbox" value = "Potato">Potato<br>
<input type = "checkbox" value = "Mayo">Mayo<br>
<input type = "checkbox" value = "Beef">Beef<br>
<input type = "checkbox" value = "Garlic">Garlic<br>
<input type = "checkbox" value = "Butter">Butter<br>
<input type = "button" value = "Get recipes" id = "getRecipesButton">
</form>
<div id = "output">The results end up here</div>Не стесняйтесь комментировать, если у вас есть какие-либо вопросы
Что вы думаете об этом быстром предложении, я знаю, что оно не очень элегантно:
<ul id = "output">The results end up here</ul>
var getRecipesButton = document.getElementById('getRecipesButton');
getRecipesButton.addEventListener("click", function(){
let selectedCheckBoxes = selectedBoxes(this.form);
document.getElementById("output").innerHTML = "";
var res = [];
recipes.forEach(function(r,k){
r['ingredients'].forEach(function(i,idx){
if (selectedCheckBoxes.includes(i.ingredient)) {
res.push(r);
}
});
});
// remove duplicate then display the recipe with the ingredient
res.filter(function(item, index){
return res.indexOf(item) >= index;
}).forEach(function(r){
var ingredient = r.ingredients.map(function(r) { return r.ingredient}).join(", ");
var name = r.name + " : "+ingredient ;
var ul = document.getElementById("output");
var li = document.createElement('li');
li.appendChild(document.createTextNode(name));
ul.appendChild(li);
});
});
Вот рабочая версия: https://jsfiddle.net/8esvh65p/
Пожалуйста. Кстати, я уверен, что мы можем «оптимизировать» код, но, возможно, на потом.
возможно. Честно говоря, я думаю, что это довольно коротко и аккуратно. Но я буду работать с этим некоторое время, так как он будет служить моим личным поиском рецептов для покупок на основе ингредиентов, которые у меня есть под рукой, поэтому я уверен, что окажусь в ситуациях, когда я хотел бы или должен был бы обновляйте его по пути (обычно так бывает с большинством вещей).
Вы можете отфильтровать свой массив рецептов только для рецептов, которые включают все выбранные ингредиенты, например:
let filtered = recipes.filter((recipe) => {
return selectedCheckBoxes.every((selected) => {
return recipe.ingredients.some((ingredient) => {
return ingredient['ingredient'] === selected;
});
});
});
Итак, для каждого из рецептов мы проверяем, содержится ли в рецепте выбранный ингредиент каждый. В таком случае:
Я отредактировал вашу скрипку, чтобы вы могли увидеть, как она работает: https://jsfiddle.net/byce6vwu/1/
Редактировать
Вы можете преобразовать возвращенный массив в html следующим образом (я также изменил выходной div на ул:
let outputRecipes = '';
filtered.forEach((recipe) => {
let stringIngredients = recipe.ingredients.map((val) => {
return val.ingredient;
}).join(',');
outputRecipes += `<li>${recipe.name}: ${stringIngredients}</li>`;
});
document.getElementById('output').innerHTML = outputRecipes;
Я отредактировал скрипку: https://jsfiddle.net/ys0qofgm/
Итак, для каждого ингредиента в массиве мы преобразуем объект ингредиента: {ingredient: "Cheese"} только в строку "Сыр" и соединяем все элементы массива, используя запятую в качестве разделителя. Затем создайте элемент ли для каждого рецепта и поместите в него строку рецепта.
Спасибо! Поскольку он возвращает массивы, я не выбрал его в качестве решения, хотя в некоторой степени он абсолютно делает то, что я искал. Я проголосовал за него, так как он является полезен и кое-чему меня научил!
Любое предложение о том, как вывести массив и возвращаемый внутренний массив?
Я отредактировал ответ, как делать то, что вы хотите.
Здорово! Не могу отблагодарить вас достаточно. Теперь у меня есть намного лучшие инструменты, чтобы изучить, как сделать что-то подобное самому.
Этот код будет делать то, что вы хотите. Он перебирает каждый ингредиент, проверяя набор рецептов и их ингредиенты, чтобы проверить, включает ли этот рецепт этот ингредиент. Возвращаются только рецепты, которые включают все выбранных ингредиентов:
//Recipes JSON-string:
var recipes = [
{
name:"recipe1",
ingredients:
[
{ingredient:"Cheese"},
{ingredient:"Tomato"},
{ingredient:"Garlic"}
]
},
{
name:"recipe2",
ingredients:
[
{ingredient:"Cheese"},
{ingredient:"Bacon"},
{ingredient:"Paprika"},
{ingredient:"Onion"}
]
},
{
name:"recipe3",
ingredients:
[
{ingredient:"Cheese"},
{ingredient:"Potato"},
{ingredient:"Mayo"},
{ingredient:"Beef"},
{ingredient:"Garlic"},
{ingredient:"Butter"}
]
}
];
//Test to retrieve single, specific entries:
// console.info(recipes[1].ingredients[0].ingredient);
//Test to get/return the checked values of the checkboxes:
function selectedBoxes(form) {
let selectedBoxesArr = [];
let inputFields = form.getElementsByTagName('input');
let inputFieldsNumber = inputFields.length;
for(let i=0; i<inputFieldsNumber; i++) {
if (
inputFields[i].type == 'checkbox' &&
inputFields[i].checked == true
) selectedBoxesArr.push(inputFields[i].value);
}
return selectedBoxesArr;
}
var getRecipesButton = document.getElementById('getRecipesButton');
getRecipesButton.addEventListener("click", function(){
let selectedCheckBoxes = selectedBoxes(this.form);
let output = document.getElementById('output');
let myRecipes = recipes.filter(r =>
selectedCheckBoxes.every(s =>
r.ingredients.some(i => i.ingredient == s)
)
);
output.innerHTML = myRecipes.map(v => v.name + ': ' + v.ingredients.map(i => i.ingredient).join(', ')).join('<br>');
});<form action = "" method = "">
<input type = "checkbox" value = "Cheese">Cheese<br>
<input type = "checkbox" value = "Tomato">Tomato<br>
<input type = "checkbox" value = "Garlic">Garlic<br>
<input type = "checkbox" value = "Bacon">Bacon<br>
<input type = "checkbox" value = "Paprika">Paprika<br>
<input type = "checkbox" value = "Onion">Onion<br>
<input type = "checkbox" value = "Potato">Potato<br>
<input type = "checkbox" value = "Mayo">Mayo<br>
<input type = "checkbox" value = "Beef">Beef<br>
<input type = "checkbox" value = "Garlic">Garlic<br>
<input type = "checkbox" value = "Butter">Butter<br>
<input type = "button" value = "Get recipes" id = "getRecipesButton">
</form>
<div id = "output">The results end up here</div>Здорово! Это работает, хотя не выводит ингредиенты, а выводит только тот, который соответствует, а не все.
@Strechingmycompetence извините за это - я недостаточно внимательно прочитал вопрос. Просто для полноты я обновил ответ, чтобы дать запрошенный вами результат.
Нет стресса! Мне нравится разнообразие подходов к этому. Это дает мне надежду на будущее и мотивацию продолжать учиться :D
Я отредактировал ваш код и уменьшил его, а также добавил getRecipe, который будет возвращать рецепты.
//Recipes JSON-string:
var recipes = [
{
name:"recipe1",
ingredients:
[
{ingredient:"Cheese"},
{ingredient:"Tomato"},
{ingredient:"Garlic"}
]
},
{
name:"recipe2",
ingredients:
[
{ingredient:"Cheese"},
{ingredient:"Bacon"},
{ingredient:"Paprika"},
{ingredient:"Onion"}
]
},
{
name:"recipe3",
ingredients:
[
{ingredient:"Cheese"},
{ingredient:"Potato"},
{ingredient:"Mayo"},
{ingredient:"Beef"},
{ingredient:"Garlic"},
{ingredient:"Butter"}
]
}
];
function selectedBoxes(form) {
let selectedBoxesArr = [];
let inputFields = form.getElementsByTagName('input');
// get all checked input values
var checked = [...inputFields].filter((item) => item.checked == true
).map((item) => item.value)
return checked;
}
// Validate the checked ingredients and get the recipes
function getRecipe(ingredients){
var recipe = [];
recipes.forEach((item)=> {
var found= false;
for(var ingredient in ingredients){
var y = ingredients[ingredient]
found= item.ingredients.filter((x) => x.ingredient.indexOf(y) != -1).length>0;
if (!found)
break;
}
if (found)
recipe.push(item.name +":"+ item.ingredients.map((x)=> x.ingredient).join(", "));
});
return recipe;
}
var getRecipesButton = document.getElementById('getRecipesButton');
getRecipesButton.addEventListener("click", function(){
let selectedCheckBoxes = selectedBoxes(this.form);
console.info(getRecipe(selectedCheckBoxes))
});<form action = "" method = "">
<input type = "checkbox" value = "Cheese">Cheese<br>
<input type = "checkbox" value = "Tomato">Tomato<br>
<input type = "checkbox" value = "Garlic">Garlic<br>
<input type = "checkbox" value = "Bacon">Bacon<br>
<input type = "checkbox" value = "Paprika">Paprika<br>
<input type = "checkbox" value = "Onion">Onion<br>
<input type = "checkbox" value = "Potato">Potato<br>
<input type = "checkbox" value = "Mayo">Mayo<br>
<input type = "checkbox" value = "Beef">Beef<br>
<input type = "checkbox" value = "Garlic">Garlic<br>
<input type = "checkbox" value = "Butter">Butter<br>
<input type = "button" value = "Get recipes" id = "getRecipesButton">
</form>
<div id = "output">The results end up here</div>Спасибо! Я проголосовал за ваш ответ, так как он является полезен и кое-чему меня научил, хотя кажется, что он возвращает только первый найденный рецепт и массивы для остальных.
Здорово! Это абсолютно сработало. Другие ответы вернули массивы (т.е. не полное решение). Я также получаю значение других ответов и могу использовать их, если мне нужно изменить функциональность. Я также настроил кнопку отправки, чтобы она была невидимой (нулевые высота, ширина, отступы и поля), и вместо этого обернул ее в eventlistener для флажков, поэтому всякий раз, когда кто-то устанавливает или снимает флажок, он будет обновляться мгновенно.