javascript onclick function not working? - javascript

I am trying to do an onclick event where when a light bulb image is clicked it goes from a light bulb off to a light bulb on image and vice versa.
I am using an external javascript file. when I click on the image nothing happens.
I cant figure out whats wrong,
my html portion:
<head>
<link rel="stylesheet" href="css/program-01.css" />
<script type="text/javascript" src="javascript/program-01.js"></script>
<title>
<h1>Program-01</h1>
</title>
</head>
<body>
<div id="LightOff">
<img src="images/light_off.png" id="light_off" alt="" onclick="LightBulbFunction()" />
</div>
</body>
my js file function:
function LightBulb() {
var image_change = document.getElementById("light_off");
if (image_change.src == "images/light_off.png") {
image_change = "images/light_on.png";
} else {
image_change = "images/light_off.png";
}
}

Suggestions/Problems:
You function names are different.
You're using the function LightBulbFunction on the onclick event. But, you don't have the function of that name in your script. You'll get
ReferenceError: LightBulbFunction() is not defined.
To change the image src attribute value, use image_change.src inside the event handler.
To solve the problem change the name of onclick attribute value to LightBulb.
function LightBulb() {
var image_change = document.getElementById("light_off");
if (image_change.src == "images/light_off.png") {
image_change.src = "images/light_on.png";
// ^^^^
} else {
image_change.src = "images/light_off.png";
// ^^^^
}
}
<div id="LightOff">
<img src="images/light_off.png" id="light_off" alt="" onclick="LightBulb()" />
<!-- ^^^^^^^^^^^ -->
</div>
Better approach will be to use addEventListener to bind events on the elements.
document.getElementById('light_off').addEventListener('click', function() {
var image_change = document.getElementById("light_off");
if (image_change.src == "images/light_off.png") {
image_change.src = "images/light_on.png";
} else {
image_change.src = "images/light_off.png";
}
}, false);
<div id="LightOff">
<img src="images/light_off.png" id="light_off" alt="" onclick="LightBulb()" />
<!-- ^^^^^^^^^^^ -->
</div>

Well in your html, the code is onclick="LightBulbFunction()" while in javascript it is LightBulb. Change either of them and make them match

You are not redefining the .src. Change
image_change =
to
image_change.src =
And your function needs to have the same LightBulb function name.

Related

How I add an item to localStorage JS?

I have a function that sets the color theme of my site when clicked, but when I reload the page or go to a new page, it reverts back to the default theme. There's a line of my code that is supposed to get the previous theme from localStorage and apply it to the new one, but I think why it isn't working is that there isn't actually any code that saves the theme to Storage. Either that, or localStorage resets when the page is reloaded/changed. Either way, I'm not sure how to fix it.
This is my code:
<a class="switch-light-purple color-palette" id="color-palette" onclick="setTheme('theme-light-purple')">
<script>
// function to set a given theme/color-scheme
function setTheme(themeName) {
localStorage.setItem('theme', themeName);
document.documentElement.className = themeName;
}
// Immediately invoked function to set the theme on initial load
(function () {
if (localStorage.getItem('theme') === 'theme-light-purple') {
setTheme('theme-light-purple');
}
})();
</script>
</a>
<a class="switch-dark-blue color-palette" id="color-palette" onclick="setTheme('theme-dark-blue')">
<script>
// function to set a given theme/color-scheme
function setTheme(themeName) {
localStorage.setItem('theme', themeName);
document.documentElement.className = themeName;
}
// Immediately invoked function to set the theme on initial load
(function () {
if (localStorage.getItem('theme') === 'theme-dark-blue') {
setTheme('theme-dark-blue');
}
})();
</script>
</a>
Separation of concerns:
Keep your html, css, and js in their respective files ALWAYS, there's no substitution for this.
So your index.html should look something like this (assuming index.html, style.css, and main.js are all in the same folder).
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="parent-container">
<a data-theme="theme-dark-blue" class="switch-dark-blue color-palette" id="color-palette">Dark Blue </a>
<a data-theme="theme-light-purple" class="switch-light-purple color-palette" id="color-palette2">Light Purple</a>
</div>
<script src="main.js"></script>
</body>
</html>
Your CSS will be in a file called style.css,
And your JS,
// This waits for the DOM to complete loading
document.addEventListener('DOMContentLoaded', function() {
// all your code goes inside this.
});
Also, as #Sebastian Simon pointed out in the comments,
Repeating the same id is invalid in HTML. Inline event handlers like onclick are not recommended. They are an obsolete, hard-to-maintain and unintuitive way of registering events. Always use addEventListener instead.
Unique IDs:
You could change the id of one of your anchor tags to color-palette2 for instance, but since you have a lot of different themes you could pick names that are more self-explanatory. But, as long as your ids are unique (1 unique id per page), it's fine.
Event Listeners:
Use .addEventListener to add events to your DOM nodes. I've done this in the code snippet I've shared. It's very easy once you get used to it.
I've also used data attributes to pass your theme in a more "dynamic" way to your logic. StackOverflow snippets don't support localStorage hence I've commented that line out.
function setTheme() {
let theme;
let savedTheme = localStorage.getItem('theme')
// check if localstorage already has a theme defined
// if it has, then set theme variable to it
// otherwise, get the theme from the data-theme attribute
// of the current anchor tag clicked represented by this.
theme = savedTheme || this.dataset.theme
let div = document.querySelector('div.parent-container')
// I'm adding this to a div
// you can add it to the body tag.
div.classList.add(theme)
// this code can be better but the idea is
// to remove all other themes and keep only the intended one.
if (theme === 'theme-dark-blue') {
div.classList.remove('theme-light-purple')
} else {
div.classList.remove('theme-dark-blue')
}
console.log(`Set theme to ${theme}`)
}
let palettes = document.querySelectorAll('.color-palette')
palettes.forEach(function(p) {
p.addEventListener('click', setTheme)
})
a {
cursor: pointer;
text-decoration: underline;
color: blue;
}
.switch-light-purple {
color: purple;
margin: 0 15px;
}
<div class="parent-container">
<a data-theme="theme-dark-blue" class="switch-dark-blue color-palette" id="color-palette">Dark Blue </a>
<a data-theme="theme-light-purple" class="switch-light-purple color-palette" id="color-palette2">Light Purple</a>
</div>
PS: the code snippet won't work since StackOverflow does not support localStorage.

