Passing argument by value to onClick function - javascript

I can't figure out how to pass an argument by value in JavaScript to onClick-function. I have been trying with closure functions but it doesn't seem to work!! aah
...
for(var i=0; i<=15; i++){
blockNr++;
meal = getMealByCategory(category, i);
place.innerHTML += "<div class='container-fluid' name='blockName' id='blockName" +
blockNr + "' onClick='addPrice(meal, 20)'></div>"; //here, always the last meal is sent
var itemPlace = document.getElementById("blockName"+blockNr);
itemPlace.innerHTML = meal; //this works fine for all meals
}

What you're doing is creating a global variable and overwriting it every time you add to the .innerHTML. Code in a string can't reference local variables, so what you want isn't possible.
One option would be to concatenate the value into the string.
place.innerHTML += "<div class='container-fluid' name='blockName' id='blockName" +
blockNr + "' onClick='addPrice(\"" + meal + "\", 20)'></div>";
This should work, but is pretty unpleasant. Instead, create your elements with DOM creation methods, and assign a function to the onclick property. That function will be able to reference the local meal.
And be sure to create a local scope, and declare meal with var.
var meal;
for(var i=0; i<=15; i++) {
meal = getMealByCategory(category, i);
createDiv(meal);
}
function createDiv(meal) {
blockNr++;
var div = document.createElement("div");
div.className = "container-fluid"
div.name = "blockName"
div.id = "blockName" + blockNr;
div.onclick = function() {
addPrice(meal, 20);
}
place.appendChild(div);
}

That is because by the time you run the on-click event the loop has fully executed and the value for meal is static as the last calculated value. If this needs to change for each element, you should pass the parameter value to the function, not pass the variable name. So something like:
"' onClick='addPrice('" + meal + "', 20)'></div>";

Related

Cached object loses its value after the page is left and I try to come back

Enviroment: I am using isml for view (demandware templating), browser is chrome.
What I am trying is to store the shopping store ID:
function cacheStores(data) {
cachedStores = {};
for (var i = data.length - 1; i >= 0; i--) {
var store = data[i];
console.log(store);
cachedStores[store.physicalId] = store;
}
It works when I am on the page, but when I leave the page (to next page) and try to go back to it, the value is empty.
ISML:
<input type="hidden" name="dwfrm_billing_shippingAddress_addressFields_houseNumber" value=>
That is the function setting name and value
function setShippingField(name, value) {
jQuery('input[name=' + name + ']', addressContainer).val(value);
}
//only set if housenumber is a field
if ($houseNumber.length) {
var matches = shippingAddress1.match(/\d+/);
if (matches) {
shippingHouseNum = matches[0];
shippingAddress1 = shippingAddress1.replace(shippingHouseNum, '');
setShippingField(checkout.initFields.s_houseNumber, shippingHouseNum);
}
}
// set hidden fields
setShippingField(checkout.initFields.s_title, billingTitle);
setShippingField(checkout.initFields.s_lastName, shippingLastName);
setShippingField(checkout.initFields.s_firstName, shippingFirstName);
setShippingField(checkout.initFields.s_address1, shippingAddress1.substr(0, MAX_ADDRESS1_LEN));
setShippingField(checkout.initFields.s_address2, shippingAddress2);
setShippingField(checkout.initFields.s_address3, store.physicalId);
setShippingField(checkout.initFields.s_zip, store.address.postalCode);
setShippingField(checkout.initFields.s_city, shippingCity);
setShippingField(checkout.initFields.s_country, billingCountry);
// set visible labels
jQuery('#customer', addressContainer).text(billingTitle + " " + shippingAddress2);
jQuery('#shopname', addressContainer).text(shippingLastName + ' ' + shippingFirstName);
jQuery('#shopstreet', addressContainer).text(shippingAddress1 + ' ' + shippingHouseNum); // includes house number
jQuery('#shopid', addressContainer).text(store.physicalId); // we're not using shop ids here
jQuery('#shopzipcity', addressContainer).text(store.address.postalCode + ' ' + shippingCity);
window.top.close();
}
It looks like client-side issue, the one you are having. I do not think it relates to the server-side logic you are using.
setShippingField(checkout.initFields.s_address3, store.physicalId);
Should not this be with something different than s_address3 field as key?
From your code snippet it is not clear what exactly you have in the checkout variable and in its initFields member. Also what exactly you pass to cacheStores function's data parameter.
On a side note, it is bad practice to use same identifier for different things in different scopes (cacheStores in one scope is function, and in another scope is object.)

