jQuery trying to build up and then append HTML - javascript

I've put a much simplified example on jsFiddle.
Basically, I'm trying to build up my HTML and then append the whole thing once I'm done. The JS looks like this:
var label = 'My label',
var checkbox = $('<input type="checkbox">').prop({
id: 'checkboxId',
name: 'checkboxId',
checked: visible
});
listItem = ('<li class="customise_option"><label>'+checkbox+' '+label+'</label></li>');
$('#mylist').append(checkbox);
$('#myotherlist').append(listItem);
Appending just checkbox is fine, but if I try to include checkbox within my listItem variable then I just get:
[object Object] My label
So, on it's own jQuery is fine with appending my checkbox as a string, but when I try to do anything with that it treats it as an object.
Having looked around there are some similar questions, but as I'm creating everything in JavaScript (rather than manipulating something that already exists in the DOM) it seems there must be a way to do what I want. Problem is I can't figure it out.
EDIT
I simplified my original example too much, not understanding the problem fully. I have updated the jsFiddle to show that on my checkbox I need to be able to add a bunch of properties. So, the checked property will be reliant on something else. As such, I need $ so I can access jQuery's prop function (I think).

var label = 'My label',
checkbox = '<input type="checkbox">';
listItem = '<li class="customise_option"><label>'+checkbox+' '+label+'</label></li>';
$('#mylist').append(checkbox);
$('#myotherlist').append(listItem);
Here's the jsfiddle. If you're adding HTML markup, all you need are strings; you weren't far away.

checkbox is a jquery object, when you say string + checkbox you're casting checkbox to a string (which gives [object Object]) and then appending it. you need to use append() there as well.

Its because checkbox = $('<input type="checkbox">') returns a jquery object.
Either stick to jquery objects and use methods like text() etc, or stick to appending string representations of HTML. Just dont mix it.

This happens because the checkbox is an object.
With this code, works
var label = 'My label',
checkbox = '',
listItem = ''+checkbox+' '+label+'';
$('#mylist').append(checkbox);
$('#myotherlist').append(listItem);

Related

show all the values with .html [duplicate]

