how can i make my function reusable whilst using the (e) parameter? - javascript

const days = document.querySelector('#days');
const hours = document.querySelector('#hours');
const minutes = document.querySelector('#minutes');
document.querySelector('#years').addEventListener('input', function (e) {
let years = e.target.value;
days.lastElementChild.innerHTML = years * 365;
hours.lastElementChild.innerHTML = years * 8760;
minutes.lastElementChild.innerHTML = years * 525600;
});
I really need help with this one. When using the e parameter i can target the value from when the event is triggered using this code. I get that i can call the parameter anything and use target to access all the juicy information about the event in the console. What i do nott understand is , why cant i pass arguments with the e to make my function reusable. I want to pass my variables via arguments and store placeholders as parameters and work against them. Instead if I store (e) as a parameter, unless i am missing something , I am forced to reference my variables inside my function because I cannot seem to pass other arguments with (e) . Is there a way i can e.target.value and still pass arguments to my function? This one has really got me stuck , thanks

One method is to record the id attribute values for output parent elements as a data attribute on the input element used to enter a year. Another method could involve setting up a table of parent elements using the id of the input as key.
A third option is to add the event listener (which is passed an event object as argument) inside a closure: i.e. inside an outer, reusable function which is called with all necessary argument values to add an event listener to a specific elements and handle events that are raised.
Here's an example of the first approach:
"use strict";
function showDHM(event) {
let years = event.target.value;
event.target.dataset.for.trim().split(/\s*,\s*/)
.map( id => document.getElementById( id))
.forEach( (element, index) => {
const multiplicand = [ 365, 8760, 525600];
element.lastElementChild.innerHTML = years * multiplicand[index];
});
}
const year1 = document.querySelector('#year1')
year1.dataset.for = "days1, hours1, mins1";
year1.addEventListener('input', showDHM);
<label> Year: <input type="number" id="year1"></lable>
<p>
<span id="days1"><span>days</span></span>,
<span id="hours1"><span>hours</span></span>,
<span id="mins1"><span>mins</span></span>
Note the code is for demonstration only: adjustment for leap years not included!
The next snippet demonstrates the closure option. The conversion process used to modify the posted code was largely mechanistic: replace hard-coded values with argument names and include the modified code in an outer function.
"use strict";
function handleYears( yearsSel, daysSel, hoursSel, minutesSel) {
const days = document.querySelector(daysSel);
const hours = document.querySelector(hoursSel);
const minutes = document.querySelector( minutesSel);
document.querySelector(yearsSel).addEventListener('input', function (e) {
let years = e.target.value;
days.lastElementChild.innerHTML = years * 365;
hours.lastElementChild.innerHTML = years * 8760;
minutes.lastElementChild.innerHTML = years * 525600;
});
}
handleYears("#year1", "#days1", "#hours1", "#mins1");
<label> Year: <input type="number" id="year1"></lable>
<p>
<span id="days1"><span>days</span></span>,
<span id="hours1"><span>hours</span></span>,
<span id="mins1"><span>mins</span></span>

Related

How to get value of "bind:value" element?

Is there some easy way to get value of bind:value element in svelte?
E.g. this is the html that I have:
<input type="text" name="prop" bind:value="{model.subObject.subSubObject.subSubSubProp}">
<span class="error" data-error-for="prop"></span>
And js that I currently have:
let fields : NodeList = document.querySelectorAll('[data-error-for]');
fields.forEach((v,k) => {
let nameOf = v.dataset['errorFor'];
let n = document.getElementsByName(nameOf);
//how to get here the value of `n.value` to be `model.subObject.subSubObject.subSubSubProp`
});
I do not need the real bound value, but actually the object path (e.g. above it would be model.subObject.subSubObject.subSubSubProp).

Vue JS - Loop through a computed property to display a list of years

I currently have the following code that lists a list of years. I feel that all this code may be very unnecessary and perhaps a computed property for validYears, would help me make this code more optimal and get rid of the unnecessary watchers. My issue is converting this to a computed property as I'm failing to grasp the correct logic to achieve this. I'd appreciate if someone can offer an example of how I can set a computed property for valid years and still return the same result.
onBeforeMount(calculateDateRange)
watch(() => props.earliestDate, (newValue, prevValue) => {
calculateDateRange();
});
// If there is a new value passed from the parent, the dropdown should display that new value.
watch(() => props.latestDate, (newValue, prevValue) => {
calculateDateRange()
});
const validYears = ref([])
function calculateDateRange () {
for(let year = props.latestDate; year >= props.earliestDate; year--){
validYears.value.push(year)
}
}
I didn't provide the rest of the code not to clutter the question, but as one can see in this component I have a set of props that determine the values in my for loop.
You could optimize it as follows :
const validYears = computed(()=>{
let _years=[]
for(let year = props.latestDate; year >= props.earliestDate; year--){
_years.push(year)
}
return _years;
})

Checking an input against a specific array string

