So I am trying to make a chrome extension that adds a panel to the Elements devtool and got something very simple to work. But when I tried setting the page to something with some more intracate JavaScript I get Uncaught TypeError: Cannot read properties of null errors.
Here is what I had before: HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="panel.js"></script>
<title>Document</title>
</head>
<body>
<p id="xpath_display"> Welcome, right click an element and click XPathGenerator to start </p>
</body>
</html>
JS
chrome.runtime.onMessage.addListener((message, sender, responce) => {
if (message.request === "sendtodevtools"){
buildUI(message.path);
}
})
function buildUI(data) {
let display = document.getElementById("xpath_display");
display.textContent = data;
}
and this worked fine. But when I tried to add tabs with some js attached like so...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="panelstyles.css"></link>
<script src="panel.js"></script>
<title>Document</title>
</head>
<body>
<div class="tab">
<button class="tablinks" onclick="openTab(event, 'XpathTab')">Xpath Display</button>
<button class="tablinks" onclick="openTab(event, 'PageTab')">Page Generation</button>
<button class="tablinks" onclick="openTab(event, 'TestTab')">Test Generation</button>
</div>
<!-- Xpath Tab Content -->
<div id="XpathTab" class="tabcontent">
<div style="padding: 10px;">
<label for="element_name">Element Name:</label>
<input id="element_name" onclick="hideNoNameError()"></input>
<p id="no_name_error" style="display: none;">Error, must have name to add</p>
</div>
<div id="xpath_display_container" style="padding: 10px; border: 2px solid black;">
<label for="xpath_display" style="display:flex;flex-direction:column;">UniqueXpath</label>
<p id="xpath_display"> Welcome, right click an element and click XPathGenerator to start </p>
</div>
<div id="id_display_container" style="padding: 10px; border: 2px solid black;">
<label for="id_display" style="display:flex;flex-direction:column;">UniqueID</label>
<p id="id_display"> Welcome, right click an element and click XPathGenerator to start </p>
</div>
<div id="QA_display_container" style="padding: 10px; border: 2px solid black;">
<label for="QA_display" style="display:flex;flex-direction:column;">QA ID</label>
<p id="QA_display"> Welcome, right click an element and click XPathGenerator to start </p>
</div>
</div>
<!-- Page Tab Content -->
<div id="PageTab" class="tabcontent">
<p id="page_display">Nothing here yet!</p>
</div>
<!-- Test Tab Content -->
<div id="TestTab" class="tabcontent">
<p id="page_display">Nothing here yet!</p>
</div>
</body>
</html>
JS
function openTab(evt, tabName) {
// Declare all variables
var i, tabcontent, tablinks;
// Get all elements with class="tabcontent" and hide them
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
// Get all elements with class="tablinks" and remove the class "active"
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
// Show the current tab, and add an "active" class to the button that opened the tab
document.getElementById(tabName).style.display = "block";
evt.currentTarget.className += " active";
}
/*
Copies text to clipboard
*/
function copy(id) {
var text = document.getElementById(id).textContent;
navigator.clipboard.writeText(text);
}
//Sets no name error to be hidden
function hideNoNameError(){
document.getElementById("no_name_error").style.display = "none";
}
chrome.runtime.onMessage.addListener((message, sender, responce) => {//Recieves message from script.js (method CreateXpath)
if (message.request === "sendtodevtools"){
buildUI(message.path, message.id);
}
})
function buildUI(xpath, id) {//Updates the text in the displays to their 1 of 1 mappings
let xpath_display = document.getElementById("xpath_display");
xpath_display.textContent = xpath;
let id_display = document.getElementById("id_display");
id_display.textContent = id;
}
I got a CSP error so I changed it again to this...
<body>
<div class="tab">
<button id="xpath_tab_button" class="tablinks">Xpath Display</button>
<button id="page_tab_button" class="tablinks">Page Generation</button>
<button id="test_tab_button"class="tablinks">Test Generation</button>
</div>
<!-- Xpath Tab Content -->
<div id="XpathTab" class="tabcontent">
<div style="padding: 10px;">
<label for="element_name">Element Name:</label>
<input id="element_name" onclick="hideNoNameError()"></input>
<p id="no_name_error" style="display: none;">Error, must have name to add</p>
</div>
<div id="xpath_display_container" style="padding: 10px; border: 2px solid black;">
<label for="xpath_display" style="display:flex;flex-direction:column;">UniqueXpath</label>
<p id="xpath_display"> Welcome, right click an element and click XPathGenerator to start </p>
</div>
<div id="id_display_container" style="padding: 10px; border: 2px solid black;">
<label for="id_display" style="display:flex;flex-direction:column;">UniqueID</label>
<p id="id_display"> Welcome, right click an element and click XPathGenerator to start </p>
</div>
<div id="QA_display_container" style="padding: 10px; border: 2px solid black;">
<label for="QA_display" style="display:flex;flex-direction:column;">QA ID</label>
<p id="QA_display"> Welcome, right click an element and click XPathGenerator to start </p>
</div>
</div>
<!-- Page Tab Content -->
<div id="PageTab" class="tabcontent">
<p id="page_display">Nothing here yet!</p>
</div>
<!-- Test Tab Content -->
<div id="TestTab" class="tabcontent">
<p id="page_display">Nothing here yet!</p>
</div>
</body>
</html>
JS
document.getElementById("xpath_tab_button").addEventListener("click",openTab(event, 'XpathTab'));
document.getElementById("xpath_tab_button").addEventListener("click",openTab(event, 'PageTab'));
document.getElementById("xpath_tab_button").addEventListener("click",openTab(event, 'TestTab'));
function openTab(evt, tabName) {
// Declare all variables
var i, tabcontent, tablinks;
// Get all elements with class="tabcontent" and hide them
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
// Get all elements with class="tablinks" and remove the class "active"
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
// Show the current tab, and add an "active" class to the button that opened the tab
document.getElementById(tabName).style.display = "block";
evt.currentTarget.className += " active";
}
but now I am getting Uncaught TypeError: Cannot read properties of null (reading 'addEventListener') on this line:
document.getElementById("xpath_tab_button").addEventListener("click",openTab(event, 'XpathTab'));
why is this coming back as null? document.getElementById("xpath_tab_button")