JQuery - Problems with appendTo() - javascript

I'm moving elements from one list to another, the issue is:
I have javascript binded functions to the <li> depending of the <ul>, if I click one <li> that is inside an <ul> with an specific ID, a function is excecuted.
When I move the <li> with success, it's assumed the <li> is already in the other <ul> (The destination one). but if I click the <li> in the new list, the event still bind with the source one <ul>
How do I do to bind the <li> with the current <ul>?
Thanks for your help.
<ul id="sourceList">
<li>element1</li>
<li>element2</li>
</ul>
<ul id="destinationList"></ul>
<script>
$('#sourceList li').click(function () {
$(this).appendTo('#destinationList');
console.log("from source");
});
$('#destinationList li').on("click", function () {
$(this).appendTo('#sourceList');
console.log("from destination");
});
</script>

Events are binded when the script is executed the first time so, in your code, every li from #sourceList has a click event attached to the first defined event listener, no matter if you move the element to another container or not. You need to use event delegation for that:
$('#sourceList').on('click', 'li', function () {
$(this).appendTo('#destinationList');
console.log("from source");
});
$('#destinationList').on('click', 'li', function () {
$(this).appendTo('#sourceList');
console.log("from destination");
});

Related

jQuery keydown callback listens only on outer <ul> rather than inner <li> element

