why does my global variable not carry its value between functions - javascript

At the top of my JavaScript document, which is linked to an HTML page, I declared:
var pizzaVar;
Then, I have a function later in the code that sets the variable's value and then calls another function:
function makePizza()
{
pizzaVar = document.getElementById("pizzaDiv").innerHTML;
givePizzaToppings();
}
But when I tried to use pizzaVar in the next function to set the innerHTML of pizzaDiv, nothing happened:
function givePizzaToppings()
{
var toppings = "<p>Onions and Bacon</p>";
pizzaVar = toppings;
}
However, if I changed the last line to
document.getElementById("pizzaDiv").innerHTML = toppings;
it worked. I don't want to have to put that in everytime I want to change pizzaDiv though, is there a way to fix this.
PS: I tried saying
var pizzaVar= document.getElementById("pizzaDiv").innerHTML;
outside of the functions but I got an error message saying:
TypeError: null is not an object(evaluating 'document.getElementById("pizzaDiv").innerHTML')

Your pizzaVar will point to a string value, which will be the HTML at the time of the assignment. It doesn't magically setup a link to change it.
If you wanted to use this global variable, you'd be better off pointing it to the div element and then using innerHTML every time you wanted to change its value.
Then you should research to understand why innerHTML is rarely the best tool to modify the DOM.

Unfortunately, whenever you want to change the .innerHtml of your pizza div, you're going to have to write document.getElementById("pizzaDiv").innerHTML on the left side of an equals sign. pizzaVar is not a pointer, and doesn't point to the .innerHtml of the div.
The error you got is telling you that document.getElementById("pizzaDiv") returned null and hence has no properties at all, much less an .innerHtml property. This is because it did not exist at the time of the .getElementById call.

Related

How do you assign onclick within for loop in javascript?

function initnav(){
var cbox=document.getElementsByClassName('box');
for(var i=0;i<cbox.length;i++){
cbox[i].innerHTML=cbox[i].id;
<!--so far I have set their captions after setting their ids same as how I want them to appear.-->
<!--what comes next is what doesn't really work.-->
getElementById(cbox[i].id).onclick=Mclick(cbox[i].id);
}
};
function Mclick(id){alert(id);}
The whole thing is in a js file, and promptly linked from my html file.
As planned, all the buttons should appear and be clickable, but what is happening instead is only one of them is visible and that one is not working when I click on it.
When I create a lot of div-oriented buttons, I wish I could run for loop and be able to assign each of them as clickable instead of writing lines as many as they are.
How do you assign onclick within for loop in javascript?
You're calling the function instead of assigning it.
getElementById(cbox[i].id).onclick = Mclick;
Of course, now your function will receive an event argument instead of an id. (Passing the id inside the loop is a huge pain; easiest fix is to not bother trying.) But it also gets the attached element as this, which is convenient:
function Mclick() {
alert(this.id);
}
Other comments:
You should try not to be in the habit of using innerHTML if you're not assigning a string that contains known HTML. Saves you from having to care about escaping. Use textContent instead.
Assigning to onclick is a bit inflexible; you can only ever assign one click handler this way, and it's hard to notice if you accidentally overwrote an existing handler. Use addEventListener.
getElementById(element.id) should surely be equivalent to element.
Don't use HTML comments within JavaScript! :) They only work for... weird backwards-compatibility reasons. JavaScript comments are either // ... or /* ... */.
Best not to capitalize a function name unless it's supposed to be a constructor; you may notice that SO's highlighting made Mclick green, because it thinks it's a class name.
So I'd end up with:
function initnav() {
var cbox = document.getElementsByClassName('box');
for(var i = 0; i < cbox.length; i++) {
cbox[i].textContent = cbox[i].id;
cbox[i].addEventListener('click', alert_id);
}
}
function alert_id(event) {
alert(this.id);
}
So basically you don't call the for loop since the for loop is in the function. If you want to call all your variables and the statements in the for loop you have put the statements in the function and call the function outside of the function but inside of the script.

Default Value in drop down list not being selected

