Assigning a function to each link after the onclick event - javascript

I want to separate my markup from the behavior but i stuck on how to associate the function i created to all the links in the document after the onclick event without including it directly in the markup. Here is my HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Image Gallery</title>
</head>
<body>
<h1>Snapshots</h1>
<ul>
<li>
Fireworks
</li>
<li>
Coffee
</li>
<li>
Rose
</li>
<li>
Big Ben
</li>
</ul>
<img id="placeholder" src="images/placeholder.gif" alt="my image gallery">
<script type="text/javascript" src="scripts/showPic.js"></script>
</body>
</html>
and here is my script
function showPic(whichPic) {
"use strict";
var source = whichPic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src", source);
}
window.onload = function() {
"use strict";
var anchors = document.getElementsByTagName("a");
console.log(anchors);
for(var i = 0, count = anchors.length; i < count; i++) {
//anchors[i].preventDefault;
// anchors[i].onclick = showPic;
}
}
I tried to loop through the links and assign the function to the onclick event of each link but it didn't work. What is the best way this could be done so that behavior is completely separate from markup?

function showPic(e) {
// e is the event, e.target is the current element
"use strict";
e.preventDefault();
var source = e.target.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src", source);
}
window.onload = function() {
"use strict";
var anchors = document.getElementsByTagName("a");
for(var i = 0, count = anchors.length; i < count; i++) {
anchors[i].onclick = showPic;
// Or you could use anchors[i].addEventListener('click',showPic);
}
}
Don't forget to remove what's in the HTML.
JS Fiddle Demo
On a side note
Void mentioned using addEventListener instead of onclick. Both are acceptable, with a difference to keep in mind:
This code:
element.onclick = func1;
element.onclick = func2;
Will result in func2 being called on click, but not func1. That is because it overwrites any previous .onclick statement on that precise element.
This code, however:
element.addEventListener('click',func1);
element.addEventListener('click',func2);
Will result in both func1 and func2 being executed, because they add up.

Best Way
Array.prototype.forEach.call(document.getElementsByTagName("a"), function(el){
el.addEventListener("click", function(event){
event.preventDefault();
showPic();
});
});

Related

How to save a list of "divs" to sessionStorage and display them when the user reloads the page?

