Passing a variable into a DOM function in Javascript - javascript

I took this example from w3schools and modify it to this. The code below is not working.
What I intend to do is hide the div with id "demo1". It is not working. What is the problem?
<!DOCTYPE html>
<html>
<head>
<script>
function myFunction(div_id)
{
//here the div_id variable seems to unparsable by the DOM event
document.getElementById(div_id).innerHTML = hello;
}
</script>
</head>
<body>
<p>Click the button to trigger a function.</p>
<button onclick="myFunction('demo1')">Click me</button>
<div id="demo1"></div>
<div id="demo2"></div>
</body>
</html>

The variable hello is not defined. You were probably looking to set the innerHTML as a String:
function myFunction(div_id) {
document.getElementById(div_id).innerHTML = "hello";
// -----------------------------------------^-----^
}
DEMO: http://jsfiddle.net/uzuKp/1/
Even though you took an example from W3Schools and modified it, I'd suggest binding events separate from the HTML and storing associated data in data-* attributes. In your example, it can be as something like this:
<p>Click the button to trigger a function.</p>
<button data-div-id="demo1">Click me</button>
<button data-div-id="demo2">Click me</button>
<button data-div-id="demo1">Click me</button>
<div id="demo1">demo1</div>
<div id="demo2">demo2</div>
And the JS:
function clickHandler() {
var targetDivId, targetDiv;
targetDivId = this.getAttribute("data-div-id");
targetDiv = document.getElementById(targetDivId);
targetDiv.innerHTML = "Hello" + new Date().getTime();
}
function loadHandler() {
var buttons, i, j, cur;
buttons = document.getElementsByTagName("button");
for (i = 0, j = buttons.length; i < j; i++) {
cur = buttons[i];
cur.onclick = clickHandler;
}
}
window.onload = loadHandler;
DEMO: http://jsfiddle.net/3K4RD/
Although I would also suggest looking at the following article to see different ways to bind events: addEventListener vs onclick
One final suggestion I have is to not set the innerHTML property. You may have a simple example here, but it's usually a better idea to use DOM methods like appendChild (to add a node) and document.createTextNode (to create text that can be appended). Of course, that would require the contents to be cleared out first, something like:
while (targetDiv.firstChild) {
targetDiv.removeChild(targetDiv.firstChild);
}
targetDiv.appendChild(document.createTextNode("Hello"));
DEMO: http://jsfiddle.net/52Kwe/
You could also store the specific string that needs to be set as the innerHTML as a data-* attribute (especially if it differs between buttons).
UPDATE:
Per your recent edit, the style property is a special property, which is actually a special object with style properties that you need to set. So for your example, you have to set the .style.display value, like:
document.getElementById(div_id).style.display = "none";

document.getElementById(div_id).style.display = 'none';
document.getElementById(div_id).style.visibility= 'hidden';

Related

how can I set a setInterval as a global variable?

I just wanna make a button to start adding some text in my body, and a button to stop adding this text.
I figured out that I can use a setTimeout in a function or a setInterval...but I couldn't Clear both of them because of the local scope...I can't declare both of them as a global scope, I want my button.onclick activate them not by default.
/* global document*/
var myStart = document.querySelector('#start'),
myEnd = document.querySelector('#end'),
myRepeat;
function start() {
"use strict";
document.body.innerHTML += '<br>Welcome StackOverFlowMembers!';
myRepeat = setTimeout(start, 1000)
}
function stop() {
"use strict";
clearTimeout(myRepeat);
}
myStart.onclick = start;
myEnd.onclick = stop;
<body>
<button id="start">Start!</button>
<button id="end">End!</button>
<script src="script.js"></script>
</body>
The problem here is not the scope of the variables. Everything is actually fine with your code on that.
The problem is here:
document.body.innerHTML += '<br>Welcome StackOverFlowMembers!';
If you replace it with:
console.log('Hello!');
Both buttons will work normally. Check this fiddle.
Basically, when you use innerHTML you destroy the event listeners. You can find more on that in this answer
As #anpel's answer explains, your innerHTML call is trashing your event listeners. In the code below, I work around that by putting the onclick attribute directly into the HTML button elements. The boolean doRepeat variable governs whether a subsequent timeout gets initiated.
/* global document*/
var myStart = document.querySelector('#start'),
myEnd = document.querySelector('#end'),
doRepeat;
function start() {
"use strict";
document.body.innerHTML += '<br>Welcome StackOverFlowMembers!';
if (doRepeat) {
setTimeout(start, 1000);
}
}
<body>
<button id="start" onclick="doRepeat=true;start();">Start!</button>
<button id="end" onclick="doRepeat=false;">End!</button>
<script src="script.js"></script>
</body>
Alternatively, you can make a separate <div> into which your function writes its text-- instead how you're doing innerHTML to the entire HTML body, which destroys all child listeners-- and you won't have to worry about your event listeners getting destroyed since those listeners aren't on children of the target div.
Here's a JS Fiddle to demonstrate that: https://jsfiddle.net/j9voxg7s/

