Attaching event handler to DOM elements - javascript

I am working on a tic tac toe game, which is almost complete. The only thing I am left wondering about is if it is possible to add an event handler for onclick from my .js file instead of directly calling it from an HTML attribute. Here is the bit of HTML that uses the onclick:
<div id="left">
<div id="board">
<div id="one" onclick="playerMove(this)">
</div>
<div id="two" onclick="playerMove(this)">
</div>
<div id="three" onclick="playerMove(this)">
</div>
<div id="four" onclick="playerMove(this)">
</div>
<div id="five" onclick="playerMove(this)">
</div>
<div id="six" onclick="playerMove(this)">
</div>
<div id="seven" onclick="playerMove(this)">
</div>
<div id="eight" onclick="playerMove(this)">
</div>
<div id="nine" onclick="playerMove(this)">
</div>
</div>
</div>
Any thoughts on the matter would be greatly appreciated.

If you use jQuery something like this should work:
$(document).ready(function() {
$('#board div').click(playerMove);
});

In plain javascript (no cross platform libraries), event handlers can be added via javascript code with addEventListener (modern browsers) or attachEvent (older versions of IE).
Here's a simple function that adds an event handler in a cross browser fashion:
// add event cross browser
function addEvent(elem, event, fn) {
if (elem.addEventListener) {
elem.addEventListener(event, fn, false);
} else {
elem.attachEvent("on" + event, function() {
// set the this pointer same as addEventListener when fn is called
return(fn.call(elem, window.event));
});
}
}
Example usage (called after the page DOM has loaded):
addEvent(document.getElementById("one"), 'click', playerMove);
Or, to install event handlers for all the board divs, you could do this:
var divs = document.getElementById("board").children;
for (var i = 0, len = divs.length; i < len; i++) {
// element nodes only
if (divs[i].nodeType === 1) {
addEvent(divs[i], 'click', playerMove);
}
}

You should really consider using jQuery for this. If you were using jQuery, this would have been as simple as:
$('#board > div').click(playerMove);
In case you want to stick with vanilla JS, you can do:
var items = document.getElementById('board').children;
for(x in items) {
items[x].onclick = function() {
playerMove(items[x]);
};
}

Use this:
document.getElementById('element_id').onclick = function(){ playerMove(this); };
For each Div, change 'element_id' with 'one', 'two', ...

Try:
document.getElementById('one').onclick();
For binding the event handler in js file:
var board = document.getElementById('board'),
divs = board.getElementsByTagName('div'),
i, len = divs.length;
for (i = 0; i < len; i++) {
divs[i].onclick = function() {
playerMove(this);
};
}

Your answer is in following 5 lines. Try it :) If someone copies/converts my code in new post or my post to j-query, That is welcome with no problem.
var yourDivID = document.getElementById('your_Div_ID');
yourDivID.addEventListener('click', function (){ playerMove(this); }, false);
function playerMove(divElement)
{
alert(divElement.id);
}
I have tried to put complete demo Here on jsfiddle.net, You can click any div out of nine to check its event if link does not work, then you can check the following code (working for me WIN7 and FireFox)
<html>
<head>
<title> Add Events Dynamically </title>
<script type="text/javascript">
function add_DivClick_Events() {
var nodes = document.getElementById('board').childNodes;
for (var i = 0; i < nodes.length; i++) {
if (i % 2 == 1) {
nodes[i].addEventListener('click', function () {
playerMove(this);
}, false);
}
}
}
function playerMove(divElement)
{
alert(divElement.id);
}
</script>
<style type="text/css">
#board div
{
width:20px;
height:20px;
border:2px solid;
}
</style>
</head>
<body onload='add_DivClick_Events()'>
<div id="left">
<div id="board">
<div id="one">
</div>
<div id="two">
</div>
<div id="three">
</div>
<div id="four">
</div>
<div id="five">
</div>
<div id="six">
</div>
<div id="seven">
</div>
<div id="eight">
</div>
<div id="nine">
</div>
</div>
</div>
</body>
</html>

Related

How do I remove a specific div out of many using one function in JavaScript?