defining static variable inside a function in angularJS

i am taking first steps in agularJS and got stuck trying to create a static variable in a function. the function gets a variable called cron_format and i want the function to save that value. thee function checks if user changed the value of cron_format and if so, posts the data.
this is the function:
$scope.saveCron = function(userId,scriptId,cronFormat,letter,comp,index){
//split cronFormat to match the value in the table, and than save changes
var newCron = $scope.split(cronFormat);
newCron[index] = letter;
//remove commas to match the cron's format
newCron = newCron.toString().replace(/,/g, " ");
if(letter!=comp) {
$.post("updateCronChange.php", "user_id=" + userId + "&script_id=" + scriptId + "&cron_format=" + newCron, function (data) {
console.log("cron changed to: "+newCron);
});
}
}
i want to store the variable newCron so that next time function being called, cronFormat will be equal to newCron from last execution...any help plz?
Use the fact that the function "closes over" the outer scope variables, and create one to store your previous value.
var prevCron; // Define a variable to hold the value between function calls.
$scope.saveCron = function(userId,scriptId,cronFormat,letter,comp,index){
//split cronFormat to match the value in the table, and than save changes
var newCron = $scope.split(cronFormat);
newCron[index] = letter;
//remove commas to match the cron's format
newCron = newCron.toString().replace(/,/g, " ");
if(letter!=comp) {
$.post("updateCronChange.php", "user_id=" + userId + "&script_id=" + scriptId + "&cron_format=" + newCron, function (data) {
console.log("cron changed to: "+newCron);
});
}
// Use the outer variable to store our current value.
prevCron = newCron;
}

Is there a way to make a dynamic variable name based on the value of another variable?

Is there a way to make the value of a variable the name for another variable? For example, I want the variable name (value_of_i) to be what ever number "i" is during that iteration. The while loop below is not what I'm using it for, it's just to explain what I'm asking.
var i = 1;
while(i<10)
{
var value_of_i = "This loop has ran " + i + "times.";
i++;
}
For the first iteration, "i" is equal to 1 so I would want the variable name to be "1":
var 1 = "This loop has ran " + i + "times.";
And the second interation:
var 2 = "This loop has ran " + i + "times.";
Yes. Using bracket notation (Here is a tutorial in MDN)
Here is a working fiddle
When doing something like containingObject[stringVariable] you are accessing the property in containingObject whose name is the value stored in stringVariable.
// this assumes browser JavaScript where window is the global namespace
// in node.js this would be a little different
var i=0;
while(i<10){
window["counters"+i] = "This is loop has ran " + i + "times.";
i++;
}
console.log(counters3);
If you'd like you can use this instead of window, however this might fail in strict mode.
Here is the main explanation of how bracket notation works from the MDN link above:
Properties of JavaScript objects can also be accessed or set using a bracket notation. Objects are sometimes called associative arrays, since each property is associated with a string value that can be used to access it. So, for example, you could access the properties of the myCar object as follows:
myCar["make"] = "Ford";
myCar["model"] = "Mustang";
myCar["year"] = 1969;
You can also access properties by using a string value that is stored in a variable:
var propertyName = "make";
myCar[propertyName] = "Ford";
propertyName = "model";
myCar[propertyName] = "Mustang";
You can't make a variable name a number, its not a valid name. So var 1="" is invalid.
But to dynamically set the value you can do
var x = "variablenamehere";
window[x] = "variablevaluehere";
Thats the same as
var variablenamehere
except that it will be scoped as a global variable and will be accessible everywhere, rather than being limited to the current function scope.
Why not store your strings in an array that is indexed by i?
That way you can reference them later efficiently and easily;
var loopI = new Array();
for(var i = 0; i < 10; ++i) {
loopI[i] = "This loop has ran " + i + "times.";
}
This works:
var o = {};
var d = "dog";
for (var k = 0; k < 5; k += 1) {
o[d+k] = k*100;
}
console.log(o.dog3); // 300
This comes closer to doing what you want:
var N = {};
var M = {};
var i = 1;
while(i<10)
{
N[i] = "This loop ran " + i + " times.";
// Or, so you can use dot notation later:
M['OO'+i] = "This loop ran " + i + " times.";
// Those are capital O's, not zeros. Numbers won't work.
i++;
}
console.log(N[3]); // This loop ran 3 times.
console.log(M.OO7); // This loop ran 7 times.
The 'OO' notation could cause bewilderment and wasted time for others trying to use your code; but it could also be a source of amusement for them. This reminds me of a chess board after white's first two moves are to bring out a knight and then put it back. The board then seems to show that black moved first, and some people will endlessly insist that the configuration proves there was illegal play unless someone tells them what happened.