How to make a button in HTML which decrement a variable?

I am trying to decrement the variable Stock by 1 each time I click the button but it's not working. The value on the website stays the same no matter how many times I click the button:
var Stock = 10;
function myFunction() {
document.getElementById("myText").innerHTML = Stock;
}
function ButtonFunction() {
Stock--;
}
<body onload="myFunction">
<button onclick="ButtonFunction()">ClickMe</button>
<h1>"The value for Stock is: " <span id="myText"></span></h1>
</body>
Your function only changes the value of the Stock variable.
It doesn't change the value of document.getElementById("myText").innerHTML which only gets changed when you call myFunction (something you never do).
You need to:
Actually call myFunction when the document loads
Call it again whenever you change the variable.
let stock = 10;
function myFunction() {
document.getElementById("myText").innerHTML = stock;
}
function buttonFunction() {
stock--;
myFunction();
}
document.querySelector("button").addEventListener("click", buttonFunction);
addEventListener("load", myFunction);
<button>ClickMe</button>
<h1>"The value for Stock is: " <span id="myText"></span></h1>
Also note that by convention, variable names which start with a capital letter are reserved for classes and constructor functions in JS, so rename your variables.
It looks like the variable is being decremented, but the inner text of the span is not then updated.
Try calling myfunction() after each click ;)
There's a number of things going on here. The one I think you're primarily interested in has been answered by Quentin. Others however remain and are (I think) far better habits to get into than variable naming conventions.
Inline event handlers = bad. Events that can be removed or supplemented = good. Use attachEventListener for the most control.
Functions with names that offer nothing are a pain. Names are the most helpful when they're descriptive.
Functions that change and display a variable can be traps. It's often better to have a third function which calls both a function to change something and another function to display it.
Here's yet another approach:
window.addEventListener('load', onLoaded, false);
function onLoaded(evt) {
displayStock();
document.querySelector('button').addEventListener('click', onButtonPressed, false);
}
var unitsOfStock = 10;
function displayStock() {
document.getElementById('myText').textContent = unitsOfStock;
if (unitsOfStock == 1)
document.getElementById('plural').textContent = '';
else
document.getElementById('plural').textContent = 's';
}
function decreaseStock() {
unitsOfStock--;
}
function onButtonPressed() {
decreaseStock();
displayStock();
}
<button>ClickMe</button>
<h1>The value for Stock is: <span id="myText"></span> unit<span id='plural'></span></h1>
var Stock = 10;
function myFunction() {
document.getElementById("myText").innerHTML = Stock;
}
function ButtonFunction() {
Stock--;
myFunction();
}
<body onload="myFunction()">
<button onclick="ButtonFunction()">ClickMe</button>
<h1>"The value for Stock is: " <span id="myText"></span></h1>
</body>
I hope it helps you. You have to call myFunction to show the new value of Stock variable in myText id in your click handler ButtonFunction().
<!DOCTYPE html>
<html lang="en">
<head>
<script>
var Stock = 10;
function myFunction() {
document.getElementById("myText").innerHTML = Stock;
}
function ButtonFunction() {
Stock--;
myFunction();
}
</script>
</head>
<body onload="myFunction" >
<button onclick="ButtonFunction()">ClickMe</button>
<h1>"The value for Stock is: " <span id="myText"></span></h1>
</body>
</html>
Whenever you click the 'Click me' button, ButtonFunction() will be called. and document.getElementById("myText") get find the html element with the id myText and reference itself to the html element. innerHTML will allow you to place your html code inside it and innerText allows you to put your text the html element with an id of myText.
<!DOCTYPE html>
<html lang="en">
<head>
<script>
var Stock = 10;
function ButtonFunction() {
Stock--;
document.getElementById("myText").innerHTML = Stock;
}
</script>
</head>
<body>
<button onclick="ButtonFunction()">ClickMe</button>
<h1>"The value for Stock is: " <span id="myText"></span></h1>
</body>
</html>