I have an HTML page as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css" type="text/css">
<title>Test</title>
</head>
<body>
<div>
<p>Hello World!</p>
</div>
</body>
</html>
Then I have a JS file that listens for clicks of the enter key, and if the user clicks enter if adds another div.
//the event handler function
function captureEnterPress(event) {
if (event.key === "Enter" || event.keyCode === 13) {
event.preventDefault();
createNewDiv();
}
}
//creates the div
function createNewDiv() {
var body = document.body;
var div = document.createElement("div");
var p = document.createElement("p");
var labelText = document.createTextNode("Hello World!");
p.appendChild(labelText);
div.appendChile(p);
body.appendChild(div);
}
onload = () => {
document.documentElement.addEventListener("keyup", captureEnterPress);
}
I am trying to have the number of divs saved, so when the user reloads the page it shows the same amount of divs like he had before.
What I tried
I tried saving an array of all the divs to sessionStorage as follows:
var myStorage = window.sessionStorage;
var elementsArray = [];
//the event handler function
function captureEnterPress(event) {
if (event.key === "Enter" || event.keyCode === 13) {
event.preventDefault();
createNewDiv();
}
}
//creates the div
function createNewDiv() {
var body = document.body;
var div = document.createElement("div");
var p = document.createElement("p");
var labelText = document.createTextNode("Hello World!");
p.appendChild(labelText);
div.appendChile(p);
body.appendChild(div);
elementsArray[elementsArray.length] = div;
myStorage.setItem("storedPage", JSON.stringify(elementsArray));
}
onload = () => {
var storedPage = JSON.parse(myStorage.getItem("storedPage"));
if(storedPage){
event.preventDefault();
for(var i = 0; i < storedPage.length; i++){
document.body.appendChild(storedPage[i]);
console.log(storedPage)
}
}
document.documentElement.addEventListener("keyup", captureEnterPress);
}
I just logged it to the console to see what the values are, but they are empty. So I tried storing the div.innerHTML instead, but then if I try to append it to the document I get and error that it's a String and not a node.
I am out of ideas, and I am pretty new to the whole state storing concept in front-end development I would appreciate if somebody could tell me what is the right way to do it.
Thanks!
Not tested, but enough to illustrate
function createNewDiv() {
// create html content
const div = `<div><p>Hello World!</p></div>`;
// concat with body
document.body.innerHTML += div;
// save in array
elementsArray[elementsArray.length] = div;
// save in storage
myStorage.setItem("storedPage", JSON.stringify(elementsArray));
}
onload = () => {
var storedPage = JSON.parse(myStorage.getItem("storedPage"));
if(storedPage){
event.preventDefault();
// get stored content array and join by empty '' and add into body
document.body.innerHTML = storedPage.join('');
}
document.documentElement.addEventListener("keyup", captureEnterPress);
}
The problem I see in this code is that JSON.stringify is not able to convert DOM elements. Article on how to do this.
However, the better way is to save the innerHTML of some container, and then restore it.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css" type="text/css">
<title>Test</title>
</head>
<body>
<div id="div-container">
<div>
<p>Hello World!</p>
</div>
</div>
</body>
</html>
JS:
var myStorage = window.sessionStorage;
var elementsArray = [];
//the event handler function
function captureEnterPress(event) {
if (event.key === "Enter" || event.keyCode === 13) {
event.preventDefault();
createNewDiv();
}
}
//creates the div
function createNewDiv() {
var divContainer = document.getElementById("div-container");
const div = "<div><p>Hello World!</p></div>";
divContainer.innerHTML += div;
console.log(divContainer.innerHTML);
myStorage.setItem("storedPage", divContainer.innerHTML);
}
onload = () => {
var storedPage = myStorage.getItem("storedPage");
if(storedPage){
event.preventDefault();
var divContainer = document.getElementById("div-container");
divContainer.innerHTML = storedPage;
}
document.documentElement.addEventListener("keyup", captureEnterPress);
}
JSFiddle: https://jsfiddle.net/wLgh1ef8/1/
Edit:
You always can see the content of sessionStorage using DevTools
F12 -> Application tab -> Session Storage

How to call my main function of JS to my html?

