I'm kind of stuck in a keyframe. I have a table with values from a fetch (json) and i should add a hover when the values is less than 5 in red and starting from 5 in green. This is my code in javascript ->
how do i have to implement the keyframe with it in css or is it different that i think?
// Html
<div id="group3">
<table class="table">
<thead>
<tr class="info">
<th></th>
<th>February</th>
<th>March</th>
<th>April</th>
<th>May</th>
<th>June</th>
<th>July</th>
<th>August</th>
</tr>
</thead>
<tbody id='mytable'>
</tbody>
</table>
</div>
//CSS
Keyframe?
//hover
let cells = document.querySelectorAll("tbody");
cells.forEach( el => el.addEventListener('mouseenter', function () {
if(el.textContent < 5){
el.classList.add('underfive');
} else if (el.textContent >=5){
el.classList.add('abovefive');
}
}));
// reset animationx
cells.forEach(el => el.addEventListener('mouseleave', function () {
if(el.textContent < 5){
el.classList.remove('underfive');
} else if (el.textContent >=5){
el.classList.remove('abovefive');
}
}));
it should be like this ->
this is the startpage, background is white
this is the end result how it should be, uploaded from a json file in a table, red value
this is the green value when it's 5 of higher
Based on what you say you want to show a different background color or styling in general than the default if the mouse is over the td.
So use :hover for that. You want to have a transition between those states so use transition.
You want to have a different color if it is above or below 5. So define what you want to have as default and add a class for the other case.
let data = [1,4,2,8,12,2,5,7];
const tr = document.querySelector('tr');
data.forEach(elem => {
let td = document.createElement('td');
td.textContent = elem;
td.classList.toggle('belowfive', elem < 5);
tr.appendChild(td);
});
td {
transition: background-color 1s;
background-color: white;
padding: 1rem;
border: 1px solid hsl(0 0% 50%);
}
td:hover {
background-color: green;
}
td.belowfive:hover {
background-color: red;
}
<table>
<tbody>
<tr>
</tr>
</tbody>
</table>
Related
In the website I am trying to create, I want a 7x7 table, each cell being a "button" that you can click on to toggle between images. Almost like a bingo board, you click on a cell and it will mark it as being completed by switching to another image. I am using localstorage to store which image is being shown so a user can keep their progress basically.
My problem is that since there is only 1 "backgroundImage" property, how do I have a different image in each box that I can toggle without affecting the others?
The javascript I provide is the same function twice, as it works for the first button but not for the second one, as I am guessing the background image is being conflicted with since they are both trying to access the same one.
HTML code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js" data-semver="3.0.0" data-require="jquery"></script>
<script src="js/script.js"></script>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<table>
<tr>
<th>T</th>
<th>W</th>
<th>I</th>
<th>S</th>
<th>T</th>
<th>E</th>
<th>D</th>
</tr>
<tr>
<th><button class="button1"></button></th>
<th><button class="button2"></button></th>
<th>Task 3</th>
<th>Task 4</th>
<th>Task 5</th>
<th>Task 6</th>
<th>Task 7</th>
</tr>
</table>
</body>
</html>
CSS:
button
{
display: inline-block;
width: 100%; /* set to 100% */
height: 100%; /* set to 100% */
margin-bottom: 0.5em;
padding-top: .6em;
padding-bottom: .6em;
color: #fff;
background-color: #aaabbb;
border-radius: 5px;
border: solid #cccccc 1px;
clear:right;
float:right;
height: 150px;
width: 150px;
}
JS:
$(function(){
if (localStorage.getItem('backgroundImage') !== null) {
url = localStorage.backgroundImage;
$('.button1').css('backgroundImage', url);
}
else
{
url = 'url(images/button1.png)';
}
$('.button1').click(function(){
if(url == "url(images/button1.png)"){
localStorage.removeItem('backgroundImage');
$('.button1').css('backgroundImage', 'url(images/button1no.png)');
localStorage.setItem('backgroundImage', 'url(images/button1no.png)');
}
else {
url = 'url(images/button1no.png)';
localStorage.removeItem('backgroundImage');
$('.button1').css('backgroundImage', 'url(images/button1.png)');
localStorage.setItem('backgroundImage', 'url(images/button1.png)');
}
});
});
//----------------------------------------------------------------------------
$(function(){
if (localStorage.getItem('backgroundImage') !== null) {
url = localStorage.backgroundImage;
$('.button2').css('backgroundImage', url);
}
else
{
url = 'url(images/button2.png)';
}
$('.button1').click(function(){
if(url == "url(images/button2.png)"){
localStorage.removeItem('backgroundImage');
$('.button2').css('backgroundImage', 'url(images/button2no.png)');
localStorage.setItem('backgroundImage', 'url(images/button2no.png)');
}
else {
url = 'url(images/button2no.png)';
localStorage.removeItem('backgroundImage');
$('.button2').css('backgroundImage', 'url(images/button2.png)');
localStorage.setItem('backgroundImage', 'url(images/button2.png)');
}
});
});
You need to store an array of the values instead of one value. Local Storage does not support complex values, but you can use JSON to encode it. So when you set the value, you would do something like this:
localStorage.setItem('backgroundImage', JSON.stringify(someArray));
And when you read it, parse it:
myArrayofValues = JSON.parse(localStorage.getItem('backgroundImage'))
Remember that by default the value will be empty, so you may want to set an initial value of an empty array first.
There are two questions here:
How to toggle bettween two images for each buttons
How to store the "current" image for each button
I would use data attributes to store both images url AND the current one (and a number telling which one is used). That makes it easy to maintain all the urls directly in your markup.
I would also use it to store the "index" of each button, just to simplify the correspondance of each buttons with the index of an array to be stored in localStorage.
So on click, you will simply toggle between 2 urls and store the new "image number" in the array, at the right index.
Notice that it isn't the url that is stored... it's already in the markup.
Now, as #Raymond Camden explained, localStorage can store a string... Not an object or an array. That is why JSON.stringify() and JSON.parse() are used.
$(document).ready(function() {
// retrieve localStorage if exist
let bg_numbers = [];
/*if (localStorage.getItem("bg_numbers") !== null) {
bg_numbers = JSON.parse(localStorage.getItem("bg_numbers"))
}*/
console.log(bg_numbers)
// Setting the data-bg_current and data-btn_index
$("button").each(function(index, btn) {
let $btn = $(btn);
// Get the urls for this button
let backgrounds = [$btn.data("bg_1"), $btn.data("bg_2")];
// Retreive the image number used, if any
let currentImage = (bg_numbers[index] && bg_numbers[index] === 1) ? 1 : 0;
// Set it
$btn.css("background-image", `url('${backgrounds[currentImage]}')`);
// Update the data attributes, since thos are zero on page load
$btn.data("bg_current", currentImage);
$btn.data("btn_index", index)
});
$("button").on("click", function() {
let $btn = $(this);
// Get the index of this button
let index = $btn.data("btn_index")
// Get the urls for this button
let backgrounds = [$btn.data("bg_1"), $btn.data("bg_2")];
// Toggle the image
let currentImage = ($(this).data("bg_current") === 1) ? 0 : 1;
$(this).css("background-image", `url('${backgrounds[currentImage]}')`);
// Update the array and save to localStorage
bg_numbers[index] = currentImage
//localStorage.setItem("bg_numbers", JSON.stringify(bg_numbers))
});
});
button {
display: inline-block;
width: 100%;
/* set to 100% */
height: 100%;
/* set to 100% */
margin-bottom: 0.5em;
padding-top: 0.6em;
padding-bottom: 0.6em;
color: #fff;
background-color: #aaabbb;
border-radius: 5px;
border: solid #cccccc 1px;
clear: right;
float: right;
height: 150px;
width: 150px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<th>T</th>
<th>W</th>
<th>I</th>
<th>S</th>
<th>T</th>
<th>E</th>
<th>D</th>
</tr>
<tr>
<th><button data-bg_1="https://via.placeholder.com/150x150.png?text=Button 1" data-bg_2="https://loremflickr.com/150/150" data-bg_current=0 data-btn_index=0></button></th>
<th><button data-bg_1="https://via.placeholder.com/150x150.png?text=Button 2" data-bg_2="https://loremflickr.com/150/150" data-bg_current=0></button></th>
<th>Task 3</th>
<th>Task 4</th>
<th>Task 5</th>
<th>Task 6</th>
<th>Task 7</th>
</tr>
</table>
I commented all lines related to localStorage here since SO snippet are disallowing it... And it was throwing an ugly error. But see my CodePen.
I tried to update data attribute as my work below.
When I click square,data attribute should be incremented.
But the result is a little bit different. It seems not to be incremented.
How can I fix them?
And Why this issue inccured?
Thanks
$("td").click(function() {
index=$(this).data('layer');
index+=1
$(this).attr('data-layer',index);
console.log(this);
});
td {
border:solid black 1px;
width:50px;
height:50px;
cursor:pointer;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td data-layer="0"></td>
</tr>
</table>
An Html element can have a dataset and/or an attribute.
In your code you get the value of the dataset and change like if it is an attribute. This is your mistake.
For more details see .data() and .attr().
If you are inrested in attribues you need to use:
$("td").click(function() {
index=$(this).attr('data-layer');
index = index + 1;
$(this).attr('data-layer',index);
console.log(this);
});
Instead, if you need to use dataset:
$("td").click(function() {
index=$(this).data('layer');
index = index + 1;
$(this).data('layer',index);
console.log($(this).data('layer'));
});
td {
border:solid black 1px;
width:50px;
height:50px;
cursor:pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td data-layer="0"></td>
</tr>
</table>
$("td").click(function() {
const index = $(this).attr('data-layer');
const newIndex = Number(index) + 1;
$(this).attr('data-layer', newIndex);
console.log(this);
});
td {
border:solid black 1px;
width:50px;
height:50px;
cursor:pointer;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td data-layer="0"></td>
</tr>
</table>
In my code, each class will be toggled by clicking them.
I would like to understand the data,class-index, in my code,class-index is changed and class will be changed aligned with this.
But when I look at developer tool, class-index dosen't seems to be changed.
<td class="classC" data-class-index="0">Value 1</td>
<td class="classB" data-class-index="0">Value 1</td>
Considering this, I add undo button,it works as a reverse of toggle,but it didn't work well.
How can I fix it?
$(function(){
var classArray = ['classA','classB','classC'];
var arrLen = classArray.length;
$("#our_calendar td").click(function() {
var classIndex = $(this).data('class-index');
$(this).removeClass(classArray[classIndex]);
if(classIndex < (arrLen-1)) {
classIndex++;
} else {
//reset class index
classIndex = 0;
}
$(this).addClass(classArray[classIndex]);
$(this).data('class-index',classIndex);
});
$("#undo").on('click',function() {
var classIndex = $(this).data('class-index');
$(this).removeClass(classArray[classIndex]);
classIndex--;
$(this).addClass(classArray[classIndex]);
$(this).data('class-index',classIndex);
})
});
.classA {
background-color: aqua;
}
.classB {
background-color: yellow;
}
.classC {
background-color: red;
}
td {
transition-duration:0.4s ;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="our_calendar">
<tr><td class="classA" data-class-index="0">Value 1</td></tr>
</table>
<button id="undo">undo</button>
With regard to the DOM not being updated, this is expected behaviour as the data() method only updates jQuery's internal cache of data attributes. It does not update the data attributes held in the relevant elements in the DOM.
With regard to your issue, the main problem is because you're using this within the #undo click handler. That will refer to the clicked button, not the td with the class on it. You just need to target the right element.
Also note that the classIndex logic can be simplified by using the modulo operator. Try this:
$(function() {
let classArray = ['classA', 'classB', 'classC'];
let arrLen = classArray.length;
let $td = $("#our_calendar td");
$td.click(function() {
let classIndex = $td.data('class-index');
$td.removeClass(classArray[classIndex]);
classIndex = ++classIndex % classArray.length;
$td.addClass(classArray[classIndex]);
$td.data('class-index', classIndex);
});
$("#undo").on('click', function() {
let classIndex = $td.data('class-index');
$td.removeClass(classArray[classIndex]);
classIndex = (--classIndex + classArray.length) % classArray.length;
$td.addClass(classArray[classIndex]);
$td.data('class-index', classIndex);
});
});
.classA { background-color: aqua; }
.classB { background-color: yellow; }
.classC { background-color: red; }
td { transition-duration: 0.4s; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="our_calendar">
<tr>
<td class="classA" data-class-index="0">Value 1</td>
</tr>
</table>
<button id="undo">undo</button>
I have a csv file which has this format:
Major;2;4;29
Major should be displayed on the 4 row 2 column.
The file can have a lot nof rows!
I have created this:
var fileInput = document.getElementById("csv"),
readFile = function () {
var reader = new FileReader();
reader.onload = function () {
document.getElementById('out').innerHTML = reader.result;
};
reader.readAsBinaryString(fileInput.files[0]);
};
fileInput.addEventListener('change', readFile);
<style type="text/css">
output {
display: block;
margin-top: 4em;
font-family: monospace;
font-size: .8em;
}
</style>
which basically takes a csv file as an input and prints all as it is raw!How can I work and divide the rows on the ";"?And I also want an honest answer what level is this for?(intern,senior?)
Here's a trivial example, it's fairly straight forward. The issue will be splitting the data, it's pretty simple if the data is simple and the delimiter unique. But if the delimiter is in the data, the splitting into values requires a little more cleverness.
This uses table.rows to get the row, then row.cells to get the cell and inserts the value. Columns and rows are zero indexed, and for rows includes the header and footer (if they exist). You can also use the tbody.rows if the header rows should be skipped.
var data = 'Major;1;2;29\nMinor;2;3;29';
function insertData(id, data) {
// Show data
console.log(data);
// Get the table
var table = document.getElementById(id);
// Split the data into records
var dataRows = data.split(/\n/);
// Split each row into values and insert in table
if (table) {
dataRows.forEach(function(s) {
var x = s.split(';');
table.rows[x[2]].cells[x[1]].textContent = x[0];
});
}
}
table {
border-collapse: collapse;
border-left: 1px solid #999999;
border-top: 1px solid #999999;
}
td, th {
border-right: 1px solid #999999;
border-bottom: 1px solid #999999;
}
<table id="t0">
<thead>
<tr>
<th>col 0<th>col 1<th>col 2
</thead>
<tbody>
<tr>
<td> <td><td>
<tr>
<td> <td><td>
<tr>
<td> <td><td>
</tbody>
</table>
<button onclick="insertData('t0', data)">Insert data</button>
I have script of onmouseover event, but I need not to include the class="none". How to disable the onmouseover in the class="none"only? I set the css of `class="none".
CSS :
.none{
background-color: transparent;
border-right: #9dcc7a;
border-color: transparent;
}
HTML:
<table id="tfhover" cellspacing="0" class="tablesorter" border="1px">
<thead>
<tr>
<th class="none"></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td class="none"></td>
<td></td>
</tr>
</tbody>
</table>
JS:-
$(function(){
var tfrow = document.getElementById('tfhover').rows.length;
var tbRow=[];
for (var i=1;i<tfrow;i++) {
tbRow[i]=document.getElementById('tfhover').rows[i];
tbRow[i].onmouseover = function(){
this.style.backgroundColor = '#f3f8aa';
};
tbRow[i].onmouseout = function() {
this.style.backgroundColor = 'transparent';
};
}
});
You could do it with css itself.
#tfhover tr td {
background-color:transparent
}
#tfhover tr:hover td:not(.link) {
background-color:#f3f8aa;
}
Or
/*#tfhover tr {
background-color:transparent;
}*/ /*This rule is not needed since default background is transparent*/
#tfhover tr:hover td {
background-color:#f3f8aa;
}
#tfhover tr td.link{
background-color:transparent;
}
Demo
Just use some if statement logic to determine whether or not to add the mouseover events to the elements.
It looks like your 1st column is always a link, so as you run through the for loop, check if it is the first column, if it is, do not add the mouseover event.
By the way you probably need a nested loop in this situation.
How about this ?
$(function() {
$("td").each(function() {
if($(this).attr("id") != "none") {
$(this).mouseover(function() {
$(this).css("background-color","#f3f8aa");
})
.mouseout(function() { $(this).css("background-color","transparent"); });
}
});
});