I'm new to jQuery and am trying to create jQuery UI buttons dynamically and them to a list. I can create one list item but no more are appended after it. What am I doing wrong?
$('#buttonList').append('<li><button>'+ username + '</button>')
.button()
.data('type', userType)
.click(function(e) { alert($(this).data('type')); })
.append('<button>Edit</button></li>');
<div>
<ul id="buttonList">
</ul>
</div>
This only creates one list item with two buttons (although the second button seems to be encased in the first one, but I can probably figure that issue out). How do I get it to create multiple list items with their own unique 'data' values (i.e. I can't do a find() on a particular button class and give it data values as all buttons would then have the same data)?
I suggest to exchange the position of what you are appending and where you are appending to. This way, you retain the appended object, and should be able to work with it as a standard jQuery selector. From your code i commented out the .button() and the .append() lines, because i'm not sure what you want to do with them. Should you need help adding those lines, just drop a comment to my answer ;)
Oh, i almost forgot: i use var i to simulate different contents for username and userType data.
A JSFiddle for you is here: http://jsfiddle.net/cRjh9/1/
Example code (html part):
<div>
<p id="addButton">add button</p>
<ul id="buttonList">
</ul>
</div>
Example code (js part):
var i = 0;
$('#addButton').on('click', function()
{
$('<li><button class="itemButton">'+ 'username' + i + '</button></li>').appendTo('#buttonList')
//.button()
.find('.itemButton')
.data('type', 'userType'+i)
.click(function(e) { alert($(this).data('type'));
})
//.append('<button>Edit</button></li>')
;
i++;
});
You need complete tags when you wrap any html in a method argument. You can't treat the DOM like a text editor and append a start tag, append some more tags and then append the end tag.
Anything insterted into the DOM has to be complete and valid html.
You are also not understanding the context of what is returned from append(). It is not the element(s) within the arguments it is the element collection you are appending to. You are calling button() on the whole <UL>.
I suggest you get a better understanding of jQuery before trying to chain so many methods together
Just a very simplistic approach that you can modify - FIDDLE.
I haven't added the data attributes, nor the click function (I'm not really sure I like the
inline "click" functions - I generally do them in jQuery and try to figure out how to make
the code efficient. Probably not very rational, but I'm often so).
JS
var names = ['Washington', 'Adams', 'Jefferson', 'Lincoln', 'Roosevelt'];
for( r=0; r < names.length; r++ )
{
$('#buttonList').append('<li><button>'+ names[r] + '</button></li>');
}
$('#buttonList').append('<li><button>Edit</button></li>');
Related
I'm having trouble detecting length and index of the appended div, I dug through a lot of things, and there's a solution with MutationObservers but somehow I'm continuously asking myself do I need it for this kind of problem,
However, let's get to the issue. I have a div populated dynamically structured like this,
<div class="array-placeholder">
<div id="tagContainer" class="row tag">
<!-- dynamic elements -->.....
</div>
</div>
when I click to this button it appends another dynamic element, see the code below :
$('body').off('click.addCollection').on('click.addCollection', function () {
//list and new widgets are just containers and datalist inside the array-placeholder div
let newElem = $(list.attr('data-widget-tags')).html(newWidget);
newElem.appendTo(list);
})
I've tried this solution to get the length of the array-placeholder div but it doesn't seem to work, the function is never launched:
$('body').on('DOMSubtreeModified', '.array-placeholder', function (event) {
console.log( $(".array-placeholder > div").length);
})
result
//nothing and when you click to the appended element via moveUpButton.closest(".tag") you 0 as index
do I have to implement MutationObserver to solve this if yes, could you guide me through this, thanks
DOMSubtreeModified
This event has been deprecated in favor of the Mutation Observer API
Yes you have to use Mutation Observer API. To implement that you can refer This
You can get all children using jquery's find('*') and then count their length;
$(".array-placeholder").find('*').length;
Or if you want only divs then do:
$(".array-placeholder").find('div').length;
I have an element with an array id id="x[]" that vary depending on the number of elements that I have on a database. It's basically a x button to delete a certain table row in the database.
<div align="center" id="x[]" class="x">
<img src="x 2.png" alt=""></div>
Problem is, I don't know how to pass this id into the jQuery selector. I want to change the form action to delete the row and create an hidden input to get the paramater I need from another field with an array id id="codsinmov[]" with the same index as x[]. What I have so far is:
$(document).ready(function(){
for(var i=0; i<x.length; i++) {
$('#x[i]').click(function(){
var $hiddenInput = $('<input/>',{type:'hidden',id:codsinmovesse, name:codsinmovesse});
$hiddenInput.val($('#codsinmov[i]').val());
$hiddenInput.appendTo('#tabelaeditavel');
$('#form').get(0).setAttribute('action', 'deletemoviment.php');
$('#form').submit();
});
}
});
But it doesn't work.. So, any ideas? Sorry, I'm a beginner at jQuery. Thank you very much!
you can use
$("div[id^='x['").click(function(){
// write code here })
So this will execute on click of those ids of div which start from x.
So as per my understanding You need not to use for loop here rather use 'this' keyword and do what you want.
I hope it will help you.
If you want to add an eventListener to ALL elements you can simply do it like that
var $myButtons = $('.buttons');
That way the whole list of Elements are stored behind the variable $myButtons.
Now you can proceed as following:
$myButtons.on("click", function(event){
console.log(this); // this will print out the clicked element
});
This way every element with the class .buttons is clickable and accessable.
If you want to dynamically select a single element with jquery depending on some value you have to exclude your [i] from the string
for example like that $('element:nth-child('+[i]+')');
I have a page where users can create tags (much like here in stackoverflow), which are then sent(POST) to the back end to be stored in a database. The user can make tags but also remove them before finally hitting Submit.
In the DOM the tags are generated along with an 'x' button. The 'x' button removes the element from the DOM, but the trouble comes when removing from the array. The closest I could get to a solution was this question, however I couldn't get it to quite work for me.
Here's the codepen
Here's the javascript (i'm using JQuery)
window.tag_array = [];
$( "#addtag" ).click(function() {
var tag = $("#input-tag").val();
//if tag is empty
if(!$('#input-tag').val()) {
alert("can't be empty");
} else {
//put tag.val into an array
tag_array.push(tag);
//add to DOM
$( "#tagsbox" )
.append( "<div class='displaytag'><i>"+tag+"</i><input type='hidden' class='tag' value="+tag+"><button onClick='return false;' class='removetag'>x</button></div>" );
//reset value in text area to null
$("#input-tag").val("");
//remove tag onclick
$('.removetag').click(function() {
$(this).parent().remove(); //remove tag from DOM
//splice from array
tag_array.splice( this, 1 ); //<--HERE IS PROBLEM (i think)
});
} //end else
alert(tag_array); //check array
});
The end result is the splice takes out too many array items.
I have also tried
tag_array.splice(tag_array.indexOf(tag),1);
to a similar result.
Please help! Thanks in advance
You should probably use something like .indexOf() to get an index of the element and then splice an array:
tag_array.splice(tag_array.indexOf(elm),1);
Working demo
The splice part is OK. The problem is that you're adding a click callback to .removetag too many times.
Everytime you append a new element, you are adding another click event to every .removetag item that is already on the page.
$('.removetag').click(function()
This way, whenever you click on one element, all the others were assign to fire the click callback too.
Solution
Instead, when creating the tag, set the click event only to the last added .removetag element:
$('.removetag').last().click(function()
Updated CODEPEN
I need to effectively sort html nodes inside some container. Here's a simplified version of what I did:
<html>
<ul class="navigation">
<li class="first">Main</li>
<li class="second">HTML и CSS tricks</li>
<li class="third">Study</li>
<li class="fourth">HTML reference</li>
</ul>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script>
var rows = $( ".navigation" ).children();
function sortAlpha(a,b){
return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1;
};
rows.sort(sortAlpha).appendTo('.navigation');
</script>
</html>
Some of the people I work with are suspicious about the line
rows.sort(sortAlpha).appendTo('.navigation');
They ask is it ok to use appendTo this way, maybe there are (or will be in the future) some drawbacks of using this method, how come using appendTo replaces the content of the parent container and why it won't just add the sorted things to the parent container? What if it's a temporary feature of jQuery and it won't work like that in the future?
I need to say that the real case is more complex, e.g. we use the library that allows us to have object-oriented programming at the front-end side, also each element which needs to be sorted is a row of a table that contains some controls that have event bindings.
The idea was to replace the content of the dom node with sorted elements so this library wouldn't notice that. I used the approach described above in the real code and it's bugless at least for now, but the question remains: 1) what are the drawbacks of this approach, 2) what can be a better option?
This is covered in the documentation for .appendTo():
We can also select an element on the page and insert it into another:
$( "h2" ).appendTo( $( ".container" ) );
If an element selected this way is inserted into a single location elsewhere in the DOM, it will be moved into the target (not cloned)...
So, since you're selecting elements that already exist on the page, and calling .appendTo() with a selector that only matches a single element, those selected elements are moved into that new target element, in the order they're in inside of your set of matched elements. It's irrelevant that you're putting them back into the same element.
What are the drawbacks?
None that I can think of. You're using a documented aspect of what the function does. It's unlikely that the way that .appendTo() works is ever going to be changed.
appendTo is supposed to appendTo...I'm surprised it just acts like .html(). To make them happy why dont you just do $('.navigation').empty().append(rows.sort(sortAlpha));
Basically, appendTo() will insert html nodes at the end of the specified element, here : .navigation
Assuming you're using jQuery Sort plugin (http://github.com/jamespadolsey/jQuery-Plugins/tree/master/sort/), if you need to reorder your navigation menu, you could simply do :
$('.navigation li').sort(function(a, b){
return $(a).text() > $(b).text() ? 1 : -1;
});
By the way, if you want to replace the full content of an element, consider html() method, which empty the node and insert the content.
Try this,
$(function() {
$.fn.sortList = function() {
var mylist = $(this);
var listitems = $('li', mylist).get();
listitems.sort(function(a, b) {
var compA = $(a).text().toUpperCase();
var compB = $(b).text().toUpperCase();
return (compA < compB) ? -1 : 1;
});
$.each(listitems, function(i, itm) {
mylist.append(itm);
});
}
$("ul.navigation").sortList();
});
Demo
I have following HTML
<div id="finalTree">
<ul>
<li class="last" style="display: list-item;">
<a id="DataSheets" href="#">Data Sheets</a>
</li></u>...........</div>
and I am first hiding all these li and then trying to show those li which match to selector. Here is my JavaScript. Here filterData is id of links.
function filterLeftNavTree(filterData){
jQuery("ul.treeview").find("li").hide();
var selectors =[];
if(filterData.indexOf("|")!=-1){
var filterData = filterData.split("|");
for(i=0;i<filterData.length;i++){
selectors.push('#'+filterData[i]);
}
var filtered = selectors.join(',');
$(filtered ).show();
}else{
$('#'+filterData+).show();
} }
the last two line doesn't works...
any one can tell me what can be possible reason. Actually I tried to show li with :has, :contains, find().filter() but all these are taking too much time if I have large tree.
Do I am trying to show it by using multiple selector, but it's not showing any thing. Any alternative having faster way to show it will be highly appreciated.
What you have (aside from the syntax error #verrerby mentioned) should be working, but why not cut down on that code a bit?
You can slim things down by adding the # on every element after the first as part of the .join(), this also greatly simplifies the logic. You can reduce it down to:
function filterLeftNavTree(filterData) {
$("ul.treeview li").hide();
$('#'+filterData.split('|').join(',#')).show();
}
Also note the change removing .find(), it's faster in browser that support it to use a single selector, and just as fast in all the others.
The only other possible reason I see for your code not working is jQuery is used for the hide and $ is used on the show, is it possible $ refers to something else? (e.g. ptototype?) To test just replace $ with jQuery on the .show() call.
You have an extra +' in the last statement, and you could do it in multiple statements instead of one (the #{id} selector is very fast):
if(filterData.indexOf("|")!=-1){
var filterData = filterData.split("|");
for(i=0;i<filterData.length;i++){
$('#'+filterData[i]).show();
}
}else{
$('#'+filterData).show();
}