How to increment data index in javascript - javascript

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>

Related

Hover keyframe values green and red

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>

Save content editable HTML table in multiple fields

I need to develop a HTML table where one of the table column is editable on its row and the table row is dynamic in term of the row number.
I come across a problem where when I automate the saveEdits() function, the code is not working.
Here is my code, where the 'cnt' is a dynamic numeric number. Example cnt=50
<!DOCTYPE html>
<html>
<head>
<style>
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
table ,tr td{
border:1px solid #dddddd;
padding: 8px;
}
tbody {
display:block;
height:600px;
overflow:auto;
}
thead, tbody tr {
display:table;
width:100%;
table-layout:fixed;
}
thead {
width: calc( 100% - 1em )
}
tr:nth-child(even) {
background-color: #dddddd;
}
</style>
<script type="text/javascript">
function saveEdits(cnt) {
//get the editable elements.
var str_out = ''
while (cnt>0){
str1 = '\'edit' + cnt + '\': document.getElementById(\'edit' + cnt + '\').innerHTML,\n'
str_out = str_out.concat(' ', str1);
cnt--;
};
var editElems= { str_out };
alert(editElems)
//save the content to local storage. Stringify object as localstorage can only support string values
localStorage.setItem('userEdits', JSON.stringify(editElems));
}
function checkEdits(){
//find out if the user has previously saved edits
var userEdits = localStorage.getItem('userEdits');
alert(userEdits) // suppose to print {"edit1":" rpeyy7<br>","edit2":" tpruiiy<br>","edit3":" opty<br>"}
if(userEdits){
userEdits = JSON.parse(userEdits);
for(var elementId in userEdits){
document.getElementById(elementId).innerHTML = userEdits[elementId];
}
}
}
</script>
</head>
<body onload="checkEdits()">
<table id="myTable">
<thead>
<tr>
<td style="background-color:#A9A9A9" > Field#1 </td>
<td style="background-color:#A9A9A9" > Field#2 </td>
<td style="background-color:#A9A9A9" > Field#3- Each Row Under field#3 is content EditableByUser </td>
</tr>
</thead>
<tbody>
// Here is the python code that loop through a diectionary content
cnt = 0
for c in sorted(data_dict.keys()) :
cnt += 1
<tr>
<td> {0} </td> //Field#1
<td> {0} </td> //Field#2
...
...
<td id="edit{0}" contenteditable="true" onKeyUp="saveEdits({0});"> {1} </td>\n'.format(cnt,comment)]
</tr>
</table>
</body>
I'm not sure where goes wrong as when I automate the saveEdits() function with 'cnt' in while loop, the above code doesn't works for me. But when I defined each row clearly like below, the data the keyed-in are properly saved to each column.
function saveEdits(cnt) {
//get the editable elements.
var editElems = {
'edit1': document.getElementById('edit1').innerHTML,
'edit2': document.getElementById('edit2').innerHTML,
'edit3': document.getElementById('edit3').innerHTML,
};
alert(editElems) //print [object Object]
//save the content to local storage. Stringify object as localstorage can only support string values
localStorage.setItem('userEdits', JSON.stringify(editElems));
}
I would be much appreciate if someone can point out my mistake. The error is very much likely on saveEdits(cnt) function but I'm not sure how to fix that cause it I define each count 1 by 1, each update that being keyed-in is actually saved properly and able to retrieve when rerun. Thanks you!

How to change index in html element

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>

HTML column layout - automatically wrap div element to next column

I want an HTML layout with max 5 rows
If I have 6 items (i.e. divs) I want to wrap the 6th element in the 2nd column of 1st row
I tried the following, But can't get the 6th element in the next column.
p {
display: inline-block;
background-color:gray;
}
.wrap {
display: inline;
background-color:red;
}
<div>
<div><p>I am bla</p></div>
<div><p>Your mom</p></div>
<div><p>Test</p></div>
<div><p>Teddy</p></div>
<div><p>James</p></div>
<div><p class="wrap">John Appleseed</p></div>
</div>
Update: the Problem is that the items needs to have a flexible width, see here: https://dl.dropboxusercontent.com/u/1771956/float_html2.png
Going back some years, the Html layout was often completely built with the table element, today most layouts are not.
However, you seem to want your layout built table-like (rows, columns...) so I would not hesitate to use a table.
<table>
<tr>
<td>row 1 column 1</td>
<td>row 1 column 2</td>
</tr>
<tr>
<td>row 2 column 1</td>
</tr>
<tr>
<td>row 3 column 1</td>
</tr>
<tr>
<td>row 4 column 1</td>
</tr>
<tr>
<td>row 5 column 1</td>
</tr>
</table>
If ancient browser support is not an issue, you can make use of css3 flexible box.
#container{
display:-webkit-flex;
display:flex;
-webkit-flex-direction:column;
flex-direction:column;
-webkit-align-content:flex-start;
align-content:flex-start;
-webkit-flex-wrap:wrap;
flex-wrap:wrap;
height:500px;
background:hotpink;
}
#container div{
display:inline-block;
width:90px;
height:90px;
margin:5px;
background-color:gray;
}
.wrap {
display: inline;
background-color:red;
}
<div id='container'>
<div><p>I am blah</p></div>
<div><p>Your mom</p></div>
<div><p>Test</p></div>
<div><p>Teddy</p></div>
<div><p>James</p></div>
<div><p class="wrap">John Appleseed</p></div>
</div>
this is not a complete solution, hopefully you can tweak it according to your needs
More about css flex # css tricks
Fixed it
I used some javascript and position absolute to calculate the layout
$(function () {
// Handler for .ready() called.
var rows = 5
var items = $("#container").children()
var firstDiv = $("#container").children().eq(0)
var height = firstDiv.height()
var margin_bottom = firstDiv.outerHeight(true) - firstDiv.innerHeight()
var margin_right = firstDiv.outerWidth(true) - firstDiv.innerWidth()
var row = 0
var index = 0
items.each(function () {
var leftPos = 0
if (index >= rows) {
var siblingDiv = $("#container").children().eq(index-rows)
if (index == 10) {
}
leftPos = siblingDiv.width() + siblingDiv.position().left + margin_right
}
var topPos = ((height + margin_bottom) * row)
$(this).css('top', topPos + 'px')
$(this).css('left', leftPos + 'px')
row += 1
index += 1
if (row >= rows) {
row = 0
}
})
});
#container {
background-color:gray;
position:relative;
top: 10px;
left:0px;
height:500px;
}
.item {
background-color:green;
position:absolute;
height:50px;
top: 0px;
left:0px;
margin-right:10px;
margin-bottom:10px;
}
JSFiddle Demo
Here is my solution:
p {
display: inline-block;
background-color:gray;
}
.wrap {
display: inline-block;
background-color:red;
}
div {
float:left;
}
.clr {
clear:both;
}
<div>
<div><p>I am bla</p></div>
<div class="clr"></div>
<div><p>Your mom</p></div>
<div class="clr"></div>
<div><p>Test</p></div>
<div class="clr"></div>
<div><p>Teddy</p></div>
<div class="clr"></div>
<div><p>James</p></div>
</div>
<div><p class="wrap">John Appleseed</p></div>

Onmouseover table row

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"); });
}
});
});

Categories