How can I set up a function that can be referenced from several event listeners and use different properties for each element? (JS)

Edit: I found the solution (found at the bottom).
The problem that I am having is that I want to consolidate my code into one small function that can be referenced multiple times. I have a currently working code, which has several functions, one for each event-listener that my webpage has. I am trying to render objects after a user clicks a "button," which is really a div element. Here's some code:
//Constructor Function
function Object(objectType) {
this.objectType = objectType;
}
//Render function for the objects
Object.prototype.render = function() {
//Getting the elements, creating them, setting to variables to be used later.
let objectDiv = document.createElement('div');
objectDiv.setAttribute('class', `${this.objectType}Object`);
objectDiv.textContent = this.objectType;
let makeButton = document.querySelector(`#${this.objectType}Section`);
//Appending element to webpage
makeButton.appendChild(objectDiv);
};
//All the current code above works like it is supposed to. I have a few buttons already that work, but they each have their own function. Like so:
//Setting up Button1 code.
let button1 = document.getElementById("makeObj1");
//Event listener for Button1, which calls the Render function for the Button1 object.
button1.addEventListener("click", goMakeButton1);
function goMakeButton() {
let button1 = new Object('Obj1');
button1.render();
}
//And so forth three times, for each button.
//I want to make it so that there is one section, and I currently have it set up like so:
let button1 = {
element: document.getElementById('makeObj1'),
name: 'Obj1',
}
let button2 = {
element: document.getElementById('makeObj2'),
name: 'Obj2',
}
let button3 = {
element: document.getElementById('makeObj3'),
name: 'Obj3',
}
let button4 = {
element: document.getElementById('makeObj4'),
name: 'obj4',
}
catButton.element.addEventListener('click', makeObj);
dogButton.element.addEventListener('click', makeObj);
sheepButton.element.addEventListener('click', makeObj);
horseButton.element.addEventListener('click', makeObj);
function makeObj(object) {
console.log('I am called');
//To check my function gets called - it does.
let myObject = new Animal(this.name);
myObject.render();
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Animal Farm</title>
<link rel="stylesheet" href="./style/style.css" />
</head>
<body>
<h1>DOM Manipulation and Events</h1>
<!-- create one big container -->
<main id="mainContainer">
<section id="Obj1Section">
<div class="make" id="makeButton1">Make Object 1</div>
</section>
<section id="Obj2Section">
<div class="make" id="makeButton2">Make Object 2</div>
</section>
<section id="Obj3Section">
<div class="make" id="makeButton3">Make Object 3</div>
</section>
<section id="HorseSection">
<div class="make" id="makeButton4">Make Objecvt 4</div>
</section>
</main>
</body>
<script src="./script/script.js"></script>
</html>
This just gives me the error of not being able to append child of null. When I try to take in a parameter and give each event listener its own parameter to pass, that fails as well and doesn't even allow me to click them. What do I do here?
The fix:
What I did was run an arrow function that called another function, passing a parameter defined in the arrow function, rather than trying to pass a parameter directly to the function from the event listener (it would just run, and then become useless.)
"use strict";
//Creating the constructor function for the buttons
function Button(buttonName) {
this.buttonName = buttonName;
}
//Render function for Buttons. Able to be used for any button name.
Button.prototype.render = function () {
//Getting the elements, creating them, setting to variables to be used later.
let buttonDiv = document.createElement('div');
buttonDiv.setAttribute('class',`${this.buttonName}Object`);
buttonDiv.textContent = this.buttonName;
let makeButton = document.querySelector(`#${this.buttonName}Section`);
//Appending element to webpage
makeButton.appendChild(buttonDiv);
};
//Setting up the condensed function:
let buttonOne = document.getElementById('Obj1');
let buttonTwo = document.getElementById('Obj2');
let buttonThree = document.getElementById('Obj3');
let buttonFour = document.getElementById('Obj4');
function buttonMake(button){
let myButton = new Button (button);
myButton.render();
}
buttonOne.addEventListener('click', ()=>{
let theButton = 'Obj1';
makeButton(theButton);
})
buttonTwo.addEventListener('click', ()=>{
let theButton = 'Obj2';
makeButton(theButton);
})
buttonThree.addEventListener('click', ()=>{
let theButton = 'Obj3';
makeButton(theButton);
})
buttonFour.addEventListener('click', ()=>{
let theButton = 'Obj4';
makeButton(theButton);
})

Only let HTML continue once all images have loaded

I recycled a lot of code from an old JS project I made back in the very beginning of my learning process, and back then I knew nothing about DOM events. Specifically in this case, onload. What I am looking for is someway to only let the website begin to run once all images have loaded, without putting everything into one big onload function, or rewriting all my code. Is there anyway to do this?
<img src="placeholder.png" onload="continue()" width="100" height="100">
<script>
function continue() {
//This is where I am stuck
}
</script>
The simplest solution would be to set the display property of the body to none when the page is loading, and then have continue() make it visible.
CSS:
body {
display: none;
}
JS:
function continue() {
document.body.style.display = "";
}
If the images aren't going to be dynamically added to DOM you can simply just do the followingaIf the images aren't going to be dynamically added to DOM you can simply just do the following
<html>
<body style="display: none;">
<img src="https://via.placeholder.com/100" alt="">
<img src="https://via.placeholder.com/200" alt="">
<img src="https://via.placeholder.com/300" alt="">
<script>
const imageCollection = Array.from(document.getElementsByTagName('img'));
const promisifier = (imageNode) => {
return new Promise((resolve, reject) => {
imageNode.addEventListener("load", () => {
console.log('image loaded', imageNode);
resolve('Loaded')
});
})
}
Promise.all(imageCollection.map(img => promisifier(img))).then((resp)=>{
document.body.style.display = 'block';
console.log('All images completed Loading');
})
</script>
</body>
</html>
If images are going to be dynamically added you could go for Mutation Observer, let me know if thats the case will add that too.

Polymer paper-collapse item change class of parent

I have a Polymer <paper-collapse-item> inside a <div> inside another <div>. When the <paper-collapse-item> is opened, I want to change add another class to the <div class="container">. But Polymer tells me the function is undefined. Right now I have:
HTML:
<div class="container>
<h1>Header</h1>
<div class="box" onclick="[[_expandBox()]]">
<paper-collapse-item class="header" header="">
<p class="longText">Some long text</p>
</paper-collapse-item>
</div>
</div>
Script:
<script>
Polymer({
is: 'text-page',
_expandBox: function() {
var exp = this.getElementsByClassName("header")[0];
var expPar = this.getElementsByClassName("box")[0].parentNode;
if (exp.hasAttribute(opened)) {
expPar.className += " paropen";
}
}
});
</script>
So how I can I call the function properly and make it add a class to the container?
EDIT
I've made some changes to the entire setup for different reasons. Still left with this issue.
HTML:
<div class="container>
<h1>Header</h1>
<collapse-item opened="{{opened}}" on-tap="_expandBox(opened)"></collapse-item>
</div>
Script:
<script>
Polymer({
is: 'text-page',
_expandBox: function(opened) {
var exp = this.getElementsByClassName("container")[0];
if (opened) {
exp.className += " paropen";
}
}
});
</script>
This tells me that: listener method _expandBox(opened) not defined
Thanks for helping me learn. I'm new to Polymer.
Following Polymer Documentation, you have to write "on-" followed by gesture event type. You have to remove brackets within event handler too. In your case:
<div class="box" on-click="_expandBox">
EDIT:
On on-tap event declaration you must to add a listener, in this case on-tap="_expandBox" (without parameters). When the event tap occurs, an event object is passed automatically to the function as the first parameter:
_expandBox: function(event) {
console.log(event.detail);
}
Your code could be:
HTML:
<div class="container>
<h1>Header</h1>
<collapse-item id="collapseItem" on-tap="_expandBox" opened="[[_functionWithParamsThatChangesThis(param1, param2, ...)]]"></collapse-item>
</div>
Script:
<script>
Polymer({
is: 'text-page',
_expandBox: function() {
var exp = this.getElementsByClassName("container")[0];
if (this.$.collapseItem.opened) {
exp.className += " paropen";
}
}
_functionWithParamsThatChangesThis(param1, param2, ...) {
if (param1, param2, ...) return true;
return false;
}
});
</script>

2 Questions / 1. Fullscreen(jQuery) / 2. Background change and save as Cookies

Hello,
i searched around the web, but can't find right peace of codes..
I want to do:
- go to Fullscreen mode on a button click.
- change a background color to dark and save it as cookies.
Fullscreen mode:
i'm new with jQuery and can't find a right code. I found one, but when i click on button to next page, it turn's off the full screen mode to normal browser window, and changes my website background colors.
Founded code:
<html>
<head>
<title>TEST</title>
</head>
<body>
<img src="fullscreen.png">
<script>
function toggleFullScreen() {
if ((document.fullScreenElement && document.fullScreenElement !== null) ||
(!document.mozFullScreen && !document.webkitIsFullScreen)) {
if (document.documentElement.requestFullScreen) {
document.documentElement.requestFullScreen();
} else if (document.documentElement.mozRequestFullScreen) {
document.documentElement.mozRequestFullScreen();
} else if (document.documentElement.webkitRequestFullScreen) {
document.documentElement.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
}
} else {
if (document.cancelFullScreen) {
document.cancelFullScreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
}
}
</script>
</body>
</html>
Change Background and save as Cookies:
I want to do, that a members chooses on radio button's a theme White or Dark. The White theme default <div> background is white #fff(White). When member chooses the Dark theme, it changes <div> background to #000000(Black) color. I'm new and can't write a code, without examples or something. Can someone tell me, how can i do it with Cookies and Javascript/jQuery?
Members settings page to change it:
<html>
<head>
<title>Settings</title>
</head>
<body>
<p>Change Theme</p>
<form>
<input type="radio" id="Light" title="White Theme">
<br />
<input type="radio" id="Dark" title="Dark theme">
<br />
<input type="submit" id="submit" value="Submit">
</form>
</body>
</html>
Page BEFORE changes the Theme to Dark:
<html>
<head>
<title>Home Page</title>
</head>
<body>
<div style="background:#fff;height:600px;width:100%;">
<!-- SOME CONTENT -->
</div>
</body>
</html>
and Page AFTER changes the Theme to Dark:
<html>
<head>
<title>Home Page</title>
</head>
<body>
<div style="background:#000000;height:600px;width:100%;">
<!-- SOME CONTENT -->
</div>
</body>
</html>
Thanks!
You can set a cookie value, like this:
document.cookie = "theme=black";
Or, if you want to keep other settings, then:
function changeCookieValue(attribute, value) {
var previousCookie = document.cookie.split(";");
for (var i = 0; i < previousCookie.length; i++) {
var key = previousCookie[i].substring(0,previousCookie[i].indexOf("="));
if (key === attribute) {
previousCookie[i] = attribute + "=" + value;
document.cookie = previousCookie.join(";");
return;
}
}
document.cookie = document.cookie + ";" + attribute + "=" + value;
}
And you can use it like this:
`changeCookieValue("black");`
This is how you can read from cookie:
function getCookieValue(attribute) {
var previousCookie = document.cookie.split(";");
for (var i = 0; i < previousCookie.length; i++) {
var key = previousCookie[i].substring(0,previousCookie[i].indexOf("="));
if (key === attribute) {
return presiousCookie[i].substring(previousCookie[i].indexOf("=") + 1);
}
}
return "";
}
You can set the class of the body, like this:
$("body").addClass(getCookieValue("theme"));
just make sure that body is already loaded when you run this part. You can design the themes like this:
.black > div {
background: #000000;
}
.white > div {
background: #fff;
}
Alternatively, you can work with localStorage, which is much more handy. As about full screen mode, there is no reason to reinvent the wheel, since there is a good fullscreen API you should use for this purpose.
And you can make sure that changeCookieValue runs with the proper parameter on click using the onclick attribute of your radio buttons.
Alternatively, you might consider storing the values inside a database and adding the needed class to body on server, when you generate it.
EDIT:
You can add the class at the loaded event:
$(function() {
$("body").addClass(getCookieValue("theme"));
});
Note, that this will be responsible to display the theme at page load. You need to display it whenever you call changeCookieValue for theme. Before you call that function $("body").removeClass(getCookieValue("theme")); and after the function is executed $("body").addClass(getCookieValue("theme")); (note, that the theme is changed). Naturally, you need a wrapper for this:
function changeTheme(theme) {
$("body").removeClass(getCookieValue("theme"));
changeCookieValue("theme", theme);
$("body").addClass(getCookieValue("theme"));
}
and trigger this changeTheme at your radio buttons.

Categories

Resources