About jquery append behavior - javascript

I have the following code:
$.getJSON('/api/video/',
function (resp) {
$("body").append("<ul/>");
$.each(resp, function (key, value) {
$("ul").append("<li/>").append(
$("<a/>", {
href: value.url,
html: value.title
}));
});
});
It produces:
...
<ul>
<li></li>
How to Connect a Mobile Broadband Antenna to Data Card
<li></li>
40000mW Laser vs. Line of Balloons!!
</ul>
...
As you can see the <a/> are not inside <li/> and my question is why (is there a good reason for the behavior or does it just work that way)? In my world $("ul").append("<li/>").append($("<a/>", ...)) adds the <a/> inside a <li/>. I see it as $("ul").append("<li/>") creates an <li/> inside the unorderd list and that the next append operates on the <li/> item and thus should add the link inside of it. However that is not the case and I wonder if there is a reason for that?
I am very grateful that you have taken time for my question!

The .append() function doesn't update the element(s) referenced by the jQuery object, so when you call the second .append() it's still being called against the <ul> element.
You could restructure it like so:
$('<li/>').append('<a/>', {
href: value.url,
title: value.title
}).appendTo('ul');

$.append() returns the item that was appended to, not the item being appended.

Related

Appending div from another html file

I have 2 menu buttons which supposed to append divs from an external html.
Now I have this:
<ul>
<li><a href="#" onclick="javascript:test2();" value="#CS" >CS</a></li>
<li><a href="#" onclick="javascript:test2();" value="#PS" >PS</a></li>
</ul>
And 2 divs on the external html, that just have simple text in them saying "text1" and "text2".
I use this code to append the data:
$.get('external/list.html', function (data) {
$(data).filter('#PS').appendTo('#content')
});
How can I "upgrade" it to take for example an attribute like value, and use it to choose what div to append? Because I prefer to have it as 1 function instead of making 2.
Also this code appends a div, but it doesn't reset it. It just keeps spamming the same div over and over and over. How can I stop it?
Option 1
Keep a single call to your $.get, as you are doing now, but pass reference of your clicked element through your function as below:
<ul>
<li><a href="#" onclick="javascript:test2(this);" value="#CS" >CS</a></li>
<li><a href="#" onclick="javascript:test2(this);" value="#PS" >PS</a></li>
</ul>
JS
function test2(ctrl)
{
var element=$(ctrl).attr('value');
$.get('external/list.html', function (data) {
$(data).filter(element).appendTo('#content');
//element will have value either #PS or #CS
});
}
Note - .appendTo will keep on appending the data to your DOM, instead use .html which replaces contents everytime
Ex:
$(data).filter(element).html('#content');
Option 2
You can also attach click event to your a tags with a common class given for both thus removing inline function call as below:
<ul>
<li>CS</li>
<li>PS</li>
</ul>
JS
$(".menu").on('click',function(){
var element=$(this).attr('value'); //this refers to clicked element
$.get('external/list.html', function (data) {
$(data).filter(element).appendTo('#content');
//element will have value either #PS or #CS
});
});
Update
Ideally html should work but I imposed it in wrong way. You just need to change one thing as below:
$("#content").html($(data).filter(element));

JQuery not acting as it should

I am trying to make a "drop down" menu where you click a div and the sibling below it will become visible or disappear. It should be extremely simple, but it is giving me trouble for some reason.
$(".dropDownClick").click(function(){
alert($(self));
$(self).next().css("display",(node.css("display")=="inline")?"none":"inline");
});
This code returns [object Object] and then doesn't change the display css of the next sibling. After a bit of testing I found that $(self).next(); will actually break the code (if I try to do something like alert($(self).next()); the code will not execute). I am assuming this is because there is no next sibling? But my HTML would suggest otherwise:
<div class="dropDownClick"><h1>Drop</h1></div>
<div class="dropDown" style="display: none;">
<ul>
<li>1</li>
<li>2</li>
</ul>
</div>
Shouldn't the div with the class "dropDown" be selected when I call .next()?
it should be this not self, also you can use .toggle() instead of manually applying the display value
$(".dropDownClick").click(function () {
$(this).next().toggle();
});
this is a special variable, which is always available - but self/node are custom variables which has to be declared before using else it will throw a reference error
Demo: Fiddle

Iterate through elements, adding click event to each of them

