This question already has answers here:
jQuery/JavaScript collision detection
(7 answers)
Closed 5 years ago.
jQuery: get td elements (or other elements), that are under absolute div (match position)
Let's say i have such html:
<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td>6</td>
</tr>
</table>
<div class="abs-hover">
*
</div>
css:
td {
padding: 8px 20px;
border: 1px solid #cecece;
}
.abs-hover {
position: absolute;
top: 20px;
left: 30px;
width: 40px;
height: 40px;
background: rgba(140,200,120,0.2);
border: 2px solid #1cabda;
}
https://jsfiddle.net/L63u02n6/
this absolute container can change it's position on page, but how can i get td, which are under this absolute box?
in first example it's td with text: 1,2,3,4
how can i achieve this? any ideas
I wrote a little script that checks if each td is inside the box.
var objTop = $('.abs-hover').offset().top,
objLeft = $('.abs-hover').offset().left,
objWidth = $('.abs-hover').width(),
objHeight = $('.abs-hover').height();
$('table tr td').each(function(e) {
var self = $(this),
selfLeft = self.offset().left,
selfTop = self.offset().top,
selfWidth = self.width(),
selfHeight = self.height();
if ((objLeft + objWidth) > selfLeft && (objLeft < (selfLeft + selfWidth) || objLeft > (selfLeft + selfWidth)) && (objTop + objHeight) > selfTop && objTop < (selfTop + selfHeight)) {
console.log(self.text() +" is inside")
}
});
td {
padding: 8px 20px;
border: 1px solid #cecece;
}
.abs-hover {
position: absolute;
top: 20px;
left: 30px;
width: 40px;
height: 40px;
background: rgba(140, 200, 120, 0.2);
border: 2px solid #1cabda;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td>6</td>
</tr>
</table>
<div class="abs-hover">
*
</div>
You can use Document.elementFromPoint()
The elementFromPoint() method of the Document interface returns the
topmost element at the specified coordinates.
var j = $('.abs-hover').position();
elemtopLeft = document.elementFromPoint(j.top, j.left);
elemtopRIght = document.elementFromPoint(j.left + 44, j.top);
elembtmLeft = document.elementFromPoint(j.left, j.top + 44);
elembtmRight = document.elementFromPoint(j.left + 44, j.top + 44);
console.log(elemtopLeft, elemtopRIght, elembtmLeft, elembtmRight)
td {
padding: 8px 20px;
border: 1px solid #cecece;
}
.abs-hover {
position: absolute;
top: 20px;
left: 30px;
width: 40px;
height: 40px;
background: rgba(140, 200, 120, 0.2);
border: 2px solid #1cabda;
}
<script src=https://code.jquery.com/jquery-2.2.4.min.js></script>
<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td>6</td>
</tr>
</table>
<div class="abs-hover">
*
</div>
You need a collision detection for this, either on ready or after some event.
A good short function for this is given here in this SO-post: https://stackoverflow.com/a/7301852/6248169
Width, height and position on screen to can get with jQuery functions.
Then you can run this jquery function here for every TD to compare with your absolute box. If it collides, you set a class on the TD and then afterwards you can select over this class so you have all TDs which are under the DIV.
Hope these words are enough for an idea how to do this and no complete code is needed here.
You could also make use of Element.getBoundingClientRect(); function call to get a the positional coordinates of any element. Then go on to compare them with that of the absolute div to find an overlap. It returns an object with attributes - top, right, bottom, left, width. Link to the API
Native JS:
function getBounds(el) {
return {
left: el.offsetLeft,
top: el.offsetTop,
right: el.offsetLeft + el.offsetWidth,
bottom: el.offsetTop + el.offsetHeight
};
}
let hoverBounds = getBounds(document.querySelector(".abs-hover"));
document.querySelectorAll("td").forEach((el) => {
let elBounds = getBounds(el);
if (
(
hoverBounds.left >= elBounds.left && hoverBounds.left <= elBounds.right ||
hoverBounds.right >= elBounds.left && hoverBounds.right <= elBounds.right
) &&
(
hoverBounds.top >= elBounds.top && hoverBounds.top <= elBounds.bottom ||
hoverBounds.bottom >= elBounds.top && hoverBounds.bottom <= elBounds.bottom
)
) {
console.log(el.innerText, "Yes");
} else {
console.log(el.innerText, "No");
}
});
I suggest use "id" for the hover element. "class" use for several elements.
Related
I had an issue with a drag/drop quiz I was trying to solve. When clicked/dragged, if the viewport needed to scroll when you left the viewport the item would not be in sync with the cursor and was impossible to drop.
I fixed this by removing overflow: hidden from the container. The problem is now if you drag down, the page keeps growing and growing in length as there is no constraint.
Code included in post but here's a CodePen also: https://codepen.io/moy/pen/rNdbLbq
I've tried setting overflow on the html/body/parent elements but that either doesn't work or reintroduces the original issue. Can anyone help with this?
Note: FYI... I'm aware this is old jQuery. It's hooked into something I can't update without breaking a lot of other stuff, so unfortunately stuck with this right now.
/*------------------------------------*\
#QUIZZES
\*------------------------------------*/
/**
* Drag & Drop Quiz.
*
* 1. Make words draggable with revert = true.
*/
$(document).ready(function() {
score = 0;
if ($('.draggable')[0]) {
$('.draggable').draggable({
revert: true /* [1] */,
snapTolerance: 30,
revertDuration: 0,
cursor: 'move',
create: function(event, ui) {
$(event.target).css('width', Math.ceil($(event.target).width()) + 1 + 'px');
},
zIndex: 100,
});
}
});
/**
* Make blank spaces accept corresponding word.
*/
$('.blank').each(function(index) {
toAccept = $(this)[0].getAttribute('data-accept'); //Compatible for lower IE
// Resize spans to correct answer
if ($(this).hasClass('resizable')) {
answer = $('.draggable.' + toAccept);
width = answer[0].scrollWidth;
width =
width -
$(this)
.css('padding-left')
.replace('px', '') *
2;
$(this).css('width', width);
}
$(this).droppable({
accept: '.' + toAccept,
drop: function(event, ui) {
$(this).append(ui.draggable);
$(this).addClass('answered');
score++;
$(ui.draggable).draggable('destroy');
$(this).droppable('destroy');
},
});
});
/**
* Multiple Choice Quiz (radio button based).
*/
function checkMultiChoiceAnswer() {
score = 0;
qs = 0;
$('.quiz__answers').each(function() {
qs++;
});
$('input').each(function(ind, ele, arr) {
if (ele.value == 'true' && ele.checked === true) {
score++;
}
});
// console.log(score);
$('.quiz__correct').text(score.toString());
$('.quiz__total').text(qs.toString());
}
function multiReset() {
qs = 0;
$('.checked').each(function(ind, ele, arr) {
$(ele).removeClass('checked');
});
$('input').each(function(ind, ele, arr) {
ele.checked = false;
});
$('.quiz__answers').each(function() {
qs++;
});
$('.quiz__total').text(qs);
$('.quiz__correct').text('0');
}
/**
* Data Entry Quiz (input based).
*/
function checkAnswersCashFlow() {
score = 0;
$('.answerable').each(function(index, element, array) {
givenAns = $(element)[0].value.replace('/[^0-9]/g', '');
givenAns = givenAns.toLowerCase();
ans = $(element)[0]
.getAttribute('data-accept')
.replace('/[^0-9]/g', '');
if (givenAns == ans) {
score++;
}
$('.quiz__correct').text(score);
});
}
function tableReset() {
$('.quiz__correct').text('0');
$('.answerable').val('');
}
/**
* Sets Quiz score to 0/X on page load and on reset. This works on the "Multiple
* Choice Quiz" and also the "Data Entry Quiz".
*/
window.onload = function() {
if (typeof $('.quiz__total')[0] != 'undefined') {
qs = 0;
$('.quiz__answers').each(function() {
qs++;
});
$('.quiz__total').text(qs);
}
if (typeof $('.answerable')[0] != 'undefined') {
total = 0;
$('.answerable').each(function(ind, ele, arr) {
total++;
});
$('.quiz__total').text(total);
}
};
/* Clearfix Mixin */
#mixin clearfix() {
&:before,
&:after {
content: "";
display: table;
}
&:after {
clear: both;
}
}
/**
* Base `html` styling.
*
* 1. A height of 100% is set so when Fancybox is open is doesn't cut off
* background images set on `.container` caused by `overflow-x: hidden` is
* set on `.page` which is extended in _page.scss.
*/
html {
background: black;
font-size: 62.5%;
height: 100%; /* [1] */
min-height: 100%; /* [1] */
-webkit-overflow-scrolling: touch;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
/**
* Base `body` styling.
*
* 1. A height of 100% is set so when Fancybox is open is doesn't cut off
* background images set on `.container` caused by `overflow-x: hidden` is
* set on `.page` which is extended in _page.scss. The `-128px` subtracts
* the height of the header/footer from the value.
*/
body {
background: red;
box-sizing: border-box;
font-size: 16px;
font-weight: 400;
height: calc(100% - 144px); /* [1] */
margin: 0 auto;
position: relative;
top: 72px;
width: 100%;
}
/**
* Fixed Header.
*/
.page-head {
box-sizing: border-box;
display: flex;
height: 72px;
padding: 0 12px;
position: fixed;
top: 0;
width: 100%;
z-index: 100;
}
/**
* Fixed Footer.
*/
.page-foot {
box-sizing: border-box;
height: 72px;
padding: 12px;
position: fixed;
bottom: 0;
text-align: center;
width: 100%;
z-index: 100;
}
/**
* `.page` wrapper element. This was added as `overflow: hidden;` set on the
* html/body tags provided inconsistent results in Internet Explorer. So we
* needed to wrap the entire page in a `div` and apply the styling to that
* instead.
*
* 1. Height of 100% is set so `.container` :before/:after elements aren't cut
* off when content is vertically shorter than these elements.
* 2. Prevents horizontal scroll bar when :before/:after elements are cropped
* when viewport is narrower than the content area. `overflow-y: auto;` is
* needed for older versions of Internet Explorer (8).
*/
.page {
height: 100%; /* [1] */
min-height: 100%; /* [1] */
overflow-x: hidden; /* [2] */
overflow-y: auto; /* [2] */
}
/**
* `.container` groups all the main page content together. A `.wrap` div is used
* to center content on the page with a max-width.
*
* 1. A `z-index` is set so the side elements are above the `.site-map`. Without
* this the side elements can go behind the shadow effect (set on :before) if
* the page is vertically short. Which doesn't look great!
* 2. The `.wrap` div's `:before` & `:after` pseudo classes are used to add
* additional graphics to the outside of either side of the container.
*/
.main {
display: flex;
box-sizing: border-box;
margin: 0 auto;
padding: 24px 0 0;
position: relative;
width: 100%;
max-width: 1024px;
z-index: 10; /* [1] */
}
.main__inner {
display: block;
margin: 0 12px;
width: 100%;
}
.wrap {
#include clearfix;
background: white;
box-shadow: inset -4px -4px 0 rgba(black, 8%), 4px 4px 0 rgba(black, 4%);
box-sizing: border-box;
border-radius: 12px;
margin: 0 auto 24px;
padding: 24px 24px 0;
position: relative;
width: 100%;
}
.missing-words__draggable {background: yellow; margin-bottom: 5px; display: block;}
<script src="https://code.jquery.com/jquery-1.12.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<div class="page">
<header class="page-head"></header>
<div class="main">
<div class="main__inner">
<div class="wrap">
<div class="boxout">
<div class="icon-title">
<h2>Quiz</h2>
</div>
<p>Test your learning now with this cash-flow forecast quiz.</p>
<p>Use your mouse to drag and drop the missing values into the correct sections of the cash flow forecast below.</p>
<div class="missing-words">
<ul class="missing-words__answers">
<li class="missing-words__answers-item draggable word-1"><span class="missing-words__draggable draggable word-1">2,500</span></li>
<li class="missing-words__answers-item draggable word-2"><span class="missing-words__draggable draggable word-2">3,000</span></li>
<li class="missing-words__answers-item draggable word-3"><span class="missing-words__draggable draggable word-3">6,500</span></li>
<li class="missing-words__answers-item draggable word-4"><span class="missing-words__draggable draggable word-4">1,000</span></li>
<li class="missing-words__answers-item draggable word-3"><span class="missing-words__draggable draggable word-5">4,500</span></li>
<li class="missing-words__answers-item draggable word-4"><span class="missing-words__draggable draggable word-6">8,000</span></li>
</ul>
<table class="table-solid">
<thead>
<tr>
<th> </th>
<th>Jan (£)</th>
<th>Feb (£)</th>
<th>Mar (£)</th>
<th>Apr (£)</th>
</tr>
</thead>
<tbody class="table-align-middle">
<tr>
<th>Cash inflows:</th>
<th> </th>
<th> </th>
<th> </th>
<th> </th>
</tr>
<tr>
<td>Sales</td>
<td>10,000</td>
<td>8,000</td>
<td>6,000</td>
<td>7,000</td>
</tr>
<tr>
<td>Investment</td>
<td>500</td>
<td>500</td>
<td>500</td>
<td>500</td>
</tr>
<tr>
<td><strong>Total inflows</strong></td>
<td><strong>10,500</strong></td>
<td><strong>8,500</strong></td>
<td><span class="missing-words__blank blank" data-accept="word-3"></span></td>
<td><strong>71,000</strong></td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<th>Cash Outflows:</th>
<th> </th>
<th> </th>
<th> </th>
<th> </th>
</tr>
<tr>
<td>Materials</td>
<td>5,000</td>
<td>6,000</td>
<td>5,000</td>
<td>4,000</td>
</tr>
<tr>
<td>Energy costs</td>
<td>2,000</td>
<td>2,000</td>
<td>2,000</td>
<td>3,000</td>
</tr>
<tr>
<td>Wages</td>
<td>1,000</td>
<td><span class="missing-words__blank blank" data-accept="word-4"></span></td>
<td>2,000</td>
<td>1,000</td>
</tr>
<tr>
<td><strong>Total outflows</strong></td>
<td><strong>8,000</strong></td>
<td><strong>7,000</strong></td>
<td><strong>9,000</strong></td>
<td><span class="missing-words__blank blank" data-accept="word-6"></span></td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td><strong>Net cash flow</strong></td>
<td><span class="missing-words__blank blank" data-accept="word-1"></span></td>
<td><strong>1,500</strong></td>
<td><strong>(2,500)</strong></td>
<td><strong>(500)</strong></td>
</tr>
<tr>
<td><strong>Opening balance</strong></td>
<td>2,000</td>
<td><span class="missing-words__blank blank" data-accept="word-5"></span></td>
<td>6,000</td>
<td>3,500</td>
</tr>
<tr>
<td><strong>Opening balance</strong></td>
<td>4,500</td>
<td>6,000</td>
<td>3,500</td>
<td><span class="missing-words__blank blank" data-accept="word-2"></span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<footer class="page-foot"></footer>
https://codepen.io/moy/pen/rNdbLbq
So, a few days ago, I posted this question (nearly identical) and received a very helpful response.
However, in order to make a table calculator, I already have a id set to every table row of a certain column to turn the table into a calculator, which kind of messes up the answer for the original question when I try to apply it for myself (the JavaScript parses the unit "kg" in with the number and displays a sum as "NaN").
As well, there is a visible text box displayed inside of every cell with the answer above, which looks kind of ugly. My current code has cells that don't appear as text boxes but are still editable, which makes for a much sleeker experience in my opinion (I know it makes no functional difference, but the appearance is something that bugs me a lot!)
Below is a mock-up of what I'd like the code to look like. I'm trying to make the numbers/input appear on the right side of the text box, but still on the left side of the unit ("kg").
Below is a mock-up of what I am trying to create (except the numbers would be on the right).
Here is the code I have:
<head>
<style>
table {
border: 1px solid black;
border-collapse: collapse;
font-family: Arial, sans-serif;
margin: 5px;
width: 100%;
}
th, td {
border: 1px solid black;
border-collapse: collapse;
font-family: Arial, sans-serif;
margin: 5px;
padding: 5px;
}
</style>
</head>
<body>
<table>
<tr>
<th>header1</th>
<th>header2</th>
</tr>
<tr>
<td>entry1</td>
<td id="entry1" oninput="myFunction()">4000</td>
</tr>
<tr>
<td>entry2</td>
<td id="entry2" oninput="myFunction()">200</td>
</tr>
<tr>
<td>Total</td>
<td id="total"></td>
</tr>
</table>
<script type="text/javascript">
document.getElementById("entry1").contentEditable = true;
document.getElementById("entry2").contentEditable = true;
function myFunction() {
var entry1 = document.getElementById("entry1").innerText;
var entry2 = document.getElementById("entry2").innerText;
var total2 = parseInt(entry1) + parseInt(entry2);
document.getElementById("total").innerHTML = total2;
}
myFunction();
</script>
</body>
As you can see, it adds up the numbers in the right column and displays a sum in the final row. However, I would like units to display here (e.g. "kg") on the side, that aren't editable and, more importantly, don't get parsed as a number in the JavaScript function. Would be great if the ugly textbox outline doesn't appear inside the cell, too.
Is this possible? Any answers appreciated!
You get NaN when you call parseInt on an empty string. To fix this, change following statement from
var total = parseInt(jack2) + parseInt(john2) + parseInt (joe2);
to
var total = (parseInt(jack2) || 0) + (parseInt(john2) || 0) + (parseInt (joe2) || 0);
and to display the unit alongside the number in the right column, add 2 span elements inside the td element and use flexbox to align them properly.
To make the number editable, add contentEditable attribute on the span element containing the number. span element containing the unit will be non-editable by default.
function myFunction() {
var jack2 = document.getElementById("jack").innerText;
var john2 = document.getElementById("john").innerText;
var joe2 = document.getElementById("joe").innerText;
var total = (parseInt(jack2) || 0) + (parseInt(john2) || 0) + (parseInt(joe2) || 0);
document.getElementById("total").innerHTML = total;
}
myFunction();
table {
width: 100%;
}
table,
tr,
th,
td {
border: 1px solid black;
border-collapse: collapse;
font-family: Arial, sans-serif;
margin: 5px;
}
th,
td {
padding: 5px;
}
td:last-child {
display: flex;
justify-content: space-between;
border: none;
}
td:last-child span:first-child {
flex-grow: 1;
margin-right: 10px;
outline: none;
text-align: right;
}
#total {
display: flex;
justify-content: flex-end;
}
<table>
<thead>
<tr>
<th>Person</th>
<th>Weight</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jack</td>
<td id="jack" oninput="myFunction()">
<span contentEditable="true">4</span>
<span>Kg</span>
</td>
</tr>
<tr>
<td>John</td>
<td id="john" oninput="myFunction()">
<span contentEditable="true">2</span>
<span>Kg</span>
</td>
</tr>
<tr>
<td>Joe</td>
<td id="joe" oninput="myFunction()">
<span contentEditable="true">3</span>
<span>Kg</span>
</td>
</tr>
<tr>
<td>Total</td>
<td id="total"></td>
</tr>
</tbody>
</table>
To avoid the result being "NAN", an if is added and we check the one of the seals is empty '' and replace it with a 0.
In the edit cell two divs are added one to edit the value and the other to add the text "kg".
<style>
table {
border: 1px solid black;
border-collapse: collapse;
font-family: Arial, sans-serif;
margin: 5px;
width: 100%;
}
th, td {
border: 1px solid black;
border-collapse: collapse;
font-family: Arial, sans-serif;
margin: 5px;
padding: 5px;
}
.input_{
width: 90%;
float: left;
}
.peso{
width: 10%;
float: right;
}
</style>
<table>
<tr>
<th>Person</th>
<th>Weight</th>
</tr>
<tr>
<td>Jack</td>
<td>
<div class="input_" id="jack" oninput="myFunction()">1</div>
<div class="peso">kg</div>
</td>
</tr>
<tr>
<td>John</td>
<td>
<div class="input_" id="john" oninput="myFunction()">2</div>
<div class="peso">kg</div>
</td>
</tr>
<tr>
<td>Joe</td>
<td>
<div class="input_" id="joe" oninput="myFunction()">3</div>
<div class="peso">kg</div>
</td>
</tr>
<tr>
<td>Total</td>
<td id="total"></td>
</tr>
</table>
<script type="text/javascript">
document.getElementById("jack").contentEditable = true;
document.getElementById("john").contentEditable = true;
document.getElementById("joe").contentEditable = true;
function myFunction() {
var jack2 = document.getElementById("jack").innerText;
var john2 = document.getElementById("john").innerText;
var joe2 = document.getElementById("joe").innerText;
if(jack2==""){
jack2=0;
}
if(john2==""){
john2=0;
}
if(joe2==""){
joe2=0;
}
var total2 = parseInt(jack2) + parseInt(john2) + parseInt (joe2);
document.getElementById("total").innerHTML = total2+" kg";
}
myFunction();
</script>
My question is similar to THIS question, but I'm unable to use divs instead of colspans with a table.
It appears to be an issue that only appears in chrome, but I need to find a workaround.
My use case is very similar to the one below. Notice how the top border for 3.3 spans two columns, which is clearly not right. In my use case, the user is able to change which cells are merged so I can't set the border for a specific cell.
How do you set a cell's border to be confined to its own cell instead of sharing with a common cell whose colspan is greater than 1?
HTML
<div style="padding: 10px">
<table>
<tr>
<td>1.1</td>
<td>1.2</td>
<td>1.3</td>
<td>1.4</td>
<td>1.5</td>
</tr>
<tr>
<td>2.1</td>
<td>2.2</td>
<td colspan="2">2.3</td>
<td>2.5</td>
</tr>
<tr>
<td>3.1</td>
<td>3.2</td>
<td>3.3</td>
<td>3.4</td>
<td>3.5</td>
</tr>
<tr>
<td>4.1</td>
<td>4.2</td>
<td>4.3</td>
<td>4.4</td>
<td>4.5</td>
</tr>
<tr>
<td>5.1</td>
<td>5.2</td>
<td>5.3</td>
<td>5.4</td>
<td>5.5</td>
</tr>
</table>
</div>
CSS
table {
table-layout: fixed;
border-spacing: 0;
border-collapse: collapse;
}
td {
border: 1px solid lightgrey;
height: 60px;
width: 60px;
text-align: center;
vertical-align: middle;
}
td.active {
border: 1px solid blue;
}
td.brdr-b-hide {
border-bottom: none;
}
td.brdr-r-hide {
border-right: none;
}
JavaScript
var fnActivate = function(target) {
target.addClass('active');
if(!target.is(':first-child')) {
target.prev().addClass('brdr-r-hide')
}
var tr = target.closest('tr');
if(!tr.is(':first-child')) {
var prevTr = tr.prev();
$('td', prevTr).eq($('td', tr).index(target)).addClass('brdr-b-hide');
}
};
var fnDeactivate = function(target) {
target.removeClass('active');
if(!target.is(':first-child')) {
target.prev().removeClass('brdr-r-hide')
}
var tr = target.closest('tr');
if(!tr.is(':first-child')) {
var prevTr = tr.prev();
$('td', prevTr).eq($('td', tr).index(target)).removeClass('brdr-b-hide');
}
}
$('table').on('click', 'td', function(e){
var target = $(e.currentTarget);
if(e.ctrlKey && target.hasClass('active')){
fnDeactivate(target);
} else if(e.ctrlKey) {
fnActivate(target);
} else {
fnDeactivate($('table td.active'));
fnActivate(target);
}
});
CODE: Plunkr
Issue was fixed by using:
table {
border-collapse: separate;
}
Code: Plunkr
It's a little different on the front end as each cell now has its own border of 1px, but it's a good workaround for the time being.
I think this usecase is best adressed with the outline css property.
See: http://jsfiddle.net/4zxv4o59/
td.active {
outline: 1px solid blue;
}
Outlines do not take up space, they are drawn above the content.
from https://developer.mozilla.org/en/docs/Web/CSS/outline
I want to add colour style into <div> tags.
This only works when using property:
`background-color`: orange;
But I want it should be changed only text, not the background.
Like this:
`color`: orange;
In this demo, don't need Javascript still working.
My demo at here:
function firefoxFix() {
if ( /firefox/.test( window.navigator.userAgent.toLowerCase() ) ) {
var tds = document.getElementsByTagName( 'td' );
for( var index = 0; index < tds.length; index++ ) {
tds[index].innerHTML = '<div class="ff-fix">' + tds[index].innerHTML + '</div>';
};
var style = '<style>'
+ 'td { padding: 0 !important; }'
+ 'td:hover::before, td:hover::after { background-color: transparent !important; }'
+ '</style>';
document.head.insertAdjacentHTML( 'beforeEnd', style );
};
};
firefoxFix();
table {
border-spacing: 0;
border-collapse: collapse;
overflow: hidden;
z-index: 1;
}
td, th, .ff-fix {
cursor: pointer;
padding: 10px;
position: relative;
}
td:hover::after,
.ff-fix:hover::after {
background-color: orange;
content: '\00a0';
height: 10000px;
left: 0;
position: absolute;
top: -5000px;
width: 100%;
z-index: -1;
}
<table>
<tbody>
<tr>
<td>20</td><td>21</td><td>23</td><td>25</td><td>27</td>
</tr>
<tr>
<td>18</td><td>20</td><td>22</td><td>24</td><td>26</td>
</tr>
<tr>
<td>17</td><td>19</td><td>21</td><td>23</td><td>25</td>
</tr>
<tr>
<td>16</td><td>18</td><td>20</td><td>22</td><td>24</td>
</tr>
</tbody>
</table>
Thanks.
The better approach I think, is to add class to html element when user is using firefox. You may use anonymous function for that, for example:
(function(html) {
if ( /firefox/.test( window.navigator.userAgent.toLowerCase() ) ) {
html.classList.add('is-firefox');
}
})(document.documentElement);
Then you can add css for that class:
.is-firefox td {
color: orange;
}
Working jsFiddle. Tested in Chrome 54 & Firefox 45.
You can try also this css fix without any javascript, like that:
#-moz-document url-prefix() {
td {
color: orange;
}
}
Here you have some more information about CSS hacks:
https://www.wired.com/2010/02/browser-specific_css_hacks/
You can add a className to all td elements at event.target .cellIndex at mouseover event, remove the className from all td elements at mouseleave event
var elems = document.querySelectorAll("td");
var elemParents = document.querySelectorAll("tr")
for (var td of elems) {
td.addEventListener("mouseover", function(e) {
var index = e.target.cellIndex;
for (let tr of elemParents) {
tr.querySelectorAll("td")[index]
.className = "color";
}
});
td.addEventListener("mouseleave", function(e) {
for (let tr of elemParents) {
for (var cell of tr.querySelectorAll("td")) {
cell.className = "";
}
}
})
}
function firefoxFix() {
if (/firefox/.test(window.navigator.userAgent.toLowerCase())) {
var tds = document.getElementsByTagName('td');
for (var index = 0; index < tds.length; index++) {
tds[index].innerHTML = '<div class="ff-fix">' + tds[index].innerHTML + '</div>';
};
var style = '<style>' + 'td { padding: 0 !important; }' + 'td:hover::before, td:hover::after { background-color: transparent !important; }' + '</style>';
document.head.insertAdjacentHTML('beforeEnd', style);
};
};
firefoxFix();
.color {
color: orange;
}
table {
border-spacing: 0;
border-collapse: collapse;
overflow: hidden;
z-index: 1;
}
td,
th,
.ff-fix {
cursor: pointer;
padding: 10px;
position: relative;
}
td:hover::after,
.ff-fix:hover::after {
background-color: blue;
content: '\00a0';
height: 10000px;
left: 0;
position: absolute;
top: -5000px;
width: 100%;
z-index: -1;
}
<table>
<tbody>
<tr>
<td>20</td>
<td>21</td>
<td>23</td>
<td>25</td>
<td>27</td>
</tr>
<tr>
<td>18</td>
<td>20</td>
<td>22</td>
<td>24</td>
<td>26</td>
</tr>
<tr>
<td>17</td>
<td>19</td>
<td>21</td>
<td>23</td>
<td>25</td>
</tr>
<tr>
<td>16</td>
<td>18</td>
<td>20</td>
<td>22</td>
<td>24</td>
</tr>
</tbody>
</table>
Hello Try This One Below
$('td').hover(function() {
var t = parseInt($(this).index()) + 1;
$('td:nth-child(' + t + ')').addClass('highlighted');
},
function() {
var t = parseInt($(this).index()) + 1;
$('td:nth-child(' + t + ')').removeClass('highlighted');
});
table, td {
border: 1px solid black;
}
td {
width: 40px;
height: 40px;
}
.highlighted {
color:orange;
background-color:black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>aa</td>
<td>aa</td>
<td>aa</td>
<td>aa</td>
</tr>
<tr>
<td>aa</td>
<td>aa</td>
<td>aa</td>
<td>aa</td>
</tr>
<tr>
<td>aa</td>
<td>aa</td>
<td>aa</td>
<td>aa</td>
</tr>
<tr>
<td>aa</td>
<td>aa</td>
<td>aa</td>
<td>aa</td>
</tr>
</table>
You can call function on every cell hover like this :
function a(ele){ //On mouse over
ele.style.color = 'orange';
}
function b(ele){ // On mouse out
ele.style.color = 'grey';
}
I have created tables of items and need them to be moved to a separate floating box (follows website users scroll when clicking an 'add' button).
At the moment I have created tables of items and managed to create the floating box:
window.onload = function() {
function getScrollTop() {
if (typeof window.pageYOffset !== 'undefined') {
return window.pageYOffset;
}
var d = document.documentElement;
if (d.clientHeight) {
return d.scrollTop;
}
return document.body.scrollTop;
}
window.onscroll = function() {
var box = document.getElementById('box'),
scroll = getScrollTop();
if (scroll <= 28) {
box.style.top = "50px";
} else {
box.style.top = (scroll + 2) + "px";
}
};
};
#box {
position: absolute;
top: 100px;
background-color: #dad9c7;
margin-left: 200px;
left: 70%;
width: 200px;
height: 50px;
border: 5px solid #393c3d;
text-align: center;
}
<div>
<u><h2>Batteries</h2></u>
<table id="myTable" class="tablesorter border">
<thead>
<tr>
<th>Battery</th>
<th>Weight</th>
<th>Capacity</th>
<th>discharge</th>
<th>Price</th>
<th>List</th>
</tr>
</thead>
<tbody>
<tr>
<td>Turnigy nano-tech 1000mAh</td>
<td>99g</td>
<td>1000mAh</td>
<td>25~50C</td>
<td>$10.15</td>
<td>Add</td>
</tr>
</tbody>
</table>
</div>
<div id='box'><u>Parts List</u>
</div>
Help will be appreciated, thank you.