Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm very new to Javascript and am struggling with how it all actually works. I can't seem to find an answer to this question.
I've created a table and given each table cell a unique ID. I've also given each cell it's own background colour with css. Using Javascript, how can I find out what the background colour is for each cell? How do I actually access that property of each cell?
Thanks
Dave
There are two parts to this:
Getting the element
Getting the color assigned to it
Getting the element
If you know the cell ID, you can use document.getElementById:
var element = document.getElementById("the-id");
If you want to do this in response to an event that happens on the cell, for instance a click, you can use an event handler. For instance, suppose the table has the id "my-table":
document.getElementById("my-table").addEventListener("click", function(event) {
var element = event.target;
while (element && element.tagName !== "TD") {
if (element === this) {
// No cell was clicked
return;
}
element = element.parentNode;
}
// ...use element here
});
That hooks the click event on the table (so you don't have to hook it on every single cell), then when the click reaches the table, finds the td that the click passed through on its way to the table (if any).
Note: Old versions IE (IE8 and earlier) don't have addEventListener, they have Microsoft's predecessor to it, attachEvent. This answer shows how to work around that if you need to.
Getting the color
If you assigned the color directly on the element, via the style attribute (<td style="color: ..."...), you can use the style object on the element:
var color = element.style.color;
If it's assigned via a stylesheet, that won't work, you need to use getComputedStyle instead:
var color = getComputedStyle(element).color;
Again, old versions of IE are a pain in this regard, they don't have getComputedStyle but they do have a currentStyle property on elements, so you can polyfill (shim) getComputedStyle:
if (!window.getComputedStyle) {
window.getComputedStyle = function(element, pseudo) {
if (typeof pseudo !== "undefined") {
throw "The second argument of getComputedStyle can't be polyfilled";
}
return element.currentStyle;
};
}
Example
Here's an example (modern browsers only) where you click a cell to get its color:
// Hook click on the table
document.getElementById("my-table").addEventListener("click", function(event) {
var element = event.target;
while (element && element.tagName !== "TD") {
if (element === this) {
// No cell was clicked
return;
}
element = element.parentNode;
}
// Show the color
alert("Color: " + getComputedStyle(element).color);
}, false);
.foo {
color: red;
}
.bar {
color: green;
}
.biz {
color: blue;
}
.baz {
color: #880;
}
<table id="my-table">
<tbody>
<tr>
<td class="foo">foo</td>
<td class="bar">bar</td>
</tr>
<tr>
<td class="biz">biz</td>
<td class="baz">baz</td>
</tr>
</tbody>
</table>
Related
function showQuestion(questionAndAnswers) {
const shuffledAnswers = _.shuffle(questionAndAnswers.answers);
questionTag.innerText = questionAndAnswers.question;
shuffledAnswers.forEach(({ text, correct }, i) => {
answerTag[i].innerText = text;
answerTag[i].dataset.correct = correct;
});
}
document.querySelectorAll(".answer").forEach((answer) => {
answer.addEventListener("click", (event) => {
if (event.target.dataset ) {
answer.style.border = "1.5px solid"
}
});
});
function nextQuestion() {
const nextIndex = currentQuestionIndex + 1;
if (nextIndex <= myQuestions.length - 1) {
showQuestion(myQuestions[nextIndex]);
currentQuestionIndex = nextIndex;
} else {
end.style.visibility = "visible";
nxt_question_btn.style.visibility = "hidden";
}
}
Basically, In this quiz app, I have 4 buttons for answers and once you click on one answer it makes the border black. The problem I am facing is that once I press the next question, it loads up another question with 4 different answers but one of the buttons will still have the border black. How do I get it to reset once I load up another question? and Extra question if it's okay, how can I only select one button at a time per question?
There is no 'reset' as there is no default, you will just have to manually undo what you did earlier, i.e to remove the border completely:
answer.style.border = "none";
To select each button individually, you will ave to give them each an ID, based of something like an iteration, instead of trying to select them by the shared class
that's a tough one, there is no easy answer without knowing what the previous style was, so it's good to store the previous value of the style in memory and reset the styles to the previous value after the next question has been loaded
// a variable declared somewhere in common scope
let prevBorder
// "backup" the old value when you want to mark the answer as "selected"
prevBorder = element.styles.border
// restore to the initial value when you want to reset the styles
element.styles.border = prevBorder
Maybe you are looking for css:initial property?
The initial CSS keyword applies the initial (or default) value of a property to an element. It can be applied to any CSS property. This includes the CSS shorthand all, with which initial can be used to restore all CSS properties to their initial state.
Or you could add class and use classList.toggle() to switch between them.
I don't have your html code and full code so can't help you fully, but this is an example that may help you implement to your code:
document.querySelectorAll('button').forEach(item => {
item.addEventListener('click', function() {
item.style.border = '10px solid black'
document.querySelectorAll('button').forEach(i => {
if (i != item)
i.style.border = "initial"
})
})
})
<button>Click</button>
<button>Click</button>
<button>Click</button>
<button>Click</button>
This question already has answers here:
How do I select text nodes with jQuery?
(12 answers)
Closed 8 years ago.
Is it possible to use JQuery to hide the input elements plus the text after the input? The code is generated, so I cannot change the text, wrap it in a span or alter it in any way.
<label>Event Location <span class="req">*</span></label><br>
<input type="radio" name="a22" id="a22_0" value="Lafayette LA">Lafayette LA<br>
<input type="radio" name="a22" id="a22_1" value="Houston TX">Houston TX<br>
<input type="radio" name="a22" id="a22_3" value="San Antonio TX">San Antonio TX
You need to iterate the parent elements (TDs in your example added as an answer), find all the text elements that follow a radio button, then wrap them in hidden spans:
e.g.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/6gzfLorp/3/
$('td').contents().each(function (e) {
if (this.nodeType == 3 && $(this).prevAll(':radio').length) {
$(this).wrap($('<span>').hide());
}
});
Note: Your question is a little ambiguous, but it would appear from your answer you have TDs which you could just hide all contents of the TD using:
http://jsfiddle.net/TrueBlueAussie/6gzfLorp/7/
$('.set-cities td').each(function (e) {
$(this).contents().wrapAll($('<span>').hide());
});
It is wrapped in a td tag. Here's what I have for now:
$("label:contains('Event Location')").parent("td").wrap("<span class='set-cities'></span>");
$('.set-cities').empty();
$('.set-cities').append("<td><label>Event Location <span class='req'>*</span></label><br><input type='radio' name='aa2' id='aa2_1' value='Houston TX' checked='checked'>Houston TX<br></td>");
I just going to change the whole block of text rather than just the city name.
In case you wanted to replace the text node directly, here's a way to do it. I borrowed from https://stackoverflow.com/a/298758/728393 and tailored it to your situation
function replaceTextAfter(selector,newtext){
var textnode = $(selector).parent().contents() // we need to contents as a collection
.filter(function(){
return this.nodeType == 3 && $(this).prev().is($(selector)); //return true if node is text and the previous node is our selector
});
textnode[0].data = newtext; //change the text
}
replaceTextAfter('#a22_0','abc');
http://jsfiddle.net/z606no23/
Thi delete all text after an element done, until a new tag
http://jsfiddle.net/alemarch/hm7ey6t5/
function deleteElemPlusText( elem ) {
var contestoHtml = $(elem).parent().html()
var thisHtml = $(elem).get(0).outerHTML // $(elem).outerHTML()
var re = new RegExp(thisHtml + "([^<])*")
var newContesto = contestoHtml.replace(re, "")
$(elem).parent().html(newContesto)
}
function deleteAllElemsPlusText( toDelete ) {
var x = $(toDelete).length;
for (var i = 0; i < x; i++) {
deleteElemPlusText($(toDelete).eq(0))
}
}
deleteAllElemsPlusText( "input[type=radio]" )
note: not all browser have outerHTML properties access, but you can use this jquery plugin http://www.darlesson.com/jquery/outerhtml/
I have the below Javascript code on my PHP page, I pass the table name and a variable to the function. The "ALL" portion of the code works fine, parses through the page and flips all of the CSS style display descriptors from 'none' to '' or back.
Where I'm running into issues is the "RED" portion. It is supposed to hide all TR which contain a TD of the class "RedCell" but I cannot seem to get this part working as intended. Please help.
JAVASCRIPT
function expandCollapseTable(tableObj, which)
{
if (which == 'ALL')
{
var rowCount = tableObj.rows.length;
for(var row=0; row<rowCount; row++)
{
rowObj = tableObj.rows[row];
rowObj.style.display = (rowObj.style.display=='none') ? '' : 'none';
}
return;
}
if (which == 'RED')
{
$('td.RedCell').find('td.RedCell').closest('tr').style.display = 'none';
return;
}
else
{
return;
}
}
CSS
.ResultTable td.RedCell{
background-color:#FF4747;
}
HTML BUTTONS AND EXAMPLE TABLE
<input type="button" value="Show/hide ALL" onclick="expandCollapseTable(TheTable, 'ALL')" />
<input type="button" value="Hide Red" onclick="expandCollapseTable(TheTable, 'RED')" />
<table id="TheTable" class="ResultTable" style="padding: 0px; background: #FFFFFF;" align="center">
<tr><td class="RedCell">2014-07-17 10:04</td><td>1998847</td><td>137717</td></tr>
<tr><td>2014-08-06 10:44</td><td>2009211</td><td>106345</td>
<tr><td class="RedCell">2014-07-31 16:47</td><td>2006727</td><td>138438</td>
So the first and third row would be hidden and second row left visible
CodePen version of code http://codepen.io/anon/pen/DrKLm
It should be:
$('td.RedCell', tableObj).closest('tr').hide();
The call to .find() was looking for another td.RedCell inside the first one.
Also, you can't use the .style property with jQuery objects, that's for DOM elements. To hide something with jQuery, use .hide() or .css("display", "none").
And you need to restrict your searching to within the given tableObj.
BTW, why aren't you using jQuery for the ALL option? That entire loop can be replaced with:
$("tr", tableObj).toggle();
Instead of going from the child up to the parent, use the jQuery :has selector to filter elements based on descendents.
$(tableObj).find('tr:has(td.RedCell)').hide();
In addition, you'll probably want to hide all of the cells only if none are already hidden. If any are hidden, you'll want to show those and keep the rest visible. Here's an example of that...
var rows = $(tableObj).find('tr:gt(0)'); // Skips the first row
if(rows.is(':hidden')) {
// Contains elements which are hidden
rows.show();
} else {
rows.hide();
}
The result would be:
function expandCollapseTable(tableObj, which) {
var rows = $(tableObj).find('tr:gt(0)');
if(which == 'RED') {
// First snippet
rows.has('td.RedCell').hide();
} else if(which == 'ALL') {
// Second snippet
if(rows.is(':hidden')) {
rows.show();
} else {
rows.hide();
}
}
}
http://codepen.io/anon/pen/xlmcK
Extra programming candy:
The second snippet could be reduced to rows[rows.is(':hidden')?'show':'hide']();
Two problems, the .find is saying to find descendents of the td.RedCell's that are td.RedCells.
There aren't any of those...
Then, use .css to set the style.
So this:
$('td.RedCell').closest('tr').css('display', 'none');
hey guys having trouble figuring out how to make it so that i can make it only open one table at once, once you open another the other should close any help here?
function showRow(cctab){
if (document.getElementById(cctab)) {
document.getElementById(cctab).style.display = '';
}
}
function hideRow(row1){
if (document.getElementById(cctab)) {
document.getElementById(cctab).style.display = 'none';
}
}
function toggleRow(cctab){
if (document.getElementById(cctab)) {
if (document.getElementById(cctab).style.display == 'none') {
showRow(cctab)
} else {
hideRow(cctab)
}
}
}
Now I want to make it so that only one table "cctab" opens after I suggest the onClick="javascript:toggleRow(cctab);" anyhelp?
Well you could save a reference to the previously shown item and hide it when another is shown:
var currentTab;
function showRow(cctab){
if (document.getElementById(cctab))
document.getElementById(cctab).style.display = '';
if (currentTab && currentTab != cctab)
hideRow(currentTab);
currentTab = cctab;
}
Note that doing inline event handler attributes is so 1999, but assuming you're sticking with it for whatever reason you don't need the javascript: in onClick="javascript:toggleRow(cctab);". (Just say onClick="toggleRow(cctab);")
First you need to store the old row somewhere.
What you've got is a system where you're using <element onclick="..."> to pass the id of the current element into the controller that shows or hides the row.
But if you look at that, what you're missing is a way of telling what the last open row was.
So what your code will need is a central object, or variables which store the old element and the new element.
How you do this is up to you, but if you did something like this:
var table_rows = { current : null /* or set a default */, previous : null };
function rowController (cctab) {
var newRow = document.getElementById(cctab);
if (newRow === table_rows.current) { toggleRow(newRow); }
else {
table_rows.previous = table_rows.current;
table_rows.current = newRow;
showRow(table_rows.current);
hideRow(table_rows.previous);
}
}
Note:
This deals with elements directly, so you don't have to do getById in your functions;
that's handled one time, and then that element is passed around and saved and checked against.
It assumes that the click is happening on the row itself, and not on anything inside of the row;
that's a separate issue that your code has.
Unless it's obvious and easy to click on the row, and not the cells inside of the row, it's difficult to tell how you want users to be able to open and close rows.
What I mean is if only the table-row has an onclick, and somebody clicks on a table-column, then then onclick isn't going to fire.
Figured out how to change the class of a div/link/whatever onclick with JS. Here's a quick demo: http://nerdi.net/classchangetest.html
Now what I'm trying to figure out is how I can revert the previously clicked link to it's old class (or "deactivate") when clicking a new link.
Any ideas? Thanks!
function changeCssClass(navlink)
{
var links=document.getElementsByTagName('a');
for(var i=0, n=links.length; i<n; i++)
{
links[i].className='redText';
}
document.getElementById(navlink).className = 'blueText';
}
With this code all links will be red and lust clicked will be blue.
I hope it will be helpfull.
function changeCssClass(ele, add_class) {
// if add_class is not passed, revert
// to old className (if present)
if (typeof add_class == 'undefined') {
ele.className = typeof ele._prevClassName != 'undefined' ? ele._prevClassName : '';
} else {
ele._prevClassName = ele.className || '';
ele.className = add_class;
}
}
Try it here: http://jsfiddle.net/Zn7BL/
Use it:
// add "withClass"
changeCssClass(document.getElementById('test'), 'withClass');
// revert to original
changeCssClass(document.getElementById('test'));
It is a much better to post your code here, it makes it easier for those reading the question and for others searching later. Linked examples are unreliable and likely won't persist for long.
Copying from the link (and formatting for posting):
<style type="text/css">
.redText, .blueText { font-family: Arial; }
.redText { color : red; }
.blueText { color : blue; }
</style>
<script language="javascript" type="text/javascript">
The language attribute has been deprecated for a very long time, it should not be used. The type attribute is required, so keep that.
function changeCssClass(navlink)
The HTML class attribute is not sepecifically for CSS, it is used to group elements. A better name might be changeClassName.
{
if(document.getElementById(navlink).className=='redText')
{
document.getElementById(navlink).className = 'blueText';
}
else
{
document.getElementById(navlink).className = 'redText';
}
}
</script>
Link 1<br><br>
When called, the function associated with an inline listener will have its this keyword set to the element, so you can call the function as:
<a ... onclick="changeCssClass(this);" ...>
Then you don't have to pass the ID and you don't need getElementById in the function.
You might consider a function that "toggles" the class: adding it if it's not present, or removed if it is. You'll need to write some small functions like hasClass, addClass and removeClass, then your listener can be:
function toggleClass(el, className) {
if (hasClass(el, className) {
removeClass(el, className);
} else {
addClass(el, className);
}
}
Then give your links a default style using a style rule (i.e. apply the redText style to all links), then just add and remove the blueText class.
You might also consider putting a single function on a parent of the links to handle clicks from A elements — i.e. event delegation.