Repeat function in javascript - javascript

Could you please tell me how to make from this 4 functions just 1. Cause they all do one thing, with just one parameter changing all the time.
Also, I need to take the value of each time the function is running and put it into a new variable so I can after calculate it.
function getValue(age)
{
for (var i = 0; i < document.getElementsByName('age').length; i++)
{
if (document.getElementsByName('age')[i].checked)
{
return document.getElementsByName('age')[i].value;
}
}
}
function getBmiValue()
{
for (var i = 0; i < document.getElementsByName('bmi').length; i++)
{
if (document.getElementsByName('bmi')[i].checked)
{
return document.getElementsByName('bmi')[i].value;
}
}
}
function getFamValue()
{
for (var i = 0; i < document.getElementsByName('fam').length; i++)
{
if (document.getElementsByName('fam')[i].checked)
{
return document.getElementsByName('fam')[i].value;
}
}
}
function getDietValue()
{
for (var i = 0; i < document.getElementsByName('diet').length; i++)
{
if (document.getElementsByName('diet')[i].checked)
{
return document.getElementsByName('diet')[i].value;
}
}
}

function getValueByElementName(element_name)
{
for (var i = 0; i < document.getElementsByName(element_name).length; i++)
{
if (document.getElementsByName(element_name)[i].checked)
{
return document.getElementsByName(element_name)[i].value;
}
}
}
Or a little bit optimization:
function getValueByElementName(element_name)
{
var elements = document.getElementsByName(element_name);
for (var i = 0; i < elements.length; i++)
{
if (elements[i].checked)
return elements[i].value;
}
}

function getValue(tagname)
{
for (var i = 0; i < document.getElementsByName(tagname).length; i++)
{
if (document.getElementsByName(tagname)[i].checked)
{
return document.getElementsByName(tagname)[i].value;
}
}
}
Pass your element name as a variable in this function and call it.

Here is an example of what you can do:
function getValue(key) {
// get this once, not on each loop iteration
var elem = document.getElementsByName(key);
// cache the length too, so not to calculate it on each loop iteration
for (var i = 0, len = elem.length; i < len; i++) {
if (elem[i].checked) {
return elem[i].value;
// this will exit the function when it finds the FIRST one.
// Is that what you want?
}
}
}
// you can call above function like this:
getValue('age');
getValue('bmi');
getValue('fam');
getValue('diet');

Related

JavaScript remove an IIFE event listener

I'm trying to remove click events from a list of id's after adding them with an IIFE like this
function setupPlayer(player){
var squareState = {};
for (i = 0; i < allSquares.length; i++) {
if(allSquares[i].innerHTML === "") {
// set up a click event for each square
document.getElementById(allSquares[i].getAttribute('id')).addEventListener('click', (clickSquare)(i));
}
}
}
The clickSquare function returns
function clickSquare(i){
var num = i;
return function() {
document.getElementById(allSquares[num].getAttribute('id')).innerHTML=player;
}
}
Then I try to remove them with
function removeClickEvents(){
for (let i = 0; i < allSquares.length; i++) {
document.getElementById(allSquares[i].getAttribute('id')).removeEventListener('click', clickSquare);
}
}
I've tried naming the returned anonymous function and using removeEventListener on that to no avail.
To remove event listener from a DOM element you need to pass the same function you used while adding event listener, as the parameter.
In javascript when you create an object it creates a new instance of that object class, so it won't be equal to another object even if it is created with same parameters
Example:
{} != {} // returns true
[] != [] // returns true
Same goes with function, whenever you write function (){} it creates a new instance of Function class.
Example:
function a() {
return function b() {}
}
a() != a() // returns true
Solution:
So for you to be able to remove the event listeners, you will have to store the functions you have passed to addEventListener
var listeners = [];
function setupPlayer(player) {
var squareState = {};
for (i = 0; i < allSquares.length; i++) {
if(allSquares[i].innerHTML === "") {
listeners[i] = clickSquare(i);
document.getElementById(allSquares[i].getAttribute('id')).addEventListener('click', listeners[i]);
}
}
}
function clickSquare(i) {
var num = i;
return function() {
document.getElementById(allSquares[num].getAttribute('id')).innerHTML=player;
}
}
function removeClickEvents() {
for (let i = 0; i < allSquares.length; i++) {
if(listeners[i]) {
document.getElementById(allSquares[i].getAttribute('id')).removeEventListener('click', listeners[i]);
}
}
}
From your code where you are using
document.getElementById(allSquares[i].getAttribute('id'))
I am assuming that allSquares[i] is a DOM element already, your code can be more simplified
var listeners = [];
function setupPlayer(player) {
var squareState = {};
for (i = 0; i < allSquares.length; i++) {
if(allSquares[i].innerHTML === "") {
listeners[i] = clickSquare(i);
allSquares[i].addEventListener('click', listeners[i]);
}
}
}
function clickSquare(i) {
var num = i;
return function() {
allSquares[num].innerHTML=player;
}
}
function removeClickEvents() {
for (let i = 0; i < allSquares.length; i++) {
if(listeners[i]) {
allSquares[i].removeEventListener('click', listeners[i]);
}
}
}
The function is being called immediately at (clickSquare)(i). At code at Question allSquares appears to be the element itself, clickSquare function can be referenced directly and event.target can be used within event handler to reference the current element in allSquares collection
let player = 123;
setInterval(() => player = Math.random(), 1000);
onload = () => {
let allSquares = document.querySelectorAll("div[id|=square]");
let button = document.querySelector("button");
button.onclick = removeClickEvents;
function setupPlayer(player) {
var squareState = {};
for (let i = 0; i < allSquares.length; i++) {
if (allSquares[i].innerHTML === "click") {
// set up a click event for each square
allSquares[i].addEventListener('click', clickSquare);
}
}
}
function clickSquare(event) {
console.log(event.target);
event.target.innerHTML = player;
}
function removeClickEvents() {
for (let i = 0; i < allSquares.length; i++) {
allSquares[i].removeEventListener('click', clickSquare);
}
}
setupPlayer(player);
}
<div id="square-0">click</div>
<div id="square-1">click</div>
<div id="square-2">click</div>
<button>remove events</button>

