Append div inside of td and set the value? - javascript

I have multiple tables that I need to populate. I use jQuery to loop through table cells. If table cell has data-text attribute I need to append div element. Div element will allow cell to have scroll bar vertical. This way table won't expend if text is too long.
Here is example of my code:
$('#'+tabID+' table tr td').each(function(){
elementID = $(this).prop('id').toUpperCase();
value = $.trim(decodeURIComponent(obj.DATA[elementID]['value']));
if($(this).attr('data-text')) {
$(this).append('<div class="hm_textScroll">'+value+'</div>');
} else {
$(this).text(value).css({'color':'blue','font-weight':'bold'});
}
});
Code above will append div element and set the value but the problem is that if I move to a different table and come back again one more div will append. That creates duplicate. I'm not sure what is the best way to prevent that? Or if there is a better way to work around this. If anyone have suggestions please let me know.
Thanks in advance.

Here you go with a solution
$('#' + tabID + ' table tr').each(function(){
$(this).find('td').each(function(){
elementID = $(this).prop('id').toUpperCase();
value = $.trim(decodeURIComponent(obj.DATA[elementID]['value']));
if(typeof $(this).attr('data-text') != 'undefined') {
if($(this).find('div.hm_textScroll').length > 0){
$(this).find('div.hm_textScroll').text(value);
} else {
$(this).append(`<div class="hm_textScroll">${value}</div>`);
}
} else {
$(this).text(value).css({'color':'blue','font-weight':'bold'});
}
});
});
First loop through each tr then loop through each td.
For check the data-attribute, use typeof $(this).attr('data-text') != 'undefined
In the if statement (true condition) I've used backtick ES6 for appending div container.
Hope this will help you.

If I understand you correctly, you would have to additionally check whether a <div class="hm_textScroll"></div> already exists in the <td>.
One possible solution using vanilla javascript would be this:
const tableElement = document.querySelectorAll('#'+tabID+'table tr td');
tableElement.forEach(td => {
if (td.hasAttribute("data-text")) {
if (!td.querySelector(".hm_textScroll")) {
td.innerHTML='<divclass="hm_textScroll">'+value+'</div>'
}
}
});

Related

JQuery: Assigning value to td span if span is empty

I have a table with functions connected to a database. If the player score exists, the value is assigned to the td span. If there is no player score, no value is assigned to the td span. I'm trying to populate the span with "0" if a score doesn't exist, or if the td span is empty.
$("table tbody tr").children('td').find("span.playerScore").each(function () {
var test = $(this).text();
if (test === "") {
$(this).parent("td").children('span').text() = "0";
}
})
This isn't working. I definitely feel it's something obvious and I'm just blind so any help is appreciated. Thanks.
This...
$(this).parent("td").children('span').text() = "0";
is not how you set the text of an element.
You need to pass the text as an argument to text:
$(this).parent("td").children('span').text("0");
It might be easier to use the :empty selector. That can save a couple lines of code.
It's important to note that the value of the text has to be enclosed inside parenthesis.
$("table tbody tr").children('td').find("span.playerScore").filter(":empty").each(function () {
$(this).parent("td").children('span').text("0");
})

Apply CSS on matching text

I am trying to apply a class where text matches with sibling elements.
My certain condition is:
I have a table with multiple rows based on data that I get through database.
One of the td elements has my defined class.
Now I wanted to apply a class only on those td elements where the text of this element matches with another one.
So It would be like, td's whose html/text is equal has that class.
I tried:
$('#table tbody>tr').find('td[class^="customtd"]').each(function() {
if($(this).html().trim() == $(this).siblings('td').html().trim()) {
$(this).addClass('active');
}else {
$(this).removeClass('active');
}
});
You'd have to iterate each sibling td (or use filter), check for a text match, then add the class:
$('#table tbody>tr').find('td[class^="customtd"]').each(function() {
var text = $(this).text();
$(this).siblings("td").filter(function() {
return $(this).text() == text;
}).addClass("active");
});
You have to set the value you are searching for and then loop through all table data. If you find a match, add the certain class.
Furthermore you should cache variables in jQuery and avoid using each() function since its performance is really bad compared to for loops.
//cache the element you are searching for
var search = $('.customtd').html().trim();
//cache the whole table so we can use a for loop
var table = $('#table tbody>tr>td');
//use for loop for more performance
for (var i = 0; i < table.length; i++) {
if(table.eq(i).html().trim() == search) {
table.eq(i).addClass('active');
}else {
table.eq(i).removeClass('active');
}
}
Here is a working example:
http://jsfiddle.net/jnh2heuh/2/