Hey so here is the code demo I made
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
</head>
<body>
<ul contenteditable class="outerList">
<li class="innerElement">Hello</li>
<li class="innerElement">World</li>
<li class="innerElement">Hello World</li>
</ul>
<script>
$(".outerList").keydown(function () {
console.log("I am the outer ul");
});
$(".innerElement").keydown(function() {
console.log("I am an inner element");
});
</script>
</body>
</html>
and here is the jsFiddle to run it
http://jsfiddle.net/scrbovyr/
Basically I have a content editable UL and I want to catch the enter key and pass in my own custom function. But I need to know which LI element the keydown event was thrown on. And as shown in the demo, I can only seem to tie a keydown event listener (or any event listener for that matter) to the outer UL element. Is there a way to attach the keydown event to each LI? Or is there at least a way to attach it to the UL but still tell which child it came from?
Thanks in advance, let me know if any additional information would help!
You will have to add contenteditable to your li elements in order to achieve that. You are setting contenteditable to your ul element, thus, the event will be binded to that element, you may edit the li elements, but they do not have contenteditable set, so the keyboard events won't be triggered for those elements.
<ul class="outerList">
<li contenteditable class="innerElement">Hello</li>
<li contenteditable class="innerElement">World</li>
<li contenteditable class="innerElement">Hello World</li>
</ul>
And then:
$(".innerElement").keydown(function() {
console.log("I am an inner element");
});
You may check the node at the current selection
If you don't want to make each li a contenteditable element, you may get the element at the current selection or caret position and perform a check against it.
The embedded example shows how you would achieve this using the Web API Interface for contenteditable selections. (I tested this in Chrome, but it may need additional logic to achieve cross-browser compatibility).
It is also worth noting that you can bind some event listeners to the children of a contenteditable element. For example, the click event may be bound to the li elements as you can see in the embedded example.
$(document).ready(function() {
function getCurrentNode() {
var node = window.getSelection().getRangeAt(0).commonAncestorContainer;
return node.nodeType === 1 ? node : node.parentNode;
}
$('.outerList').on('click keyup', function (e) {
var $target = $(getCurrentNode()),
$closest = $target.closest('b');
console.log(e.type);
console.log('I am the outer ul');
console.log($target);
// Optional. Filter by clostest selector.
if ($closest.length) {
console.log('Target matches selector', $closest);
}
});
$('.innerElement').on('click', function (e) {
console.log(e.type);
console.log('I am an inner element');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul contenteditable class="outerList">
<li class="innerElement">Hello</li>
<li class="innerElement"><i>Hello</i></li>
<li class="innerElement"><b><i>Hello</i></b></li>
<li class="innerElement"><b>Hello</b></li>
<li class="innerElement">Hello</li>
<li class="innerElement">Hello</li>
</ul>

Changing HTML list item to active in navbar

I am loading my navbar into each page with $("#navbar-partial").load("navbar.html) at the bottom of the page in script tags.
The navbar list code is below:
<ul id="main-nav" class="nav nav-sidebar">
<li>
</li>
<li>
</li>
<li>
</li>
<li>
</li>
</ul>
Ive tried this and some variations of this but cant get it to work:
$(document).ready(function () {
$('.nav li').on('click', function (e) {
$(this).addClass('active').siblings().removeClass('active');
});
});
This is in the same script tag at the bottom of the html page, after the load call.
Any ideas?
Thanks
You should use delegation
$(document).on('click', ".nav li", function(e) {
$(this).addClass('active').siblings().removeClass('active');
});
Because the content isn't present on DOM ready (given the asynchronous nature of Ajax), you'll need to use on() to bind the click handler to an ancestor element, which is present in the DOM at the point of DOM-ready, the element with id="navbar-partial", into which you're loading the new content:
// selecting the element present on DOM-ready:
// binding the 'click' event that's fired on elements
// matching the '.nav li' selector:
$('#navbar-partial').on('click', '.nav li', function (e) {
$(this).addClass('active').siblings().removeClass('active');
});
You could bind to an element further up the DOM tree, but binding to the closest element is reduces the amount of bubbling required to detect the event.
References:
on().

Elements appeneded not triggering events

I have a list
<ul id="list">
<li> element one <span class="remover">X</span></li>
<li> element two <span class="remover">X</span></li>
</ul>
and this list is dynamically appended with
<input type="text" id="adder">
<button id="add">Add</button>
<script>
$("#add").click(function(){
$("#list").append('<li>'+$("#adder").val()+' <span class="remover">X</span></li>');
});
</script>
but the problem is this with part
<script>
$(".remover").click(function(){
$(this).parent().remove();
});
</script>
The remove works perfectly with the static added items, but when it comes to the new appended items nothing happens on click, doesn't even trigger the function
I'd suggest:
$('#list').on('click', '.remover', function(e){
$(this).parent().remove();
});
JS Fiddle demo.
References:
on().
parent().
remove().
Call the click function on list and set remover as target like so:
$( '#list' ).on( 'click', '.remover', function (e) {
$(e.target).parent().remove();
});
You can't set a click event directly on it, it has to be set on the element that never is added to the page.
you should use
on('click',function(){})
not
.click()
refer to : http://api.jquery.com/on/
as click will relate to current item within document , while on is related to future items that will be added to document , however you should always use on with something that already exists in your document like for example the parent of the future added element so use something like
$("#parent").children("li").children('.remover').on("click",function(){bla bla bla;});

Checkbox in a div with onclick toggle double toggles (how to block inner toggle)

I have a checkbox inside an <li> as apart of a menu. The wrapping item has a click handler which toggles the checkbox (to be consistent with the feel of the menu as whole). The problem is if the user clicks directly on the checkbox it will do its default toggle, and then the outer handler also toggles it. How can I prevent this double-toggle?
<li onclick='/*toggle checkbox*/'><input type='checkbox'/>...</li>
I've tried disabled but that alters the rendering, which I don't want.
I'm using jquery in case there is a feature there which helps.
You can use the .stopPropagation() function to prevent the click from propagation up the DOM tree.
Here's an example
$(document).ready(function () {
$("input[type=checkbox]").click(function (evt) {
evt.stopPropagation();
$("#thetext").html("checbox clicked");
});
$("li").click(function () {
$("#thetext").html("li clicked");
});
});
html
<ul>
<li>
<input type='checkbox' />
</li>
</ul>
<div id="thetext">hm</div>
Here is jQuery method for this http://api.jquery.com/event.stopPropagation/

How to create click event for specific link in a jQuery listview.

I'm trying to create a function that starts when you click on a specific link in a listview.
The issue is that event doesn't seem to fire when you click the link. The list is created dynamically. I'm not sure if that causes an issue.
<label for="listviewForLastTenCalls">Last Ten Calls:</label>
<ul data-role="listview" id="listviewForLastTenCalls">
</ul>
<script>
$('#listviewForLastTenCalls li').click(function(){
//alert('click event handler fired');
</script>
Demo
<ul data-role="listview" id="listviewForLastTenCalls">
<!-- items dynamically generated -->
</ul>
JS
$(document).on('click', '#listviewForLastTenCalls li a', function () {
// code
});
The issue is you are adding the click listener after you have created the list. When you first create the listener there is nothing for it to listen to. You need to add the on click event after you add the <li>
$('#listviewForLastTenCalls li a').click( function () {
// code
});
I hope this is not your fully markup,...
<label for="listviewForLastTenCalls">Last Ten Calls:</label>
<ul data-role="listview" id="listviewForLastTenCalls">
</ul>
<script>
$('#listviewForLastTenCalls li').click(function(){
//alert('click event handler fired');
}); //<--
</script>
And if the list is creadted dynamically, you have to attach the event, after list was created...
You have to do event delegation for dynamically added elements.
$('"#listviewForLastTenCalls"').on("click",'li' ,function(){
alert('triggered');
});
And why on() works ??
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on().
Something like this:
$(function() {
$("#listviewForLastTenCalls li").on('click', function() { alert('clicked'); });
});

Categories

Resources