Selenium and Chrome, having trouble selecting element - javascript

I'm using Selenium and Chrome to write a script. I'm having trouble getting Selenium to select and click on two elements. Here's the element I'm trying to select:
HTML of Element 1:
<td class="menuItem" id="tWlans" style=""><a href="frameWlan.html"
id="cWlans" accesskey="W" onmouseover="highlight('Wlans')"
onmouseout="removeHighlight('Wlans')" onclick="selectTab('Wlans')"
onfocus="highlight('Wlans')" onblur="removeHighlight('Wlans')"
target="mainFrame"><u>W</u>LANs</a></td>
HTML of Element 2:
<td class="listNoPad">
<input type="TEXT" name="1.6.7.wlan_id" class="statictextboxlink"
onclick="editThisWlan(this.value,this.name)" readonly="" size="7" value="7">
</td>
I've tried selecting the element by id and by XPath, neither of which works.
function siteNavigate() {
sleep(4500);
driver.findElement(By.xpath('//*[#id="cWlans"]')).click();
//driver.findElement(By.id('cWlans')).click();
}
Thanks in advance for any help and suggestions.
Edit:
function helpAction(pageId, startpage) {
var baseHref = window.location.href;
var index = baseHref.indexOf("/screens");
baseHref = baseHref.substring(0, index);
var href = "/helpfiles/oweb/index.html";
var editWindow = window.open(baseHref + href, "editWindow", "left=100 top=50 menubar=no,toolbar=yes,width=800,height=600,status=yes,resizable=yes");
if (navigator.appName != "Netscape") {
editWindow.location.href = baseHref + href;
editWindow.location.reload(true);
}
editWindow.focus();
}
function feedbackAction() {
var URL = 'http://www.cisco.com/go/wireless-feedback';
var feedbackWindow = window.open(URL, "FeedbackWindow", "left=100 top=50 menubar=no,toolbar=no,scrollbars=yes,titlebar=yes,width=800,height=800,status=yes,resizable=yes");
feedbackWindow.focus();
}
function selectTab(tabName) {
// All this function does is update the value of the hidden field and call the updatePage() function
// Obtain object reference to hidden field
var fieldObj = document.getElementById("hSelectedTab");
// Store the new tab selection in the hidden field
fieldObj.value = tabName;
updatePage();
}
function highlight(tabName) {
//remove highlight for all the tabs
removeHighlightAll();
var highlightObj = document.getElementById("t" + tabName);
// Only highlight if srcElement is a tab object.
highlightObj.style.backgroundColor = "#25546B";
}
function removeHighlight(tabName) {
var highlightObj = document.getElementById("t" + tabName);
highlightObj.style.backgroundColor = "";
}
function removeHighlightAll() {
document.getElementById("tMonitor").style.backgroundColor = "";
document.getElementById("tWlans").style.backgroundColor = "";
document.getElementById("tSwitch").style.backgroundColor = "";
document.getElementById("tWireless").style.backgroundColor = "";
document.getElementById("tSecurity").style.backgroundColor = "";
document.getElementById("tManagement").style.backgroundColor = "";
document.getElementById("tCommands").style.backgroundColor = "";
document.getElementById("tHelp").style.backgroundColor = "";
document.getElementById("tFeedback").style.backgroundColor = "";
}
function updatePage() {
// Clear the current tab selection
removeSelection();
// Obtain object reference to hidden field
var fieldObj = document.getElementById("hSelectedTab");
// Retrieve the selected tab
var selectedTab = fieldObj.value;
// Highlight the selected tab
cellObj = document.getElementById("t" + selectedTab);
cellObj.className = "selected";
}
function removeSelection() {
removeHighlightAll();
// Brute force method to clear the tab selection
document.getElementById("tMonitor").className = "menuItem";
document.getElementById("tWlans").className = "menuItem";
document.getElementById("tSwitch").className = "menuItem";
document.getElementById("tWireless").className = "menuItem";
document.getElementById("tSecurity").className = "menuItem";
document.getElementById("tManagement").className = "menuItem";
document.getElementById("tCommands").className = "menuItem";
document.getElementById("tHelp").className = "menuItem";
document.getElementById("tFeedback").className = "menuItem";
}
function DisplayMsgIfAny() {
if (document.forms[0].err_flag.value == 1) {
alert(document.forms[0].err_msg.value);
} else if (document.forms[0].result_flag.value == 1) {
alert(document.forms[0].cmd_result.value);
}
document.forms[0].err_flag.value = 0;
document.forms[0].result_flag.value = 0;
document.forms[0].buttonClicked.value = 0;
}
//need to get image for the OEMS and change the logo image.
function getLogoImage() {}
A {
TEXT-DECORATION: none
}
#home_icon {
height: 12px;
}
A:link {
COLOR: #ffffff;
TEXT-DECORATION: none
}
A:hover {
COLOR: #ffffff;
TEXT-DECORATION: none
}
A:active {
COLOR: #000000;
TEXT-DECORATION: none
}
A:visited {
COLOR: #ffffff;
TEXT-DECORATION: none
}
A.command {
COLOR: #ffffff;
TEXT-DECORATION: none
}
A.command:hover {
COLOR: #ff9100;
TEXT-DECORATION: underline
}
P {
FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
TD {
FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif
}
P {
FONT-SIZE: 11px;
MARGIN: 0px;
COLOR: #333366
}
TD {
FONT-SIZE: 12px
}
TD.menuItem {
PADDING-RIGHT: 10px;
PADDING-LEFT: 10px;
PADDING-BOTTOM: 4px;
PADDING-TOP: 5px;
BORDER-BOTTOM: #000000 5px solid;
width: 1%;
white-space: nowrap;
}
TD.selected {
PADDING-RIGHT: 10px;
PADDING-LEFT: 10px;
PADDING-BOTTOM: 4px;
COLOR: #000000;
PADDING-TOP: 5px;
BORDER-BOTTOM: #ff9100 5px solid;
width: 1%;
white-space: nowrap;
}
TD.space {
WIDTH: 50%;
}
.style2 {
COLOR: #ffffff
}
<script language="JavaScript" src="../servicescript41.js"></script>
<body leftmargin="0" topmargin="0" marginwidth="0" marginheight="0" onload="updatePage(); DisplayMsgIfAny();">
<table width="100%" height="53" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td style="PADDING-BOTTOM: 4px" align="middle" background="../images/background_web41.jpg" width="180">
<img src="../images/cisco/cisco-logo-2007.gif" width="67" height="40" alt="logo" />
</td>
<td valign="bottom" background="../images/background_web41.jpg">
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td class="menuItem" id="tMonitor" style=""><u>M</u>ONITOR</td>
<td class="selected" id="tWlans" style=""><u>W</u>LANs</td>
<td class="menuItem" id="tSwitch" style=""><u>C</u>ONTROLLER</td>
<td class="menuItem" id="tWireless" style="">W<u>I</u>RELESS</td>
<td class="menuItem" id="tSecurity" style=""><u>S</u>ECURITY</td>
<td class="menuItem" id="tManagement" style="">M<u>A</u>NAGEMENT</td>
<td class="menuItem" id="tCommands" style="">C<u>O</u>MMANDS</td>
<td class="menuItem" id="tHelp">HE<u>L</u>P</td>
<td class="menuItem" id="tFeedback" style=""><u>F</u>EEDBACK</td>
<td class="space"> </td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<div style="position:absolute; right:0px; top:0px; margin: 3px 10px 0px 0px">
<p>Sa<u>v</u>e Configuration | <u>P</u>ing | <a class="command" href="#" accesskey="g" onclick="javascript:logoutAction();">Lo<u>g</u>out</a> | <u>R</u>efresh</p>
</div>
<form method="post" action="/screens/banner.html">
<input type="hidden" name="access_control" size="16" maxlength="15" value="1">
<input name="hSelectedTab" type="hidden" id="hSelectedTab" value="Wlans">
<input type="hidden" name="err_flag" size="16" maxlength="15" value="0">
<input type="hidden" name="err_msg" size="512" maxlength="511" value="">
<input type="hidden" name="result_flag" size="16" maxlength="15" value="0">
<input type="hidden" name="cmd_result" size="512" maxlength="511" value="Config Saved">
<input type="hidden" name="ping_address" size="50" maxlength="50" value="">
<input type="hidden" name="interfaceType" size="11" maxlength="11" value="">
<input type="hidden" name="buttonClicked" size="16" maxlength="15" value="0">
</form>
</body>
Edit 2:
Error message from Node.js:
NoSuchElementError: no such element: Unable to locate element: {"method":"css selector","selector":"*[id="cWlans"]"}
(Session info: chrome=61.0.3163.100)
(Driver info: chromedriver=2.33.506120 (e3e53437346286c0bc2d2dc9aa4915ba81d9023f),platform=Windows NT 10.0.15063 x86_64)
at WebDriverError (C:\Selenium\node_modules\selenium-webdriver\lib\error.js:27:5)
at NoSuchElementError (C:\Selenium\node_modules\selenium-webdriver\lib\error.js:192:5)
at Object.checkLegacyResponse (C:\Selenium\node_modules\selenium-webdriver\lib\error.js:546:15)
at parseHttpResponse (C:\Selenium\node_modules\selenium-webdriver\lib\http.js:509:13)
at doSend.then.response (C:\Selenium\node_modules\selenium-webdriver\lib\http.js:441:30)
at process._tickCallback (internal/process/next_tick.js:109:7)
From: Task: WebDriver.findElement(By(css selector, *[id="cWlans"]))
at thenableWebDriverProxy.schedule (C:\Selenium\node_modules\selenium-webdriver\lib\webdriver.js:807:17)
at thenableWebDriverProxy.findElement (C:\Selenium\node_modules\selenium-webdriver\lib\webdriver.js:1014:17)
at siteNavigate (C:\Selenium\byot.js:29:8)
at sleep.then (C:\Selenium\byot.js:21:5)
From: Task: WebElement.click()
at thenableWebDriverProxy.schedule (C:\Selenium\node_modules\selenium-webdriver\lib\webdriver.js:807:17)
at WebElementPromise.schedule_ (C:\Selenium\node_modules\selenium-webdriver\lib\webdriver.js:2010:25)
at WebElementPromise.click (C:\Selenium\node_modules\selenium-webdriver\lib\webdriver.js:2092:17)
at siteNavigate (C:\Selenium\byot.js:29:37)
at sleep.then (C:\Selenium\byot.js:21:5)

Ok, I apologize in advance. I didn't realize initially that the page had several iframes nested inside the page. To make a very long story short, the frames ended up being the problem the whole time. The site was set up with four frames, some of which changed depending on context and some that essentially stayed static after the initial login. The hardest part was knowing which frame to switch to, and keeping track of which context I was currently focused in on.
Here's what I ended up with:
const {Builder, By, until} = require('selenium-webdriver');
var webdriver = require('selenium-webdriver');
var driver = new webdriver.Builder().withCapabilities(webdriver.Capabilities.chrome()).build();
driver.get('http://sitetonavigate.com');
driver.manage().window().maximize();
driver.findElement(By.name('bSubmit ')).click();
function sleep (time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
// Wait until Chrome is fully loaded to launch AutoIT login script
sleep(4500).then(() => {
autoIT();
});
function autoIT() {
var child_process = require('child_process');
var workerProcess = child_process.execFile("C:\\Selenium\\autoITscript.exe");
sleep(2500).then(() => {
siteNavigate();
});
}
function siteNavigate() {
driver.switchTo().frame("banner");
driver.findElement(By.id('cWlans')).click();
//Select correct WLAN
sleep(2500).then(() => {
driver.switchTo().defaultContent();
driver.switchTo().frame("mainFrame");
driver.switchTo().frame("content");
driver.findElement(By.xpath('/html/body/form/table[3]/tbody/tr[8]/td[2]/input')).click();
});
}

You can use:
Element1 :
driver.findElement(By.id('tWlans')).click();
Element2 :
driver.findElement(By.name('1.6.7.wlan_id')).click();

You are clicking on the TD because it has the ID, tWlans. You (presumably) want to click on the A tag contained within. I would suggest the CSS selector, #tWlans > a. The code is below. I added a wait but it may or may not be needed.
WebDriverWait wait = new WebDriverWait(driver, 5);
wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#tWlans > a"))).click();
As for the second element, it wasn't in your full HTML posted so I'm not sure if it's unique but you can try these couple CSS selectors:
input[name='1.6.7.wlan_id']
input[onlick^='editThisWlan']

Related

JavaScript DOM table manipulation

First Problem
How to modify the function cut() to apply "line-through" to all td elements not for only the first.
Second Problem
When I generate the table I don't know what I'm missing in this.details to automatically generate the th of the table only one time (not to display in html like in the code below) because I tried
this.details = `<tr>
<th>Item description<\th>
<th>Action<\th>
<td>${this.item}</td>
<td>${this.action}</td>
</tr>`;
and the th is generate for each td.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>list</title>
</head>
<body>
<h2>list</h2>
<div class="container">
<input type="text" name="item" id="item">
<label for="item"></label>
<input type="button" value="Add item" class="addBtn" id="add">
</div>
<div class="container" id="sort">
<input type="button" value="Sort asc" class="btn">
<input type="button" value="Sort desc" class="btn">
</div>
<div class="tableData" id="table">
<table id="display-none">
<tr>
<th class="show-succes">product</th>
<th class="show-succes">mark</th>
</tr>
</div>
<script src="app.js"></script>
</body>
</html>
function Item(item, action, table) {
this.item = item;
this.action = `<input type="button" value="Mark as buyed" class="newBtn" id="buton" onclick="cut()" `;
this.details = `<tr>
<td>${this.item}</td>
<td>${this.action}</td>
</tr>`;
this.table = table;
this.addToTable = function () {
this.table.innerHTML += this.details;
};
}
const addBtn = document.getElementById('add');
addBtn.addEventListener('click', addNewItem);
function addNewItem() {
const items = document.getElementById('item').value;
const actions = 'mark as buyed'
const myTable = document.getElementById('display-none');
const item = new Item(items, actions, myTable);
item.addToTable();
}
function cut() {
let el = document.querySelector("td");
el.style.textDecoration = "line-through";
}
*{
margin: 0px;
padding: 0px;
box-sizing: border-box;
text-decoration: none;
}
h2 {
text-align: center;
padding: 60px ;
}
input[type="text"]{
margin-right: 20px;
}
label{
padding: 15px;
}
.btn{
padding: 5px;
margin-top: 20px;
margin-right: 10px;
}
#sort{
margin-left: -90px;
}
.container{
display: flex;
justify-content: center;
}
#table{
width: 40%;
text-align: center;
margin-left: 650px;
margin-top: 20px;
}
Your approach is much more involved than necessary and really wouldn't do you any good to try to fix it.
See comments inline below for the most simple approach.
// Get reference to the elements you'll use
// over and over, just once.
const input = document.getElementById("item");
const tbl = document.querySelector("table");
const add = document.querySelector(".addBtn");
// Add an event handler for the add button click
add.addEventListener("click", function(){
let row = tbl.insertRow(); // Add a row to the table
let itemCell = row.insertCell(); // Add a td to the row
itemCell.textContent = input.value; // Put the input value in the td
let actionCell = row.insertCell(); // Add a second td to the row
let chk = document.createElement("input"); // Create a new input
chk.type = "checkbox"; // Make the input a checkbox
chk.value = "bought"; // Set a value for the checkbox
// Set up an event handler for the new checkbox
chk.addEventListener("click", function(){
// Find the nearest ancestor tr and then query it
// for the first td in it. Then toggle the use of the
// "strike" CSS class to add or remove strikethrough.
this.closest("tr").querySelector("td").classList.toggle("strike");
});
actionCell.appendChild(chk); // Add the checkbox to the td
input.value = ""; // Clear out the textbox
tbl.classList.remove("hidden"); // Show the table
});
body {
font-family:Calibri, Helvetica, Arial;
}
h1 {
font-size:1.8em;
}
div {
margin:1em;
}
.strike {
text-decoration-line: line-through;
}
.hidden {
display:none;
}
<h1>SHOPPING LIST</h1>
<div class="addItems">
<input type="text" id="item">
<input type="button" value="Add item" class="addBtn">
</div>
<table class="hidden">
<tr>
<th>Item</th>
<th>Bought?</th>
</tr>
</table>