I have nested function in function of JavaScript and I want to call it in my main function photoGallery() of my html code, but didn't work. Where I'm wrong ?
JavaScript:
function photoGallery1() {
kartinki = new Array('images/green_salad1.png', 'images/green_salad2.png', 'images/green_salad3.png');
index = 0;
function next() {
index++;
if ( index >= kartinki.length) index = 0;
document.getElementById('image2').src = kartinki[index];
}
function previous() {
index--;
if ( index < 0) index = kartinki.length -1;
document.getElementById('image2').src = kartinki[index];
}
function start() {
index = 0;
document.getElementById('image2').src = kartinki[index];
}
}
The HTML code:
<!Doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width">
<meta charset="utf-8">
<title>The right eating of employed people</title>
<link rel='stylesheet' media='screen and (max-width: 1000px)' href='css/narrow.css'/>
<link rel='stylesheet' media='screen and (min-width: 1001px) and (max-width: 1235px)' href='css/medium.css' />
<link rel='stylesheet' media='screen and (min-width: 1236px)' href='css/wide.css' />
<link rel="stylesheet" href="css/calendarview.css">
<script src="js/photogallery.js"></script>
<script src="js/prototype.js"></script>
<script src="js/calendarview.js"></script>
<script type="text/javascript">
window.onload = function() {
Calendar.setup({
parentElement : 'calendar'
})
window.onload = photoGallery1()
}
</script>
First:
window.onload = photogallery1();
Results in an undefined value for the window.onload property.
As #mrbinky3000 said, you need to call photogallery1() in your onload event handler.
Furthermore, you need an object with public methods in order to make this accessible from an outside scope, in which case you need a Constructor Function:
function Photogallery() {
// Don't forget the "var" directive to prevent these from being global
var kartinki = new Array('images/green_salad1.png', 'images/green_salad2.png', 'images/green_salad3.png');
var index = 0;
this.next = function () {
index++;
if ( index >= kartinki.length) index = 0;
document.getElementById('image2').src = kartinki[index];
}
this.previous = function () {
index--;
if ( index < 0) index = kartinki.length -1;
document.getElementById('image2').src = kartinki[index];
}
this.start = function () {
index = 0;
document.getElementById('image2').src = kartinki[index];
}
}
Now your onload changes a little:
var photoGallery = null;
window.onload = function () {
// the other stuff you had
photoGallery = new Photogallery();
}
Don't forget to declare the photoGallery variable to avoid it being an implicitly declared global variable.
Now a little HTML to call the methods on your object:
<button type="button" onclick="photoGallery.next()">Next</button>
<button type="button" onclick="photoGallery.previous()">Previous</button>
I think this is what you were going for. That window.onload = photoGallery1() inside of the window.onload callback made no sense to me.
window.onload = function() {
Calendar.setup({
parentElement : 'calendar'
});
photoGallery1();
}
This will call the photoGallery1() function when the window.onload event fires. There are a lot of issues, however, with your script. Lots of things to improve.
First of, you are assigning the executed photoGallery1() function to window.onload, so basically the result of photoGallery1(). You need to assign the function itself:
window.onload = photoGallery1;
In your function photoGallery1() there is no functions being executed or returned. When we refer to scope, it means where certain functions and variables is visible from.
If you look at the functions inside photoGallery1, they are inside the scope of photoGallery1 and can not be accessed or executed from the outer scope.
One possible solution would be to do:
function photoGallery1() {
function start() {
// do your things
}
// invoke function
start();
}
window.onload = photoGallery1;
Another is to expose some of your funnctions by returning some of the functions that you need:
function photoGallery1() {
function start() {
// do your things
}
function next(){};
function previous(){};
return {
start: start,
next: next,
previous: previous
}
}
// Execute your functions
var photoGallery = photoGallery1();
window.onload = photoGallery.start;
photoGallery1() should be instantiated
var Gallery = new photoGallery1();
Functions you declared in the body of photoGallery1() are private, so you have to attach them to events inside photoGallery1.
You can look at the function as the Class and Constructor in one. So use it accordingly.
I'm not exactly sure what you are trying to accomplish, but if it is a photo gallery like my common sense would indicate, then these three things may help.
Remove any superfluous information from your example, as it confuses the issue you are trying to solve. (f.e. the calendar.js and CSS stylesheet calls). This will allow others to help you in a more effective manner.
Separate your function from your form. It is generally good practice to use HTML strictly for the skeleton of the web page/app and keep the abilities of the skeleton (the functions the page/app can do) in the javascript. This is demonstrated in my example.
Instead of nesting functions try turning your "photogallery" into an object and assigning the "next", "previous", and "start" methods to the appropriate event. (In my example I assigned "next" and "previous to buttons and "start" to window.onload)
The External Javascript File: "photogallery.js"
/*
* Wrapping code in an iife is always good practice to prevent the pollution of the global
* name space.
*/
(function(){
/*
* Declare your array of images and index outside of the photoGallery1 object so the
* methods of photoGallery1 can cleanly reference them before photoGallery1 is initialized
* in the global execution context
*/
var kartinki = ['images/green_salad1.png', 'images/green_salad2.png', 'images/green_salad3.png'];
var index = 0;
var photoGallery1 = {
next: function (){
index++;
/*
* Here the index will never be greater than kartinki.length so check against
* (kartinki.lenghth - 1) or use index == kartinki.length
*/
if (index > (kartinki.length - 1)) { index = 0 };
document.getElementById('image2').src = kartinki[index];
},
previous: function() {
index--;
if ( index < 0) { index = kartinki.length - 1 };
document.getElementById('image2').src = kartinki[index];
},
start: function() {
document.getElementById('image2').src = kartinki[index];
}
}
/*
* Do the below inside an external javascript file rather than the html you can set the
* window object's onload property to an anonymous function, in which you can call any
* functions you want to happen when the page loads (i.e. photoGallery1.start() is called).
*/
window.onload = function(){
photoGallery1.start()
}
//Setting the "next" and "previous" methods to there corresponding buttons
document.getElementById('prev').onclick = photoGallery1.previous
document.getElementById('next').onclick = photoGallery1.next
})()
The HTML file: "index.html"
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>The right eating of employed people</title>
</head>
<body>
<img id="image2">
<button id="prev">Previous</button> <button id="next">Next</button>
<!-- Add the script tag at the bottom of the body so the browser can render the
html elements referenced in photogallery.js before they are needed. If you don't do
this document.getElementById("image2") will return null, as it has not been created
at the time of photogallery.js's execution.
-->
<script src="/photogallery.js"></script>
</body>
</html>
If you have any questions please don't hesitate to ask! :D
If I got, you want the 3 functions inside photoGallery1() to be called only when photoGallery1() is called. If it is the point, just call them at the end before to close.
function photoGallery1() {
kartinki = new Array('images/green_salad1.png', 'images/green_salad2.png', 'images/green_salad3.png');
index = 0;
function next() {
index++;
if ( index >= kartinki.length) index = 0;
document.getElementById('image2').src = kartinki[index];
}
function previous() {
index--;
if ( index < 0) index = kartinki.length -1;
document.getElementById('image2').src = kartinki[index];
}
function start() {
index = 0;
document.getElementById('image2').src = kartinki[index];
}
next();
previous();
start();
}
Thank you to all for the helping and tips! :) Already is working fine and how I wanted! Lastly I post the final codes.
HTML:
<!Doctype html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width">
<meta charset="utf-8">
<title>Правилното хранене на заетите хора</title>
<link rel='stylesheet' media='screen and (max-width: 1000px)' href='css/narrow.css'/>
<link rel='stylesheet' media='screen and (min-width: 1001px) and (max-width: 1235px)' href='css/medium.css' />
<link rel='stylesheet' media='screen and (min-width: 1236px)' href='css/wide.css' />
<link rel="stylesheet" href="css/calendarview.css">
<script src="js/photogallery.js"></script>
<script src="js/prototype.js"></script>
<script src="js/calendarview.js"></script>
<script type="text/javascript">
window.onload = function() {
Calendar.setup({
parentElement : 'calendar'
})
photoGallery = new Photogallery();
}
</script>
<body>
......
<p id="photogallery">
<img src="images/prev.png" border="0"><img src="images/home.png" border="0" onclick="photoGallery.start()"><img src="images/next.png" border="0">
</p>
....
</body>
</html>
JavaScript code:
function Photogallery() {
var kartinki = new Array('images/green_salad1.png', 'images/green_salad2.png', 'images/green_salad3.png');
var index = 0;
this.next = function () {
index++;
if ( index >= kartinki.length) index = 0;
document.getElementById('image2').src = kartinki[index];
}
this.previous = function () {
index--;
if ( index < 0) index = kartinki.length -1;
document.getElementById('image2').src = kartinki[index];
}
this.start = function () {
index = 0;
document.getElementById('image2').src = kartinki[index];
}
}
var photoGallery = null;
window.onload = function () {
photoGallery = new Photogallery();
}