I am trying to create a quiz that randomly selects a question from pool of questions in an array, which is answered in an input box that is to be checked against the corresponding answer string in the array. I used math.floor(math.random() *); to get my random number. The random number is intended to be used to find both the question and answer, which are arranged in order to correspond to one another, e.g. ['question1','question2'] and ['answer1','answer2'].
I am having difficulty with trying to get my input to properly be checked against the corresponding answer value from the array. I am fairly novice at Javascript, so I am not sure as to how to do this. I tried using the document.getElementById command to compare the two. I suspect it has something to do with the fact that ansNum doesn't get the value of questNum because of the fact that questNum is only given its value inside the generateQuiz function. (I realize ansNum is likely redundant, but I was just playing around to see if anything would happen)
Javascript:
const questions = ['What do young Roman males wear?','Who is the Roman god of the smith?','Who is the 6th king of Rome?'];
const answers = ['toga praetexta','vulcan','servius tullius'];
function getQuestNum() {
questNum = Math.floor(Math.random() * 3);
};
function getAnsNum() {
ansNum = questNum();
}
function generateQuiz() {
getQuestNum();
document.getElementById("question").innerHTML = questions[questNum];
};
function checkCorrect() {
getAnsNum();
if (answer[ansNum] = document.getElementById("input").innerHTML) {
document.getElementById("verification").innerHTML = "Correct!";
}
};
Codepen Link
An image of the code
Based on your code, I fixed it with some changes. It is not the best way to do this i think. I posted the js part here.
const questions = ['What do young Roman males wear?','Who is the Roman god of the smith?','Who is the 6th king of Rome?'];
const answers = ['toga praetexta','vulcan','servius tullius'];
var questNum;
function getQuestNum() {
questNum = Math.floor(Math.random() * 3);
};
function getAnsNum() {
ansNum = questNum;
}
function generateQuiz() {
getQuestNum();
document.getElementById("question").innerHTML = questions[questNum];
};
function checkCorrect() {
getAnsNum();
if (answers[ansNum] = document.getElementById("input").value) {
document.getElementById("verification").innerHTML = "Correct!";
}
};
First you need a global variable questNum then you can use it in all of your functions.
The function getAnsNum() is redundant, at least i think so, just use questNum in your checkCorrect() function.
For getElementByID function, insert an ID attribute to your input
<input id="input" type="text" name="input">
For input, if you want to take the value of the input field, use document.getElementById("input").value instead of innerHTML.
If you not sure about any result, console.log it or use Chrome dev debug tool to check the result. In the checkCorrect function, your array name should be answers instead of answer.
Shorter ver:
const questions = ['What do young Roman males wear?','Who is the Roman god of the smith?','Who is the 6th king of Rome?'];
const answers = ['toga praetexta','vulcan','servius tullius'];
var questNum;
function getQuestNum() {
questNum = Math.floor(Math.random() * 3);
};
function generateQuiz() {
getQuestNum();
document.getElementById("question").innerHTML = questions[questNum];
};
function checkCorrect() {
if (answers[questNum] = document.getElementById("input").value) {
document.getElementById("verification").innerHTML = "Correct!";
}
};
It would be simpler to create an array of objects that each contain both a question and an answer - and create a function that generates your random number and returns the object at the corresponding index.
Then you'll have access to everything you need without worrying about whether or not you can maintain access to the original randomly selected number, or matching up indices between two different arrays.

How is the Argument value set - Javascript

I am new to javascript.
I am trying to understand how the value is set to 'USD' for 'outCurr' argument in the following code, am I missing anything. I understood the rest of the code but could not figure this out.
The example is taken from https://docs.angularjs.org/guide/concepts#model
angular.module('invoice1', [])
.controller('InvoiceController', function()
{
this.qty = 1;
this.cost = 2;
this.inCurr = 'EUR';
this.currencies = ['USD', 'EUR', 'CNY'];
this.usdToForeignRates = { USD: 1, EUR: 0.74, CNY: 6.09 };
this.total = function total(outCurr)
{
return this.convertCurrency(this.qty * this.cost, this.inCurr, outCurr);
};
this.convertCurrency = function convertCurrency(amount, inCurr, outCurr)
{
return amount * this.usdToForeignRates[outCurr] / this.usdToForeignRates[inCurr];
};
this.pay = function pay() {
window.alert("Thanks!");
};
});
What I understand is that both function take 'outCurr' as argument/parameter but I cant see any value assigned to it. Please let me know if I have missed anything.
In the index.html file, there is an ng-repeat that loops through the current currencies (['USD', 'EUR', 'CNY'] array and calls total(c) function and pass each currency.
<b>Total:</b>
<span ng-repeat="c in invoice.currencies">
{{invoice.total(c) | currency:c}}
</span>
So, you need to look at the html file too, as with AngularJS binding and expressions happens in the HTML file.
Hope that helps.
The variable "outCurr" is assigned automatically once the function is called. In the code snippet you see here, the function convertCurr is never called in the Javascript. The special thing about AngularJS is that it enables these functions to be called in the HTML itself. You'll notice that, as explained by Omar, in the snippet below, it passes in the outCurr for each currency in the "currencies" array, thus displaying the resulting value in every currency.
<span ng-repeat="c in invoice.currencies">
{{invoice.total(c) | currency:c}}
</span>

Add another value to nested javascript object?

I have the following JavaScript object, with a property called rates, which contains another object with the actual rates. Now I want to add a new rate "CAD":0.972254 to the rates. How can I add this one value to the list?
var Currency = {
rates: {"USD":1.0,"EUR":1.3497,"GBP":1.60403},
convert: function(amount, from, to) {
return (amount * this.rates[from]) / this.rates[to];
}
};
You can do it either way
Currency['rates']['CAD'] = 0.972254;
Or,
Currency.rates.CAD = 0.972254
Fiddle Here
You can assign a new property to existing object like:
Currency.rates.CAD = 0.972254
Currency.rates.CAD = 0.972254;

Categories

Resources