Dynamically increasing font size

I would like to increase the font size of the paragraph as well as the font size of the number in the button.
I copied and pasted my sizer function from StackOverflow (a few alterations) and thought it would work and still can't get it to work. Can someone help?
Since I've spent so much time on just the first part, as a beginner programmer, I'm wondering what I am missing. Does anyone have any ideas from my code or their experience as to what I might be missing?
Thanks as always.
<html>
<button onclick='incrementer(); sizer()' id='count' value=0 />0</button>
<p id='test'>a</p>
<script>
clicks = 0
incrementer = function () {
clicks += 1
click = document.querySelector("#count").textContent = clicks;
click.innerHTML = document.getElementById("count").value = document.getElementById('test');
}
sizer = function changeFontSize() {
div = document.getElementById("test");
currentFont = div.style.fontSize.replace("pt", "");
div.style.fontSize = parseInt(currentFont) + parseInt(clicks) + "pt";
}
</script>
</html>
Some things here:
I woudn't append two functions to your onclick here. Just append one and call your second function from the first one that gets fired via onclick. That looks a lot more tidy
Don't forget to put var before every variable, without it's not valid JavaScript
I didn't quite understand what you tried with your currentFont variable, so I removed it. It's not necessary and causes the script to not working correctly
<html>
<button onclick='incrementer()' id='count' value=0 />0</button>
<p id='test'>a</p>
<script>
var clicks = 0;
var incrementer = function() {
clicks += 1;
var click = document.querySelector("#count").textContent = clicks;
click.innerHTML = document.getElementById("count").value = document.getElementById('test');
sizer();
}
var sizer = function changeFontSize() {
var div = document.getElementById("test");
div.style.fontSize = parseInt(clicks) + "pt";
}
</script>
</html>
Here's a from-scratch version that does what you're asking for. I'll point out a few things that I did to help you out.
https://codepen.io/anon/pen/VBPpZL?editors=1010
<html>
<body>
<button id="count">0</button>
<p id="test">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</p>
</body>
</html>
JS:
window.addEventListener('load', () => {
const button = document.querySelector('#count');
const paragraph = document.querySelector('#test');
const startingFontSize = window.getComputedStyle(document.body, null)
.getPropertyValue('font-size')
.slice(0, 2) * 1;
let clicks = 0;
button.addEventListener('click', () => {
clicks++;
// this is a template literal
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
const fontSize = `${startingFontSize + clicks}px`;
button.innerHTML = clicks;
button.style.fontSize = fontSize;
paragraph.style.fontSize = fontSize;
});
});
The code runs when the page is loaded, so we attach an event listener on the window object listening for the load event.
We then store references to the button and the paragraph elements. These are const variables because their values won't change. This also limits their scope to the containing function.
We get the initial font size for the body element, because in this example we aren't explicitly setting a base font in css so we're just using the one for the document. getComputedStyle is a somewhat expensive operation, and in this case we only need to get it in the beginning because it won't change, so we also store it as a const. The value is returned as a string like "16px" but we need the number, hence the slice and multiplying by one to cast the string into a number. parseInt would also do the same thing.
Notice that clicks is defined with let. This means that the variable can be changed. var still works of course, but in modern practices its best to use const and let when declaring variables. This is partly because it forces you to think about what kind of data you're working with.
We add an event listener to the button element and listen for the click event. First, we increment the clicks variable. Then we declare fontSize using a template literal which adds our new clicks count to the startingFontSize and "px" to get a string.
Finally, the innerHTML value of the button element is updated. Then we update the fontStyle property for both elements.
The issue here is that there is no initial value for the fontSize of your <p> tag so div.style.fontSize returns an empty string.
You can use window.getComputedStyle instead of div.style.fontSize and you will get the current fontSize.
There is already a post explaining this method
https://stackoverflow.com/a/15195345/7190518
You don't have an initial font-size style on your <p> tag, so it div.style.fontSize is always empty. Also, best practice is to always use var when introducing new variables in javascript.
One good trick to help debugging things like these is to use console.log() at various points, and see whats coming out in your browser console. I used console.log(div.style.fontSize) and the answer became clear.
Working below after adding <p style='font-size:12px'>a</p>:
<html>
<button style='font-size:12px;' onclick='incrementer(); sizer()' id='count' value=0 />0</button>
<p id='test' style='font-size:12px;'>a</p>
<script>
var clicks = 0
incrementer = function () {
clicks += 1
click = document.querySelector("#count").textContent = clicks;
click.innerHTML = document.getElementById("count").value = document.getElementById('test');
}
var sizer = function changeFontSize() {
var div = document.getElementById("test");
var btn = document.getElementById("count");
var newSize = parseInt(div.style.fontSize.replace("pt", "")) + parseInt(clicks);
div.style.fontSize = newSize + "pt";
btn.style.fontSize = newSize + "pt";
}
</script>
</html>
I don't understand the logic of this solution, but you can simplify it avoiding to use a lot of var (anyway always prefer let or const if you don't need to change), using a single function and writing less code.
function increment(e){
const ctrl = document.getElementById('test');
let current = parseInt(e.dataset.size);
current += 1;
e.innerHTML = current;
e.dataset.size = current;
ctrl.style.fontSize = current + 'pt';
}
<button onclick="increment(this);" data-size="20">20</button>
<p id='test' style="font-size:20pt;">A</p>

