get data attribute and append optimize - javascript

I have been fiddling around and with some code I found here I managed to get some working code although I wonder if it can be optimized further.
I have tried to comment the code so my thought process is shown. If anyone knows a better way to achieve to [get the data-tid attribute and append the value to a span in that tablerow to a td] I would love to hear it.
<table>
<tr data-tid="3"><td class="col_f_icon">aaa</td><td class="col_f_content">fdsfdsf</td></tr>
<tr data-tid="2"><td class="col_f_icon">aaa</td><td class="col_f_content">fdsfdsf</td></tr>
<tr data-tid="5"><td class="col_f_icon">aaa</td><td class="col_f_content">fdsfdsf</td></tr>
<tr data-tid="6"><td class="col_f_icon">aaa</td><td class="col_f_content">fdsfdsf</td></tr>
</table>
$j = jQuery.noConflict();
$j(document).ready(function() {
topiclistview = $j('[data-tid]').length;
// check if data-tid exists
if (topiclistview > 0) {
//set vars
var tids = $j('[data-tid]');
var tids_array = [];
//get the data attribute values and put them in an array
$j(tids).each(function(index, item) {
tids_array.push($j(item).data('tid'));
});
//run over all tr with the class .col_f_content and append the attribute value
$j('.col_f_content').each(function(index, item){
$j('<span>'+tids_array[index]+'</span>').appendTo($j(item));
//console.log('tr item'+tids_array[index]);
});
}
});