I'm learning JavaScript and this is a practice scenario for me.
What I have already is a button that clones content, and within that content that has been cloned, there is a button to remove it.
When I click the button that prompts you to remove the content, it removes the first set of content.
What I want to happen is when you click the button that prompts you to remove the content, it removes the content related to that button and nothing else.
This is the CodePen link.
https://codepen.io/JosephChunta/pen/YzwwgvQ
Here is the code.
function addContent() {
var itm = document.getElementById("newContent");
var cln = itm.cloneNode(true);
document.getElementById("placeToStoreContent").appendChild(cln);
}
function removeContent() {
var x = document.getElementById("content").parentNode.remove();
}
// This is for debug purposes to see which content is which
document.getElementById('orderContent')
.addEventListener('click', function(e) {
const orderedNumber = document.querySelectorAll('.thisIsContent');
let i = 1;
for (p of orderedNumber) {
p.innerText = '' + (i++);
}
});
.contentThatShouldBeHidden {
display: none;
}
<div id="placeToStoreContent">
</div>
<button id="orderContent" onclick="addContent()">Add Content</button>
<div class="contentThatShouldBeHidden">
<div id="newContent">
<div id="content">
<p class="thisIsContent">This is a prompt</p>
<button onclick="removeContent()">Remove this</button>
<hr />
</div>
</div>
</div>
When you'r trying to remove by ID, it takes the first ID it finds.
To remove the correct content, send this onclick.
<button onclick="removeContent(this)">Remove this</button>
And handle it in your function:
function removeContent(el) {
el.parentNode.remove();
}
Example:
function addContent() {
var itm = document.getElementById("newContent");
var cln = itm.cloneNode(true);
document.getElementById("placeToStoreContent").appendChild(cln);
}
function removeContent(el) {
el.parentNode.remove();
}
// This is for debug purposes to see which content is which
document.getElementById('orderContent')
.addEventListener('click', function(e) {
const orderedNumber = document.querySelectorAll('.thisIsContent');
let i = 1;
for (p of orderedNumber) {
p.innerText = '' + (i++);
}
});
.contentThatShouldBeHidden { display: none; }
<div id="placeToStoreContent">
</div>
<button id="orderContent" onclick="addContent()">Add Content</button>
<div class="contentThatShouldBeHidden">
<div id="newContent">
<div id="content">
<p class="thisIsContent">This is a prompt</p>
<button onclick="removeContent(this)">Remove this</button>
<hr />
</div>
</div>
</div>
In your remove button, do this:
<!-- The "this" keyword is a reference to the button element itself -->
<button onclick="removeContent(this)">Remove this</button>
And in your javascript:
function removeContent(element) {
element.parentNode.remove();
}

How to loop and set inner content of DOM elements in jQuery and JavaScript?