Javascript: Return original innerHTML on mouseout

I am sorry for this very basic question. I am very new to javascript and learning it.
I am stuck with one easy problem-
This is what i am trying to do-
I have a header that has some innertext
<h1 id="bd" onmouseover="fun1()" onmouseout="fun2()"> sample</h1>
I am chaging innerHTML of this header on mouseover like this-
function fun1()
{
document.getElementById("bd").innerHTML="a";
}
well on mouseout i do the same but for getting original innerHTML for this header tag.
function fun2()
{
document.getElementById("bd").innerHTML=document.getElementById("bd").innerHTML;
}
But onmouseout function shows me changed innerHTML, that is a in this case.
How do i get original innerHTML sample again onmouseout?
I want this to be done in javascript.
I tried another way more
function fun1()
{
document.getElementById("bd").innerHTML="a";
}
function fun3()
{
var ds=document.getElementById("bd").innerHTML;
alert(ds);
}
function fun2()
{
document.getElementById("bd").innerHTML=fun3();
}
but it is not working also.
A very generic version would be the following:
First change your markup a bit:
<h1 id="bd" onmouseover="fun1(this)" onmouseout="fun2(this)"> sample</h1>
This way you don't need to look up your element again in your callback function. This works then for more than one element you mouse over. Then you go:
function fun1(elm) {
if (!fun1.cache) fun1.cache = {}; // extend your function with a cache
fun1.cache[elm.id] = elm.innerHTML; // write into cache -> fun1.cache.bd
elm.innerHTML = 'a';
}
function fun2(elm) {
if (fun1.cache && fun1.cache[elm.id]) { // see if cache exists and...
elm.innerHTML = fun1.cache[elm.id]; // read from it
}
}
This way you build a caching system that doesn't need an extra global variable but stays closer to your function.
The next step would be to use only one function and send the new value as a parameter. Create something like a toggle function:
<h1 id="bd" onmouseover="fun(this, 'a')" onmouseout="fun(this)"> sample</h1>
and then your function:
function fun(elm, newValue) {
if (!fun.cache) fun.cache = {};
var value = newValue || fun.cache[elm.id]; // no newValue means recover old value
fun.cache[elm.id] = elm.innerHTML; // alway save the old value
elm.innerHTML = value;
}
If you need more explanations about this and creating Objects just leave a comment to this answer and I'll come back with more details...
Good luck!!
Store the first innerHtml in a global variable ,and use this variable to backup the first innerHtml.
var oldInner = '';
function fun1()
{
oldInner = document.getElementById("bd").innerHTML;
document.getElementById("bd").innerHTML="a";
}
function fun2()
{
document.getElementById("bd").innerHTML=oldInner;
}
You'll need to store the original value somehow:
var originalInnerHTML = "";
function fun1()
{
originalInnerHTML = document.getElementById("bd").innerHTML;
document.getElementById("bd").innerHTML="a";
}
function fun2()
{
document.getElementById("bd").innerHTML=originalInnerHTML
}
Currently you just get the existing innerHTML and set it as the new innerHTML - it's always going to be the same. So this line never changes anything:
document.getElementById("bd").innerHTML=document.getElementById("bd").innerHTML;
once you have changed the innerhtml of an element, old data is gone
In order to get the old data you first need to have it store in some other place.
For ex : on mouseover you can first copy the original html to a hidden div, and upon mouseout you can again copy from the hidden div to the main div.
hope this helps.
A very easy implementation will be to have the two text you want to display in the div. so you have:
<h1 id="bd">
<span id='sample1'>sample1</span>
<span id='sample2' style='display: none'>a</span>
</h1>
var el = document.getElementById("bd");
el.onmouseover = function() {
document.getElementById("sample1").setAttribute("style", "display: none");
document.getElementById("sample2").setAttribute("style", "");
}
el.onmouseout = function() {
document.getElementById("sample2").setAttribute("style", "display: none");
document.getElementById("sample1").setAttribute("style", "");
}

