Jquery/TinySort Shifting Entire DIV Container - javascript

I am trying to setup a very simple way to sort content. I found TinySort and it seems to be able to do the job, however I need the sorting to move the entire container div not just rearrange the content.
Essentially, I have set up links to activate the sorting function and they are working to sort the spans I have it looking for, however it moves the spans around within the divs containing them.
I built a simply JSFIDDLE to display my struggle.
https://jsfiddle.net/og6jfLjf/
When you sort by Price the prices move and are in order, however they didn't pull the containers with them. They just moved within each container.
$(document).ready(function() {
$(".price-sort").click(function () {
tinysort("span.price");
});
$(".title-sort").click(function () {
tinysort("span.title");
});
});
div{
width: 100px;
height:100px;
background-color: #000;
color: #fff;
margin:10px;
}
#div1{
background-color:#666;
}
#div4{
background-color:#aaa;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinysort/2.2.2/tinysort.js"></script>
<div id="div4"><span class="title">Title 1</span> - $<span class="price">5</span></div>
<div id="div1"><span class="title">Title 3</span> - $<span class="price">4</span></div>
<div id="div2"><span class="title">Title 2</span> - $<span class="price">6</span></div>
Sort By Price |
Sort By Title |

Solved the problem. I wasn't telling the function to include the div. So I adjusted the script to sort the divs based on the span within them. Here is a working JSFIDDLE to show it.
https://jsfiddle.net/oym96zL5/
$(document).ready(function() {
$(".price-sort").click(function () {
tinysort('div','span.price');
});
$(".title-sort").click(function () {
tinysort('div','span.title');
});
});

