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>
Related
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>
So overall I am trying to make the boxes change color when someone puts a mouse over them. Color has to be random. I know I am missing a connection point between my functions but I cant figure out what it is.
<!DOCTYPE html>
<html onmousedown='event.preventDefault();'
onmouseenter = "colorize();"
>
<head>
<title> Boxes </title>
<meta charset='utf-8'>
<style>
table {
border-spacing: 6px;
border: 1px rgb(#CCC);
margin-top: .5in;
margin-left: 1in;
}
td {
width: 40px; height: 40px;
border: 1px solid black;
cursor: pointer;
}
</style>
<script>
Create a function called colorize that is passed an element object as its
parameter and sets the elements background color style property using the
rgb(r,g,b) method setting each r,g and b to a random number between 0 and
255.
function colorize() {
var
r = ('0'+(Math.random()*255|0).toString(16)).slice(-2),
g = ('0'+(Math.random()*255|0).toString(16)).slice(-2),
b = ('0'+(Math.random()*255|0).toString(16)).slice(-2);
return '#' +r+g+b;
}
function colorize(co) {
document.body.style.background = co;
}
</script>
</head>
<body>
<table>
<tbody>
<script type="text/javascript">
Use document.write() and for-loops to fill in the table to create a 16x16 box table. For each td element, create a onmouseenter call to colorize, passing it the element itself (this).
var row = 16;
var cols = 16;
for(var r=0;r<row;r++){
document.write("</tr>");
for(var c=0;c<cols;c++){
document.write("<td></td>");
}
document.write("</tr>");
}
</script>
</tbody>
</table>
</body>
</html>
I'm not sure what you wanted to do with body background, nothing said about that in your text. ALos your colorizer func is overwritten. maybe you wanted something like this... ?
<!DOCTYPE html>
<html>
<head>
<title> Boxes </title>
<meta charset='utf-8'>
<style>
table {
border-spacing: 6px;
border: 1px rgb(#CCC);
margin-top: .5in;
margin-left: 1in;
}
td {
width: 40px; height: 40px;
border: 1px solid black;
cursor: pointer;
}
</style>
<script>
function colorize(el) {
var r = ('0'+(Math.random()*255|0).toString(16)).slice(-2),
g = ('0'+(Math.random()*255|0).toString(16)).slice(-2),
b = ('0'+(Math.random()*255|0).toString(16)).slice(-2);
el.style.backgroundColor = '#' +r+g+b;
}
</script>
</head>
<body>
<table>
<tbody>
<script type="text/javascript">
var row = 16;
var cols = 16;
for(var r=0;r<row;r++){
document.write("</tr>");
for(var c=0;c<cols;c++){
document.write("<td onMouseEnter='colorize(this);'></td>");
}
document.write("</tr>");
}
</script>
</tbody>
</table>
</body>
</html>
You need to have your colorize function update each cell in your table. Replace both colorize() and colorize(co) with one function:
function colorize() {
var r = ('0'+(Math.random()*255|0).toString(16)).slice(-2),
g = ('0'+(Math.random()*255|0).toString(16)).slice(-2),
b = ('0'+(Math.random()*255|0).toString(16)).slice(-2);
for (var i = 0; i < document.getElementsByTagName("td").length; i++){
document.getElementsByTagName("td")[i].style.backgroundColor = "#"+r+g+b;
}
}
i play with Ids and adding onmousedown in html tag that calls the func.
function colorize() {
var
r = ('0'+(Math.random()*255|0).toString(16)).slice(-2),
g = ('0'+(Math.random()*255|0).toString(16)).slice(-2),
b = ('0'+(Math.random()*255|0).toString(16)).slice(-2);
return '#' +r+g+b;
}
function change(){
var x = document.getElementById("1");
var y = document.getElementById("2");
x.style.color = colorize();
y.style.color = colorize();
}
<table frame="box" onmousedown="change()"id="1" >
<tr>
<th>Month</th>
<th>Savings</th>
</tr>
<tr>
<td>January</td>
<td>$100</td>
</tr>
</table>
<table frame="box" onmousedown="change()" id="2" >
<tr>
<th>Month</th>
<th>Savings</th>
</tr>
<tr>
<td>February</td>
<td>$200</td>
</tr>
</table>
I need to fill the background of table td based on td values. Below is the sample code i wrote for filling the td cell value.
applySchedules = function(schedules){
$.map(schedules, function(value, index){
$('#'+value.start).css('background', 'green');
});
}
var temp = [{start:9, end:10}, {start:13, end:14}]
applySchedules(temp);
tr {
border-width:2px;
outline:solid;
}
td {
border-width:2px;
width:60px;
outline:solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<table>
<tr>
<td id="8">8AM</td>
<td id="9">9AM</td>
<td id="10">10AM</td>
<td id="11">11AM</td>
<td id="12">12PM</td>
<td id="13">1PM</td>
<td id="14">2PM</td>
<td id="15">3PM</td>
<td id="16">4PM</td>
<td id="17">5PM</td>
<td id="18">6PM</td>
<td id="19">7PM</td>
<td id="20">8PM</td>
</tr>
</table>
Basically i will get json array of time slots that are occupied for the given day. The problem comes when the slot span more than or less than 1hour. The time slots are allotted in multiple's 30 mins.
Like {start:10,end:11.30},{start:12,end:12.30},{start:14.30,end:15}
Looking for some pointers how to handle these kind of cases.
Sample Output :
I would advise:
increase number of spans such way, that there would be your 30 minute item
Don't use just numbered ID's -> it is not a very good way
$(function(){
var applySchedules = function(schedules){
$.map(schedules, function( value,index){
var startHour = value.start.split(":")[0];
var endHour = value.end.split(":")[0];
var halfStart = value.start.split(":")[1];
var halfEnd = value.end.split(":")[1];
var startContainer = $('#time'+ padLeft( startHour, 2));
var endContainer = $('#time'+ padLeft( endHour, 2));
if( parseInt( halfStart )){
startContainer.append( $("<div />").addClass("start") );
}
if( parseInt( halfEnd )){
endContainer.append( $("<div />").addClass("end") );
}
if( ( parseInt(endHour) - parseInt(startHour) ) > 0){
for( var i = 1; i < parseInt(endHour) - parseInt(startHour); i++ ){
$('#time'+ padLeft( (parseInt(startHour) + i)+"", 2)).append( $("<div />").addClass("full") );
}
}
});
}
function padLeft(str,size,padwith) {
if(size <= str.length) {
return str;
} else {
return Array(size-str.length+1).join(padwith||'0')+str
}
}
var initTime = function(){
for( var i =0; i< 24; i++ ){
var $item;
if( i < 12 ){
$item = $("<td/>").text( padLeft(i+"",2)+":00 AM" );
}else if( i == 12 ){
$item = $("<td/>").text( padLeft( (i)+"",2)+":00 PM" );
} else {
$item = $("<td/>").text( padLeft( (i-12)+"",2)+":00 PM" );
}
$item.attr("id", "time" + padLeft(i+"",2));
$("#timeContainer").append($item);
}
}
var temp=[{start:"9:00",end:"9:30"}, {start:"13:00",end:"13:30"}, { start:"14:00", end:"14:30"}, {start:"15:30", end:"18:30"}]
initTime();
applySchedules(temp);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<style>
tr{border-width:2px; outline:solid;}
td{border-width:2px; width:60px; outline:solid; position:relative;}
div.start {
width: 50%;
background: green;
position: absolute;
height: 100%;
top: 0;
right: 0;
z-index:-1;
}
div.end {
width: 50%;
background: green;
position: absolute;
height: 100%;
top: 0;
left: 0;
z-index:-1;
}
div.full{
width: 100%;
background: green;
position: absolute;
height: 100%;
top: 0;
z-index:-1;
}
</style>
<body>
<table>
<tr id="timeContainer">
</tr>
</table>
</body>
UPDATED ANSWER
Some first approach to code
If you are adamant on using your current setup, might I suggest using CSS gradients:
...
$('#'+value.start).css('background','repeating-linear-gradient(to right, #00FF33, #00FF33 23px, #FFFFFF 23px, #FFFFFF 46px)');
...
46px is the width of the <td> in the fiddle, this would probably have to be generated dynamically. The second two values are half of the width of the whole <td> which creates a gradient covering only half of the whole <td>. You can then split this into smaller section by doing more complicated maths but I suggest referring to https://css-tricks.com/stripes-css/ for more information on this trick.
Here's the fiddle:
http://jsfiddle.net/85mJN/190/
Hello I develop a app where td appear and disapear side by side.
lastInsertTd = 0;
function newSlidingTd() {
tr = jQuery('#myline');
var lastTd = jQuery('#myline').children().last();
td = jQuery("<td></td>")
.attr('id', 'slidingTd' + lastInsertTd+1)
.attr('style', 'display:none;vertical-align:top;width:100%');
tr.append(td);
tdSuivant = jQuery('#slidingTd' + lastInsertTd+1);
tdActuel = jQuery('#slidingTd' + lastInsertTd);
/*animation*/
tdActuel.toggle('slide', {
direction: 'left'
}, 500);
tdSuivant.toggle('slide', {
direction: 'right'
}, 500);
lastInsertTd = lastInsertTd+1;
}
table {
width:100px
}
td {
border: black solid 1px;
width:100%
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<table>
<tr id="myline">
<td id='slidingTd0' onclick="newSlidingTd()">
1
</td>
</tr>
</table>
But when I call my event, my new td doesn't slide from the right but a little bit lower. How can I go through this "bug"? (this also happen when I create div inside td)
if it's slightly lower, then most likely it's some issue with displaying whitespaces.
Try setting line-height: 0; in the parent element (tr I'd guess), or remove the whitespace between < /td >< td >
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"); });
}
});
});