How do i get the specific values from json data in React

I am getting an error in console while i am trying to get a specific value from json data. This is the error:
'Uncaught TypeError: Cannot read property 'processen_id' of undefined'
Here is my code:
$.get("/getProces", function (data) {
if (data.error) {
} else {
for (var i = 0; i <= data.message.length; i++) {
var obj = data.message[i]
console.log(obj.processen_id)
}
}
})
}
This is what i get when i log (data):
You have a mistake in your code in the for loop
<= instead of <
$.get("/getProces", function (data) {
if (data.error) {
} else {
for (var i = 0; i < data.message.length; i++) {
var obj = data.message[i]
console.log(obj.processen_id)
}
}
})
}
The error message means that obj is undefined. That means, that data.message[i] gets an undefined value. The problem is the loop. You get an i that is larger then the array. Change <= to <:
for (var i = 0; i < data.message.length; i++) {
var obj = data.message[i]
console.log(obj.processen_id)
}
index out of range: for (var i = 0; i <= data.message.length; i++) { should be for (var i = 0; i < data.message.length; i++) { instead.
you can also optimize your code in this way:
$
.get("/getProces")
.then((res) => res.error ? Promise.reject(res) : Promise.resolve(res))
.then((data) => {
for (var i = 0; i < data.message.length; i++) {
var obj = data.message[i]
console.log(obj.processen_id)
}
})

JSHint won't allow forEach in a for loop

I keep getting EsLint errors for having forEach in my loop. How can I fix the following code:
for (var i = 0; i < this.m_V.length; ++i) {
var o = this.m_V[i];
var node = o.m_Data.GetCurr(this.m_C);
if (node && node.m_datae.length) {
for (var j = 0; j < node.m_datae.length; ++j)
var dataelement = node.m_datae[j].m_dataat
AreaId.forEach(function(area) {
dataelement.forEach(function(value) {
if (area === value.m_V) {
if (vo.m_p) {
var a = v.m_p.map;
....
}
}
}
}, this);
}, this);
}
}
}
How can I move the forEach out of the code? I tried to move the forEach out but then it didn't know what my variables node and 'o' were.

JavaScript continue label scope