You can make a table, it's easier if you have a lot of data. Click the "Item" header and the "Price" header to sort the rows.
$(document).ready(function() {
var table = document.getElementById('xtable'),
tableHead = table.querySelector('thead'),
tableHeaders = tableHead.querySelectorAll('th'),
tableBody = table.querySelector('tbody');
tableHead.addEventListener('click', function(e) {
var tableHeader = e.target,
textContent = tableHeader.textContent,
tableHeaderIndex, isAscending, order;
if (textContent !== 'add row') {
while (tableHeader.nodeName !== 'TH') {
tableHeader = tableHeader.parentNode;
}
tableHeaderIndex = Array.prototype.indexOf.call(tableHeaders, tableHeader);
isAscending = tableHeader.getAttribute('data-order') === 'asc';
order = isAscending ? 'desc' : 'asc';
tableHeader.setAttribute('data-order', order);
tinysort(tableBody.querySelectorAll('tr'), {
selector: 'td:nth-child(' + (tableHeaderIndex + 1) + ')',
order: order
});
}
});
});
table.blue {
padding: 0;
box-shadow: 0 1px 9px 1px #ccc;
border-radius: 6px;
margin: 20px auto;
}
.blue th {
color: #FFF;
background: #2C7EDB;
padding: 10px;
text-align: center;
vertical-align: middle;
}
.blue tr:nth-child(odd) {
background-color: #333;
color: #FFF;
}
.blue tr:nth-child(even) {
background-color: #D3E9FF;
color: #333;
}
.blue td {
border-style: solid;
border-width: 1px;
border-color: #264D73;
padding: 5px;
text-align: left;
vertical-align: top;
}
.blue thead th:first-child {
border-top-left-radius: 6px;
}
.blue thead th:last-child {
border-top-right-radius: 6px;
}
.blue tbody tr:last-child th:first-child {
border-bottom-left-radius: 6px;
}
.blue tbody tr:last-child td:first-child {
border-bottom-left-radius: 6px;
}
.blue tbody tr:last-child td:last-child {
border-bottom-right-radius: 6px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinysort/2.2.2/tinysort.js"></script>
<table class="blue" id="xtable">
<thead>
<tr>
<th data-order="asc">
<a>Item
</a>
</th>
<th>Qty
</th>
<th data-order="asc"><a>Price</a> </th>
<th>Desc</th>
</tr>
</thead>
<tbody>
<tr> <td> Porche </td><td>1</td> <td> $100, 000.00 </td><td>Sports car</td> </tr>
<tr><td>Toilet Paper</td> <td> 5 </td><td>$50.00</td> <td> 8 rolls </td></tr>
<tr> <td> Laptop </td><td>1</td> <td> $600.00 </td><td>HP i7 12GB 1TB</td> </tr>
</tbody>
</table>

Related

toggle button of objects displayed using javascript doesn't seem to work as intended

I have displayed my array of objects using dom manipulation. but it seems there is something wrong with the toggle function that i have called to the buttons.
i require each button to switch from "read" to "not read" but it only works for the first object displayed. the second one toggles the first but doesn't toggle itself? could i please get an explanation as well
let clicked = false;
function toggle(){
if(!clicked){
clicked = true;
document.getElementById("readbtn").innerHTML = "Not read";
}
else{
clicked = false;
document.getElementById("readbtn").innerHTML = "Read";
}
}
function Book(name, author, ReadOrNot) {
this.name = name
this.author = author
this.ReadOrNot = ReadOrNot
}
const book1 = new Book("The Hobbit", "J.R.R Tolkien", "Read")
const book2 = new Book("A Game of Thrones", "George R.R. Martin", "Not read")
let myLibrary = []
function addBookToLibrary(...arr) {
myLibrary.push(...arr)
}
addBookToLibrary(book1)
addBookToLibrary(book2)
console.log(myLibrary)
function addBookToTable(){
let tbody = document.querySelector('tbody')
myLibrary.forEach(b =>{
let tr = document.createElement('tr')
let content = '<td>' + b.name + '</td><td>' + b.author + '</td>'
if(b.ReadOrNot == 'Read'){
content += '<td><button id="readbtn" class="btn rdbtn" onclick="toggle()">Read</button></td>'
}
else if(b.ReadOrNot == 'Not read'){
content += '<td><button id="readbtn" class="btn rdbtn" onclick="toggle()">Not read</button></td>'
}
content += '<td><button class="btn delbtn">Delete</button></td>'
tr.innerHTML = content
tbody.appendChild(tr)
})
}
addBookToTable()
*{
box-sizing: border-box;
--darkblue: #465c6b;
--blue: #779bb3;
--lightgrey: rgb(244, 242, 242);
}
table{
border-collapse: collapse;
width: 30em;
background-color: white;
border-radius: 5px;
box-shadow: 0px 10px 30px 5px rgba(0,0,0,.15);
margin: 100px auto;
}
table thead td{
background-color: rgb(38, 36, 36);
color: whitesmoke;
border-bottom: .5px solid black;
font-size: 15px;
letter-spacing: 1px;
padding: 8px;
}
table tbody td {
padding: 8px;
}
table tbody tr td:nth-child(4){
text-align: center;
}
table tbody tr td:nth-child(3){
text-align: center;
}
table thead tr td:nth-child(3){
text-align: center;
}
table td{
font-size: 18px;
color: rgb(38, 36, 36);
}
.btn.delbtn{
background-color: #990026;
min-width: 100px;
}
<table>
<thead>
<tr>
<td>Name</td>
<td>Author</td>
<td>Status</td>
<td> </td>
</tr>
</thead>
<tbody>
</tbody>
</table>

How to get data attribute of element when click on it or it child

I am making a Table.
document.querySelector('table').addEventListener('click', (e) => {
console.log(e.target);
console.log(e.target.dataset.item);
})
td {
padding: 8px;
border: 1px solid black;
background-color: blue;
}
span {
background-color: red;
padding: 4px;
}
<table>
<tr>
<td data-item="item1"><span>1</span></td>
<td data-item="item2"><span>2</span></td>
<td data-item="item3"><span>3</span></td>
<td data-item="item4"><span>4</span></td>
<td data-item="item5"><span>5</span></td>
</tr>
</table>
When I click the BLUE PART, I can get data-item attribute. But when I click the RED PART, I can't.
I wanna fix it, if I click <span/> in <td/>, I want to get data-item attribute from <td />.
Try to use closest by your child tag instead of dataset.
document.querySelector('table').addEventListener('click', (e) => {
console.log(e.target.closest("td").dataset.item);
})
td {
padding: 8px;
border: 1px solid black;
background-color: blue;
}
span {
background-color: red;
padding: 4px;
}
<table>
<tr>
<td data-item="item1"><span>1</span></td>
<td data-item="item2"><span>2</span></td>
<td data-item="item3"><span>3</span></td>
<td data-item="item4"><span>4</span></td>
<td data-item="item5"><span>5</span></td>
</tr>
</table>
Check if name of clicked element is span select parent of it using parentNode property
document.querySelector('table').addEventListener('click', (e) => {
var ele = e.target.nodeName == "SPAN" ? e.target.parentNode : e.target;
console.log(ele.dataset.item);
})
td {
padding: 8px;
border: 1px solid black;
background-color: blue;
}
span {
background-color: red;
padding: 4px;
}
<table>
<tr>
<td data-item="item1"><span>1</span></td>
<td data-item="item2"><span>2</span></td>
<td data-item="item3"><span>3</span></td>
<td data-item="item4"><span>4</span></td>
<td data-item="item5"><span>5</span></td>
</tr>
</table>
You could check for the keys in the dataset of the clicked item and if it does have some properties then use e.target otherwise move up one level e.target.parentNode:
document.querySelector('table').addEventListener('click', (e) => {
var el = Object.keys(e.target.dataset).length ?
e.target: e.target.parentNode;
console.log(el.dataset.item);
})
td {
padding: 8px;
border: 1px solid black;
background-color: blue;
}
span {
background-color: red;
padding: 4px;
}
<table>
<tr>
<td data-item="item1"><span>1</span></td>
<td data-item="item2"><span>2</span></td>
<td data-item="item3"><span>3</span></td>
<td data-item="item4"><span>4</span></td>
<td data-item="item5"><span>5</span></td>
</tr>
</table>
Why do you listen on the whole table in the first place?
Listen only on "td" elements:
let cells = document.getElementsByTagName('td');
for (var i=0; i < cells.length; i++) {
let cell = cells[i];
cell.addEventListener('click', (e) => {
let element = e.target.nodeName;
if (element === 'TD') {
console.log(e.target.dataset.item);
} else if (element === 'SPAN') {
console.log(e.target.parentNode.dataset.item);
}
});
}
I don't think setting the listener on the table matters, because in your case, it doesn't trigger the event on the table anyways.
Some styles for better inspection:
table {
background-color: orange;
border-spacing: 10px;
}
https://jsfiddle.net/aleks351/p0b46wqs/6/

Crosshair highlight for table on hover

I have the code below that works perfect for crosshair function. This is fine, however wondering if there is a way to stop the highlight beyond the cursor (hover).
For example, instead of a "cross" shape highlight you end up with a backward "L" shape highlight. So instead of highlighting the whole row & column it only highlights column 3 down to row 2 and row 2 only to column 3. No extended highlight. Hope that makes sense?
Here is my css code:
table {
border-collapse: collapse;
overflow: hidden;
z-index: 1;
}
.permissions table,
th,
td {
border: 2px solid #ccc;
width:90px;
height:90px;
text-align:center;
vertical-align:middle;
font-size:13px;
}
td, th, .row, .col, .ff-fix {
cursor: pointer;
position: relative;
}
tr, col {
border: 1px solid black;
}
td:hover {
background-color:red;
}
td:hover:first-child {
background-color:red;
}
td:hover:nth-child(3n) {
background-color:red;
}
tr:last-child td:hover {
background-color:red;
}
td:hover::before,
.row:hover::before,
.ff-fix:hover::before {
background-color: #ffa;
content: '\00a0';
height: 100%;
left: -5000px;
position: absolute;
top: 0;
width: 10000px;
z-index: -1;
}
td:hover::after,
.col:hover::after,
.ff-fix:hover::after {
background-color: #ffa;
content: '\00a0';
height: 10000px;
left: 0;
position: absolute;
top: -5000px;
width: 100%;
z-index: -1;
}
Here is my html code:
<table>
<col /><col /><col />
<tr>
<th class="col">First Name</th>
<th class="col">Middle Name</th>
<th class="col">Last Name</th>
</tr>
<tr>
<td>Peter</td>
<td>Jeffery</td>
<td>Griffin</td>
</tr>
<tr>
<td>Lois</td>
<td>Marie</td>
<td>Griffin</td>
</tr>
<tr>
<td>Margie</td>
<td>Ann</td>
<td>Thatcher</td>
</tr>
</table>
Following the logic of your CSS, you apply a full-width ::before and a full-height ::after which are displayed over the table. To adjust how these are displayed (a cross vs a "backward L"), adjust the corresponding horizontal and vertical positioning.
Try replacing your td:hover::before and td:hover::after selectors with the following to display the highlighting as a "backward L". Note the positioning is set using right and bottom rule sets, as opposed to your original positioning using left and top.
td:hover::before,
.row:hover::before,
.ff-fix:hover::before {
background-color: #ffa;
content: '\00a0';
height: 100%;
right: 90px;
position: absolute;
top: 0;
width: 10000px;
z-index: -1;
}
td:hover::after,
.col:hover::after,
.ff-fix:hover::after {
background-color: #ffa;
content: '\00a0';
height: 10000px;
left: 0;
position: absolute;
bottom: 90px;
width: 100%;
z-index: -1;
}
See how it looks in this JSFiddle.
I know this is old, but here's a method using Javascript. I prefer this method because it allows for custom backgrounds, and doesn't require CSS workarounds.
HTML:
<table id="hoverTable">
<thead>
<th>Column1</th>
<th>Column2</th>
<th>Column3</th>
<th>Column4</th>
</thead>
<tbody>
<tr>
<td>Item</td>
<td>Item</td>
<td>Item</td>
<td>Item</td>
</tr>
<tr>
<td>Item</td>
<td>Item</td>
<td>Item</td>
<td>Item</td>
</tr>
<tr>
<td>Item</td>
<td>Item</td>
<td>Item</td>
<td>Item</td>
</tr>
<tr>
<td>Item</td>
<td>Item</td>
<td>Item</td>
<td>Item</td>
</tr>
</tbody>
</table>
SCSS:
body {
background:grey;
}
.hoverHighlight {
background-color:yellow !important;
cursor:default;
}
#hoverTable {
font-family:arial;
border-spacing:0;
border-collapse: collapse;
th, td {
border:2px solid black;
text-align:center;
padding:5px;
margin:0;
}
th {
background:#1167b1;
color:white;
}
td {
text-align:center;
background:#d0efff;
}
}
Javascript:
window.addEventListener('load', function () {
addHoverEventsAndClasses();
})
function toggleHighlight(element, trueOrFalse) {
const currentRow = returnCurRow(element);
const index = element.currentTarget.cellIndex;
const table = document.getElementById('hoverTable').rows;
for (var i = 0; i < table.length; i++) {
const data = table[i];
const cells = data.querySelectorAll(".cell");
if(data.rowIndex === currentRow) {
cells.forEach((td) => {
trueOrFalse ? td.classList.add("hoverHighlight") : td.classList.remove("hoverHighlight");
});
}
cells.forEach((cell) => {
if(cell.cellIndex === index) {
trueOrFalse ? cell.classList.add("hoverHighlight") : cell.classList.remove("hoverHighlight");
}
});
}
};
function addHoverEventsAndClasses() {
const mainTableTDs = document.querySelectorAll("#hoverTable td");
const mainTableTRs = document.querySelectorAll("#hoverTable tr");
//Dynamically add class names to each row and cell to target
addClass(mainTableTDs, "cell");
addClass(mainTableTRs, "row");
mainTableTDs.forEach((td) => {
td.addEventListener("mouseenter", highlightCol);
td.addEventListener("mouseleave", removeHighlightCol);
});
}
//Helper function for adding highlight classes
function addClass(el, cl) {
el.forEach((child) => {
child.classList.add(cl);
});
};
//Toggle highlight functions. Did it this way so multiple arguments could be passed
function highlightCol(e) {
toggleHighlight(e, true);
}
function removeHighlightCol(e) {
toggleHighlight(e, false);
}
//Grab the current row
const returnCurRow = (e) => {
return e.currentTarget.parentElement.rowIndex;
}