Use "event's" output as a variable

I have a problem to manipulate checkbox values. The ‘change’ event on checkboxes returns an object, in my case:
{"val1":"member","val2":"book","val3":"journal","val4":"new_member","val5":"cds"}
The above object needed to be transformed in order the search engine to consume it like:
{ member,book,journal,new_member,cds}
I have done that with the below code block:
var formcheckbox = this.getFormcheckbox();
formcheckbox.on('change', function(checkbox, value){
var arr=[];
for (var i in value) {
arr.push(value[i])
};
var wrd = new Array(arr);
var joinwrd = wrd.join(",");
var filter = '{' + joinwrd + '}';
//console.log(filter);
//Ext.Msg.alert('Output', '{' + joinwrd + '}');
});
The problem is that I want to the “change” event’s output (“var filter” that is producing the: { member,book,journal,new_member,cds}) to use it elsewhere. I tried to make the whole event a variable (var output = “the change event”) but it doesn’t work.
Maybe it is a silly question but I am a newbie and I need a little help.
Thank you in advance,
Tom
Just pass filter to the function that will use it. You'd have to call it from inside the change handler anyway if you wanted something to happen:
formcheckbox.on('change', function(cb, value){
//...
var filter = "{" + arr.join(",") + "}";
useFilter(filter);
});
function useFilter(filter){
// use the `filter` var here
}
You could make filter a global variable and use it where ever you need it.
// global variable for the search filter
var filter = null;
var formcheckbox = this.getFormcheckbox();
formcheckbox.on('change', function(checkbox, value){
var arr = [],
i,
max;
// the order of the keys isn't guaranteed to be the same in a for(... in ...) loop
// if the order matters (as it looks like) better get them one by one by there names
for (i = 0, max = 5; i <= max; i++) {
arr.push(value["val" + i]);
}
// save the value in a global variable
filter = "{" + arr.join(",") + "}";
console.log(filter);
});

PrototypeJS loop won't run

I have a loop which won't run using Prototype + Scriptaculous. It runs once for the first object in my array then stops.
var myMessages = new Object();
myMessages = ['success','info','warning','error']; // define the messages types
function hideAllMessages()
{
var messagesHeights = new Array(); // this array will store height for each
enter code here
// This one runs just once for the first item in the array
var i = 0;
myMessages.each(function(element) {
alert(element);
messagesHeights[i] = $('.' + element).getHeight();
i++;
$$('.' + element + ' message').invoke('hide');
});
//This won't run at all===============================
for (var index = 0; index < myMessages.length; index++)
{
messagesHeights[index] = $('.' + myMessages[index]).getHeight();
$('x').hide();
//$('.' + myMessages[i]).css('top', -messagesHeights[i]); //move element outside viewport
}
}
I'm not a prototype user, but here's what I see so far:
$ is for IDs. I believe you need $$ here:
$$('.' + element)
This returns an Array, so I think you need invoke() like this:
$$('.' + element).invoke('getHeight');
Also, .each() passes the index as the second argument to the callback, so you don't need to maintain your own i.
myMessages.each(function(element, i) {
Also, this:
$$('.' + element + ' message')
...would seem to be looking for elements with the tag named message. I assume you want a class instead.
$$('.' + element + ' .message').invoke('hide');

Categories