Created
May 21, 2020 16:04
-
-
Save JakubKoralewski/a45ee04c1e2657214987a49001b66db0 to your computer and use it in GitHub Desktop.
mr masseratti
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<form action="{% url 'new' %}" method="post"> | |
{% csrf_token %} | |
{% for field in form %} | |
<div class="field-wrapper"> | |
{{ field.errors }} | |
{{ field.label_tag }} {{ field }} | |
{% if field.help_text %} | |
<p class="help">{{ field.help_text|safe }}</p> | |
{% endif %} | |
</div> | |
{% endfor %} | |
<div class="steps"> | |
<div id="step-adder"> | |
<label for="s-desc">Step description:</label> | |
<textarea id="s-desc"></textarea> | |
<div id="ingredients-adder"> | |
<label for="i-name">Ingredient name:</label> | |
<input type="text" id="i-name"> | |
<label for="i-photo">Ingredient photo:</label> | |
<input type="url" id="i-photo"> | |
<label for="i-amount">Quantity: </label> | |
<input type="number" id="i-amount" step="0.1"> | |
<label for="i-amount-type"></label> | |
<select id="i-amount-type"> | |
<option value="x">items</option> | |
<option value="g">grams</option> | |
<option value="kg">kilograms</option> | |
<option value="ml">milliliters</option> | |
<option value="tbsp">tablespoons</option> | |
<option value="tsp">teaspoons</option> | |
</select> | |
<button onclick="addIngredient(event, this)" type="button">Add this ingredient</button> | |
<ol id="ingredients-list" style="margin: 1rem 2rem;"> | |
No ingredients were specified for this step yet. | |
</ol> | |
</div> | |
<button onclick="addStep(event, this)" type="button" value="">Add this step</button> | |
</div> | |
<ol id="step-list" style="margin: 1rem 2rem;"> | |
No steps specified for this recipe yet. | |
</ol> | |
</div> | |
<input type="submit" value="Submit"> | |
</form> | |
<script> | |
let newStepNumberWillBe = 0 | |
const ingredient = { | |
"i-name": 'name', | |
"i-photo": 'photo', | |
"i-amount": 'amount', | |
"i-amount-type": 'amountType' | |
} | |
const step = { | |
"s-desc": 'description', | |
} | |
function getCustomForm(schema, parentElem) { | |
let {elem, ...inputs} = schema | |
const actualInputs = {} | |
console.log(parentElem.children) | |
Array.from(parentElem.children).forEach( | |
(elem) => { | |
if (elem.id in inputs) { | |
actualInputs[inputs[elem.id]] = elem | |
} | |
} | |
) | |
return actualInputs; | |
} | |
const steps = [] | |
const stepsElem = document.querySelector(".steps") | |
const stepAdder = stepsElem.querySelector("#step-adder") | |
const ingredientAdder = stepAdder.querySelector("#ingredients-adder") | |
const stepListElem = document.querySelector("#step-list") | |
let stepListOriginalText = stepListElem.innerText | |
const ingredientListElem = document.querySelector("#ingredients-list") | |
let ingredientListOriginalText = ingredientListElem.innerText | |
const formElem = document.querySelector("form") | |
function addStep(e, elem) { | |
let parsed = getCustomForm(step, stepAdder) | |
console.log("Adding step", parsed) | |
let newObj = {} | |
Object.keys(parsed).map((key, i) => { | |
newObj[key] = getValueOfInput(parsed[key]) | |
}) | |
if (newStepNumberWillBe + 1 > steps.length) { | |
steps[newStepNumberWillBe] = new Step(newObj) | |
} else { | |
steps[newStepNumberWillBe].assignObject(newObj) | |
} | |
insertStepIntoDOM(steps[newStepNumberWillBe], newStepNumberWillBe) | |
console.log("steps:", steps) | |
newStepNumberWillBe++ | |
} | |
class Step { | |
constructor(params) { | |
this.assignObject(params) | |
} | |
assignObject({description = "", ingredients = []}) { | |
this.description = description | |
this.ingredients = this.ingredients && this.ingredients.length !== 0 ? this.ingredients : ingredients | |
} | |
} | |
function getValueOfInput(input) { | |
return input.value; | |
} | |
function removeElem(event, index, elem) { | |
steps[index] = null | |
const toBeRemoved = stepListElem.querySelector(`li[data-index="${index}"]`) | |
stepListElem.removeChild(toBeRemoved) | |
// if (!stepListElem.querySelector('li')) { | |
// stepListElem.innerHTML = stepListOriginalText | |
// } | |
const toBeRemovedFromForm = formElem.querySelector(`input.input-step[data-index="${index}"]`) | |
formElem.removeChild(toBeRemovedFromForm) | |
} | |
function insertStepIntoDOM(step, index) { | |
// if (!stepListElem.querySelector('li')) { | |
// stepListElem.innerHTML = '' | |
// } | |
let ingredientsHTML | |
console.log("adding step: ", step) | |
if (step.ingredients.length !== 0) { | |
ingredientsHTML = step.ingredients.filter(x => !!x).map(ing => { | |
// if (!ing) { | |
// return `` | |
// } | |
return ` | |
<li id="ingredient-src"> | |
<p id="ingredient-name">${ing.name}</p> | |
<p id="ingredient-photo">${ing.photo}</p> | |
<p id="ingredient-amount">${ing.amount}</p> | |
<p id="ingredient-amount-type">${ing.amountType}</p> | |
</li> | |
` | |
}).join('\n') | |
} else { | |
ingredientsHTML = `Nox ingredients specified for this step.` | |
} | |
const HTMLStep = ` | |
<div class="step"> | |
<p id="desc-src">${step.description}</p> | |
<div id="ingredients-src"> | |
<ul> | |
${ingredientsHTML} | |
</ul> | |
</div> | |
<button type="button" onclick="removeElem(event, ${index}, this)">Remove</button> | |
</div> | |
` | |
let ifExists = stepListElem.querySelector(`li[data-index="${index}"]`) | |
if (ifExists) { | |
ifExists.innerHTML = HTMLStep | |
} else { | |
const li = document.createElement("li") | |
li.dataset.index = index | |
li.innerHTML = HTMLStep | |
stepListElem.appendChild(li) | |
} | |
// ingredientListElem.innerHTML = ingredientListOriginalText | |
const HTMLFormStep = ` | |
<input | |
class="input-step" | |
data-index="${index}" | |
id="step-${index}-description" | |
value="${step.description}" | |
style="display: none;" | |
> | |
` | |
// let ifExistsFormElem = formElem.querySelector(`input.input-step[data-index="${index}"]`) | |
// if (ifExistsFormElem) { | |
// ifExistsFormElem.value = step.description | |
// } else { | |
// formElem.innerHTML += HTMLFormStep | |
// } | |
} | |
function removeIngredient(event, index, elem) { | |
console.log("removing ingredient index: ", index) | |
let thisIngredientsStep = steps[newStepNumberWillBe] | |
if (thisIngredientsStep) { | |
thisIngredientsStep.ingredients[index] = null | |
} | |
const toBeRemoved = ingredientListElem.querySelector(`li[data-index="${index}"]`) | |
toBeRemoved.parentNode.removeChild(toBeRemoved) | |
window.requestAnimationFrame(() => { | |
if (!ingredientListElem.querySelector('li')) { | |
ingredientListElem.innerHTML = ingredientListOriginalText | |
} | |
}) | |
const formElems = formElem.querySelectorAll(`input.ingredient-step[data-index="${index}"]`) | |
formElems.forEach(elem => formElem.removeChild(elem)) | |
} | |
function insertIngredientIntoDOM(ingredient, index, stepIndex) { | |
// if (!ingredientListElem.querySelector('li')) { | |
// ingredientListElem.innerHTML = '' | |
// } | |
let ingredientsHTML = `No ingredients specified for this step.` | |
console.log("adding ingredient: ", ingredient, index) | |
const HTMLIngredient = ` | |
<p id="ingredient-name">${ingredient.name}</p> | |
<p id="ingredient-photo">${ingredient.photo}</p> | |
<p id="ingredient-amount">${ingredient.amount}</p> | |
<p id="ingredient-amount-type">${ingredient.amountType}</p> | |
<button type="button" onclick="removeIngredient(event, ${index}, this)">Remove</button> | |
` | |
let allExistingIngredients = ingredientListElem.querySelectorAll('li') | |
let ifExists | |
if (allExistingIngredients.length > 0) { | |
ifExists = Array.from(allExistingIngredients).find(li => li.dataset.index === index) | |
} | |
console.log("ifExists", ifExists) | |
if (ifExists) { | |
ifExists.innerHTML = HTMLIngredient | |
} else { | |
const li = document.createElement("li") | |
li.dataset.index = index | |
li.innerHTML = HTMLIngredient | |
ingredientListElem.appendChild(li) | |
} | |
const HTMLFormIngredient = ` | |
<input | |
class="ingredient-step" | |
data-index="${index}" | |
id="step-${stepIndex}-ingredient-name-${index}" | |
value="${ingredient.name}" | |
style="display: none;" | |
> | |
<input | |
class="ingredient-step" | |
data-index="${index}" | |
id="step-${stepIndex}-ingredient-photo-${index}" | |
value="${ingredient.photo}" | |
style="display: none;" | |
> | |
<input | |
class="ingredient-step" | |
data-index="${index}" | |
id="step-${stepIndex}-ingredient-amount-${index}" | |
value="${ingredient.amount}" | |
style="display: none;" | |
> | |
<input | |
class="ingredient-step" | |
data-index="${index}" | |
id="step-${stepIndex}-ingredient-amountType-${index}" | |
value="${ingredient.amountType}" | |
style="display: none;" | |
> | |
` | |
formElem.innerHTML += HTMLFormIngredient | |
} | |
function addIngredient(e, elem) { | |
let parsed = getCustomForm(ingredient, ingredientAdder) | |
console.log("Adding ingredient", parsed) | |
if (steps[newStepNumberWillBe] === undefined) { | |
steps[newStepNumberWillBe] = new Step({}) | |
} | |
let newIngredient = {} | |
Object.keys(parsed).map((key, i) => newIngredient[key] = getValueOfInput(parsed[key])) | |
steps[newStepNumberWillBe].ingredients.push(newIngredient) | |
console.log("steps: ", steps) | |
insertIngredientIntoDOM(newIngredient, steps[newStepNumberWillBe].ingredients.length - 1, newStepNumberWillBe) | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
should I file a bug inside Chromium?
Wow Firefox also has the same bug ๐