Finding all anchors in a page and attaching functions without jquery

I'm working in a little app, mostly using jquery, everything is working fine but I'd like to rewrite every jquery part with plain javascript to fully understand what I'm doing.
I've read this previus post, and everything makes perfect sense but I can't get any code to run in my browser.
How to select all <a> tag and register onclick event?
This is my code:
<html>
<head>
<script type="text/javascript">
var a = document.getElementsByTagName('a');
var f = function () {alert('ok');}
for (var i = a.length - 1; i >= 0; i--) {
a[i].onClick = f;
}
</script>
</head>
<body>
test1
test2
</body>
</html>
In jquery I'd simply use this to find all anchors and run my function when clicked:
$('a').on('click',function (){
alert('ok');
});
Any thoughts?
thanks in advance, Gustavo
This is how I would do it:
var anchors = document.querySelectorAll("a"),
i;
for (i=0; i<anchors.length; i+=1) {
anchors[i].addEventListener("click", function() {
alert("triggered!");
});
}
test1
test2
Here's a shorter version if browser supports Array.prototype.forEach (most modern browsers do)
var anchors = document.querySelectorAll("a");
anchors.forEach(function(a) {
a.addEventListener("click", function() {
alert("triggered!");
});
});
test1
test2

Eventhandlers in a separate document

