I need guidance editing a file. I have posted the Javascript below. This is a link to my working example http://www.closetos.com/top-shelf-awards_copy_copy.
The problem occurred when I added an additional row to the table. Now, when you select the text link in a cell in the second row, it stays selected and active, when clicking on something in the top row.
function $(id)
{
return document.getElementById(id);
}
function Coalesce(Value, Default)
{
if(Value == null)
return Default;
return Value;
}
function Switcher(numberOfSections, sectionContainerID, activeClass, inactiveClass)
{
this.NumberOfSections = Coalesce(numberOfSections, 1) - 1;
this.SectionContainerID = Coalesce(sectionContainerID, "sectionContainer");
this.ActiveClass = Coalesce(activeClass, "active");
this.InactiveClass = Coalesce(inactiveClass, "");
}
Switcher.prototype.Switch = function(TheLink, SectionID)
{
// Make sure all sections are hidden
var SectionContainer = $(this.SectionContainerID);
for(var ct = 0; ct < SectionContainer.childNodes.length; ct++)
{
var node = SectionContainer.childNodes[ct];
if(node.nodeType != 1)
continue;
node.style.display = "none";
}
var First = true;
// Reset button styles
for(var ct = 0; ct < TheLink.parentNode.childNodes.length; ct++)
{
if(TheLink.parentNode.childNodes[ct].nodeType != 1)
continue;
else node = TheLink.parentNode.childNodes[ct];
node.className = this.InactiveClass;
if(First)
{
node.className += " firstCell";
First = false;
}
}
// Show the selected section
$(SectionID).style.display = "block";
TheLink.className = this.ActiveClass;
if(TheLink == node)
TheLink.className += " lastCell";
}
You problem is in this section of code. this looks only at the row that the clicked cell is in. TheLink.parentNode is a reference to the row that the cell is in.
for(var ct = 0; ct < TheLink.parentNode.childNodes.length; ct++) <--- parenNode == row
{
if(TheLink.parentNode.childNodes[ct].nodeType != 1)
{
continue;
}
else
{
node = TheLink.parentNode.childNodes[ct];
}
node.className = this.InactiveClass;
if(First)
{
node.className += " firstCell";
First = false;
}
}
In order to make this work with multiple rows you need to modify it to look at other rows in the table:
for(var ct = 0; ct < TheLink.parentNode.parentNode.childNodes.length; ct++)
{
for( innerL = 0; innerL < TheLink.parentNode.parentNode.childNodes[ct].childNodes.length; innerL++)
{
if(TheLink.parentNode.parentNode.childNodes[ct].childNodes[innerL].nodeType != 1)
{
continue;
}
else
{
node = TheLink.parentNode.parentNode.childNodes[ct].childNodes[innerL];
}
node.className = this.InactiveClass;
if(First)
{
node.className += " firstCell";
First = false;
}
}
}
in the block above you are looking at the parentNode's (the tr) parentNode (tbody) and then iterating through its grandchildren. This allows you to capture all the cells in the table, not just the row.
Here is an example of it working. When you follow the link you need to hit the green 'run' button on the bottom left of the page to get the script to load.
Related
I have a code that's supposed to show the table cell value when clicked on and also highlight the table cell that has been clicked on (Using CSS class). However, the table cell isn't highlighting for some reason. It works when I remove the table cell value code. I'm not sure what's wrong.
const myWords = ["LOL", "HEY", "TOYS", "YES", "SIR", "JOY"];
//Highlighting Table Cell code
//Goes through every 'td' on page
for (let node of document.querySelectorAll("td")) {
node.onclick = function() {
if (node.className == "") {
node.className = "selected"
} else {
node.className = ""
}
}
}
//Get Table Value code
var selectedWord = "";
var clicking = document.getElementsByTagName('td');
//Everytime the user click on a cell...
for (var i = 0; i < clicking.length; i++) {
var click = clicking[i];
click.onclick = function() {
selectedWord += this.innerHTML;
alert(selectedWord);
//Calls a function for each word in myWords
myWords.forEach(myFunction);
function myFunction(item, index) {
//If a word matches the selected word...
if (item == selectedWord) {
alert(item);
}
}
}
}
I'm trying to change the background color of each individual cell but with some if statemnets.
I have some code that does it for 1 cell, but I want it to do the same for all the active cells.
My google script code:
function changeColor(){
// Change the background color
let colorRed = '#f23a53';
let colorOrange = '#f29f3a';
let colorGreen = '#7de396';
let actCell = SHEET.getActiveCell();
let actData = actCell.getValue();
if (Number.isInteger(actData)) {
if (actData < 5) {
actCell.setBackground(colorRed);
} else if (actData < 9) {
actCell.setBackground(colorOrange);
} else if (actData == 9|| actData == 10) {
actCell.setBackground(colorGreen);
}
} else {
SHEET.getRange('D1').setValue(SpreadsheetApp.getActive().getActiveRange().getA1Notation()+" doesn't contain an integer.");
}
}
Should I make a list of every active cell, then loop over it and run the function 'changeColor'?
Or is there a way to get the active range and look at every single cell at a time with a built in function?
Thx for your time.
To perform your request on an active range that contians more than one cell, use getActiveRange() instead of getActiveCell()
This will return you a 2-D range rather than a single cell.
Respecitively, you need to to loop through the cells of this range and verify either your conditions are fulfilled.
Useful is the method getCell().
Sample modificaiton of your code:
function changeColor(){
// Change the background color
let colorRed = '#f23a53';
let colorOrange = '#f29f3a';
let colorGreen = '#7de396';
let SHEET = SpreadsheetApp.getActive().getActiveSheet();
let actRange = SHEET.getActiveRange();
let actData = actRange.getValues();
var startRow = actRange.getRow();
var startColumn = actRange.getColumn();
var integer = false;
for(var i = 0; i < actData.length; i++){
for(var j = 0; j < actData[0].length; j++){
var actCell = actRange.getCell(1+i, 1+j);
var value = actData[i][j];
if (Number.isInteger(value)) {
integer = true;
if (actData[i][j] < 5) {
actCell.setBackground(colorRed);
} else if (value < 9) {
actCell.setBackground(colorOrange);
} else if (value == 9|| value == 10) {
actCell.setBackground(colorGreen);
}
}
}
}
if(integer == false) {
SHEET.getRange('D1').setValue(SpreadsheetApp.getActive().getActiveRange().getA1Notation()+" doesn't contain an integer.");
}
}
I have implemented a text search in html using javascript also I am able to highlight it, now I am looking to navigate within the html document using a next and previous buttons, If anyone can suggest some options and solutions that would be really great. Thanks in advance.
For reference I am using the below code for highlighting the search text.
function MyApp_HighlightAllOccurencesOfStringForElement(element,keyword) {
if (element) {
if (element.nodeType == 3) { // Text node
while (true) {
var value = element.nodeValue; // Search for keyword in text node
var idx = value.toLowerCase().indexOf(keyword);
if (idx < 0) break; // not found, abort
var span = document.createElement("span");
var text = document.createTextNode(value.substr(idx,keyword.length));
span.appendChild(text);
span.setAttribute("class","MyAppHighlight");
span.style.backgroundColor="yellow";
span.style.color="black";
text = document.createTextNode(value.substr(idx+keyword.length));
element.deleteData(idx, value.length - idx);
var next = element.nextSibling;
element.parentNode.insertBefore(span, next);
element.parentNode.insertBefore(text, next);
element.parentNode.insertBefore();
element = text;
MyApp_SearchResultCount++; // update the counter
}
} else if (element.nodeType == 1) { // Element node
if (element.style.display != "none" && element.nodeName.toLowerCase() != 'select') {
for (var i=element.childNodes.length-1; i>=0; i--) {
MyApp_HighlightAllOccurencesOfStringForElement(element.childNodes[i],keyword);
}
}
}
}
}
Here's a jsfiddle with the idea:
(see working at http://jsfiddle.net/TAxdp/)
function goNext(){
jump(1);
}
function goPrev(){
jump(-1);
}
function jump(howHigh){
prevSelected = currSelected;
currSelected = currSelected + howHigh;
if (currSelected < 0){
currSelected = MyApp_SearchResultCount + currSelected;
}
if (currSelected >= MyApp_SearchResultCount){
currSelected = currSelected - MyApp_SearchResultCount;
}
prevEl = document.getElementsByClassName("MyAppHighlight")[prevSelected];
if (prevEl){
prevEl.style.backgroundColor="yellow";
}
el = document.getElementsByClassName("MyAppHighlight")[currSelected];
el.style.backgroundColor="green";
el.scrollIntoView(true); //thanks techfoobar
}
p.s. "highlight all" must be clicked before next/previous.
You can navigate through the matches by using the scrollIntoView() method:
For example, traversing to the first match:
document.getElementsByClassName("MyAppHighlight")[0].scrollIntoView(true);
Documentation for scrollIntoView()
How would I rewrite this function so that any hidden rows are completely ignored?
function stripeRows(table) {
var numRows = table.rows.length;
for (var i = 1; i < numRows; i++) {
var ID = table.rows[i].id;
if (i % 2 == 0) {
table.rows[i].className = "GridRow";
}
else {
table.rows[i].className = "GridRowAlt";
}
}
}
EDIT: turns out my suggestion to use CSS will not work - go figure... In any case you can use jQuery
$('tr:visible:odd').addClass('even');
$('tr:visible:even').addClass('odd');
(note the inversion, since jQuery counts from 0). No need to loop at all! :-)
See it working
However you detect hidden rows, you must at least decouple your counter from your row index, e.g. via for(... in ...). If you find a hidden row, continue your loop:
var i = 0;
for (var row in table.rows) {
if(row.style.visibility == 'hidden')
// or similar (see other answers), e.g.: if($('#element_id:visible').length > 0)
continue;
var ID = row.id;
if (i % 2 == 0) {
row.className = "GridRow";
}
else {
row.className = "GridRowAlt";
}
++i;
}
How can I toggle multiple rows in a table if the <td> class is set to an specific class. For instance toggle all rows if they contain the class="foo".
<table id="bar">
<tr>
<td>hello</td>
<td class="foo">there</td>
<td class="foo">bye</td>
</tr>
</table>
Here's a non-jQuery solution, written just for you: http://phrogz.net/tmp/toggling_rows_with_class.html
Here's the relevant JS:
window.onload = function() {
var visible = true;
document.getElementById('toggle').onclick = function() {
visible = !visible;
var tds = findElementsWithClass('td', 'foo');
for (var i=0, len=tds.length; i<len; ++i) {
tds[i].parentNode.style.display = visible ? '' : 'none';
}
};
}
function findElementsWithClass(tagName, className) {
if (document.querySelectorAll) {
return document.querySelectorAll(tagName + "." + className);
} else {
var results = [];
var all = document.getElementsByTagName(tagName);
var regex = new Regexp("(?:^|\\s)" + tagName + "(?:\\s|$)");
for (var i=0, len=all.length; i<len; ++i) {
if (regex.test(all[i].className)) {
results.push(all[i]);
}
}
return results;
}
}
Modify the class
Why is everyone using selectors? There is already a class attached to all the appropriate elements, so why not just modify the class?
This function will find the class of a given name, and set an attribute for that class. Be careful if you have multiple classes with coincident names in different stylesheets, because the function isn't!
function changeStyle(stylename,attribute,newvalue) {
var cssRules = 'rules';
if(document.styleSheets[0].cssRules) {
cssRules = 'cssRules';
}
for(var sheetId=0; sheetId<document.styleSheets.length; sheetId++) {
var sheet = document.styleSheets[sheetId];
for(var ruleId=0; ruleId<sheet[cssRules].length; ruleId++) {
var rule = sheet[cssRules][ruleId];
if(rule.selectorText == "."+stylename) {
rule.style.setProperty(attribute,newvalue,"");
}
}
}
return false;
}
Now, just call
changeStyle('foo','display','none');
and the cells should disappear, then with 'block' to get them back (IE can't do the more recent display styles like ). I suspect that in a table you'll want to hide entire rows rather than just cells, but you can also make them disappear by setting visibility to hidden - they will still take up space, but not draw.
See, no jquery, no homemade element selectors. Just a slightly annoying bit of javascript to loop through the stylesheets and their rules...
td = document.getElementsByTagName('td');
for (var i = 0; i < td.length; i++) {
if (td[i].className === 'foo')
if (!td[i].style.display)
td[i].style.display = 'none';
else
td[i].style.display = '';
}
}
http://jsfiddle.net/qwertymk/cyZn9/2/
Something like this should do it:
var trs = document.getElementsByTagName("tr");
for (var i in trs) {
var tr = trs[i];
if (tr.getElementsByClassName("foo").length > 0)
tr.style.display = (tr.style.display == "none" ? "block" : "none");
}
This will toggle the display on any TR that contains a child with class="foo".
Something like this?
$("table td.specific_class").toggle();
Edit
/* Go through the table rows */
var trs = document.getElementsByTagName("tr");
for (var i = 0; i < trs.length; i++ ) {
var myClass, tds, line_done = false;
/* Go through the table cells */
tds = trs[i].getElementsByTagName("td");
for ( var k = 0; k < tds.length; k++ ){
/* Check each class of each cell */
myClasses = tds[k].className.split(' ');
for ( var j = 0; j < myClasses.length; j++ ){
/* If the class corresponds we toggle the row and break until the next row */
if ( myClasses[j].className == "foo" ){
trs[i].style.display = trs[i].style.display == "none" ? "block" : "none";
line_done = 1;
break;
}
}
if ( line_done ){
break;
}
}
}
try this one
<html>
<head>
<title>test</title>
<script type="text/javascript">
var toggle = function (action) {
var trs = document.getElementById('bar').getElementsByTagName('tr'),
trs_count = trs.length,
needed = [],
total = 0,
pattern = /\bfoo\b/g,
initial= 'show';
for (i=0; i<trs_count; i++) {
var tds = trs[i].getElementsByTagName('td'),
tds_count = tds.length;
for (j=0; j<tds_count; j++) {
if (pattern.exec(tds[j].className)) {
needed.push(tds[j]);
total++;
}
}
}
toggle = function (action) {
if (this.display == null) {
this.display = initial;
}
if (action == null) {
this.display = (this.display == 'hide') ? 'show' : 'hide';
}
else {
this.display = action;
}
for (i=0; i<total; i++) {
if (this.display == 'show') {
needed[i].style.display = 'block';
}
else {
needed[i].style.display = 'none';
}
}
return true;
}
return toggle();
}
</script>
</head>
<body>
<table id="bar">
<tr><th>Header</th></tr>
<tr><td class="foo">1 Data foo</td></tr>
<tr><td>2 Data</td></tr>
<tr><td class="foo">3 Data foo</td></tr>
<tr><td>4 Data</td></tr>
</table>
<button type="button" onclick="toggle()">toggle</button>
</body>
</html>