jQuery n times .append($('<td></td>')) = less than n columns?
var user = {};
var row = $('<tr></tr>')
.append($('<td></td>').text(user ? user.call_id : ''))
.append($('<td></td>').text(user ? user.phone_number : ''))
.append($('<td></td>').text(开发者_开发技巧user ? user.dialed_number : ''))
.append($('<td></td>').html(user && user.admin ? '<span class="textgreen">admin</span>' : 'guest'))
.append($('<td></td>').append(_talking(user ? user.mute : 0)))
.append($('<td></td>').append($('<span></span>').addClass('timer').text(user ? user.duration : '')))
.append($('<td></td>').addClass('nowrap').append(_userButtons(user)))
;
alert( row.find('td').size() ); // = does NOT always alert 7, but a smaller value
Why is that so?
At the moment, user.dialed_number
is undefined
, therefore the missing column is the third one. And it doesn't matter how much I repeat that column, the result is always 6
in my project.
** UPDATE **
Here is a simplified jsfiddle showing the problem; it should output 7
, but it shows 4
AHA!
$('<td></td>').text(undefined)
is the same as
$('<td></td>').text()
Which as per the jquery document for .text (look at the top right of the doc) it returns the text inside the element. Then you append that text (which is an empty string) to the <tr>
. And that is why the <td>
is not appended
Simple fix:
$('<td></td>').text((true ? undefined : 'false') || '') // oops should be ||
will do an empty string when the first part can be coerced to null (like undefined, 0, null, '', and 0.0)
Proof of concept: JS Fiddle
If any one of the expressions passed to .text()
evaluates to null
or undefined
, the call to .text()
will return the text of the TD
- which is nothing - instead of the jQuery collection representing the TD
. So you'd append 6 TD
s and a nothing.
You're checking that the user
exists each time, but not checking if the property exists which is returning undefined
and making your statement append the contents of the td
(which is nothing) instead of the td
itself.
If you change your tests to check for the property instead, it works: Demo
In your jsfiddle, the reason it is only showing 4 is that the properties on user
are not defined.
Look at this jsfiddle
Maybe your user properties are not defined?
I would strongly suggest you stop trying to be quite so clever and single-step each append
and see what's happening, rather than trying to do it all in one line. For one thing, it probably isn't doing what you think it should be doing anyway the way you wrote it - each td
is getting inserted INSIDE the previous one!
Try this way:
var row = $('<tr></tr>');
row.append($('<td></td>').text(user ? user.call_id : ''));
row.append($('<td></td>').text(user ? user.phone_number : ''));
row.append($('<td></td>').text(user ? user.dialed_number : ''));
row.append($('<td></td>').html(user && user.admin ? '<span class="textgreen">admin</span>' : 'guest'));
row.append($('<td></td>').append(_talking(user ? user.mute : 0)));
row.append($('<td></td>').append($('<span></span>').addClass('timer').text(user ? user.duration : '')));
row.append($('<td></td>').addClass('nowrap').append(_userButtons(user)));
alert( row.find('td').size() ); // = alerts 6 when it should be 7
Also, when I run your code even with your crazy syntax (after ensuring that all functions and variables are defined and exist) I get 7.
The script appends the cell to the previous cell, not the row. $.end() returns the selected object at the beginning of the chain, i.e.:
$('tr', this).append($('<td>').text(user ? user.call_id : ''))
.end().append($('<td>').text(user ? user.phone_number : ''))
.end().append($('<td>').text(user ? user.dialed_number : '')) //etc.
corrected version
function _talking() {
return $('<span>TalkingFn</span>');
}
function _userButtons() {
return $('<button>button1</button><button>button2</button>');
}
var user = {};
var row = $('<tr></tr>')
.append($('<td></td>').text(user.call_id ? user.call_id : '{calli_id}'))
.append($('<td></td>').text(user.phone_number ? user.phone_number : '{phone_number}'))
.append($('<td></td>').text(user.dialed_number ? user.dialed_number : '{dialed_number}'))
.append($('<td></td>').html(user && user.admin ? '<span class="textgreen">admin</span>' : 'guest'))
.append($('<td></td>').append(_talking(user.mute ? user.mute : 0)))
.append($('<td></td>').append($('<span></span>').addClass('timer').text(user.duration ? user.duration : '')))
.append($('<td></td>').addClass('nowrap').append(_userButtons(user)))
;
alert( row.find('td').size() ); // = alerts 6 when it should be 7
$('#foo > tbody').append(row);
精彩评论