If there is an array in a function, and I would like to grab one value out of this array, depending if it exists or not, how would I do that with JavaScript?
To explain this question well look at the code below . . .
If we have a function:
function updateData(dataObj) {
for (var i = 0; i < dataObj.length; i++) {
var id = dataObj[i]['id'];
}
grabID(dataObj);
}
I am trying to grab whichever id that has a value, so I created the function grabID:
function grabID(dataObj) {
for (var i=0; i< dataObj.length; i++) {
var id = dataObj[i]['id'];
if (typeof(id) == 'string') {
//take that id and use it in the function below this one
}
else {
continue;
}
}
}
Now this is the function that I want to place the id in, so I can draw a graph:
function drawGraph() {
var id = //the id grabbed in the grabID function
//use this id for drawing purposes
}
So the only help I need is how can I bring this id string from the grabID function. The parts that are commented are the parts that I need help with.
I hope this code helped explained what I am looking for exactly. I know I might have wrote unnecessary functions or lines of code, but this is the way I am thinking of in my head right now. The function updateData is not initially used to grab one id only (the id that has value). That is why I created another function called grabID.
You can call the grabID function and within it return the ID, then pass the result of the call to your drawGraph function:
function grabID(dataObj) {
for(var i=0; i< dataObj.length; i++)
{
var id = dataObj[i]['id'];
if(typeof(id) == 'string')
//take that id and use it in the function below this one
return id;
else
continue;
}
// return null if no ID was retrieved
return null;
}
function updateData(dataObj) {
for (var i = 0; i < dataObj.length; i++) {
var id = dataObj[i]['id'];
}
var id = grabID(dataObj);
if(id !== null) drawGraph(id);
}
function drawGraph(grabbedId)
{
var id = grabbedId; //the id grabbed in the grabID function
//use this id for drawing purposes
}
Try calling drawGraph from within your grabID function, like so. Use the id variable as a parameter to drawGraph.
function grabID(dataObj) {
for(var i=0; i< dataObj.length; i++){
var id = dataObj[i]['id'];
if(typeof(id) == 'string')
drawGraph(id)
else
continue;
}
}
}
function drawGraph()
{
var id = //the id grabbed in the grabID function
//use this id for drawing purposes
}
Related
First take a look at my simple codes below:
function mySecondFunction(objArray,setFunc)
{
for (let i = 0; i < objArray.length; i++)
{
objArray[i].info.setTop(72);
}
}
function myFunction()
{
let myObjArray = [];
for (let i = 0; i < 10; i++)
{
myObjArray.push({
info:{topVar:0,
bottomVar:0,
get top() {return this.topVar;},
get bottom() {return this.bottomVar;},
setTop: function(input) {this.topVar = input;},
setBottom: function(input) {this.bottomVar = input; }
}
});
}
mySecondFunction(myObjArray); // This works Fine
mySecondFunction(myObjArray,setTop); // I want something like this!!!
}
As you can see, I want to pass a method of an object to another function. I know a lot of possible solutions to avoid this, but I want to know whether it is possible or not.
Detach it and pass as an argument. Remember to use call to set the intended this value.
function mySecondFunction(objArray, setFunc)
{
for (let i = 0; i < objArray.length; i++)
{
setFunc.call(objArray[i].info, 72);
/* explicitly telling that:
please set 'this' value in this function to be 'objArray[i].info' when running,
allowing, e.g. `this.topVar` in
`setTop: function(input) {this.topVar = input;}`
to be operating on `objArray[i].info.topVar` */
}
}
function myFunction()
{
let myObjArray = [];
for (let i = 0; i < 10; i++)
{
myObjArray.push({
info:{topVar:0,
bottomVar:0,
get top() {return this.topVar;},
get bottom() {return this.bottomVar;},
setTop: function(input) {this.topVar = input;},
setBottom: function(input) {this.bottomVar = input; }
}
});
}
mySecondFunction(myObjArray, myObjArray[0].info.setTop);
/* once detaching the method from the object,
(if we are not using arrow functions),
we lose 'this' value, meaning we are losing
the target of object that we want to operate on */
console.log(myObjArray)
}
myFunction();
You can target item number in the array list. You can do statically (i.e. 1-???) or dynamically with an iteration and a variable. You can then the object property within that. For example:
myObjArray[0].info.setTop
That will target the 1st item in the array. Be sure to omit parentheses (()) when passing the method as you want to pass the function reference not the result
I have the following piece of code:
var i = 0;
for (var anchor in window.globals.html.anchors) {
var value = window.globals.html.anchors[anchor];
value.addEventListener('click', function(i) {
var currData = window.globals.data[i],
data_clientId = 0;
if (currData.client_product_id !== undefined) {
data_clientId = currData.getAttribute('data_clientId');
} else if (currData.product_id !== undefined) {
data_clientId = currData.product_id;
}
Statistics.send(data_clientId);
window.open(window.globals.data[i].url, '_blank');
}(i));
i++;
}
Which means I want to access global array by interator inside the click event listener. If I don't pass no i to the click event I get the maximum number possible in each iteration, as i would be a global variable.
But right here it seems that all iterations of click events are invoke before clicking anything, onload.
Why is that so, what's wrong?
Looks like you are calling the handler whilst trying to add it to addEventListener. You need to wrap it in a function thus creating a closure that encapsulates your i variable.
var i = 0;
for (var anchor in window.globals.html.anchors) {
var value = window.globals.html.anchors[anchor];
value.addEventListener('click', (function(i) {
return function() {
var currData = window.globals.data[i],
data_clientId = 0;
if (currData.client_product_id !== undefined) {
data_clientId = currData.getAttribute('data_clientId');
} else if (currData.product_id !== undefined) {
data_clientId = currData.product_id;
}
Statistics.send(data_clientId);
window.open(window.globals.data[i].url, '_blank');
}
}(i)));
i++;
}
Notice now that the function you are passing to addEventListener is invoked immediately and returns a function itself where your variable i is scoped.
I have the following code definition
$(document).on('click', firstRow, processEvent(firstRow, rowArray));
Which uses the parameters below. As it currently stands I am passing the function processEvent rather than the function definition stored in the variable, and so the function is being invoked immediately.
I wish to set up click handlers dynamically, and for my feature to work I need to be able to pass two parameters to the callback on the click event. The first is a reference to the DOM element(s) the click is attached to, and the second is an array of DOM elements indentifiers (stored as strings) .
How can I pass a function reference with multiple arguments to the callback of my jQuery(document).on('click' event?
var firstRow = '.first-row';
var secondRow = '.second-row';
var thirdRow = '.third-row';
var rowArray = [firstRow, secondRow, thirdRow];
var hideRow = function(input){
var Input = input;
$(Input).show();
};
var showRow = function(input){
var Input = input;
$(Input).hide();
}
// alert(rowArray);
//Hide second and third rows
$('.second-row, .third-row').hide();
var processEvent = function(e, fooArray){ // currently set to one
var E = e; // Cache ID of calling object
var a = fooArray;
// alert(E);
// alert(a);
var arrayLength = a.length;
for (var i = 0; i < arrayLength; i++) {
foo = a[i];
// alert(row); //
alert(foo);
if (foo = e){
showRow(e);
}
else {
hideRow(foo);
}
}
} // function testProcessEvent(){ processEvent(); }
$(document).on('click', firstRow, processEvent(firstRow, rowArray));
This is my first attempt
$(document).on('click', firstRow , someFunction(firstRow ));
Use
$(document).on('click', firstRow, function () {
//place the code here
processEvent(firstRow, rowArray);
});
I have a jquery/javascript function that creates an array to be placed in a form's hidden field. However, this is a nested form and so I need to invoke this function many times to populate the hidden field for all the children: test_suite_run[test_runs_attributes][//id][packages_id]. This means that I need to run this function with a different child id each time.
I have added //id to indicate the only differences between the many function calls. I do not know how to duplicate this function without copying it many times manually and replacing //id with the indexes 0...n, for each nested child instance. Could this somehow be done by passing parameters to the javascript function?
Sorry if this a little confusing, I will be happy to explain in more detail if needed.
JQuery Function
$(document).ready(function () {
arr = new Array();
$(document).on('change', 'select[id ^="s_package//id"]', function () {
var arr = $('select[id ^="s_package//id"]').map(function () {
return this.value
})
result = ""
for (j = 0; j < arr.length - 1; j++) {
result += (arr[j] + ", ");
}
result += (arr[arr.length - 1])
$("input[name='test_suite_run[test_runs_attributes][//id][packages_id]']").val(result);
});
});
You can pass an array of ids to use in your function and iterate them:
function somethingMeaningful(ids) {
for (var i = 0, l = ids.length; i < l; i++) {
var id = ids[i];
// do something with this id
}
}
$(function() {
somethingMeaningful(['id1', 'id2', 'idn']);
});
It might also be possible to simplify your selector and calculate the id at runtime, depending on their actual format:
$(document).on('change', 'select[id^="s_package"]', function () {
var id = $(this).attr('id').slice('s_package'.length);
// Do stuff with real id
});
function createTextFields(obj) {
for (var i = 0; i < obj.length; i++) {
var dataDump = {};
for (var key in obj[i]) {
var textField = Ti.UI.createTextField(pm.combine($$.labelBrown, {
left: 200,
height:35,
value:obj[i][key],
width:550,
keyboardType:Ti.UI.KEYBOARD_NUMBER_PAD,
layout:'horizontal',
backgroundColor:'transparent',
id:i
}));
dataDump[key] = textField.value;
var callback = function (vbKey) {
return function (e) {
dataDump[vbKey] = e.source.value;
};
}(key);
}
globalData.push(dataDump);
}
}
I am using the simlar code for Adding the data and it works fine. I posted the problem yesterday and it got resolved...
Last Object is always getting updated?
Now when i go to edit page, it shows me four text fields or number of text fields added... now when i edit something and click on save... the value get's updated on the fourth or the last TextFields Object...
Don't define functions inside loops. Computationally expensive and leads to problems, like this one. Here's a fix that should solve it:
function createTextFields(obj) {
var callback = function (vbKey, localDump) {
return function (e) {
localDump[vbKey] = e.source.value;
};
}
var i;
var max = obj.length;
for (i = 0; i < max; i++) {
var dataDump = {};
for (var key in obj[i]) {
dataDump[key] = textField.value;
var callBackInstance = function(keyn, dataDump);
}
globalData.push(dataDump);
}
}
JavaScript does not have block level scope, so your variables dataDump and callback, though "declared" inside for-loops actually belong to the function. As in, you're saving a value to dataDump, then you're overwriting it, each time you go through the loop. Which is why finally only the code that operated on the last value remains.
Take a look at What is the scope of variables in JavaScript? too.