I'm trying to change the appearance of my h1. I've done a part of the code but I noticed that it doesn't work in Chrome. Anyone know why? And if you have a suggestion how to better write the code below:
Link: http://codepen.io/Winterfox/pen/KzRbpZ
window.onload = function() {
var ownHeading = document.getElementById("heading");
var newHeading = document.getElementById("newheading");
ownHeading.addEventListener("input", buildLayout);
function buildLayout() {
newHeading.innerHTML = ownHeading.value;
};
/*---------------------------------------------------------*/
var changeStyleBtn = document.getElementsByClassName("changestyle-btn");
var changeStyleUl = document.getElementById('change-h-font');
for (var i = 0; i < changeStyleBtn.length; i++) {
changeStyleBtn[i].addEventListener('click', changeStyle, false);
}
function changeStyle() {
changeStyleUl.style.display = "block";
};
/*-------------------------------------------------------*/
var changeStyleLi = changeStyleUl.getElementsByTagName('li');
for (var i = 0; i < changeStyleLi.length; i++) {
changeStyleLi[i].addEventListener('click', changeFont, false);
}
function changeFont() {
// here it stops working in chrome (can't click on lis)
alert("clic");
console.log(this);
};
};
Issue appears to be with the ul element being embedded #changestyle-btn div
<div class="changestyle-btn">+
<ul class="changestyle" id="change-h-font">
<li>1</li>
<li>2</li>
</ul>
</div>
Once I move the element out of the div it works fine in Chrome.
<div class="changestyle-btn">+</div>
<ul class="changestyle" id="change-h-font">
<li>1</li>
<li>2</li>
</ul>
This is most likely because you have already bound a click event to the #changestyle-btn div so when you attempt to click the li element it is only firing the first event.
Related
I want to add button element to each list element (JavaScript).
This is my code. I used fro loop. In the output, only the last element of the list is getting the button element. What am I doing wrong.
function createButtonElement() {
var btn = document.createElement("button"); `
btn.appendChild(document.createTextNode("Delete Me"));
var a = document.querySelectorAll("li");
for(var v =0; v<a.length;v++)
{
a[v].appendChild(btn);
}
}
You created only one button and append it on the first <LI>, then you append it to the second <LI>... as he can't be on two different place this command move your button to the second place, and so on.
to duplicate élent you have to use the cloneNode method : https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode
sample code :
const MyList = document.querySelector('#My-List')
, AddButtons = document.querySelector('#Add-Buttons')
AddButtons.onclick=_=>
{
let newBt = document.createElement('button')
newBt.textContent = 'Delete Me'
document.querySelectorAll("#My-List li").forEach(eLI=>eLI.appendChild( newBt.cloneNode(true)) )
}
MyList.onclick=e=>
{
if (e.target.tagName.toLowerCase() !='button') return
let pLI = e.target.parentElement
MyList.removeChild(pLI)
}
<button id="Add-Buttons">Add Buttons to each element on list</button>
<ul id="My-List">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
PLUS
I added the way to deal with the click on the added buttons, via the event delegation
This behavior is documented in Node.appendChild() on MDN:
If the given child is a reference to an existing node in the document,
appendChild() moves it from its current position to the new position
(there is no requirement to remove the node from its parent node
before appending it to some other node).
Instead, instantiate a new button for each li within your loop:
function createButtonElement() {
var a = document.querySelectorAll("li");
for (var v = 0; v < a.length; v++) {
var btn = document.createElement("button");
btn.appendChild(document.createTextNode("Delete Me"));
a[v].appendChild(btn);
}
}
<li>a</li>
<li>b</li>
<li>c</li>
<button onclick="createButtonElement()">Click</button>
You need to create a new button for each item, otherwise the button just moves from item to item until you get to the last one.
function createButtonElement() {
var a = document.querySelectorAll("li");
for(var v =0; v<a.length;v++)
{
let btn = document.createElement("button");
btn.appendChild(document.createTextNode("Delete Me"));
a[v].appendChild(btn);
}
}
<button onclick="createButtonElement()">click</button>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
You need to create the button for each li element
function createButtonElement() {
var a = document.querySelectorAll("li");
for(var v =0; v<a.length;v++) {
var btn = document.createElement("button");
btn.appendChild(document.createTextNode("Delete Me"));
a[v].appendChild(btn);
}
}
I work on a website, and I have a js problem.
I resume the situation:
I made a dynamic form with some tabs in.
I can switch tabs with a js click function
When I click on the "+" tab , it creates a new tab ( new <li> on the <ul>, and new <div> on main div )
But when I want to go on the new tab freshly created, the click function don't answer.
I put a console.log on the first line of the click function, and no log output.
the click function works well with static content, but with fresh content don't work.
How can I make it works with dynamic content ?
http://jsfiddle.net/npx2mes2/
http://jsfiddle.net/npx2mes2/1/
$("#tabs_menu_n1").on('click', 'a', function(e)
the problem was on registering the event, you should attach it to parent first, and then on every child.
change the line $(".tabs_menu_n1 a").click(function(e) { to $(document).on('click', ".tabs_menu_n1 a", function (e) {
Demo
Explanation.
when the elements are being added to DOM dynamically you must register the for the events every time the element is added. So instead of doing this process every time simply register events like below, therefore you don't want to register the events fro dynamically created elements
$(document).on('click', ".selector", function (e) {));
Now i can add elements with selector class dynamically and can handle click event on the element without registering the click event every time i add the element.
Note: You can use parent selector in place of document
A bit simplified sample without jQuery.
But idea same: add click handler to ul and check inside that clicked a tag.
var x = 2;
var original = document.getElementById('H1_n1');
function a(content, href) {
var link = document.createElement("a");
link.textContent = content;
link.setAttribute('href', href);
return link;
}
function li_a(id, content, href) {
var listItem = document.createElement("li");
listItem.setAttribute('id', id);
listItem.appendChild(a(content, href));
return listItem;
}
function div(id, textContent) {
var d = document.createElement("div");
d.setAttribute('class', 'tab_content_n1')
d.setAttribute('id', id)
d.textContent = textContent;
return d;
}
function add_rec() {
var i = x++;
var mdiv = document.getElementById("tab_n1");
mdiv.appendChild(div('H1_n' + i, '\nHello world from n' + i + '.\n'));
pbtn = document.getElementById('pbtn');
var ul = document.getElementById("tabs_menu_n1");
ul.insertBefore(li_a("hn" + i, "H" + i, "#H1_n" + i), pbtn);
}
document.getElementById('tabs_menu_n1').addEventListener('click', function(e) {
var el = e.target;
if (el.nodeName !== 'A') return;
if (el.hash == "#+") add_rec();
else {
e.preventDefault();
var current = document.querySelectorAll("#tabs_menu_n1 .current, #tab_n1 .current");
for (var i = 0, len = current.length; i < len; i++) {
current[i].classList.remove('current');
}
el.classList.add('current');
document.querySelector(el.hash).classList.add('current');
}
}, false);
.tab_content_n1 {
display: none;
}
.tab_content_n1.current {
display: block;
animation: fadeIn 1s;
}
a.current {
color: red;
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
<div class="tab_space">
<ul id="tabs_menu_n1" class="nav nav-tabs tabs_menu_n1 tab_body">
<li><a class="current" href="#M_n1">mai</a>
</li>
<li>red
</li>
<li id="hn1">hor
</li>
<li id="pbtn">+
</li>
</ul>
</div>
<div id="tab_n1" class="tab_n1">
<div class="tab_content_n1 current" id="M_n1">mai</div>
<div class="tab_content_n1" id="R_n1">red</div>
<div class="tab_content_n1" id="H1_n1">hor</div>
</div>
I´ve just started to learn JavaScript and made a click function to change value of i depending on which li element is being clicked. Instead of having 3x of basically same function is it possible to send variable with addEventLisener to check with a if statement. Because if I add 1 or 2 more li it would add a lot of unnecessary code.
HTML:
<div><img src="image1" />
<ul>
<li id="list1">1</li>
<li id="list2">2</li>
<li id="list3">3</li>
</ul>
</div>
JavaScript:
var list1 = getElementById('list1');
var list2 = getElementById('list2');
var list3 = getElementById('list3');
list1.addEventListener("click", clicked1);
list2.addEventListener("click", clicked2);
list3.addEventListener("click", clicked3);
var i = 0;
function clicked1(){
i= 0;
loop();
}
function clicked2(){
i = 1;
loop();
}
function clicked3(){
i = 2;
loop();
}
function loop(){
if (i > 2){
i=0;
}
var imageloop = getElementById('slideshow').getElementsByTagName('img');
imageloop[0].src = 'image' + i;
i++
setTimeout(loop,3000);
}
So when one of the li element is being clicked it will change the img currently displaying.
Bind to the list, not the list item - <ul id="ul1">... :
document.getElementById('ul1').addEventListener('click', function (e) {
var li = e.target;
alert(li.id); // list1, list2, respectively, etc.
});
http://jsfiddle.net/seancannon/D6HX4/
As Teemu said, bind to the list and use e.target. Then, change i according to e.target.innerHTML (because for your purposes, that's easier since the innerHTML is similar to the id, but simpler).
Assuming the <ul> element now has an id of "list":
var list = document.getElementById("list");
var i = null;
list.addEventListener("click", function(e) {
window.i = parseInt(e.target.innerHTML, 10);
console.log(window.i);
});
You don't need Separate code for each <li>,
Here is How to do it in single function:
HTML:
<div>
<ul id="All_List">
<li id="list1">1</li>
<li id="list2">2</li>
<li id="list3">3</li>
</ul>
</div>
JavaScript:
var clicked_li=0; /* It'll store the number of <li> being clicked */
var ul=document.getElementById("All_List"); /* <ul> Element with all <li> */
window.onload=function(){
var lis=ul.getElementsByTagName("li"); /* All <li>'s from <ul> */
for(var i=0;i<lis.length;i++){
var li=lis[i]; /* Specific <li> from <ul> ie, lis[0] means first <li> of <ul> */
li.addEventListener("click", function(){ /* Listen and bind click event to that <li> */
clicked_li=getIndex(this); /* Store Which <li> Was clicked in clicked_li */
alert("'list"+clicked_li+"' was clicked!");
/* if you just want to get the id you can use event.target.id; instead of getIndex(); */
}, false);
}
};
function getIndex(node) {
var childs = node.parentNode.getElementsByTagName("li"); /* Get parent <ul> and all child <li> of that parent */
for (var i = 0; i < childs.length; i++) {
if (node == childs[i]) break; /* Find which <li> from current <ul> was clicked */
}
return (i+1); /* Return No.(index) of that <li> starting with 1 */
}
and here is the:
fiddle for the same.
Hope it'll help you. Cheers!
This is an "improve/clearer" of Vedant Terkar answer. Which may give a more clear aspect on
the answer he gave.
if we give ul id group. We dont need id for each of the list-item inside the ul.
<ul id="group">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
Javascript
var i=0;
we set i to be a global variable and equal to 0 assuming it will display image(0) if nothing else is called.
window.onload=function(){
var lis=document.getElementById("group").getElementsByTagName('li');
We are now creating a Nodelist which is called lis. Then we loop through the NodeList to se which list-element is being clicked at.
for(i=0;i<lis.length;i++){
var li=lis[i];
li.addEventListener("click",index, false);
}
}
function index(){
var lis = document.getElementById("group").getElementsByTagName('li');
i = getIndex(this);
for(var a=0; a < lis.length; a++){
if(a ==i){
lis[i].innerHTML = 'Choosen';
}else{
lis[a].innerHTML = 'list'+a;
}
}
}
function getIndex(node) {
var childs = node.parentNode.getElementsByTagName("li");
for (var i = 0; i < childs.length; i++) {
if (node == childs[i]) break;
}
return (i);
}
I have the div structure
<div id="navigate">
<div class="menu">
<div class="group">Mail</div>
<div class="item">Folders</div>
<div class="item">Messages</div>
</div>
<div class="menu">
<div class="group">Contacts</div>
<div class="item">Friends</div>
<div class="item">Work</div>
</div>
<div class="menu">
<div class="group">Setting</div>
<div class="item">General</div>
<div class="item">Account</div>
</div>
</div>
Right now all items are hidden, and only divs with class 'group' is shown. What I would like to do is if I mouse over a specific menu div, only items of that menu would appear.
Right now I have this code:
function initialise()
{
hideAllItems();
setMouseOvers();
}
function hideAllItems()
{
var nav = document.getElementById("navigate");
var items = nav.getElementsByClassName("item");
for(var i = 0; i < items.length; i++)
{
items[i].style.visibility = "hidden";
items[i].style.display = "none";
}
}
function setMouseOvers()
{
var nav = document.getElementById("navigate");
var menuArr = nav.getElementsByClassName("menu");
for(var x = 0; x < menuArr.length; x++)
{
var itemArrs = menuArr[x].getElementsByClassName("item");
/*var show = function(){ show(itemArrs); };
var hide = function(){ hide(itemArrs); };*/
menuArr[x].onmouseover=function(){ show(itemArrs); };
menuArr[x].onmouseout=function(){ hide(itemArrs); };
}
}
function show(itemArr)
{
for(var i = 0; i < itemArr.length; i++)
{
alert(itemArr[i].innerHTML);
itemArr[i].style.visibility = "visible";
itemArr[i].style.display = "block";
}
}
function hide(itemArr)
{
for(var i = 0; i < itemArr.length; i++)
{
itemArr[i].style.visibility = "hidden";
itemArr[i].style.display = "none";
}
}
And this works, thought it only displays General and Account no matter which menu I hover over. I vaguely understand whats going wrong, but I can't see anyway to fix it. Any ideas? I do not want to change the html structure (e.g. add ids, or create specific classes) if i can help it!
I know that you most probably are looking for a javascript solution, but you could use a simple CSS solution:
.group:hover ~ .item {
display: block;
}
Working Fiddle
But be aware that it is not supported by older IE (< 8) browsers SUPPORT. It depends on your target group if you want to use it.
Why not simply using CSS: DEMO
.menu .item{
display:none;
}
.menu:hover .item{
display:block;
}
As you ask for an JavaScript Only solution (no change in HTML/css) i suggest the following:
The problem is using "itemArrs" in an anonymous function, as only the latest written "itemArrs" is used for all of them, use "this" instead.
for example:
...
groups[x].onmouseover=function(){ show(this); };
...
and
function show(item) {
var items = item.parentNode.getElementsByClassName("item");
...
A complete JS-only solution that works can be found here:
http://jsfiddle.net/Wn4d4/3/
i have a page around 500 div as below.
<div onclick='test()' class='test>
<ul class='innermenu'>
<li>1</li>
.....
</ul>
</div>
when the test function is called it need to hide the menu (innermenu) who calls that function.
my problems are
uniquely identify the div without using id
How to hide only the particular ul alone.
OK, first the quick fix, though it is not the best way to use JS on your page:
Change the call to this:
<div onclick="test(this);" class="test">
Then, in test, use this:
function test(el){
var uls = el.getElementsByTagName('ul');
for(var i = 0; i < uls.length; i++){
if(uls[i].className == 'innermenu'){
uls[i].style.display = "none";
break;
}
}
}
This will hide just the child ul of the div that is clicked.
A better way
OK, for the longer answer. Either attach the events after the fact using attachEvent and addEventListener or use a library like jQuery to help you out. Here is the raw solution:
Set up your HTML this way (no onclick):
<div class="test">
And then at the very end of your HTML put this:
<script type="text/javascript">
var divs = document.getElementsByTagName('div');
function test(){
var uls = this.getElementsByTagName('ul');
for(var i = 0; i < uls.length; i++){
if(uls[i].className == 'innermenu'){
uls[i].style.display = "none";
break;
}
}
};
for(var i = 0; i < divs.length; i++){
var div = divs[i];
if(div.className !== "test") continue;
if(window.addEventListener){
div.addEventListener( 'click', test, true ); //FF, Webkit, etc
} else if (window.attachEvent) {
div.attachEvent('onclick', test); // IE
} else {
div.onclick = test; // Fallback
}
}
</script>
Now, you don't have JavaScript code in your HTML, and you can get rid of the extra parameter on the test function.
There is a method
document.getElementsByClassName
but it isn't supported in all browsers.
javascript
function test(elem)
{
var childElem = elem.children[0];
childElem.style.display = 'none';
}
<div onclick='test(this)' class='test'>
<ul class='innermenu'>
<li>1</li>
<li>2</li>
</ul>
</div>
If you can use jQuery then you can do something like this
$("div.test").click(function(){
$(this).find("ul.innermenu").hide();
});
If you don't want assign ids, you can try this to hide the div which gets clicked:
<div onclick="hideMe(this);" class='test>
<script>
function hideMe(elem)
{
elem.style.display = 'none';
}
</script>
Try passing "this" as parameter:
<div onclick='test(this)' class='test>
<ul class='innermenu'>
<li>1</li>
.....
</ul>
function test(sender) {
//sender is DOM element that is clicked
alert(sender.id);
}
If getElementsByClassName is not supported by all browsers as mentioned by #rahul, you can iterate through the dom and find it yourself - provided there is only one <ul> with class name "innermenu"
var uls = document.body.getElementsByTagName("ul");
var len = uls.length;
for(var i = 0; i < len; i++)
{
var ul = uls.item(i);
if(ul.getAttribute("class") == "innermenu")
{
ul.style.display = "none";
break;
}
}