How do I add multiple entries in a list in JavaScript

I have a program for a makeshift task list that I am working on that should allow a user to enter more than one task by separating the tasks with a comma. I am not sure how I would write a portion of code to allow this function. I am trying to also make the lists themselves separate so if a user needed to delete a task, all the tasks would not be deleted too.
"use strict";
var $ = function(id) { return document.getElementById(id); };
var tasks = [];
var displayTaskList = function() {
var list = "";
// if there are no tasks in tasks array, check storage
if (tasks.length === 0) {
// get tasks from storage or empty string if nothing in storage
var storage = localStorage.getItem("tasks") || "";
// if not empty, convert to array and store in global tasks variable
if (storage.length > 0) { tasks = storage.split("|"); }
}
// if there are tasks in array, sort and create tasks string
if (tasks.length > 0) {
tasks.sort();
list = tasks.join("\n");
}
// display tasks string and set focus on task text box
$("task_list").value = list;
$("task").focus();
};
var addToTaskList = function() {
var task = $("task");
if (task.value === "") {
alert("Please enter a task.");
} else {
// add task to array and local storage
tasks.push(task.value);
localStorage.tasks = tasks.join("|");
// clear task text box and re-display tasks
task.value = "";
displayTaskList();
}
};
var clearTaskList = function() {
tasks.length = 0;
localStorage.tasks = "";
$("task_list").value = "";
$("task").focus();
};
window.onload = function() {
$("add_task").onclick = addToTaskList;
$("clear_tasks").onclick = clearTaskList;
displayTaskList();
};
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 100%;
background-color: white;
width: 700px;
margin: 0 auto;
border: 3px solid blue;
padding: 0 2em 1em;
}
h1 {
font-size: 150%;
color: blue;
margin-bottom: .5em;
}
label {
float: left;
width: 8em;
}
input {
width: 22em;
margin-right: 1em;
margin-bottom: 1em;
}
#tasks {
margin-top: 0;
float: right;
}
<!DOCTYPE html>
<html>
<head>
<title>Ch09 Task Manager</title>
<link type="text/css" rel="stylesheet" href="task_list.css">
<script type="text/javascript" src="task_list.js"></script>
</head>
<body>
<main>
<h1>Task Manager</h1>
<div id="tasks">
<span id="name"> </span>Tasks<br>
<textarea id="task_list" rows="8" cols="50"></textarea>
</div>
<label for="task">Task</label><br>
<input type="text" name="task" id="task"><br>
<input type="button" name="add_task" id="add_task" value="Add Task">
<input type="button" name="clear_tasks" id="clear_tasks" value="Clear Tasks"><br>
<input type="button" name="delete_task" id="delete_task" value="Delete Task">
<input type="button" name="toggle_sort" id="toggle_sort" value="Toggle Sort"><br>
<input type="button" name="set_name" id="set_name" value="Set Name">
<input type="button" name="filter_tasks" id="filter_tasks" value="Filter Tasks"><br>
</main>
</body>
</html>
I found a lot of other stuff that needed fixing, so I did (mostly having to do with how you use jQuery). Works for me locally. Snippet runner doesn't want to do some of this stuff - sorry! Don't know about that.
var tasks = [];
var displayTaskList = function() {
var list = "";
if (tasks.length === 0) { // if there are no tasks in tasks array, check storage
var storage = localStorage.getItem("tasks") || ""; // get tasks from storage or empty string if nothing in storage
if (storage.length > 0) {
tasks = storage.split("|");
} // if not empty, convert to array and store in global tasks variable
}
if (tasks.length > 0) { // if there are tasks in array, sort and create tasks string
tasks.sort();
list = tasks.join("\n");
}
$("#task_list").val(list); // display tasks string and set focus on task text box
$("#task").focus();
};
var addToTaskList = function() {
var task = $("#task").val();
console.log(`entering addtotask list with task value = ${task}`);
if (task === "") {
alert("Please enter a task.");
} else {
if (task.indexOf(',') === -1) {
tasks.push(task); // add task to array and local storage
} else {
const split = task.split(','); // 2 lines for readability
split.forEach(atask => {
tasks.push(atask);
});
}
localStorage.tasks = tasks.join("|");
$("#task").val(""); // clear task text box and re-display tasks
displayTaskList();
}
};
var clearTaskList = function() {
tasks.length = 0;
localStorage.tasks = "";
$("#task_list").val("");
$("#task").focus();
};
window.onload = function() {
$("#add_task").on('click', function() {
addToTaskList();
});
$("#clear_tasks").on('click', function() {
clearTaskList();
});
displayTaskList();
};
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 100%;
background-color: white;
width: 800px;
margin: 0 auto;
border: 3px solid blue;
padding: 0 2em 1em;
}
h1 {
font-size: 150%;
color: blue;
margin-bottom: .5em;
}
label {
float: left;
width: 8em;
}
input {
width: 22em;
margin-right: 1em;
margin-bottom: 1em;
}
#tasks {
margin-top: 0;
float: right;
}
<body>
<main>
<h1>Task Manager</h1>
<div id="tasks">
<span id="name"> </span>Tasks<br>
<textarea id="task_list" rows="8" cols="50"></textarea>
</div>
<label for="task">Task</label><br>
<input type="text" name="task" id="task"><br>
<input type="button" name="add_task" id="add_task" value="Add Task">
<input type="button" name="clear_tasks" id="clear_tasks" value="Clear Tasks"><br>
<input type="button" name="delete_task" id="delete_task" value="Delete Task">
<input type="button" name="toggle_sort" id="toggle_sort" value="Toggle Sort"><br>
<input type="button" name="set_name" id="set_name" value="Set Name">
<input type="button" name="filter_tasks" id="filter_tasks" value="Filter Tasks"><br>
</main>
<script src="//code.jquery.com/jquery-3.4.1.min.js"></script>
</body>