Javascript Onclicks not working?

I have a jQuery application which finds a specific div, and edit's its inner HTML. As it does this, it adds several divs with onclicks designed to call a function in my JS.
For some strange reason, clicking on these never works if I have a function defined in my code set to activate. However, it works fine when calling "alert("Testing");".
I am quite bewildered at this as I have in the past been able to make code-generated onclicks work just fine. The only thing new here is jQuery.
Code:
function button(votefor)
{
var oc = 'function(){activate();}'
return '<span onclick=\''+oc+'\' class="geoBut">'+ votefor +'</span>';
}
Elsewhere in code:
var buttons = '';
for (var i = 2; i < strs.length; i++)
{
buttons += button(strs[i]);
}
var output = '<div name="pwermess" class="geoCon"><div class="geoBox" style=""><br/><div>'+text+'</div><br/><div>'+buttons+'</div><br/><div name="percentages"></div</div><br/></div>';
$(obj).html(output);
Elsewhere:
function activate()
{
alert("Testing");
}
You may want to take a look at jQuery.live(eventType, eventHandler), which binds an event handler to objects (matching a selector) whenever they are created, e.g.:
$(".somebtn").live("click", myClickHandler);
Follows a dummy example, may be this can help you.
<!DOCTYPE html>
<html>
<head>
<style>
</style>
<script src="http://cdn.jquerytools.org/1.2.5/jquery.tools.min.js"></script>
<script type="text/javascript">
$(function() {
$('.go-right').click(function(){
c="Hello world";
$("#output").html(c);
});
});
</script>
</head>
<body >
<div id="output"></div>
<a class="go-right">RIGHT</a>
</body>
</html>
Change this:
var oc = 'function(){activate();}'
To be this instead:
var oc = 'activate();'

Categories

Resources