I'd like to keep all my JavaScripts in a separate document and I like it that way. Now I've had problems with the last bit of code to move from my HTML-code into my separate JavaScript document.
I got two eventhandlers that looked like this:
<a href="http://www.commercial.se" onclick="confirmLeave()" target="_blank">
and
<IMG SRC="folder/pic_small.jpg" alt="Description" onClick="view(this);">
This is the javascript code for the two eventhandlers:
function confirmLeave()
{
if(confirm("Vill du lämna Blomstermåla-Bladet?")) {
return true;
} else {
if(window.event) {
window.event.returnValue = false;
} else {
e.preventDefault();
}
return false;
}
}
And
function view(img) {
imgsrc = img.src.split("_")[0] + "_big.jpg";
viewwin = window.open(imgsrc,'viewwin', "width=790,height=444,location=0");
viewwin.focus();
}
I've managed to solve my problem of not having the javascript code in my HTML document for the first onClick eventhandler by changing my HTML to this:
<a href="http://www.commercial.com" id="external-link" target="_blank">
And adding this to my javascript document:
function init()
{
var link = document.getElementById("external-link");
link.onclick = confirmLeave;
}
window.onload = init;
I've tried adding a similar solution to the other eventhandler but I can't figure out the code I need to use for it to work. I would like to know how to add that event handler into the init function as well.
Try this
<a href="http://www.commercial.com" class="external-link" target="_blank">
<IMG SRC="folder/pic_small.jpg" alt="Description" id = "external-image">
function init() {
var link = document.getElementById("external-link");
var links = document.getElementsByClassName("external-link");
for (var i = 0; i < links.length; i++) {
links[i].onclick = confirmLeave;
}
var image = document.getElementById("external-image");
image.onclick = view;
}
window.onload = init;​
Instead of img in your function just use this
function view() {
imgsrc = this.src.split("_")[0] + "_big.jpg";
viewwin = window.open(imgsrc,'viewwin', "width=790,height=444,location=0");
viewwin.focus();
}
If you don't want to change the view function, you can do something similar, with the slight difference that you need to pass the image as an argument to the view function. You can do this by setting an anonymous function as the click handler.
<IMG SRC="folder/pic_small.jpg" alt="Description" id="some-img">
function init()
{
var img = document.getElementById("some-img");
img.onclick = function(){
view(this);
};
}

Calling a particular function when multiple events are bound

I have a site wide JS, which creates listeners for various events, but in certain conditions I need to call a particular function, like in code below, I need to call function call, but its not getting called.
<html>
<head>
<script>
window.onload = function ()
{
var inputs = document.getElementsByTagName("input");
var len = inputs.length;
for (var i=0; i < len; i++)
{
if (inputs[i].getAttribute("type") == "text")
{
var element = inputs[i];
element.onfocus = function()
{
var id = element.getAttribute("id");
alert(id);
}
}
}
}
function call(element)
{
element.value="";
}
</script>
</head>
<body>
<input type="text" name="myvar1" value="same content" id="noviceid" onfocus="call(this);">
<input type="text" name="myvar2" value="same content" id="noviceid" onfocus="call(this);">
</body>
</html>
Please suggest. I would like to call both onfocus. I am new to javascript.
So, once your page has loaded (with proper call onfocus handlers), you run window.onload that overwrites all these handlers. I guess it's not what you intended to do. Instead, you can use DOM2 events, if possible:
element.addEventListener("focus", function(event)
{
var id = event.target.getAttribute("id");
alert(id);
}, false);

Categories

Resources