How to change class of specified <td>?

function change() {
var tds = document.getElementsByTagName("td");
var tds2 = tds.className;
console.log(tds);
for (var i = 0; i < tds.length; i++) {
if (tds[i].className === "marked") {
tds[i].className = "UNmarked";
} else {
tds[i].className = "marked";
}
}
}
function generTab(rows, cols) {
var html = "<table id='tb01'>";
for (var i = 1; i <= rows; i++) {
html += "<tr>"
for (var j = 1; j <= cols; j++) {
html += "<td class='marked' onclick='change()'>" + "</td>";
}
html += "</tr>"
}
return html + "</table>";
}
td.marked {
height: 50px;
width: 50px;
border: solid thin black;
cursor: pointer;
background-color: white;
}
td.UNmarked {
height: 50px;
width: 50px;
border: solid thin black;
cursor: pointer;
background-color: purple;
}
<div class="line">
Number of rows:
<input type="text" id="rows" />
</div>
<div class="line">
Number of cols:
<input type="text" id="cols" />
<span class="error"></span>
</div>
<input type="button" value="Generuj" id="gener" />
</div>
<div id="scene"></div>
I'm generating table by my own, and I want to change class of specified <td> by clicking on on it. The problem is that when I click on whichever <td> it is changing the classes of all of them, but I want to change that <td> class which I click.
May be you can do some thing like the following with a single class:
var tds = document.querySelectorAll("td");
tds.forEach(function(td){
td.addEventListener('click', function(){
this.classList.toggle('marked')
});
});
td {
border: 1px solid lightgray;
padding: 10px;
font-size: 20px;
}
.marked{
background-color: #4CAF50;
color: white;
}
<table>
<tr>
<td>1</td><td>2</td><td>3</td>
</tr>
<tr>
<td>4</td><td>5</td><td>6</td>
</tr>
</table>
Add click event listeners to all the td elements and implement a simple onClick function which adds/removes the desired css class.
const tds = Array.from(document.querySelectorAll('td'));
const onClick = ({ target }) => {
tds.forEach(td => td === target ? td.classList.add('active') : td.classList.remove('active'))
}
tds.forEach(td => td.addEventListener('click', onClick));
.active {
color: red;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<table style="width:100%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
</body>
</html>
The code you've written should be toggling the class of all tds in the document. I believe you're trying to change the class of the td that is being clicked. To do that, try something like (apologies in advance as I'm on my phone):
function change(e) {
let td = e.target;
if (td.classList.contains('marked')) {
td.className = 'UNmarked';
} else {
td.className = 'marked';
}
}
and be sure that that change is bound as the click event for each td.
If you can use jQuery...
$("td").click(function(){
$(this).toggleClass("marked")
.toggleClass("UNmarked");
});

Javascript Cell Filling

I'm trying to fill an HTML table with some values from my JS code.
The first few lines work, but my function doesn't.
Does anyone know why? I've included my code below.
function set(id,num) {
document.getElementById(id).innerHTML = num;
}
var num1 = set("1.4", 55); //ok
var num2 = set("1.6", 56); //ok
var num3 = set("1.12", 57); //ok
function addition() { //notok
//var n1 = document.getElementById("1.4").innerHTML;
//var n2 = document.getElementById("1.6").innerHTML;
//var n3 = document.getElementById("1.12").innerHTML;
//document.getElementById("1.14").innerHTML = parseInt(n1) + parseInt(n2) + parseInt(n3);
document.getElementById("1.14").innerHTML = 55 + 56 + 57;
}
body {
background-color: white;
}
table {
font-size: 15px;
border-collapse: collapse;
border: solid black 1px;
border-radius: 6px;
margin-top: 100px;
margin-left: auto;
margin-right: auto;
}
td, th {
border: solid black 1px;
padding: 10px;
}
.theader {
background-color: rgb(254, 102, 0);
}
th:first-child{
border-top: none;
}
td {
text-align:center;
}
td:first-child, th:first-child {
font-weight: bold;
}
h1 {
margin-top: 150px;
text-align: center;
color: black;
}
tr { background-color: white}
.change { background-color: black; color:white }
.normal { background-color: white }
.notchange{ background-color: white }
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<link href="StyleSheet1.css" rel="stylesheet" />
</head>
<body>
<h1>Test</h1>
<table>
<tr class="normal" onmouseover="this.className='change'" onmouseout="this.className='notchange'">
<td>Row1</td>
<td id="1.1">11</td>
<td id="1.2">11</td>
<td id="1.3">12</td>
<td id="1.4"></td>
<td id="1.5">14</td>
<td id="1.6"></td>
<td id="1.7">16</td>
<td id="1.8">17</td>
<td id="1.9">18</td>
<td id="1.10">19</td>
<td id="1.11">20</td>
<td id="1.12"></td>
<td id="1.13">22</td>
<td id="1.14"></td>
</tr>
...........
</table>
<script type="text/javascript" src="MyJavaScript1.js"></script>
</body>
</html>
I am writing just a table with JS, ("1.4","1.6","1.12") cells filling properly but i can not fill the cell "1.14".
You never actually invoke the function so it doesn't run.
Change your code to look like this:
function set(id,num) {
document.getElementById(id).innerHTML = num;
}
var num1 = set("1.4", 55); //ok
var num2 = set("1.6", 56); //ok
var num3 = set("1.12", 57); //ok
function addition() { //notok
document.getElementById("1.14").innerHTML = 55 + 56 + 57;
}
// added this line:
addition();
I added the last line (and removed commented lines) which will invoke the method (thus running the code inside) and I moved the function to the top of the file. While not neccessary to move the function thanks to function hoisting I feel it's good practice to declare a function before invoking it.
Additional note
You're assigning the result of the set function to a variable with the following line:
var num1 = set("1.4", 55); //ok
You don't have to do this. You can just call set("1.4", 55).
======== OLD ANSWER BELOW ==========
You're using getElementById and .valueOf wrong. getElementById
refers to a HTML element. For example:
getElementById("cell1") would pick the element which looks like:
<td id="cell1"></td>
.valueOf returns the primitive value of a String object, for example:
var str = "Hello World!";
var res = str.valueOf();
console.log(res); // prints: Hello World!
So assuming your html looks like this:
<table>
<tr>
<td id="cell1"></td>
<td id="cell2"></td>
<td id="cell3"></td>
</tr>
</table>
The Javascript code to fill the cell's would look something like
this::
document.getElementById("cell1").innerHTML = "1.4";
document.getElementById("cell2").innerHTML = "1.6";
document.getElementById("cell3").innerHTML = "1.12";
function addition() { //OK
var n1 = document.getElementById("1.4").innerHTML;
var n2 = document.getElementById("1.6").innerHTML;
var n3 = document.getElementById("1.12").innerHTML;
document.getElementById("1.14").innerHTML = parseInt(n1) + parseInt(n2) + parseInt(n3);
}
addition();
And it works. My fault. I deleted to function call and forget to write again.

Next button only brings the first image and stops

I have been trying to create a next and back buttons that go through the images one by one that are in the table.
But the next button, it only brings the first image and stops.
How can the same button "next" have the function of going through all the images?
<p id = "slider"></p>
<div id="galDiv">
<style>
table, th, td {
border: 1px solid black;}
</style>
<table>
<tr>
<td id="1"><img src="gallery/a.jpg" style="width:100px;height:100px;"></td>
<td id="2"><img src="gallery/k.jpg" style="width:100px;height:100px;"></td>
<td id="3"><img src="gallery/2.jpg" style="width:100px;height:100px;" ></td>
<td id="4"><img src="gallery/3.jpg" style="width:100px;height:100px;" ></td>
</tr>
</table>
</div>
<button id="nxt">NEXT</button>
<script>
document.getElementById("nxt").onclick = function()
{myFunction()};
function myFunction() {
var div = document.getElementById('galDiv');
var nextSibling = div.nextSibling;
while(nextSibling && nextSibling.nodeType != 1) {
nextSibling = nextSibling.nextSibling }
}
</script>
How can also create a back button ?
If you are trying to create a facebook like image viewer, you shouldn't use table element.
In order to create such thing you should create a div with container fixed side ,within this div you should have a div with floating images and then your button should change the right position of the inner div.
Or you could use a jquery library such as http://www.jacklmoore.com/colorbox
Your code does nothing. The next sibling to #galDiv is the <button>.
Is this what you wanted?
document.getElementById("nxt").onclick = myFunction;
function myFunction() {
var picture = [
"firstPicture",
"secondPicture",
"thirdPicture",
"fourthPicture"
];
var place = {
"firstPicture": 0,
"secondPicture": 1,
"thirdPicture": 2,
"fourthPicture": 3
};
var table = document.querySelector('table');
if (!table.className) {
table.className = "firstPicture";
}
var nextPicture = (place[table.className] + 1) % 4;
table.className = picture[nextPicture];
}
img[src="gallery/a.jpg"] {
border: 5px solid red;
}
img[src="gallery/k.jpg"] {
border: 5px solid green;
}
img[src="gallery/2.jpg"] {
border: 5px solid blue;
}
img[src="gallery/3.jpg"] {
border: 5px solid black;
}
table {
border-collapse: collapse;
position: absolute;
padding: none;
border: none;
}
#galDiv {
width: 113px;
height: 113px;
overflow: hidden;
position: relative;
}
.firstPicture {
left: 0;
}
.secondPicture {
left: -112px;
}
.thirdPicture {
left: -224px;
}
.fourthPicture {
left: -336px;
}
<p id = "slider"></p>
<div id="galDiv">
<table>
<tr>
<td id="1"><img src="gallery/a.jpg" style="width:100px;height:100px;"></td>
<td id="2"><img src="gallery/k.jpg" style="width:100px;height:100px;"></td>
<td id="3"><img src="gallery/2.jpg" style="width:100px;height:100px;" ></td>
<td id="4"><img src="gallery/3.jpg" style="width:100px;height:100px;" ></td>
</tr>
</table>
</div>
<button id="nxt">NEXT</button>
I added the curimg attribute to the slider. Read the script for yourself. You'll need to add in modulus arithmetic to round around the table entries. As for the 'prev' function. Figure out the same thing with a -1 when selecting the tdnode.
Don't forget to set the curimg attribute after you append the child.
Good luck!
<p id = "slider" curimg='1'></p>
<div id="galDiv">
<style>
table, th, td {
border: 1px solid black;}
</style>
<table>
<tr>
<td id="1"><img src="gallery/a.jpg" style="width:100px;height:100px;"></td>
<td id="2"><img src="gallery/k.jpg" style="width:100px;height:100px;"></td>
<td id="3"><img src="gallery/2.jpg" style="width:100px;height:100px;" ></td>
<td id="4"><img src="gallery/3.jpg" style="width:100px;height:100px;" ></td>
</tr>
</table>
</div>
<button id="nxt">NEXT</button>
<script>
document.getElementById("nxt").onclick = function()
{myFunction()};
function myFunction() {
//Get the slider, parse the int of the 'curimg' attribute
cid = document.getElementById('slider');
current_image = parseInt( cid.getAttribute('curimg') );
//Get the td of that id+1
tdnode = document.getElementById(current_image + 1);
//Clone the image childNode into the slider.
cid.appendChild( td.childNodes[0].cloneNode() );
}
</script>

Categories

Resources