jQuery newbie here.
If I have this html:
<ul id="floor-selector">
<li id="floor-1">Ground Floor</li>
<li id="floor-2">Second Floor</li>
<li id="floor-3">Third Floor</li>
<li id="floor-4">Premier Floor (Premier Floor)</li>
</ul>
I want to add a click event to each li item, such that I can get the id of the element I am on. Right now I just have an alert with the index I'm on (and it's not working either), but I really want the ID of the item I'm on, not the index of the array returned by my selector.
Here's what I tried, but it doesn't seem to work, I think I might have the wrong understanding of each() or click().
$('#floor-selector li').each( function(index, node) {
node.click( function(){ alert('I am on the '+index+'th element'); } );
// but I really want to get the ID of this element
});
This should work:
$('#floor-selector li').on('click', function() {
alert('I am the '+$(this).attr('id')+' element');
});
Behind the scenes jQuery does a bunch of magic and essentially binds the function you pass to the element. this therefore references the element that you are clicking and passing it to jQuery functio: $(this) gives you back that element wrapped in a jQuery object. Of course you could simply access the id on this directly.

Jquery select all children within children

I'm sure this will be a simple question but I still struggle with DOM selectors in Jquery so here is a model of my html code:
<fieldset class="product-options" id="product-options-wrapper">
<ul class="options-list">
<li><a href>Item1.1</a></li>
<li><a href>Item1.2</a></li>
<li><a href>Item1.3</a></li>
</ul>
...other html items here
<ul class="options-list">
<li><a href>Item2.1</a></li>
<li><a href>Item2.2</a></li>
<li><a href>Item2.3</a></li>
</ul>
</fieldset>
Now how do I select all of the 'li a' items in both lists (or X number of lists) with class name .options-list and bind them with a click function.
Currently I have:
$('fieldset#product-options-wrapper ul.options-list > li a').bind('click', function(e) {
//code here
});
And it only gets the first options-list.
Thanks, greatly appreciated!
EDIT: If i click on a Item2.X list item first, then it will grab that options list. But as soon as I click on the Item1.x list items it disregards the second .options-list
If you are going to bind to each li element, you should bind it to the ul element instead (helps greatly with performance when there are a lot of events).
$('.options-list', '#product-options-wrapper').bind('click', function(e)
{
e.preventDefault();//In case you don't want to go to a different page
var clicked = e.target;//The href that was clicked
/* If you only want this to happen if the a tag was clicked, add the following line
if(clicked.tagName == 'A')*/
//Rest here
});
How about $('.options-list a').bind('click', function(e) { });?
You can use delegate in this case to make it even simpler. Try this
$('#product-options-wrapper ul.options-list').delegate('li > a', 'click', function(e) {
//code here
});
Your method seems sound to me. I created a test fiddle using your HTML (and an extra anchor to prove that it won't get the click added) and your JS (with minor modifications).
http://jsfiddle.net/chrisvenus/esZxH/1/
The selector you had did work but since you said you wanted the a to be a direct child of the li (or at least I read it that way) I slightly tweaked it in my version above. ARe you sure its not just your function is not doing quite what you want while executing or can you confirm that your click function isn't being run at all?

Jquery get attribute of few ul to create another attribute

I have the following HTML:
<ul actualpage=0>
<li/>
<li/>
....
</ul>
<ul actualpage=0>
<li/>
<li/>
....
</ul>
Im trying to get the value of actualpage of each ul and create a new attribute. Its easy but not in one jquery sentence... Its possible? Until now i have the following line (between ## simbols the missing part that i need.
/*
select all uls with attribute actualpage and create a new attribute on each with the current actualpage value
*/
$('ul[actualpage]').attr('newactualpage',##Current value of actualpage attr of UL##);
Well maybe this isn't as nice as you'd like, but
$('ul[actualpage]').each(function(_, ul) { $(ul).attr('newactualpage', $(ul).attr('actualpage')); });
One might think that
$('ul[actualpage]').attr('newactualpage',$(this).attr('actualpage'))
is the answer.
However, this is evaluated before the call to attr, so it's going to equal whatever this equals in the calling context.
You could use:
$('ul[actualpage]').attr('newactualpage',function(){
return $(this).attr('actualpage');
});
or this:
$('ul[actualpage]').each(function()
{
$(this).attr('newactualpage',$(this).attr('actualpage'));
};
In both, this refers to the element that your selector matched.
You can use function as second argument for .attr(), eliminating the need of .each():
$('ul[actualpage]').attr('newactualpage', function() { return $(this).attr('actualpage') });

Categories