Map.prototype.updateMap = function (vehicles) {
nextVehicle:
for (var i = 0; i < vehicles.length; i++) {
for (var j = 0; j < this.oldVehicles.length; j++) {
var vehicle = vehicles[i];
var oldVehicle = this.oldVehicles[j];
if (vehicle.registration == oldVehicle.registration) {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
}
continue nextVehicle;
});
}
}
}
};
The code above does not work. I have a feeling this is to do with scope, I can't reach the nextVehicle label from inside the oldVehicle.getPosition method. How can I get around this?
Separate the matching logic from the update logic.
Map.prototype.updateMap = function (vehicles) {
// Only need to look up array lengths once
var vehiclesLength = vehicles.length,
oldVehiclesLength = this.oldVehicles.length;
for (var i = 0; i < vehiclesLength; i++) {
var vehicle = vehicles[i];
var oldVehicle = null;
// Find oldVehicle
for (var j = 0; j < oldVehiclesLength; j++) {
if (vehicle.registration == oldVehicle[j].registration) {
oldVehicle = oldVehicles[j];
break;
}
}
// Check for update if found
if (oldVehicle){
// Create closure for async callbacks
(function(oldV, lat,lng){
oldV.getPosition(function(latLng) {
if (lat != oldV.lat) {
var newPos = new plugin.google.maps.LatLng(lat,lng);
oldV.setPosition(newPos);
}
});
})(oldVehicle, vehicle.latitude, vehicle.longitude);
}
}
};
Just move the continue nextVehicle; line from inside the callback to immediately following the call to oldVehicle.getPosition(...):
Map.prototype.updateMap = function (vehicles) {
nextVehicle:
for (var i = 0; i < vehicles.length; i++) {
for (var j = 0; j < this.oldVehicles.length; j++) {
var vehicle = vehicles[i];
var oldVehicle = this.oldVehicles[j];
if (vehicle.registration == oldVehicle.registration) {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
}
});
continue nextVehicle;
}
}
}
};
This assumes the call to getPosition is a synchronous operation.
Edit:
Now if getPosition is asynchronous, you will need to use an asynchronous loop:
Something along this line might do the trick:
Map.prototype.updateMap = function (vehicles) {
var i = 0, j = -1, self = this;
var updatePosition = function() {
j++;
if (j == self.oldVehicles.length) {
j = 0;
i++;
}
if (i === vehicles.length) {
return; // We're done
}
var vehicle = vehicles[i];
var oldVehicle = self.oldVehicles[j];
if (vehicle.registration !== oldVehicle.registration) {
updatePosition();
}
else {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
updatePosition();
}
});
}
};
updatePosition();
};

Dyanamic Execution of javascript code

I have the following JavaScript:
var djs = function (ob) {
return {
remove: function () { //removes element
if (is_array(ob)) {
for (var i = 0; i < ob.length; i++)
ob[i].parentNode.removeChild(ob[i]);
} else {
ob.parentNode.removeChild(ob);
}
},
empty: function () { //makes element empty
if (is_array(ob)) {
for (var i = 0; i < ob.length; i++)
ob[i].innerHTML = "";
} else {
ob.innerHTML = ""
}
},
html: function (str) { //gets or sets innerHTML
if (str) {
if (is_array(ob)) {
for (var i = 0; i < ob.length; i++)
ob[i].innerHTML = str;
} else {
ob.innerHTML = str;
}
} else {
if (is_array(ob)) {
for (var i = 0; i < ob.length; i++)
rob += ob[i].innerHTML;
return rob;
} else {
return ob.innerHTML;
}
}
}
}
}
Here every time I am checking whether ob is an array or not and executing code. I want to minimize this, like instead of:
if (is_array(ob)) {
for (var i = 0; i < ob.length; i++)
ob[i].parentNode.removeChild(ob[i]);
} else {
ob.parentNode.removeChild(ob);
}
I want to use a function like, doEval(ob,code,return), in this case,
doEval(ob,"parentNode.removeChild("+ob+")",NULL);
"return" parameter will return if I specify any like innerHTML. Can any one help?
Don't repeat is_array check:
var djs=function(ob) {
if (!is_array(ob)) ob = [ob];
#SHiNKiROU is right of course, but just to provide an example of how to solve your problem with higher-order functions:
function doToAll(ob, callback) {
if(is_array(ob)) {
for (var i = 0; i < ob.length; i++) {
callback(ob[i]);
}
} else {
callback(ob);
}
}
...
remove:function(){ //removes element
doToAll(ob, function(actualOb) { actualOb.parentNode.removeChild(actualOb); });
},
...
But again, use #SHiNKiROU:s answer for this particular case.
Try this:
function doEval(a, b, c) {
if(is_array(a)) {
eval(b);
} else {
eval(c);
}
}
NULL doesn't exist by the way, it is null.

Categories