Lets say I have an empty div:
<div id='myDiv'></div>
Is this:
$('#myDiv').html("<div id='mySecondDiv'></div>");
The same as:
var mySecondDiv=$("<div id='mySecondDiv'></div>");
$('#myDiv').append(mySecondDiv);
Whenever you pass a string of HTML to any of jQuery's methods, this is what happens:
A temporary element is created, let's call it x. x's innerHTML is set to the string of HTML that you've passed. Then jQuery will transfer each of the produced nodes (that is, x's childNodes) over to a newly created document fragment, which it will then cache for next time. It will then return the fragment's childNodes as a fresh DOM collection.
Note that it's actually a lot more complicated than that, as jQuery does a bunch of cross-browser checks and various other optimisations. E.g. if you pass just <div></div> to jQuery(), jQuery will take a shortcut and simply do document.createElement('div').
EDIT: To see the sheer quantity of checks that jQuery performs, have a look here, here and here.
innerHTML is generally the faster approach, although don't let that govern what you do all the time. jQuery's approach isn't quite as simple as element.innerHTML = ... -- as I mentioned, there are a bunch of checks and optimisations occurring.
The correct technique depends heavily on the situation. If you want to create a large number of identical elements, then the last thing you want to do is create a massive loop, creating a new jQuery object on every iteration. E.g. the quickest way to create 100 divs with jQuery:
jQuery(Array(101).join('<div></div>'));
There are also issues of readability and maintenance to take into account.
This:
$('<div id="' + someID + '" class="foobar">' + content + '</div>');
... is a lot harder to maintain than this:
$('<div/>', {
id: someID,
className: 'foobar',
html: content
});
They are not the same. The first one replaces the HTML without creating another jQuery object first. The second creates an additional jQuery wrapper for the second div, then appends it to the first.
One jQuery Wrapper (per example):
$("#myDiv").html('<div id="mySecondDiv"></div>');
$("#myDiv").append('<div id="mySecondDiv"></div>');
Two jQuery Wrappers (per example):
var mySecondDiv=$('<div id="mySecondDiv"></div>');
$('#myDiv').html(mySecondDiv);
var mySecondDiv=$('<div id="mySecondDiv"></div>');
$('#myDiv').append(mySecondDiv);
You have a few different use cases going on. If you want to replace the content, .html is a great call since its the equivalent of innerHTML = "...". However, if you just want to append content, the extra $() wrapper set is unneeded.
Only use two wrappers if you need to manipulate the added div later on. Even in that case, you still might only need to use one:
var mySecondDiv = $("<div id='mySecondDiv'></div>").appendTo("#myDiv");
// other code here
mySecondDiv.hide();
if by .add you mean .append, then the result is the same if #myDiv is empty.
is the performance the same? dont know.
.html(x) ends up doing the same thing as .empty().append(x)
Well, .html() uses .innerHTML which is faster than DOM creation.
.html() will replace everything.
.append() will just append at the end.
You can get the second method to achieve the same effect by:
var mySecondDiv = $('<div></div>');
$(mySecondDiv).find('div').attr('id', 'mySecondDiv');
$('#myDiv').append(mySecondDiv);
Luca mentioned that html() just inserts hte HTML which results in faster performance.
In some occassions though, you would opt for the second option, consider:
// Clumsy string concat, error prone
$('#myDiv').html("<div style='width:'" + myWidth + "'px'>Lorem ipsum</div>");
// Isn't this a lot cleaner? (though longer)
var newDiv = $('<div></div>');
$(newDiv).find('div').css('width', myWidth);
$('#myDiv').append(newDiv);
Other than the given answers, in the case that you have something like this:
<div id="test">
<input type="file" name="file0" onchange="changed()">
</div>
<script type="text/javascript">
var isAllowed = true;
function changed()
{
if (isAllowed)
{
var tmpHTML = $('#test').html();
tmpHTML += "<input type=\"file\" name=\"file1\" onchange=\"changed()\">";
$('#test').html(tmpHTML);
isAllowed = false;
}
}
</script>
meaning that you want to automatically add one more file upload if any files were uploaded, the mentioned code will not work, because after the file is uploaded, the first file-upload element will be recreated and therefore the uploaded file will be wiped from it. You should use .append() instead:
function changed()
{
if (isAllowed)
{
var tmpHTML = "<input type=\"file\" name=\"file1\" onchange=\"changed()\">";
$('#test').append(tmpHTML);
isAllowed = false;
}
}
This has happened to me . Jquery version : 3.3.
If you are looping through a list of objects, and want to add each object as a child of some parent dom element, then .html and .append will behave very different. .html will end up adding only the last object to the parent element, whereas .append will add all the list objects as children of the parent element.

jQuery + JSON - .each not retrieving unique values

This is my codepen: http://codepen.io/JTBennett/pen/OpEeBG
This is the jQuery in question:
$('.gvListing').each(function(){
var cntTxt = $('.dispCntry').text()
$(this).attr('data-country',cntTxt)
var valueC = $('.ddCountry:selected').val();
var valueR = $('.ddRegion:selected').val();
$('#testDiv').text(valueC)
});
(^this all happens at the bottom of the JS on the codepen link)
The issue looks like this:
So the data attribute is being filled up with every .dispCntry div's contents even though I'm doing this function in .each() .gvListing div. I have a feeling I'm missing something stupid, like the letter i somewhere - but I can't seem to get it right.
var cntText=$('.dispCntry').text();
will take every text of input that has .dispCntry class.
It does not concentrate on your .each() .gvListing div.
Either you have to use only one .dispCntry class input, or give unique class or id to each .dispCntry elements

Moving links in jQuery, adding to string causes [object Object]