How to open a dialog box on click of a dynamic cell value using jquery

I have an HTML table:
<tbody>
<tr>
<td> <ul id="element"></td>
</tr>
</tbody>
The values in the table are passed from the database using jquery:
element += '<li>' + valueOfElement.ELEMENTNAME + '</li>'
I want to show some information related to the element name in a dialog box when user clicks the element name. I am new to JavaScript so I don't know how to make a dynamic value clickable and how to open a dialog box on click of the element.
You can add an anchor tag around your element.
element += "<li><a href='javascript:void(0)' onclick='myDialogFunction()'>" + valueOfElement.ELEMENTNAME + "</a></li>";
To answer your styling question, just add this CSS rule to affect all anchor tags
a {
text-decoration: none;
color: #000;
}
or you can assign your links a class
<html>
<a class='mystyledlink' />
</html>
<style>
.mystyledlink {
text-decoration: none;
color: #000;
}
</style>
Using jquery you can bind a click event to the elements that will show the dialog box. Without seeing your dialog box or what all that entails I can't really include it but you could do something like this.
$('tbody').on('click','li',function(){
var value = $(this).text();
//do something with value and show dialog box
})
This approach is in vanilla JavaScript. You could try something like this: Make use of addEventListener to listen for click events on all your clickable cells. You could make use of document.querySelectorAll like I did to access all cells.
var tdGroup = document.querySelectorAll( 'td' ),
i;
for( i = 0; i < tdGroup.length; i++ ){
tdGroup[ i ].addEventListener( 'click', messages )
}
function messages(){
alert( 'you clicked' + this.textContent );
}
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
}
html {
font-family: sans-serif;
overflow: hidden;
}
body {
display: flex;
}
table {
margin: auto;
border-collapse: collapse;
position: relative;
top: 2rem;
}
th {
text-transform: uppercase;
}
th,
td {
padding: 1rem;
border: 1px #000 solid;
text-align: center;
transition-property: background;
transition-duration: 1s;
}
td:hover {
cursor: pointer;
background-color: #eee;
color: #333;
}
td:active {
background-color: #ddd;
color: #444;
transition-duration: 0.25s;
}
p {
width: 100%;
padding: 1rem;
text-align: center;
background-color: #000;
color: #eee;
position: absolute;
top: 0;
left: 0;
}
<p>Click a secondary item of the table for more information</p>
<table>
<tr>
<th>
Technology Field
</th>
<th>
Language
</th>
<th>
Resources
</th>
<th>
Related technologies
</th>
</tr>
<tr>
<td id="front-end">
Front End
</td>
<td id="javaScript">
JavaScript
</td>
<td id="stack">
StackOverflow
</td>
<td id="hcs">
HTML, CSS, SASS
</td>
</tr>
</table>