Performance-wise? This is probably a good shot:
// iterate over all elements having the data-tid attribute
$("[data-tid]").each(function() {
// Create our span. No need for a jQuery wrapper.
var span = document.createElement("span");
// Set the span text. No need to involve jQuery's data() function
span.appendChild(document.createTextNode(this.getAttribute("data-tid")));
// Add the span to your second cell (col_f_content). This should be way faster
// than creating a new jQuery object via class selector.
this.cells[1].appendChild(span);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr data-tid="3">
<td class="col_f_icon">aaa</td>
<td class="col_f_content">fdsfdsf</td>
</tr>
<tr data-tid="2">
<td class="col_f_icon">aaa</td>
<td class="col_f_content">fdsfdsf</td>
</tr>
<tr data-tid="5">
<td class="col_f_icon">aaa</td>
<td class="col_f_content">fdsfdsf</td>
</tr>
<tr data-tid="6">
<td class="col_f_icon">aaa</td>
<td class="col_f_content">fdsfdsf</td>
</tr>
</table>
Alternatively, depending upon your needs, you could achieve something similar with CSS only:
tr[data-tid]:after {
display: table-cell;
vertical-align: middle;
content: attr(data-tid);
}
<table>
<tr data-tid="3">
<td class="col_f_icon">aaa</td>
<td class="col_f_content">fdsfdsf</td>
</tr>
<tr data-tid="2">
<td class="col_f_icon">aaa</td>
<td class="col_f_content">fdsfdsf</td>
</tr>
<tr data-tid="5">
<td class="col_f_icon">aaa</td>
<td class="col_f_content">fdsfdsf</td>
</tr>
<tr data-tid="6">
<td class="col_f_icon">aaa</td>
<td class="col_f_content">fdsfdsf</td>
</tr>
</table>

I'd try something like this:
$('[data-tid]').each(function(){
var value = $(this).data('tid');
$('<span>' + value + '</span>')
.appendTo($(this).find('.col_f_content'));
});
(PS: Untested)

You don't need to use intermediate arrays, and you can store the set of elements the first time you select them (when you test if there are any elements with [data-tid]).
It should be more performant to select based on a class, so if it's possible to add a class a class to the data-tid element html, we could use that for our selector.
$(document).ready(function() {
'use strict';
// We want to work with these elems
var topiclist = $('[data-tid]');
if (topiclist.length > 0) {
// Just get the data, make a new elem and append it
// All in 1 pass
topiclist.each(function(_, el) {
var $el = $(el);
$el.append('<td>' + $el.data('tid') + '</td>');
});
}
});
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<table>
<tr data-tid="3"><td class="col_f_icon">aaa</td><td class="col_f_content">fdsfdsf</td></tr>
<tr data-tid="2"><td class="col_f_icon">aaa</td><td class="col_f_content">fdsfdsf</td></tr>
<tr data-tid="5"><td class="col_f_icon">aaa</td><td class="col_f_content">fdsfdsf</td></tr>
<tr data-tid="6"><td class="col_f_icon">aaa</td><td class="col_f_content">fdsfdsf</td></tr>
</table>
Also note, I'm appending a <td> with your contents to the <tr>, which is the element you selected. <span> is not a legal child of <tr>. If you want to do something with a <span>, you'll need to wrap it in a <td> if it's in a table.

Related

How do I filter a table by any matching code/name and not every available field

I'm trying to do the following: I have a table populated with data from the DB. Apart from that, I have an input where you can write something and a button that will filter, only showing the lines that have that string. This is working now!
The thing is, the input should only allow you to filter by foo.name/foo.code (two propertys of my entity).
I'm adding the code I have in case anyone can guide me out, I've tried several things but this are my first experiences with JQuery while I have a strict story-delivery time. Thanks everyone!
<tbody>
<c:forEach var="foo" items="${foo}">
<tr id = "fooInformation" class="mtrow">
<th id="fooName" scope="row">${foo.name}</th>
<td id="fooCode" class="left-align-text">${foo.code}</td>
<td class="left-align-text">${foo.country}</td>
<td class="left-align-text">${foo.region}</td>
<td class="left-align-text">${foo.subregion}</td>
</tr>
</c:forEach>
</tbody>
$("#search").click(function () { -> button id
var value = $("#fooRegionSearch").val(); -> value of the input
var rows = $("#fooRegionTable").find("tr"); -> table id
rows.hide();
rows.filter(":contains('" + value + "')").show();
});
To start with, your HTML is invalid - there cannot be elemenets with duplicate IDs in HTML. Use classes instead of IDs.
Then, you need to identify which TRs pass the test. .filter can accept a callback, so pass it a function which, given a TR, selects its fooName and fooCode children which contain the value using the :contains jQuery selector:
$("#search").click(function() {
var value = $("#fooRegionSearch").val();
var rows = $("#fooRegionTable").find("tr");
rows.hide();
rows.filter(
(_, row) => $(row).find('.fooName, .fooCode').filter(`:contains('${value}')`).length
).show();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="fooRegionTable">
<tr id="fooInformation" class="mtrow">
<th class="fooName" scope="row">name1</th>
<td class="fooCode" class="left-align-text">code1</td>
<td class="left-align-text">${foo.country}</td>
<td class="left-align-text">${foo.region}</td>
<td class="left-align-text">${foo.subregion}</td>
</tr>
<tr id="fooInformation" class="mtrow">
<th class="fooName" scope="row">name2</th>
<td class="fooCode" class="left-align-text">code2</td>
<td class="left-align-text">${foo.country}</td>
<td class="left-align-text">${foo.region}</td>
<td class="left-align-text">${foo.subregion}</td>
</tr>
</table>
<button id="search">click</button><input id="fooRegionSearch" />

How to loop through a table and get the td elements to follow a condition

I just want make so it the tr hides when the td does not follow the requirements, tried with jQuery and JavaScript, don't know what's wrong.
$(document).ready(function(){
$("td").each(function() {
var id = $(this).attr("price_search");
if (id > value4 && id < value5) {
$(this).hide;
}
else {
$(this).hide;
}
});
});
You can do this.
Hope this will help you.
$(document).ready(function() {
var value4 = 2;
var value5 = 4;
$("td").each(function() {
var id = $(this).attr("price_search");
if (id > value4 && id < value5) {
$(this).hide();
} else {
$(this).show();
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td price_search="3">10</td>
<td price_search="2">20</td>
<td price_search="3">30</td>
</tr>
</table>
I am going to go out on a limb here and make broad assumptions on content not in the question.
Your .hide; is invalid syntax
You are missing value for two variables value4 and value4 which frankly are not well named variables at all. I will make an assumption that those are better named and that they come from somewhere during the page rendering.
I make an assumption that you have something you want to filter/hide by those upper/lower price points.
I make the assumption the attribute might contain values that need to be parsed (not a number as they are)
var lowerPricePoint = .45;
var upperPricePoint = 5.25;
$(function() {
$("td").filter('[price_search]').each(function() {
// parse out a price from perhaps formatted values
let price = Number.parseFloat($(this).attr("price_search").replace(/\$|,/g, ''));
// toggle visibility of the row
$(this).closest('tr').toggle(price > lowerPricePoint && price < upperPricePoint);
});
});
td {
border: solid black 1px;
padding: 0.4em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<table>
<tr>
<td>Wear it</td>
<td price_search="123.13">Shoes</td>
</tr>
<tr>
<td>Drive it</td>
<td price_search="$23,123.13">Car</td>
</tr>
<tr>
<td>Drink it</td>
<td price_search="3.13">Beet Juice</td>
</tr>
<tr>
<td>Eat it</td>
<td price_search="12.13">Can of expensive corn</td>
</tr>
<tr>
<td>Cheap</td>
<td price_search="35">Radish</td>
</tr>
<tr>
<td>Use it</td>
<td price_search="1.45">Paper towel</td>
</tr>
<tr>
<td>Plain</td>
<td price_search="$1.87">Butter</td>
</tr>
<tr>
<td>Herb</td>
<td price_search="$2.45">Butter</td>
</tr>
<tr>
<td>Cheap</td>
<td price_search="15">Gum</td>
</tr>
</table>

jQuery show a class and hide all others

this is what I would like to do:
I have this list HTML
<table>
<tr>
<td class = "point">Point1</td>
</tr>
<tr>
<td class = "point">Point2</td>
</tr>
<tr>
<td class = "meanCurvature">mean Curvature 1</td>
</tr>
<tr>
<td class = "meanValue">mean Value 1</td>
</tr>
</table>
and a selector with several options.
Then I have a
JS
if($("#selector").val() == "strain"){
$(".point").show();
$(".meanCurvature").hide();
$(".meanValue").hide();
}
if($("#selector").val() == "curvature"){
$(".meanCurvature").show();
$(".point").hide();
$(".meanValue").hide();
}
if($("#selector").val() == "average"){
$(".meanValue").show();
$(".meanCurvature").hide();
$(".point").hide();
}
I would like to know: now I only have three class and it is handable, but is there a way to say "Show this class and Hide all other"?
I suggest this if you have limited number of rows in your table.
if($("#selector").val() == "strain"){
$(".point").show();
$('td').not('.point').hide();
}
if($("#selector").val() == "curvature"){
$(".meanCurvature").show();
$('td').not('.meanCurvature').hide();
}
if($("#selector").val() == "average"){
$(".meanValue").show();
$('td').not('.meanValue').hide();
}
you may want something like this
if($("#selector").val() == "strain"){
$(".point").show();
$(".point").parent().siblings('tr').children('td').hide();
}
If it were me, I would say
$("td").hide();
$(".desiredClass").show();
This will first hide all your table elements, then reveal the one you're interested in. However, I would also assign a class to your table, so you can avoid interfering with other tables on the page:
<table class="myTable">
...
and the javascript would then be
$(".myTable td").hide()
$(".desiredClass").show()
You could further improve this using advanced selectors
$(".desiredClass").show()
$(".myTable td:not(.desiredClass)").hide()
The above could would avoid any possible 'stuttering' by hiding and then revealing the desired element.
You can do it by showing all tds and then hide the ones that have other classes using not() function. Alternatively you can hid all tds and then show your selected class.
Before doing that, you need to convert your selector value to the desired class using a simple switch.
function apply() {
var selectedVal = $("#selector").val();
switch (selectedVal) {
case "strain":
selectedVal = "point";
break;
case "curvature":
selectedVal = "meanCurvature";
break;
case "average":
selectedVal = "meanValue";
break;
}
$("td").show().not("." + selectedVal).hide();
}
apply();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="selector" onchange="apply()">
<option>strain</option>
<option>curvature</option>
<option>average</option>
</select>
<table>
<tr>
<td class="point">Point1</td>
</tr>
<tr>
<td class="point">Point2</td>
</tr>
<tr>
<td class="meanCurvature">mean Curvature 1</td>
</tr>
<tr>
<td class="meanValue">mean Value 1</td>
</tr>
</table>
You can make it easier and get rid of the switch if you can change your selector values to match the classes:
function apply() {
$("td").show().not("." + $("#selector").val()).hide();
}
apply();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="selector" onchange="apply()">
<option value="point">strain</option>
<option value="meanCurvature">curvature</option>
<option value="meanValue">average</option>
</select>
<table>
<tr>
<td class="point">Point1</td>
</tr>
<tr>
<td class="point">Point2</td>
</tr>
<tr>
<td class="meanCurvature">mean Curvature 1</td>
</tr>
<tr>
<td class="meanValue">mean Value 1</td>
</tr>
</table>
you can use the :not selector such as:
$("td:not(.classToActuallyShow)").hide();
Will select all the table data(td) elements and hide them, unless they have a specific class.
My approach would be combine all those classes into one selector. Hide them all then filter the one you want to show based on a stored object that matches the value to the class
var classMatches ={
'strain':'point',
'curvature':'meanCurvature',
'average': 'meanValue'
};
var matchingClass = classMatches[$("#selector").val()];
$('.point, .meanCurvature, .meanValue')
.hide()
.filter('.'+ matchingClass ).show()
You can use not() as selector or as a method to selects all elements except the specified element.
Another way would be use multiple elements selector, like $(".point, .meanValue").hide();But it isnt reccomended if you have a lot of classes in this case.
Check this working example:
$("#selector").change(function(){
if($(this).val() == "strain"){
$(".point").show();
$("td:not(.point)").hide();
}
if($(this).val() == "curvature"){
$(".meanCurvature").show();
$(".point, .meanValue").hide();
}
if($(this).val() == "average"){
$(".meanValue").show();
$("td:not(.meanValue)").hide();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="selector">
<option disabled selected>Select option</option>
<option>strain</option>
<option>curvature</option>
<option>average</option>
</select>
<table>
<tr>
<td class = "point">Point1</td>
</tr>
<tr>
<td class = "point">Point2</td>
</tr>
<tr>
<td class = "meanCurvature">mean Curvature 1</td>
</tr>
<tr>
<td class = "meanValue">mean Value 1</td>
</tr>
</table>

Selecting content with JQuery

Any ideas why this doesn't work?
http://jsfiddle.net/zk4pc/2/
I'm trying to get it so that everytime there is an element with the class "insert_name", the name is printed from the table.
Could you also help me make the selection more advanced (for instance only using the data from the first tr in the "client-profile" class?
Thanks!
HTML
<body onload="printMsg()">
<div id="api_data" style="display:none;">
<div class="client-profile">
<div class="head icon-5">Customer Details</div>
<table id="client-information">
<tbody>
<tr>
<td class="left">Name:</td>
<td class="color">Matthew Tester
</td>
</tr>
<tr class="dark">
<td class="left">E-mail:</td>
<td class="color">asdfg</td>
</tr>
<tr>
<td class="left">Registration:</td>
<td class="color">2013-11-21</td>
</tr>
<tr class="dark">
<td class="left">Status:</td>
<td class="color"><span class="active">Active</span>
</td>
</tr>
<tr>
<td class="left">Last Login Time:</td>
<td class="color" title="2014-05-28 11:43:46">1 hour ago</td>
</tr>
<tr class="dark">
<td class="left">Last Login From:</td>
<td class="color">123.123.123.123</td>
</tr>
<tr>
<td class="left">Location:</td>
<td class="color">United Kingdom</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="insert_name"></div>
</body>
Javascript
(function printMsg() {
var node = document.getElementsByClassName('insert_name');
node.innerHTML = $('[class*="color"]').eq(0).text();
})();
jsFiddle Demo
The issue is with your node selection. When you select by class name it returns an array of elements. Since you are only looking for the div with that class name, access the first index to reference it.
var node = document.getElementsByClassName('insert_name')[0];
edit
To make this iterate all of the nodes you could take this approach
var nodes = document.getElementsByClassName('insert_name');
var text = $('[class*="color"]').eq(0).text();
for(var i = 0; i < nodes.length; i++){
nodes[i].innerHTML = text;
}
Alternatively, since jQuery is already included, you could remove the body's onload event and just use this
jsFiddle Demo
$(function(){
$('.insert_name').html($('[class*="color"]').eq(0).text());
});
To ensure this only acts on the client-profile class the selector would be
$('.insert_name').html($('.client-profile [class*="color"]').eq(0).text());
If you are just trying to insert the name rather than all of the content, this should do the trick:
$(function() {
$('.insert_name').text($('td:contains("Name:")').next().text());
});
Here is the fiddle:
http://jsfiddle.net/b8LKQ/
Hope that helps!
I added a little more jQuery:
$(function() {
$('[class*="color"]').each(function(){
$('.insert_name').append($(this).text());
});
});
http://jsfiddle.net/zk4pc/7/
Hope that helps!

Don't remove content from table td first child

(JSfiddle Example)
I want to exclude the text in td first child from being removed so that the text Sale,Age remains, for example:
The original HTML:
<table class="toptable"><thead>
<tr>
<th class="dsdds_image">-</th>
<th class="r3dde_image">-</th>
<th class="s43434_image">-</th>
</tr></thead><tbody>
<tr>
<td class="44665_description">Name</td>
<td class="3434d_description">Alan</td>
<td class="a34df_description">John</td>
</tr>
<tr>
<td class="dfs4rf_title">Age</td>
<td class="adf43df_title">8</td>
<td class="dsffds4_title">9</td>
</tr></tbody>
</table>
After remove(), it should be
<table class="toptable"><thead>
<tr>
<th class="dsdds_image"></th>
<th class="r3dde_image"></th>
<th class="s43434_image"></th>
</tr></thead><tbody>
<tr>
<td class="44665_description">Name</td>
<td class="3434d_description"></td>
<td class="a34df_description"></td>
</tr>
<tr>
<td class="dfs4rf_title">Age</td>
<td class="adf43df_title"></td>
<td class="dsffds4_title"></td>
</tr></tbody>
</table>
I use an if statement to check if it is :first-child before the remove function but it's still clearing the first child text. Could anyone give me some suggestions?
$('#cleartable').on('click', function () {
var clear = $(".toptable td,.toptable th")
if (clear.not(':first-child')){ //*******This part
clear.contents().filter(function(){
return this
}).remove();
}
clear.each(function() {
var $this = $(this)
if ($this.attr('class')){
var changeclass = $(this).attr("class");
$this.attr('class',changeclass.replace(/^[^_]+/,"placeholder"));//See this?
}
});
});
Try
Fiddle demo
clear.filter(function () {
return $(this).index() !== 0; //return false for the first indexed element inside the parent
//return !$(this).is(':first-child'); you can also use
}).remove(); //if you don't wanna remove them set empty text .text('') .
.index()
.filter()
.is()
Maybe an easy way :
var clear = $(".toptable td+td,.toptable th")
In your code you are using
if (clear.not(':first-child'))
jQuery's .not() will return a jQuery instance not boolean value, so this may not be doing what you expect.
A quick and easy way to do what you want is
clear.not(':first-child').text('');

Categories

Resources