I have a drop down list [ Incident, Question, Problem, Task]. I have written a code when an end user logins in and has a tag called product the default value should be problem. However it does not seem to work. It still gives the user the option to select values from the list.
$j(document).ready(function() {
if(location.pathname == '/requests/new') {
var ct = currentUser.tags;
if(ct.indexOf("product") >= 0){
$j(document.getElementById("ticket_fields_75389").value = "Problem");
}
else {
$j(document.getElementById("ticket_fields_75389").value = "");
}
}
})
Note: This answer is incorrect. I will delete it once I know the OP read my comment.
It still gives the user the option to select values from the list.
Well, of course, setting value will only change the initially selected value. If you want "fix" the value of the select element, so that the user cannot change it, you have to make it read-only. Lets stick with jQuery (what you have is a weird mix of DOM API and jQuery †):
$j("#ticket_fields_75389").val("Problem").prop('readonly', true);
†: Let's have a close look at the line
$j(document.getElementById("ticket_fields_75389").value = "Problem");
What exactly is happening here? Obviously we have a function call ($j(...)) and we pass something to it. This "something" is the result of the expression
document.getElementById("ticket_fields_75389").value = "Problem"
This finds an element by ID and assigns the string "Problem" to the value property. This is an assignment expression. The result of an assignment expression is the assigned value, i.e. "Problem".
That is the value that is passed to $j(...), so we have $j("Problem");. Since $j refers to jQuery, this would search for all elements with tag name Problem, which does not exist in HTML. It would also return a jQuery object, but you are not doing anything with it.
Hence the wrapping in $j(...) is completely unnecessary or even wrong, even though it doesn't throw a syntax or runtime error.

Passing value to function from html

I'm trying to pass a value from html to a function but when I do I get an error - reference error: cant find the variable: "var value". The code below I'm removing spaces and replacing them with underscores then trying to pass that to a function called onToDate.
var theFunction2 = theFunction.replace(/ /g,"_");
$('#inserted').append('<div id="'+theFunction2+'"><li onclick="onToDate('+theFunction2+')"><img width="30px" height="25px" src="style/soccer.png"><div id="popupContactClose2">'+counted+'</div></img>'+ rs.rows.item(0)['playing']+'</li>');
onToDate is simply there to alert the value passed to it:
function onToDate(hello){
alert(''+hello+'');
console.log(''+hello+'');
}
This is where I get the error. I don't really get whats happening I've used this before and it worked fine.
Any help would be great,
Thanks
onclick="onToDate('+theFunction2+');
is turning into something like:
onToDate(some_thing);
so in the above case, some_thing is a variable that is undefined, meaning that this is a Reference error.
So,
onclick="onToDate(\"'+theFunction2+'\");
should fix it
First of all #IAbstractDownvoteFactor is right. You should fix onclick definiton.
If this code runs in $(document).ready() block, then your onToDate function is not accesible from that scope. Your click event calls from global scope. You should define it like this;
window.onToDate = function(hello){
alert(hello);
}
And no need for those single quotes...

Javascript getVariableName

This is my first post.
I'm trying to do some basic meta-programming with javascript, and I was wondering if there is a way of get the id of a particular object and with that id, access to the variable name, or get simply the variable name of a particular object. I wanna recreate a situation in which you first create every single html in a web page, and append to some of the html tags events associated to a particular class -example class Person-. for example: Supposed the next code:
var someFunction = function(someText){alert(someText);}
function SomeClassFunction(){
this.aClassFunction = someFunction;
}
var aVariableName = new SomeClassFunction();
and in the HTML code suppose I have the next piece of code.
<html>
<head>
<title></title>
</head>
<body>
<div onclick="aVariableName.aClassFunction('Some text to show in alert');">
</div>
</body>
</html>
Then, as you may notice the onclick event uses the aVariableName I created before, but because I first create the name of the variable and then append the name in the code cause I knew aVariableName was the name of that object. What I wanna do or implement is to create the text above in html without know the variable name of an specific object. I have surfed on the net but, unfortunately I haven't found anything about it.
i dont know how to get the name of a variable from the code its self without doing a whole load of work parsing stuff, which will get messy, and i'd shoot someone for this.
var someValue;
var foo = function() { someValue; }
alert((foo + '')); // this is now a string, use substr to extract variable name
You know you can set events like this in javascript someElement.onclick = someFunction so you dont really need to know the name of the variable if all you're doing is setting an event handler.
In general, no — you can't get the name of a particular variable or its "id" either.
If you really want to, it may be possible to do Bad Things with exceptions and stack traces to get that information… But I don't know off the top of my head how to do that.
Edit: I assume that, by “variable ID”, you mean “a unique identifier for the object referenced by that variable”, like Python's id builtin:
>>> x = {}
>>> y = z = {}
>>> (id(x), id(y), id(z))
(123, 567, 567)
I'm not 100% sure that I understand your question correctly in regards to meta-programming, but typically you would attach an event handler to the click event of the DOM element, then you can examine properties of the element within the handler.
There are a couple things in JavaScript that facilitate meta-programming: eval will let you interpret arbitrary code, so you can build a string of code and eval it. The security concerns are numerous. You can also access properties of an object by index or by name, e.g.
aVariableName.aClassFunction
is the same as
aVariableName["aClassFunction"]
Hope that helps.