Wrap every child divisible by 5 and previous 4 in a div

I've been working on this JSFiddle to practice my understanding of jquery, but now I'm stuck.
How do you wrap a child element in a div to follow this pattern: child elements 1-5, then child elements 6-10, then child elements 11-15, and so on?
I'm working on a tally counter, so I want every 5 tallies to cluster together. That way, I can more easily select the last child and apply a class to make it rotate, in order to "cross out" the previous 4 tallies.
edit: (To clarify: I've been looking into selecting by index and by nth-child/nth-of-type, but those methods can only really grab the fifth element, or maybe even multiples of five? It doesn't grab the previous divs, too.)
edit 2: (So, you can actually use those selectors! I figured I was getting something wrong. It's always something simple.)
$(".button").click(function() {
var $button = $(this);
var oldValue = $button.parent().find("input").val();
if ($button.text() == "+") {
var newVal = parseFloat(oldValue) + 1;
} else {
// Don't allow decrementing below zero
if (oldValue > 0) {
var newVal = parseFloat(oldValue) - 1;
} else {
newVal = 0;
}
}
$("#counternumber").val(newVal);
});
$("#plus").click(function() {
var tally = "<div class='tally'>I</div>";
$("#dummy").append(tally)
});
$(function(){
$('#scratchpad.tally:nth-of-type(5)').wrap('tallyfamily');
});
JSFiddle.
Here is a general solution to wrap elements in groups of 5:
$(".holder > div:nth-child(5n-4)")
.addClass("first-of-group")
.each(function(){
$(this).nextUntil(".first-of-group")
.addBack()
.wrapAll("<div class='wrapper'>");
})
.removeClass("first-of-group");
http://jsfiddle.net/nJJM8/1/
Basically, :nth-child(5n-4) gets the first element in each group of 5. Then a class is temporarily added to keep track of these. nextUntil is used to find all elements up until the next element with that class. And finally wrapAll is used to wrap the matched elements in a div.
EDIT: Even easier:
var $divs = $(".holder > div");
for (var i = 0; i < $divs.length; i += 5) {
$divs.slice(i, i + 5).wrapAll("<div class='wrapper'>");
}
http://jsfiddle.net/kMzeN/1/
You're almost there, but a couple of things to note. You will only call your "wrap" function once, as it's outside of the click event. If you are dynamically adding, then you'll want to call it each time.
Secondly, with the HTML in your fiddle, you will never get the 5th record because you are appending your selector is looking for the 5th element with ID "scratchpad" with the class of tally. You'd need to change your selector to something that looks for all tallies, like so:
$(".tally:nth-of-type(5)").css('color', 'red');
I've updated the fiddle you were working on, and my code highlights each 5th record, so you can see what's going on. You were close, but you'll also want to add to your "nth-of-type" selector the use of "n", this way it gets every 5th record, not just the 5th one. So the full function becomes this
$("#plus").click(function() {
var tally = "<div class='tally'>I</div>";
$("#dummy").append(tally);
$(".tally:nth-of-type(5n)").css('color', 'red');
});
Fiddle: http://jsfiddle.net/Hfz9L/16/
To rotate (or apply any other property) to each 5th element, you don't even need to wrap them. Just specify a css class using the nth-of-type(5n) and it will affect every 5th element.
#scratchpad .tally:nth-of-type(5n) {
display: inline-block;
transform:rotate(20deg);
-ms-transform:rotate(20deg); /* IE 9 */
-webkit-transform:rotate(20deg); /* Opera, Chrome, and Safari */
}
Here is your fiddle updated: http://jsfiddle.net/Hfz9L/20/
Check this Working Demo Fiddle
$("#plus").click(function() {
var tally = "<div class='tally'>I</div>";
$("#dummy").append(tally);
$('#scratchpad .tally:nth-of-type(5n+1)').prevUntil('span').wrapAll('<span style="margin-right:5px;color:red;text-decoration:line-through;"></span>');
});
$('#scratchpad .tally:nth-of-type(5n+1)').prevUntil('span').wrapAll('<span style="margin-right:5px;color:red;text-decoration:line-through;"></span>');
Some changes:
$('#scratchpad .tally:nth-of-type(5n+1)') and not $('#scratchpad.tally:nth-of-type(5)'). - .tally is the child of #scratchpad ; selector to be used :nth-of-type(5n+1)
Use .wrapAll() - to wrap the selected elements in a <span> or any other element.
.prevUntil() - get all the previous elements.
You can make a for loop and do this:
for(i=1;i<=noOfChildElements/5;i++)
{
$('.child:nth-child('+i+'), .child:nth-child('+(i+1)+'), .child:nth-child('+(i+2)+'), .child:nth-child('+(i+3)+'), .child:nth-child('+(i+4)+')').wrapAll("<div />");
}
Basically I'm going through the child elements in the for loop and at every turn of the loop I'm selecting the 5 next child elements and wrapping them in a div using the .wrapAll() function. Hope this helps.

