Click event for dynamically generated elements on listview - javascript

I tried to apply click event to elements dynamically generated.
This example is work well. http://jsfiddle.net/PzSYM/361/
But my code does not work. http://jsfiddle.net/EurT4/8/
This is same code with above link.
HTML
<ul id="timer_listview" data-role="listview">
<li class="timerList">
<button>on</button>
<span class='status'>play</span>
</li>
<li class="timerList">
<button>on</button>
<span class='status'>play</span>
</li>
<li class="timerList">
<button>on</button>
<span class='status'>play</span>
</li>
</ul> </div>
JavaScript(Jquery)
var counter = 0;
$('#addButton').click(function () {
$('#console').text('new line added');
var text = '<li class="timerList"><button>new' + (++counter) + '</button><span class="status">play</span></li>';
$('#timer_listview').prepend(text);
$('#timer_listview').listview("refresh");
});
var play = 'play';
$('.timerList').on('click', 'button', function () {
$('#console').text('clicked');
var status = $(this).parent().find('span.status');
if (status.text() == play) {
status.text('pause');
$('#console').text('Status Changed');
}
});
CSS
.status {
display: none; }
I got a panic why it does not work. :(
Thank you for reading my question.
p.s Anytime welcome to edit my writing.
UPDATE
I solved this problem. http://jsfiddle.net/EurT4/10/ .
The point is using closest parent.
Thanks to Milind Anantwar.

You are adding elements .timerList dynamically. You need to use:
$('#timer_listview').on('click', '.timerList', function() {
$('#console').text('clicked');
var status = $(this).parent().find('span.status');
if (status.text() == play) {
status.text('pause');
$('#console').text('Status Changed');
}});

<script>
function onclickButton(e)
{
alert(e+"Clicked");
}
</script>
<button onclick="onclickButton(1)">Button1</button>
<button onclick="onclickButton(2)">Button2</button>
<button onclick="onclickButton(3)">Button3</button>
<button onclick="onclickButton(4)">Button4</button>

Related

Trouble with to-do list close button

I have some code that seems to be working, but in a rather odd fashion. When I first refresh the page I have the close button that seems to work fine, but when I make a new to-do list item the close button seems to cease working and I can't pinpoint why.
let addItem = document.getElementById("submitButton");
let userInput = document.getElementById("toDoInput");
let output = document.getElementById("output");
let toDoItem = document.querySelector(".toDoItem");
let close = document.querySelector(".close");
let toDo = document.querySelector(".todo");
/*User clicked the addItem Button
If there is any text inside the text field then add that text to the todo list */
addItem.addEventListener("click", addToDo);
function addToDo(){
var html = `
<ul class="todo">
<li class="toDoItem">
<p>${userInput.value}</p>
<div class="close">X</div>
</li>
</ul>
`;
output.innerHTML += html;
// Resetting input to blank once a submit button has been added.
userInput.value = '';
}
// Figure out how to make closing functionality simple this implementation
// isn't working
close.addEventListener("click", function(e){
console.log("clicked");
let x = e.target.parentElement;
x.style.display = "none";
e.preventDefault();
});
<header>
<input type="text" placeholder="Enter Item Here..." id="toDoInput">
<button id="submitButton">+</button>
</header>
<section id="output">
<ul class="todo">
<li class="toDoItem">
<p>Clean Room!</p>
<div class="close">X</div>
</li>
</ul>
</section>
<script src="todo.js"></script>
I'm also not sure if I'm using best practice as I'm new to web development, so any tips would be thoroughly appreciated as well!
You need a live event handler on your close button(s). This example should help. To offer something more, it's easier and more straight forward to use jQuery for it if you can and don't mind using a JS library.
jQuery example:
$(document).on("click", ".close", function() {
$(this).parent().hide();
});
No need to prevent default behavior since it's a div.
The issue here is that when you re-render the content of the "output" section you lose the event listener bound to the original ".close" element. A few options to work around the issue, have a look at this thread for some examples.
You got pretty close man, and you definitely do not need jQuery.
As you can see below, you don't need to push the <ul> dynamically. It will never change!
<header>
<input type="text" placeholder="Enter Item Here..." id="toDoInput">
<button id="submitButton">+</button>
</header>
<section id="output">
<ul class="todo">
</ul>
</section>
And here is your refactored javascript:
let addItem = document.getElementById("submitButton");
let userInput = document.getElementById("toDoInput");
let output = document.getElementById("output");
let toDoItem = document.querySelector(".toDoItem");
let toDo = document.querySelector(".todo");
/*User clicked the addItem Button
If there is any text inside the text field then add that text to the todo
list */
addItem.addEventListener("click", addToDo);
function addToDo(e){
e.preventDefault();
var html = `<li class="toDoItem">
<p>${userInput.value} </p> <p class="close"
onclick="removeChildElement(this);">X</p>
</li>`;
output.innerHTML += html;
let close = document.querySelector(".close")
// Resetting input to blank once a submit button has been added.
userInput.value = '';
}
// Figure out how to make closing functionality simple this implementation
// isn't working
function removeChildElement(e) {
let x = e.parentElement;
let xParent = x.parentElement;
xParent.removeChild(x);
console.log(xParent);
}
As you can see i made a few changes. Most importantly your close button issue. The function gets the parent on its parent ( ^ 2 ) and then removes its child. Which would be your <li> element!
Enjoy the fiddle: https://jsfiddle.net/fjbyy6uw/35/
Use Event Delegation. Details are commented in Demo. Added a <form> so HTMLFormControlsCollection API can be used, it's simpler, less writing, and I'm lazy.
/* All form controls are referenced by HTMLFormControlsCollection */
var form = document.forms.toDo;
var td = form.elements;
var add = td.add;
var inp = td.input;
var out = td.output;
var toDo = document.querySelector('.toDo');
add.addEventListener("click", addToDo);
/* Limited the dynamically created node to `<li>`. It doesn't make sense to
|| have several `<ul>` having only one `<li>` each.
*/
function addToDo() {
var html = `
<li class="item">
<span>${inp.value}</span>
<b class="close">X</b>
</li>
`;
toDo.innerHTML += html;
}
/* Event Delegation is a way of leveraging event bubbling so
|| that a single ancestor node can be registered to listen for
|| an event (e.currentTarget) and by means event propagation
|| (bubbling) can locate the event origin (node clicked/e.target).
|| In this demo e.currentTarget is output#output and e.target are
|| any b.close. This was possibble by using e.target in conditions
*/
/* removeChild() is used because display:none is not entirely
|| gone. The markup remains just not in the DOM, so it may not
|| look like it's there, under certain conditions a node could be
|| considered present.
*/
out.addEventListener("click", function(e) {
if (e.target !== e.currentTarget) {
if (e.target.className === "close") {
let x = e.target.parentElement
x.parentElement.removeChild(x);
}
}
});
.item {
display: flex;
max-width: 250px;
justify-content: space-between;
}
.item span,
.item b {
display: table-cell;
}
.item b {
cursor: pointer
}
input,
output,
button {
font: inherit
}
<form id='toDo'>
<header>
<input type="text" placeholder="Enter Item Here..." id="input">
<button id="add" type='button'>+</button>
</header>
<output id="output">
<ul class="toDo">
<li class="item">
<span>Clean Room!</span>
<b class="close">X</b>
</li>
</ul>
</output>
</form>

Show specific div when atag is click. And hide other divs

I'm faily new to jquery and coding in general. I'm having a few troubles with this.
What i want is for when the page loads, the 'Vlogging' link is active and 'Details 1' is shown. Then when you click on either 'Filmmaking' or 'Beme'... 'Details 2 or 3 is shown and which ever one was there goes away.
I have everything set up right so far just need to get it to where when you click on one of the other links the correct 'Details' text shows itself.
Thank you so much and i have it in a fiddle right now!
http://jsfiddle.net/t1huc43d/
Here is the code than needs tuned:
$(function() {
$("togglediv1").click(function() {
$("#togglediv1").removeClass("display-start");
$("li").removeClass("display");
$(this).addClass("display");
});
});
This code will save you a lot of time. I added a custom attribute called "data". This attribute is used to tie the link to the tab you wish to display. This code will make it a lot easier to add additional tabs and etc. Look at the bottom for the changed HTML and JavaScript.
<div id="wrap">
<ul id="divtoggle">
<li><a class="link" data="1">Vlogging</a></li>
<li><a class="link" data="2"> Filmmaking</a></li>
<li><a class="link" data="3"> Beme</a></li>
</ul>
<div class="text">
<div class="tab" data="1">Details 1</div>
<div class="tab" data="2">Details 2</div>
<div class="tab" data="3">Details 3</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script>
$(function () {
$(".link").click(function () {
$(".active").removeClass("active");
$(this).addClass("active");
dataAttr = $(this).attr("data");
$(".tab").hide();
$(".tab[data="+dataAttr+"]").show();
});
$(".link:first").click();
});
</script>
$(function() {
$("#togglediv1").click(function() {
$("#one").removeClass("display");
$("#one").addClass("display-start");
$("#two").removeClass("display-start");
$("#two").addClass("display");
$("#three").removeClass("display-start");
$("#three").addClass("display");
});
});
$(function() {
$("#togglediv2").click(function() {
$("#one").removeClass("display-start");
$("#one").addClass("display");
$("#two").removeClass("display");
$("#two").addClass("display-start");
$("#three").addClass("display");
$("#three").removeClass("display-start");
});
});
...
Updated jsfiddle: http://jsfiddle.net/t1huc43d/3/
Since your ids aren't that conducive in tracking what is clicked and what isn't, I decided to just use this to find what you've clicked in correspondence with the details.
Your updated javascript:
$(function() {
$("li").click(function() {
$("#togglediv1").removeClass("active-start");
$("li").removeClass("active");
$(this).addClass("active");
let temp = $("#divtoggle").children();
var index;
for (let i = 0; i < temp.length; i++)
{
if (this == temp[i] )
{
index = i;
break;
}
}
$(".display-start").addClass("display");
$(".display-start").removeClass("display-start");
let text_children = $(".text").children()
let the_child = text_children[index];
$(text_children[index]).addClass("display-start");
$(text_children[index]).removeClass("display");
});
});
JQuery actually has some components to help you out, but to me, the shortest and CLEANEST way of doing this is the following:
The first thing I'd do is set an id of each of the titles, incrementing them by 1. Then, I'd do the same for the details like so:
<div id="wrap">
<ul id="divtoggle">
<li><a class="title" id="title-1">Vlogging</a></li>
<li><a class="title" id="title-2"> Filmmaking</a></li>
<li><a class="title" id="title-3"> Beme</a></li>
</ul>
<div class="text">
<div class='display' id="detail-1">Details 1</div>
<div class='display' id="detail-2">Details 2</div>
<div class='display' id="detail-3">Details 3</div>
</div>
</div>
After that, the JQuery is pretty simple. Setup a click event on the class title. The first thing to do is to parse the id of the clicked title. Once you have that, target the related detail and show it:
$(document).ready(function() {
$(".title").click(function() {
//*** get id
var id = $(this).attr("id").split("-")[1];
if (typeof id != "undefined"){
//*** hide other descriptions and show yours
$(".display").hide();
$("#detail-" + id).show();
}
});
});
DEMO: http://jsbin.com/volikofihe/edit?html,js,console,output
Here you go. Simplified your CSS a little. Toggling a .active class on the top links, and a .display class on the text divs. When you click on a link, the code uses the $.index() of that link in the list as the index of the text div to show. So if you click on the 2nd link, it will show the 2nd text box.
$(function() {
$toggleLinks = $('#divtoggle a'),
$displays = $('.text div');
$toggleLinks.on('click', function(e) {
e.preventDefault();
$toggleLinks.removeClass('active');
$(this).addClass('active');
$displays.removeClass('display');
$displays.eq($(this).closest('li').index()).addClass('display');
});
});
li {
color: grey;
font: effra;
font-weight: bold;
}
a:hover {
color: #aaaaaa;
cursor: pointer;
}
.active {
color: orange;
}
.text div {
display: none;
}
.text .display {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrap">
<ul id="divtoggle">
<li><a class="active">Vlogging</a></li>
<li><a>Filmmaking</a></li>
<li><a>Beme</a></li>
</ul>
<div class="text">
<div class='display'>Details 1</div>
<div>Details 2</div>
<div>Details 3</div>
</div>
</div>
Preserved as much of your existing code as possible. Updated fiddle.
I added a data-controls custom attribute to each of your li elements so as to associate them to each of the corresponding data divs:
<li data-controls="one"><a id="togglediv1" class="active-start">Vlogging</a></li>
<li data-controls="two"><a id="togglediv2"> Filmmaking</a></li>
<li data-controls="three"><a id="togglediv3"> Beme</a></li>
Then I updated the JavaScript to remove and add the classes, as needed.

How to let url with anchor tags show a hidden div

How can I show an hidden div when using anchors that are linked with their linked a tag that is in the hidden div. If you know what I mean..
See the fiddle: http://jsfiddle.net/2sjdeucf/
I mean when visiting the url site.com/#1 Then I want the div shown, so the same like when you press on the button named 1.
Html
1
2
3
<br><br><br>
<div id="clicks">
<a class="click" id="showInfo" data-target=".1"><button>1</button></a>
<a class="click" id="showDataInput" data-target=".2"><button>2</button></a>
<a class="click" id="showHistory" data-target=".3"><button>3</button></a>
</div>
<div class="1 target" style="display: none;"><a name="1">1</a></div>
<div class="2 target" style="display: none;"><a name="1">2</a></div>
<div class="3 target" style="display: none;"><a name="1">3</a></div>
<div id="text">"I WANT THIS DIV GONE EVERYTIME I LET DIV 1, 2 OR 3 SHOW BY CLICKING THE BUTTONS. BUT SHOW UP AGAIN WHEN 1, 2 OR 3 IS NOT SHOWING/SELECTED"</div>
Javascript
var $targets = $('.target');
$('#clicks .click').click(function () {
var $target = $($(this).data('target')).toggle();
$targets.not($target).hide();
$('#text').css('display', $('div.target:visible').length ? 'none':'')
});
Thank you
You need get initial hash and subscribe for hash changes via onhashchange, so your code becomes (I slightly modified your code, final version is, tested locally in Chrome):
function doToggle(num) {
var target = $('div.target' + num);
target.toggle();
$('.target').not(target).hide();
$('#text').css('display', $('div.target:visible').length ? 'none' : '')
}
$('#clicks .click').click(function () {
var num = $(this).data('target');
doToggle(num);
});
function handleHash() {
doToggle("." + location.hash.substring(1));
}
window.onhashchange = handleHash;
$(handleHash);
You can use window.location.hash to detect the values after the hash.
exp:
var val=window.location.hash.substring(1);//substring to remove the #
if(val.length!==0){
$(".target").hide();
$("."+val).show();
}
I'm not sure to understand well but I tried to stick to your instruction within your .text div, so this code shoud do the trick :
function showHideDiv() {
$('.target').each(function(){
if($(this).is(':visible')){
$('#text').hide();
}
});
}
$(document).on('load', showHideDiv);
$('.click').on('click', showHideDiv);
$('#clicks .click').click(function () {
$('div.target' + $(this).data('target')).toggle();
$('#text').css('display', $('div.target:visible').length ? 'none':'')
});
Working JSFiddle
You can use :target pseudoclass and hash based links (browser support)
div {
display: none;
}
div:target {
display: block;
}
jsfiddle

How to add click event to an element with JQuery which is created by serverside

I create an ul list in serverside as you can see the below. I want to add click event to a elements with jquery but I can't access any elements. Here my codes:
Server side:
StringBuilder sbSubCitchens = new StringBuilder();
sbSubCitchens.Append(#"<div id=""content_1"" class=""subCats"">");
sbSubCitchens.Append("<ul>");
foreach (kitchen kitchen in kitchenList)
{
sbSubCitchens.Append(#"<li><a class="" " + kitchen.KitchenId + #""">" + kitchen.Name + "</a> </li>");
}
sbSubCitchens.Append("</ul>");
sbSubCitchens.Append("</div>");
ltrKitchenList.Text = sbSubCitchens.ToString();
Javascript:
$(document).ready(function () {
$(".mCSB_container ul li a").click(function () {
// do smth...
});
})
Html output :
<div class="mCSB_container" style="position: relative; top: 0px;">
<ul>
<li><a class=" 1">Cafe</a> </li>
<li><a class=" 2">Dünya Mutfağı</a> </li>
</ul>
</div>
Try this:
$(".mCSB_container ul li a").click(function (e) {
e.preventDefault();
// do smth...
});
I think the click may be working, but since you aren't preventing the default action, the link may be reloading the page.
Also make sure the html output is what you expect, since the server-side code you posted, by itself, won't give you the output you posted (and therefore the selector wouldn't work).
I think you have to put the "href" parameter:
Some stuff

Make jquery toggle work with dynamic content

I've the following code on my website: http://jsfiddle.net/dJLK3/1/
As you can see, it works just fine.
The problem is: those divs and link triggers come from a database. Today I have 1, tomorrow it can be 10...
I can not figure out how to convert it and make it work without needing to right lot's of codes like link1, link2, link3, link4, link5 and so on...
Anyone? :)
Use data attr and jQuery.data. reference
Update:
according to this comment.
html
<div class="menu">
Link1
Link2
</div>
<div id="div1" class="slide"></div>
<div id="div2" class="slide"></div>​
js
$('.menu').on('click', '.link', function(){
var id = $(this).data('slideContent');
$('.slide').not('#' + id).slideUp(function() {
$('#' + id).slideToggle();
});
});
​css
.slide {
display: none;
height: 100px;
width: 100px;
position: fixed;
top: 30px;
}
demo
References:
slideUp - http://api.jquery.com/slideUp/
slideToggle - http://api.jquery.com/slideToggle/
Update
Here's a fiddle with a possible answer - FIDDLE - Update - With new requirements
Code posted here for clarification
<div id='link_collection'>
Link1
Link2
</div>
<div id='div_collection'>
<div class='div current'></div>
<div class='div'></div>
</div>
$(document).ready(function() {
$('#link_collection').on('click', '.link', function() {
var divCollection = $('#div_collection .div'),
index = $(this).index(), hasClickedMeAgain,
current = divCollection.filter('.current');
hasClickedMeAgain = current.index() === index;
if (hasClickedMeAgain){
current.slideToggle();
return false;
}
current.slideUp(function() {
$(this).removeClass('current');
divCollection.eq(index).addClass('current').slideToggle();
});
})
});
This way, you don't need to keep tag of anything. Just keep inserting the div and link in the order in which they arrive, and the code then handles itself. All the best.
Will this work for you? Use the same class attribute for all of them. And have the following code on document.ready() to assign on click events:
HTML:
<a class="ui-link-option">Link 1</a>
<a class="ui-link-option">Link 2</a>
<div class="ui-link-option-text">Text Here 1</div>
<div class="ui-link-option-text">Text Here 2</div>
Javascript:
$("a.ui-link-option").each(
function (index) {
var $this = $(this);
$this.data("index", index);
$this.bind("click", function(e) {
var $this = $(this);
var linkIndex = $this.data("index");
$("div.ui-link-option-text").each(
function (index) {
if (index == linkIndex) {
$(this).slideToggle();
} else {
$(this).hide();
}
}
);
});
}
);

Categories