onchange attribute won't call function

I have an HTML document (here), which creates an iframe-based media player for a collection of songs within albums (I just used letters to define these albums and songs in the mymusic array, for simplicity).
Focusing on the top 3 iframes, the way I have set out the user interaction is to generate the HTML for forms of available albums and songs using Javascript, and write them to the iframes in the body. If you run it and make a selection in the Albums menu, you will see that the options in the Songs menu correspond with the mymusic array, so this works.
However, when I choose a song, the function nowplaying(trackindex,albumindex) should be called using an onchange event in the Songs form, the same way as in the form generated using showinitial() ... but the function does not get called.
I have ruled out the coding of nowplaying itself as a cause, because even when I change nowplaying to alert("hello"), it does not get called. So this leads me to think the problem is with the onchange attribute in "anything", but I can't see the problem. The way I coded it is no different to before, and that worked fine, so why won't this work?
Any help would be much appreciated!
Firebug is your friend....
i is not defined
function
onchange(event) {
parent.nowplaying(this.SelectedIndex,
i); }(change )
onchange is getting called, but i is not defined when calling nowplaying.
This is the result of this line:
p+="<html><head></head><body><form><select onchange='parent.nowplaying(this.SelectedIndex,i);' size='";
which is using "i" in the string, when it should append it as a variable:
p+="<html><head></head><body><form><select onchange='parent.nowplaying(this.SelectedIndex," + i + ");' size='";
To clarify, i is defined when anything(i) is called, but you aren't writing i into the code, just the letter "i". When nowplaying(this.SelectedIndex,i) is called, i is no longer defined, because you aren't inside of the anything() function anymore. You need to expand i when you append the html to p, so that the value is there and not the variable i.
function anything(i){
p+="...<select onchange='parent.nowplaying(this.SelectedIndex,i);'...";
Your onchange event handler is set from a string. When run, it will not have access to i, which is a local variable from the anything function that has long since gone away.
The simple fix would be:
p+="...<select onchange='parent.nowplaying(this.SelectedIndex,'+i+');'...";
which turns the current value of i at string-making time into an integer literal inside the string.
However, it's not generally a good idea to be creating code from strings. It's normally better to write the event handler as a normal function object:
// You will need the below workaround to get the iframe document in IE too
//
var iframe= document.getElementById('songs');
var idoc= 'contentDocument' in iframe? iframe.contentDocument : iframe.contentWindow.document;
idoc.open();
idoc.write(s);
idoc.close();
idoc.getElementsByTagName('select')[0].onchange= function() {
// This is a closure. The 'i' variable from the parent 'anything' function is
// still visible in here
//
parent.nowplaying(this.selectedIndex, i);
};
However you would generally want to avoid setting handlers from one frame on a different one. I'm not really sure what the iframes are gaining you here other than headaches. Why not just simply use positioned divs with overflow? You can still rewrite their content through innerHTML if you need to... though I would prefer to populate them using DOM methods, to avoid all the HTML-injection problems your current script has.

Categories

Resources