Getting the content of the first cell from a dynamically created element inside another cell

I am unable to retrieve the content of the first cell. I'm trying it like this:
console.log($(this).closest("tr").find('td:first').innerHTML);
//or...
console.log($('td:first', $(this).parents('tr')).text());
Code:
$('.editable').click(function () {
var text = $(this).text();
if (typeof $(this).find("textarea")[0]=="undefined")//checking if we have a textarea already
{
$(this).text('');
$('<textarea />').appendTo($(this)).val(text).select().blur(function () {
var newText = $(this).val();
$(this).parent().text(newText).find('textarea').remove();
console.log($(this).closest("tr").find('td:first').innerHTML);
});
}
});
JSfiddle: http://jsfiddle.net/KjknL/
I think the problem has to do with the textarea being added dynamically. But I cannot move from it. If I use .prev() or .next(), it returns empty. Any ideas?
try this: http://jsfiddle.net/KjknL/2/
the textarea doesn't exist anymore because you removed it just before trying to reach the first td from it.
console.log($(this).closest("tr").find('td:first').html());
$(this).parent().text(newText).find('textarea').remove();

jQuery to select elements based on the text inside them

How to select a tag having a specific text inside it and nothing else? For example if I have the following:
<table>
<tr>
<td>Assets</td><td>Asset</td>
</tr>
<tr>
<td>Play</td><td>Players</td><td>Plays</td>
</tr>
</table>
Is there any way that I may select the <td>Asset</td> and nothing else. I tried it with contains i.e. $("table tr td:contains(Play)") but it returns all the tds in the second tr (as it should). Whereas I just want <td>Play</td>.
Is there any way to achieve this, like there's a way to select elements based on their attributes. Is there any way to select elements based on the text inside them?
How about that:
var lookup = 'Asset';
$('td:contains('+ lookup +')').filter(function() {
return $(this).text() === lookup;
});
Demo
Try before buy
Try something like this :
$("table tr td").filter(function() {
return $(this).text() === "Play";
})
If it was an input field you can specify something similar, but a little more exact with $('input[name~="Plays"]) so that it would filter out every other word, leaving the value isolated.
Other than that, the only way I know of doing this with a table is with what you had, but also throwing a conditional statement to check the text inside them.
Here is my version of accomplishing this:
http://jsfiddle.net/combizs/LD75y/3/
var play = $('table tr td:contains(Play)');
for (var i = 0, l = play.length; i < l; i++) {
if ($(play[i]).text() === "Play") {
// your script to modify below
$(play[i]).css({"color" : "red"});
}
}

Categories

Resources