I'm trying to move a link around but when I try to include it within a string it doesn't work. If I remove the string it does though. Why is this happening and how do I fix it?
$(document).ready(function(){
var link = $('a');
//Remove the '<div>'s and it works...
$('div').after('<div>'+link+'</div>');
});
See pen for an example: http://cdpn.io/AKnsL
Thanks.
ED: I probably should of noted that this is a simplified version of what I am trying to do, I'm trying to rebuild a menu (don't ask why...) and I have each link assigned to a variable which is then added in place to a rather long string of divs and such, which is all then added in "after" another div. I only mention in case it changes the way this could be done, and I should mention I'm no JS pro :)
Thanks#2!
The issue is because a jQuery selector, such as $('a') returns an object, and appending a string and an object results in what you've seen.
If you want to move the link to a different element in the DOM, use append():
var link = $('a');
$('div').append(link);
$("a") is actually an object, not a string. If you use $("div").after(link), jQuery will work out that you actually want to append the DOM element.
The problem comes in when you do '<div>' + link + '</div>', where JavaScript is creating the string before jQuery gets involved. this is where [object Object] comes from - this is JavaScript's way of creating a sensible String value for an object. What's being evaluated is $("div").after("<div>[object Object]</div>");
You can get around this by first creating your new div, appending the a to that, then appending your new div to the original.
$(document).ready(function() {
var link = $("a"),
new_div = $("<div />").append(link);
$("div").after(new_div);
});
You could use:
$('div').after('<div/>',{html:link});
Try:
div.innerHTML=""+$('a').attr("href").toString()+"";
or:
var str="";
str+=""+$('a').attr("href").toString()+""; // str will contain links href in it
That will append text to div as a string with its href as text to be appended.

jquery access to element after append by variable as id

Via ajax i retrieve some json data, make it as html and append it to my page.
Here I have a problem. I cant access element by id, if id is variable.
For example, http://jsfiddle.net/f8g5e/1/
<div id="123">Hello</div>
<div id="321">Bye</div>
<div id="out"></div>
$(function(){
key = '123';
$('#' + key).hide();
$('#321').hide();
});
The simples thing is works! #123 and #321 elements are hidden. Yeah, it's pretty obviosly.
But, in my project, when I append data to page:
$('#123') //returns element
$('#' + key) //returns null
Some code:
// generating data
var htmlData = '<div id="123">Greetings!</div><div id="321">Bye bye</div>';
// appending data
$('#tweets').empty();
$('#tweets').append(htmlData);
What are the possible causes i can't access elements?
Thanks.
UPDATE
Dont know how it works in JSFiddle, but when I changed my IDs to properly names it began to work now. Thanks to all! Next time, I'll take more attention to w3c dom standarts ;) Happy New Year!
The only reason I can think of that $('#'+key) wouldn't work is because the variable key is undefined.
Note: you're not supposed to start an ID with a number according to the W3C spec. However, most browsers allow it, so I doubt this is causing your problem.
However, if you have two divs with the same ID attribute, then JavaScript will only select the first one it finds -- IDs are supposed to be unique. If this is happening, use classes instead.
You can either do this:
$(function() {
$('#321,#123').hide();
});
or you can do this:
$(function() {
var key = '123';
var doit = '321';
$('#' + key + ',#' + doit).hide();
});

How insert an input field in a table cell?

Sorry for the noob question: I want to create a table with input fields where the can add new ones, if they are needed. But I can'T figure out how add another input field inside a cell where another input field already exists.
My code is:
var par=obj.parentNode;
while(par.nodeName.toLowerCase()!='tr')
{ par=par.parentNode; }
// this gives me the index of the row.. works fine.
cell1=document.getElementById('avz_tabelle').rows[par.rowIndex].cells;
// this puts the content of the cells into the array "cell1"
var feld = cell1[1].createElement("input");
feld.setAttribute("name","avz_keywords" + avz_array + "[]");
feld.setAttribute("onblur","");
feld.setAttribute("type","text");
feld.setAttribute("size","30");
// Now I create a input element
// And now comes the problem:
cell1[1].appendChild(feld); // --> doesn't work
Has anyone a suggestion for me?
I got the idea to work without a table, theoratically that would work with my way. But that wouldn't be satisfying :/
If you look in a debugging console, you should see something like
TypeError: Object #<HTMLDivElement> has no method 'createElement'
Instead of creating the element from cell1[1], use document.createElement()
var feld = document.createElement("input");
You should use document.createElement("input"); instead of cell1[1].createElement("input");
As always (and as also stated in another answer here), the JavaScript console should be the first place to look for hints on what the problem is!
And wouldn't it actually be much easier if each table cell you want to add values to got a separate ID? Something containing perhaps the row index and the column index ... Then you could just select it directly.

Categories

Resources