Main row heading colours when odd/even CSS in place

I have an expand/collapse table that automatically adjusts the odd/even row colours (dark grey and light grey) when expanding/collapsing..
What I am trying to achieve is that for some particular rows, I need to apply a background-colour (the class I used for this is mainRow).. However, because of my Javascript functions, I believe this is making the CSS to not perform as expected.
Here is my fiddle: http://jsfiddle.net/oampz/JNQx4/1/
HTML:
<table class="tbl tbl--highlight stripes half-mb">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Height</th>
<th>Weight</th>
</tr>
</thead>
<tbody>
<tr class="mainRow">
<td class="ShowMe">+ 0000111</td>
<td>0000111</td>
<td>0000111</td>
<td>0000111</td>
</tr>
<tr id="itsHidden" class="visuallyhidden">
<td>0000222</td>
<td>0000222</td>
<td>0000222</td>
<td>0000222</td>
</tr>
<tr>
<td>0000333</td>
<td>0000333</td>
<td>0000333</td>
<td>0000333</td>
</tr>
<tr>
<td>0000444</td>
<td>0000444</td>
<td>0000444</td>
<td>0000444</td>
</tr>
<tr class="mainRow">
<td class="ShowMe">+ 0000555</td>
<td>0000555</td>
<td>0000555</td>
<td>0000555</td>
</tr>
<tr id="itsHidden2" class="visuallyhidden">
<td>0000666</td>
<td>0000666</td>
<td>0000666</td>
<td>0000666</td>
</tr>
<tr>
<td>0000777</td>
<td>0000777</td>
<td>0000777</td>
<td>0000777</td>
</tr>
</tbody>
</table>
CSS:
table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
}
th {
min-width: 22px;
}
.stripes tbody > tr.odd {
background: #f2f2f2;
}
.stripes li:nth-child(2n) {
background: #f2f2f2;
}
.tbl {
border: 1px solid #d1d1d1;
font-size: 12px;
font-size: 0.75rem;
line-height: 2;
clear: both;
}
.tbl th, .tbl td {
padding: 3px;
text-align: left;
border-right: 1px solid #d1d1d1;
}
.tbl th {
border-bottom: 1px solid #d1d1d1;
}
.tbl--highlight tbody tr:hover {
background: #d4e8fc;
cursor: pointer;
}
.tbl--input td {
overflow: hidden;
}
.half-mb {
margin: 0 0 12px 0;
}
.visuallyhidden {
display: none;
}
.visuallyhidden.focusable:active,
.visuallyhidden.focusable:focus {
display: block;
}
.mainRow {
background-color: #0c5cac;
}
Javascript:
$(function(){
function stripeTable(){
$("table.stripes tr").removeClass("odd");
$("table.stripes tr:visible:odd").addClass("odd");
}
stripeTable();
$(".ShowMe").click(function() {
$("#itsHidden").toggleClass("visuallyhidden");
$("#itsHidden2").toggleClass("visuallyhidden");
stripeTable();
});
});
Any help appreciated
Unsure about what is really your problem.
If it is that you want your mainRow rows to be always blue, it's just a problem of specifity in your CSS. Both odd class and mainRow class set a background, and the odd selector has more specifity.
The easy solution is to add an important in the later
.mainRow {
background-color: #0c5cac !important;
}
There are people that say that using !important is a bad habit. But, as everything in life, I think that sometimes it is the easier way to solve an issue, and this is probably one of those cases.
updated fiddle

Categories

Resources