Imagine I have a table of data in HTML and each of the rows have, say, one of three possible classes: RowA, RowB, and RowC; which represent the information in the rows. (For example, Small, Medium, and Large cars).
Above the table, I have 3 checkboxes: "Show Small Cars", "Show Medium Cars", "Show Large Cars".
If the user deselects "Show Small Cars", then the rows containing small cars should disappear.
This is how I would do it:
function showHideRows(classToShowOrHide, checkBoxSender)
{
var tableObj = document.getElementById("myDataTable");
for (i = 0; i < tableObj.childNodes.length; i++)
if (tableObj.childNodes[i].className == classToShowOrHide)
tableObj.childNodes[i].style.display = checkBoxSender.checked ? "visible" : "none";
}
Is there a better way? For example, can I modify the css class using javascript to include/exclude a display: none?
I'm not using jQuery.
If you define your markup/styles as this:
<table class="showSmallCars showMediumCars">
<tr class="smallCar">...<tr>
<tr class="mediumCar">...<tr>
</table>
CSS:
table tr { display:none; }
table.showSmallCars tr.smallCar { display:table-row; }
table.showMediumCars tr.mediumCar { display:table-row; }
then it is enough for you to modify class attribute on table to present records of groups you need:
Thus <table class="showSmallCars showMediumCars"> will show smalls an mediums
and <table class="showSmallCars showMediumCars showLargeCars"> will show all of them.
And no need to scan all rows in script.
jQuery is a cleaner way to do it; go to http://www.jquery.com and follow the instructions there to start using it, then your function becaomse
function showHideRows(classToShowOrHide, checkBoxSender)
{
$('.' + classToShowOrHide, '#myDataTable').each(function(){
$(this).css('display', ((checkBoxSender.checked) ? 'visible' : 'none'));
});
}
If you want to do it in vanilla JS, something like this should be about right. Probably a gremlin in the following code somewhere, I don't do much vanilla JS any more :) jQuery is that good.
window.onload=function(){
if (document.getElementsByClassName == undefined) {
document.getElementsByClassName = function(className)
{
var hasClassName = new RegExp("(?:^|\\s)" + className + "(?:$|\\s)");
var allElements = document.getElementsByTagName("*");
var results = [];
var element;
for (var i = 0; (element = allElements[i]) != null; i++) {
var elementClass = element.className;
if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass))
results.push(element);
}
return results;
}
}
}
function showHideRows(classToShowOrHide, checkBoxSender)
{
for (i = 0; i < document.getElementsByClassName(classToShowOrHide); i++)
document.getElementsByClassName(classToShowOrHide)[i].style.display = checkBoxSender.checked ? "visible" : "none";
}
Really, the basics of showing and hiding rows can be done very cleanly in CSS. Javascript is only required to tell the surrounding table what type it should show - and that's just a matter of setting a class name.
If this is your HTML:
<table>
<thead>
<tr>
<td>Name</td>
<td>Type</td>
<td>Price</td>
</tr>
<tbody>
<tr class="rowA">
<td>Falcon</td>
<td>Large</td>
<td>$160.00</td>
</tr>
<tr class="rowA">
<td>Commodore</td>
<td>Large</td>
<td>$160.00</td>
</tr>
<tr class="rowB">
<td>Camry</td>
<td>Medium</td>
<td>$110.00</td>
</tr>
<tr class="rowB">
<td>Lancer</td>
<td>Medium</td>
<td>$105.00</td>
</tr>
<tr class="rowC">
<td>Prius</td>
<td>Small</td>
<td>$75.00</td>
</tr>
<tr class="rowC">
<td>Civic</td>
<td>Small</td>
<td>$80.00</td>
</tr>
</tbody>
</thead>
</table>
Use this CSS:
/* The rows to show */
table.showTypeA .rowA,
table.showTypeB .rowB,
table.showTypeC .rowC {
display: table-row;
}
/* Then, hide the other types */
table.showTypeA .rowB,
table.showTypeA .rowC,
table.showTypeB .rowA,
table.showTypeB .rowC,
table.showTypeC .rowA,
table.showTypeC .rowB {
display: none;
}
All you need to do with javascript is set a class on the table of 'showTypeA', 'showTypeB', 'showTypeC', and the browser will take care of the rest.
I know you asked for JavaScript, but you could do it failry easy with jQuery.
Like:
http://jsfiddle.net/XJRVt/17/
You would proberbly also need to do a check on page load :)
Related
i have a site where i paste my entire source code into a box and update all the td tags with a background color if there isnt currently a "bgcolor" attribute.
I've been messing with this for some time but i can't get my ogSource to update. I've tried many ways such as assigning new variables, returns etc etc. No luck.
the below code properly scans for the appropriate td and adds the background color, it just doesnt apply it to the ogSource. I've removed all my other code to make this as basic as possible.
Can anyone assist with this?
Thanks in advance.
var ogSource = '<table id="test1"> <tr> <td> <table id="test2"> <tr> <td> </td> </tr> </table></td> </tr> </table>'
ogSource.replace(/\<td(.*?)\>/g, function(matches) {
if (!matches.includes('bgcolor')) {
var idx = matches.lastIndexOf(">");
if (idx > -1) {
matches = matches.substr(0, idx) + " bgcolor='pink'" + matches.substr(idx);
}
}
});
console.log(ogSource);
EDIT/UPDATE
After a lot of messing around- this was a solution that was able to capture all the source code pasted and make the modification needed.
ogSource = ogSource.replace(/\<td(.*?)\>/g, function( matches , i ) {
var idx = matches.lastIndexOf(">");
if (idx > -1) {
if (!matches.includes('bgcolor')) {
ogSource = matches.substr(0, idx) + " bgcolor='pink'" + matches.substr(idx);
} else {
ogSource = matches;
}
} return ogSource;
});
console.log(ogSource);
My initial answer was off the mark but quite a bit, however, I think regex in general may not be the best solution due to the amount of edge cases present and the DOMParser might be a better solution for this.
Essentially, you pass the html string into the DOMParser method parseFromString and store that in a variable, then select all td elements and check if they have a bgColor attribute, if they don't, give them one, then output the new DOM string.
Here's an example:
const domParser = new DOMParser();
const DOM = domParser.parseFromString(`<table id="test1"> <tr> <td> <table id="test2"> <tr> <td> </td> </tr> </table></td> </tr> </table>`, "text/html");
// Find all tds
const tds = DOM.querySelectorAll("td");
for(let i = 0; i < tds.length; i++) {
let currentTD = tds[i];
if(!currentTD.hasAttribute("bgColor")) {
currentTD.setAttribute("bgColor", "someValue");
}
}
console.log(DOM.body.innerHTML); // If you only want to return the table content
console.log(DOM.querySelector("html").innerHTML); // If you want all of the html code that was added
I have a block of HTML code
<td>{{stock.C4}}</td>
<td>{{stock.C5}}</td>
<td>{{stock.C6}}</td>
<td>{{stock.C7}}</td>
<td>{{stock.C8}}</td>
{{stock.C4}} has an output of None in the html cell.
I want (maybe javascript?) code that basically says
if {{stock.C4}} == 'None'
element.style.backgroundColor = "red"
code that makes the cell a color based on the html/jinja value
If the content of the cell il really empty, you can add the rule
td:empty {
background-color: red;
}
to your css (adapt the selector and the styles to your needs).
the :empty pseudoclass is supported since ie9 (no need to say that other browser support it from day zero).
Also mobile support seems quite good.
Use document.querySelectorAll to get all the td of a specific table, the use array#forEach to check if it is empty using innerHTML, if so use classList.add to add a css class to it
var getAllTD = document.querySelectorAll("#demoTable td");
getAllTD.forEach(function(item) {
if (item.innerHTML === '') {
item.classList.add('empty')
}
})
.empty {
background: green;
}
<table border="1" id="demoTable">
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td></td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td></td>
</tr>
</table>
Here is a possible solution using Mustache (that requires to change your data structure) :
var stocks = [
["A1", "A2", "None"],
["None", "B2", "B3"],
["C1", "None", "C3"]
];
var view = {
stocks: stocks,
isNone: function () {
return this == "None";
}
};
var template = ""
+ "{{#stocks}}"
+ "<tr>"
+ "{{#.}}"
+ "{{#isNone}}<td class=\"none\">{{.}}</td>{{/isNone}}"
+ "{{^isNone}}<td>{{.}}</td>{{/isNone}}"
+ "{{/.}}"
+ "</tr>"
+ "{{/stocks}}"
;
var table = document.getElementById("table");
table.innerHTML = Mustache.render(template, view);
table,td{border:1px solid black;border-collapse:collapse;}
td.none{background:#ffa7b7}
td{padding:.25em}
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>
<table id="table"></table>
i am trying to update first row width with JavaScript,
I have multiple tables
<table page="1">
<tbody>
<tr><td>aaaa</td><td>bbbbb</td></tr>
<tr><td>cccc</td><td>ddddd</td></tr>
....
</tbody>
</table>
<table page="2">
<tbody>
<tr><td>eeee</td><td>fffff</td></tr>
<tr><td>gggg</td><td>hhhhh</td></tr>
....
</tbody>
</table>
and an array
var cw = ["100","500"];
i am trying to create a function that will change only the tds from first row inside each table, so the end result should be
<table page="1">
<tbody>
<tr><td style="width:100px;">aaaa</td><td style="width:500px;">bbbbb</td></tr>
<tr><td>cccc</td><td>ddddd</td></tr>
....
</tbody>
</table>
<table page="2">
<tbody>
<tr><td style="width:100px;">eeee</td><td style="width:500px;">fffff</td></tr>
<tr><td>gggg</td><td>hhhhh</td></tr>
....
</tbody>
</table>
Since i only started using JavaScript i don't know best way to do things, yet, so i put this jsfiddle together from different examples, the problem is that i will have a lot of tables in one page (around 300) and i would like to know if this is the best way to do it:
var cw = ["100","500"];
var i,j,col;
var tables = document.getElementsByTagName("table");
for(i = 0;i<tables.length;i++) {
for ( j = 0, col; col = tables[i].rows[0].cells[j]; j++) {
col.style.width = cw[j]+'px';
}
}
i am afraid that 2 loops will make the browser unresponsive or slow, so can this be done safer with JavaScript or jquery?
Also i need this to work on IE, Chrome and Firefox
Thanks
Here is an example of how it should work
var size = ["100px", "500px"];
var tr = document.querySelectorAll('tbody tr:first-child');
for (i = 0; i < tr.length; i++) {
tr[i].firstElementChild.style.width = size[0];
tr[i].querySelector('td:nth-child(2)').style.width = size[1];
}
td {
background: yellow;
}
// Background for showing purpose only!
<table page="1">
<tbody>
<tr><td>aaaa</td><td>bbbbb</td></tr>
<tr><td>cccc</td><td>ddddd</td></tr>
</tbody>
</table>
<table page="2">
<tbody>
<tr><td>eeee</td><td>fffff</td></tr>
<tr><td>gggg</td><td>hhhhh</td></tr>
</tbody>
</table>
Enjoy!
I'm not sure you'll be able to get away from using two loops. One to go through each table and find the first row and the second to apply the widths to each td. Here's my jQuery version:
function assignWidths(arr){
$('table').each(function(){
var firstRowTds = $(this).find('tr').eq(0).children('td');
firstRowTds.each(function(i){
$(this).css('width', arr[i] + 'px');
});
});
}
<body>
<input type="text" id="search"/>
<table id="boxdata">
<tr>
<td class="namebox1">jQuery</td>
</tr>
<tr>
<td class="namebox2">javascript</td>
</tr>
<tr>
<td class="namebox3">php</td>
</tr>
<tr>
<td class="namebox4">sql</td>
</tr>
<tr>
<td class="namebox5">XML</td>
</tr>
<tr>
<td class="namebox6">ASP</td>
</tr>
</table>
</body>
<script>
$(document).ready(function(){
$('#search').keyup(function(){
searchBox($(this).val());
});
});
function searchBox(inputVal) {
$('#boxdata').find('tr').each(function(index, row){
var names = $(row).find('td');
var found = false;
if(names.length > 0) {
names.each(function(index, td) {
var regExp = new RegExp(inputVal, 'i');
if(regExp.test($(td).text()) & inputVal != ''){
found = true;
return false;
}
});
if(found == true)
$(row).addClass("red");
else
$(row).removeClass("red");
}
});
}
</script>
there's a textfield for searching words and there are 6 words in the each 6 boxes below textfield.(I omitted css codes. but, it wouldnt matter to solve the problem.). if i type a letter 's' then the words that including letter 's' like 'javascript', 'sql', 'ASP' these font-color will be changed black to red. And i made it by using table elements in html but i'd like to change all elements into div style to put some data fluidly later. i have difficulty to fix especially jquery. how can i fix it?
You can simplify this a little bit.
function searchBox(inputVal) {
var regExp = new RegExp(inputVal, 'i');
$('#boxdata').find('tr').removeClass('red').filter(function() {
return $(this).find('td').filter(function() {
return regExp.test( $(this).text() );
}).length && $.trim(inputVal).length;
}).addClass('red');
}
So remove the red class from all <tr>'s first, then filter them, test the text of each <td>, if it matches, return the <tr> and then add the class red again.
Here's a fiddle
As for changing from a table to div, the jQuery would depend on how you structure your markup, but the principle would remain the same.
Here's another fiddle
You can make javascript code HTML agnostic by using css classes instead of element names. Demo.
function searchBox(inputVal) {
var regExp = new RegExp(inputVal = $.trim(inputVal), 'i'),
highlight = 'red';
$('#wrapper').find('.word') //instead of tr/td/div
.removeClass(highlight)
.each(function(){
var $this = $(this);
inputVal && regExp.test($this.text()) &&
$this.addClass(highlight);
});
}
I have a table that is a history of a mysql record.
I want to add a button that will highlight the changes.
<table>
<tr>
<td>100</td>
<td>200</td>
<td>300</td>
</tr>
<tr>
<td>100</td>
<td>200</td>
<td>600</td>
</tr>
</table>
In this example the 600 would be highlighted as it was 300 and is now 600.
UPDATE: Thanks, I should have said there would be more than 2 rows. could be upto 20 rows
This jsFiddle shows an example that will iterate over a table of any size and highlight the cells that have changed from the previous row.
$(function() {
var $rows = $("tr");
for (oldIndex = 0; oldIndex < $rows.length-1; oldIndex++) {
var newIndex = oldIndex + 1;
var $oldCols = $("td", $rows[oldIndex]);
var $newCols = $("td", $rows[newIndex]);
for (col = 0; col < $oldCols.length; col++) {
var $newCol = $($newCols[col]);
if ($($oldCols[col]).html() != $newCol.html()) {
$newCol.addClass("highlight");
}
}
}
});
Your solution should go along these lines. Assuming set1 and set2 are id's of two trs here is a sample code (not tested).
var s1 = $('tr#set1 td');
var s2 = $('tr#set2 td');
var l = $('tr#set1 td').length;
for(var i =0; i<l i++){
if(s1.eq(i).text() != s2.eq(i)){
$(s2.eq(i)).highlight();
}
}
$('table tr.new td').each(function(i){
//First TR td, Previous Rows
td = $(this);
check = $('table tr.prev td:eq('+i+')');
if(td[0].innerText != check[0].innerText)
{
check.addClass('Changed');
}
})
This should do it but you need to add 2 classes:
<table>
<tr class="new">
<td>150</td>
<td>200</td>
<td>300</td>
</tr>
<tr class="prev">
<td>100</td>
<td>200</td>
<td>600</td>
</tr>
</table>
Demo: http://jsfiddle.net/hjXZd/1/
Hope this helps.
I advise you to do an attr for each TD and place the mysql id in there so that you will only compare the rows that are the same in the DB, otherwise if your first list has more items then the second list the results will be corrupt.
Assuming your table has the id results, here is a solution:
var topRow = $('table#results tr:eq(0)');
var bottomRow = $('table#results tr:eq(1)');
topRow.find('td').each(function(index,item){
var shadow = bottomRow.find('td:eq('+index+')');
if($(item).contents().text()!=shadow.contents().text()){
shadow.css({'background':'yellow'});
}
});
Update: this solution compares the top row with all following ones:
$('table#results tr:eq(0) td').each(function(index,item){
var orig = $(item).contents().text();
$('table#results tr:gt(0)').find('td:eq('+index+')').each(function(index2,item2){
var shadow = $(item2);
if(orig!=shadow.contents().text()){
shadow.css({'background':'yellow'});
}
});
});
Using Jquery .live you can handle multiple elements.
See here
http://api.jquery.com/live/
You have to give ids for the changed values.. which can be inside divs.
Hope td also may work
On button click using this .live you can chnage style of div
like highlighting.
Use addClass function os jquery itslef or you can add css using jquery add