I'm trying to loop through divs and set the content of a div inside the outer div. I tried this.
Here is the HTML div's I want to loop through and I want to set the content of div with class content-detail with the value for its attribute data-form data.
//the javascript code I used is this
$(function($) {
for (var i of $(".item .content-detail")) {
var container = document.querySelector($(i)[0]);
var formData = $(i).attr("data-formdata");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<div class="item">
<div class="down-div"> </div>
<div class="detail">
<h4>Detail</h4>
<div id="div_" class="content-detail" data-formdata="my Item">
</div>
<div class="text-center">
<button class="btn btn-blue center"> SET !</button>
</div>
</div>
</div>
<div class="item">
<div class="down-div"> </div>
<div class="detail">
<h4>Detail</h4>
<div id="div_" class="content-detail" data-formdata="my Item">
</div>
<div class="text-center">
<button class="btn btn-blue center"> SET !</button>
</div>
</div>
</div>
But am stuck at this point var container = document.querySelector($(i)[0]);
I don't know how to get the jquery selector of that current div to a variable.
This may need some tweaks, but it should be close...
$(function ($) {
$(".item .content-detail").each(function(index, element) {
element.text($(element).attr("data-formdata"))
})
});
Take a look at the .each() method
$(function($) {
for (var i of $(".item .content-detail")) {
//var container = document.querySelector($(i)[0]);
var container = i;
var formData = $(i).attr("data-formdata");
}
});
I just needed the element
If you want to set the content of each DIV, you don't need a for loop. The .text() method takes a callback function, and it will be called on each element that matches the selector. The returned value is used as the new content.
$(".item .content-detail").text(function() {
return $(this).data("formdata");
});
This works.
$(function($) {
$(".item .content-detail").text(function(){
return $(this).attr("data-formdata");
})
});
Can you not just use JS like this:
[UPDATED]
function test() {
var divs = document.getElementsByTagName("div");
for (var i = 0; i < divs.length; i++) {
var divsSub = divs[i].getElementById("div_").querySelectorAll(".content-detail");;
for (var iS = 0; iS < divsSub.length; iS++) {
var x = divsSub[iS].getAttribute("data-formdata");
divsSub[iS].innerHTML = x;
}
}
}

How do you properly write onclick events in JavaScript?

I'm trying to use an onclick event with an anchor tag that will change the innerHTML of another element on the page. I'm not sure what I'm doing wrong, so all the code I'm using is below. I hope you guys can point out my mistake and tell me what it was I misunderstood. The JavaScript file is included after the body, but you can see that on the JSfiddle here. So, when I click Settings, I want the BookmarkList div to show it's own HTML code, and the same for Home. The BookmarkList div will be the center of attention for this site. I'm just not sure what I'm doing wrong for this.
HTML:
<body id="bodyBG">
<div class="wrapper">
<div class="box header">
Header
</div>
<div class="box content">
<div class="box subcontent1">
<div class="sdfgsdfgsdfg"><input id="categoryName" placeholder="Category Name"></input></div>
<div class="sdfgsdfg"><input id="urlLink" placeholder="Site Address"></input></div>
<div class="sdfgsddfg"><input id="bookmarkName" placeholder="Bookmark Name"></input></div>
<div><button>Save</button></div>
<hr>
<input placeholder="Search Bookmarks"></input>
<button>Search</button>
</div>
<div class="box subcontent2">
Settings
<hr>
Home
Back
Forwards
</div>
<div id="bookmarkList" class="box subcontent3 bookmark-list">
</div>
</div>
<div class="box footer">Footer</div>
</div>
<script src="assets/js/bookmark-action-script.js"></script>
</body>
JavaScript:
var settingsNav = document.getElementById('settingsNav');
var homeNav = document.getElementById('homeNav');
var changeThis = document.getElementById("bookmarkList");
function myFunction(this) {
if (this === settingsNav) {
changeThis.innerHTML = "<h3>Bookmarks</h3><hr>";
}
else if (this === homeNav) {
changeThis.innerHTML = "<h3>Bookmarks</h3><hr><p>Store all your bookmarks here!</p><ul><li>An secure storage means for your privacy needs!</li><li>24/7 Availability</li></ul>";
}
else (this != settingsNav | homeNav) {
changeThis.innerHTML = "Nothing to see here!";
}
};
document.getElementById("settingsNav").addEventListener("click");
document.getElementById("homeNav").addEventListener("click");
The Solution:
I always add the solution that was appropriate for my problems, so future observers can see what issue I had and what the solution was. My issue was not adding the function to my eventlistener. You do not need to specify onclick events inside the HTML code if you specify event listeners with accompanying functions in your JavaScript code. But without the functions tied to the eventlisteners, nothing will happen. I understand that now.
var settingsNav = document.getElementById('settingsNav');
var homeNav = document.getElementById('homeNav');
var changeThis = document.getElementById("bookmarkList");
function myFunction(event) {
var el = this;
if (el === settingsNav) {
changeThis.innerHTML = "<h3>Bookmarks</h3><hr>";
} else if (el === homeNav) {
changeThis.innerHTML = "<h3>Bookmarks</h3><hr><p>Store all your bookmarks here!</p><ul><li>A secure storage means for your privacy needs!</li><li>24/7 Availability</li></ul>";
} else if (el != settingsNav || homeNav) {
changeThis.innerHTML = "Nothing to see here!";
}
};
document.getElementById("settingsNav").addEventListener("click", myFunction);
document.getElementById("homeNav").addEventListener("click", myFunction);
Remove attribute event handlers from HTML. Change function (this) to function (event). You did not add an event handler at.addEventListener()call, where you can passmyFunction` as a reference to to function to call when event is dispatched.
OR in JavaScript should be || instead of | at second else..if
Note, <input> element is self-closing, </input> is invalid HTML.
<body id="bodyBG">
<div class="wrapper">
<div class="box header">
Header
</div>
<div class="box content">
<div class="box subcontent1">
<div class="sdfgsdfgsdfg"><input id="categoryName" placeholder="Category Name"></div>
<div class="sdfgsdfg"><input id="urlLink" placeholder="Site Address"></div>
<div class="sdfgsddfg"><input id="bookmarkName" placeholder="Bookmark Name"></div>
<div><button>Save</button></div>
<hr>
<input placeholder="Search Bookmarks">
<button>Search</button>
</div>
<div class="box subcontent2">
Settings
<hr>
Home
Back
Forwards
</div>
<div id="bookmarkList" class="box subcontent3 bookmark-list">
</div>
</div>
<div class="box footer">Footer</div>
</div>
<script>
var settingsNav = document.getElementById('settingsNav');
var homeNav = document.getElementById('homeNav');
var changeThis = document.getElementById("bookmarkList");
function myFunction(event) {
var el = this;
if (el === settingsNav) {
changeThis.innerHTML = "<h3>Bookmarks</h3><hr>";
} else if (el === homeNav) {
changeThis.innerHTML = "<h3>Bookmarks</h3><hr><p>Store all your bookmarks here!</p><ul><li>An secure storage means for your privacy needs!</li><li>24/7 Availability</li></ul>";
} else if (el != settingsNav || homeNav) {
changeThis.innerHTML = "Nothing to see here!";
}
};
document.getElementById("settingsNav").addEventListener("click", myFunction);
document.getElementById("homeNav").addEventListener("click", myFunction);
</script>
</body>
Your code works fine in Chrome by fixing couple of syntax errors.
update else to else if
else if (clk != settingsNav | homeNav)
update this parameter to something else in myFunction
function myFunction(clk)
no need to add event since you called myFunction in onclick, so remove:
document.getElementById("settingsNav").addEventListener("click");
document.getElementById("homeNav").addEventListener("click");
Somehow it didn't work in jsfiddler.

looking for a good pratice to hide and display some divs

Hello everybody I would like to hide some divs and display others when I click on a specifiks links.
Actually I did like this :
<html>
<head>
<script>
function loadA(){
document.getElementById("A").style.display="block";
document.getElementById("B").style.display="none";
document.getElementById("C").style.display="none";
document.getElementById("D").style.display="none";
}
function loadB(){
document.getElementById("A").style.display="none";
document.getElementById("B").style.display="block";
document.getElementById("C").style.display="none";
document.getElementById("D").style.display="none";
}
function loadC(){
document.getElementById("A").style.display="none";
document.getElementById("B").style.display="none";
document.getElementById("C").style.display="block";
document.getElementById("D").style.display="none";
}
function loadD(){
document.getElementById("A").style.display="none";
document.getElementById("B").style.display="none";
document.getElementById("C").style.display="none";
document.getElementById("D").style.display="block";
}
</script>
</head>
<body>
<div class="menu">
A
B
C
D
</div>
</body>
</html>
This is work with me but as you see it's not a good practice and sure there is another way better than this , can you show me please !
A solution without javascript:
.container > div{
display:none
}
.container > div:target{
display:block
}
<div class="menu">
<a href="#A" >A</a>
<a href="#B" >B</a>
<a href="#C" >C</a>
<a href="#D" >D</a>
</div>
<div class="container">
<div id="A" >A content</div>
<div id="B" >B content</div>
<div id="C" >C content</div>
<div id="D" >D content</div>
</div>
https://developer.mozilla.org/en-US/docs/Web/CSS/%3Atarget
https://css-tricks.com/css3-tabs/
You can create one function and reuse it for each element:
function loadDiv(id){
document.getElementById("A").style.display="none";
document.getElementById("B").style.display="none";
document.getElementById("C").style.display="none";
document.getElementById("D").style.display="none";
document.getElementById(id).style.display="block";
}
And pass the correct id into each onclick:
<div class="menu">
A
B
C
D
</div>
Here's how you should do it. No inline javascript, handling click events with an eventListener and wrapping all elements together with a class, making it much less code to write and maintain:
JS:
function divLoader(e){
var hide = document.getElementsByClassName("hideAndShow");
for (var i = 0; i<hide.length;i++) {
hide[i].style.display="none";
}
document.getElementById(e.target.getAttribute('data-link')).style.display="block";
}
var anchors = document.querySelectorAll('.menu > a');
for (var i = 0; i<anchors.length; i++) {
anchors[i].addEventListener('click',divLoader);
}
HTML:
<div class="menu">
A
B
C
D
</div>
<div id="A" class="hideAndShow" style="display:none;">A</div>
<div id="B" class="hideAndShow" style="display:none;">B</div>
<div id="C" class="hideAndShow" style="display:none;">C</div>
<div id="D" class="hideAndShow" style="display:none;">D</div>
In such cases where you have similar repetitive code you can use a common technique called "Abstraction". The main idea is the turn the common code into parameters of a single function in your case it would be:
function loadByID(id){
document.getElementById("A").style.display="none";
document.getElementById("B").style.display="none";
document.getElementById("C").style.display="none";
document.getElementById("D").style.display="none";
document.getElementById(id).style.display="block";
}
However this is also still a little bit redundant, for larger menus and displaying multiple links you can do something like
function loadByIDs(ids){
var links = document.getElementsByTagName("a");
for(var i = 0; i < links.length; i++){
document.getElementById(links[i].id).style.display = none;
}
for each(var id in ids){
document.getElementById(id).style.display = block;
}
}
This will work much better when you have too much links and want to display more than one link at a time (so you will need to pass in an array)
Note: If you are using Jquery you can just use .each() function to get rid of the first for loop
Hope this helps!
I think the best practice in your case is to define a general function that work however the number of links with specific class in my example the class is link, take a look at Working Fiddle.
Now your script will work with dynamic links added in div, you have just to add html without touching the js will detect change.
HTML :
<div class="menu">
A
B
C
D
</div>
JS :
load = function(e){
//select all links
var links = document.getElementsByClassName('link');
//Hide all the links
for (i = 0; i < links.length; i++) {
links[i].style.display = "none";
}
//Show clicked link
e.target.style.display = "block";
}
Hope this make sens.
HTML
<body>
<div id="main">
<ul id="nav">
<li>Home</li>
<li>About Us</li>
</ul>
<div id="container">
<div id="wrapper">
<div class="content">
<div id="menu_home">
<h2>Menu 1</h2>
</div>
<div id="menu_about">
<h2>Menu 2</h2>
</div>
</div><!--content-->
</div><!--wrapper-->
</div><!--container-->
</div><!-- main-->
</body>
JS
$(document).ready(function(){
$("#menu_home").slideUp("fast");
$("#menu_about").slideUp("fast");
$("#menu_home").show();
$("#nav a").click(function(){
var id = $(this).attr('id');
id = id.split('_');
$(".content div").slideUp("fast");;
$(".content #menu_"+id[1]).slideToggle("fast");
});
});
Here is the example
function loadA()
{
document.getElementById("A").style.visiblity="show";
document.getElementById("B").style.visiblity="hide";
document.getElementById("C").style.visiblity="hide";
document.getElementById("D").style.visiblity="hide";
}
if visibility dont work,just change the visibility keyword with visible and hide with hidden.
and one more thing,u should not write function for each div..what can u do just pass id of a div which u want to show and hide others..see below
function trigger(id)
{
var alldiv={"A","B","C","D"};
for(i=0;i<alldiv.length;i++)
{
if(alldiv[i]==id)
document.getElementById(id).style.visiblity="show";
else
document.getElementById(alldiv[i]).style.visiblity="hide";
}
}

is it possible to hide div when another button is click?

I am trying to hide the div's when different buttons are clicked but I don't know how to. (So when 'Test 1' is clicked it should hide 'Test 2' Div and vice versa) I checked here and on Google but couldn't find an answer for it.
Javascript :
function showHide(divId) {
var theDiv = document.getElementById(divId);
if (theDiv.style.display == "none") {
theDiv.style.display = "";
} else {
theDiv.style.display = "none";
}
}
HTML :
<input type="button" onclick="showHide('hidethis')" value="Test It">
<div id="hidethis" style="display:none">
<h1>TEST ME!</h1>>
</div>
<input type="button" onclick="showHide('hidethis2')" value="Test It 2">
<div id="hidethis2" style="display:none">
<h1>TEST MEEEEEEEEEEEEEEE 2!</h1>
</div>
JSFIDDLE: is not doing it here but works locallyhttp://jsfiddle.net/S5JzK/
<input type="button" onclick="showHide('hidethis')" value="Test It" />
<div id="hidethis" style="display:none">
<h1>TEST ME!</h1>
</div>
<input type="button" onclick="showHide('hidethis2')" value="Test It 2">
<div id="hidethis2" style="display:none">
<h1>TEST MEEEEEEEEEEEEEEE 2!</h1>
</div>
function showHide(divId) {
$("#"+divId).toggle();
}
Check the Fiddle http://jsfiddle.net/S5JzK/7/
Please try this, it works well and so simple,
<html>
<head>
<style>
.manageDiv{
display:none;
}
</style>
</head>
<body>
<input type="button" class="testButton" value="Test It" />
<input type="button" class="testButton" value="Test It 2" />
<div id="hidethis2" class="manageDiv">
<h1>TEST MEEEEEEEEEEEEEEE 2!</h1>
</div>
</body>
</html>
$(function(){
$(".testButton").on("click", function(){
$("#hidethis2").toggleClass("manageDiv");
});
});
To it work in fiddle, in your example, you need to select (No wrap - in head) on the left.
Look the example below, using pure javascript:
HTML
<input type="button" onclick="showHide('hidethis')" value="Test It">
<div id="hidethis" style="display:none">
<h1>TEST ME!</h1>
</div>
<input type="button" onclick="showHide('hidethis2')" value="Test It 2">
<div id="hidethis2" style="display:none">
<h1>TEST MEEEEEEEEEEEEEEE 2!</h1>
</div>
JAVASCRIPT
function showHide(divId) {
/* Hide all divs */
var elements = document.getElementsByTagName('div');
for (var i = 0; i < elements.length; i++) {
elements[i].style.display = "none";
}
/* Set display */
var theDiv = document.getElementById(divId);
theDiv.style.display = "";
}
http://jsfiddle.net/S5JzK/9/
ANOTHER JAVASCRIPT EXAMPLE
function showHide(divId) {
/* Hide the divs that you want */
var div1 = document.getElementById('#hidethis');
var div2 = document.getElementById('#hidethis2');
div1.style.display = "none";
div2.style.display = "none";
/* Set display */
var theDiv = document.getElementById(divId);
theDiv.style.display = "";
}
Using JQuery:
function showHideDiv(divId, bShow) {
if (bShow) {
$("#" + divId).show();
} else {
$("#" + divId).hide();
}
}
your code seems fine. are you sure you enter the function upon click? try adding a breakpoint using developer tools or an alert.
Anyways, I see you tagged this post with jquery. you can you it to do the task more elegantly.
$("#" + theDiv).hide();
or for showing it:
$("#" + theDiv).show();
"JSFIDDLE: is not doing it here but works locally"
Yes, because by default jsfiddle wraps your JS in an onload handler, which means the function declaration is local to that handler. Inline html attribute event handlers like your onclick="showHide('hidethis')" can only call global functions.
Under jsfiddle's Frameworks & Extensions heading there's a drop-down where you can change the default "onload" to "No wrap - in head" (or "No wrap - in body"). That'll make your function declaration global as in your local implementation.
Demo: http://jsfiddle.net/S5JzK/8/

Categories

Resources