Getting a document.body error. help! - javascript

I have the following JavaScript code:
function createNotification(title, body, canDismiss, callback)
{
//create the container
var nContainer = document.createElement("div");
nContainer.setAttribute("id", "note"+title);
nContainer.setAttribute("class","nContainer");
nContainer.className = "nContainer";
//create the title
var nTitle = document.createElement("div");
nTitle.setAttribute("class", "nTitle");
nTitle.className = "nTitle";
nTitle.innerHTML = title;
//if canDismiss is true then add controls
if (canDismiss)
{
var nDismiss = document.createElement("div");
nDismiss.setAttribute("class", "nDismiss");
nDismiss.className = "nDismiss";
nDismiss.innerHTML = "[close]";
nDismiss.onclick = function(){destroyNotification(title);callback();};
nTitle.appendChild(nDismiss);
}
//append the title to the container
nContainer.appendChild(nTitle);
//create the body and append to container
var nBody = document.createElement("div");
nBody.setAttribute("class", "nBody");
nBody.className = "nBody";
nBody.innerHTML = body;
nContainer.appendChild(nBody);
document.body.appendChild(nContainer);
//fade background
fadeIt(title);
}
function destroyNotification(title)
{
//get the specified notification
var note = document.getElementById("note"+title);
//remove the notification
document.body.removeChild(note);
//unfade the background
unfadeIt(title)
}
function fadeIt(title)
{
//create a partially opaque div and append it to the document
var Fade = document.createElement("div");
Fade.setAttribute("id", "fade"+title);
Fade.setAttribute("class","fade");
Fade.className = "fade";
document.body.appendChild(Fade);
}
function unfadeIt(title)
{
//get the specified fade element
var Fade = document.getElementById("fade"+title);
//remove the specified fade element
document.body.removeChild(Fade);
}
I am getting a document.body error. Can anyone please help?
This is the html:
<html>
<head>
<title></title>
<script langauge="javascript" type="text/javascript" src="notification.js"> </script>
<link rel="stylesheet" type="text/css" href="notification.css" />
<script language="javascript" type="text/javascript">
createNotification("The Title", "Some sort of message for our body", true, function(){alert("A Callback");});
</script>
</head>
<body>
</body>
</html>
The error I got from firebug is:
document.body is null
[Break on this error] document.body.appendChild(nContainer);

You're executing the function createNotification before the page is even loaded. The body element doesn't even exist when you call it.
Call the function on the bottom of the page or add a load event [link].

There is property "body" for document object.
document.getElementsByTagName("body")[0].removeChild(note);

When are you executing your code? I mean, when are the methods getting called: after the document has loaded or somewhere before? Also I could not understand one line of code in createNotification:
function nBody.innerHTML = body;
Can you call this method inside the body tag instead of the head tag? Or can you use a window.onload event to call this function?

Related

Using Javascript to dynamically create buttons onload

So I'm having troubles understanding what I'm doing wrong here.
The big picture I'm trying to implement is a page with an iframe that is controlled with buttons that change the source of the iframe when pressed. The buttons would be dynamically created from a data structure that I wouldn't know the size of, which means that I needed to implement it as a loop.
So far I just added a pre-populated object and tried to implement the dynamic creation of the buttons to the HTML page, but I'm unable to create the buttons.
The code I'm trying to run is
<HEAD>
<TITLE>Testing stuff</TITLE>
</HEAD>
<BODY onload="script();">
<FORM>
<H2>Dynamically add button to form.</H2>
<span id="fooBar"> </span>
</FORM>
</BODY>
<script>
var URLobj = {
url1 : "https://www.lipsum.com/",
url2 : "https://www.cnet.com/news/",
url3 : "https://stackoverflow.com/"
};
function add(name, URL) {
//Create an input type dynamically.
var element = document.createElement("BUTTON");
//Assign different attributes to the element.
element.setAttribute("type", "button");
element.setAttribute("value", URL);
element.setAttribute("name", name);
alert(name);
var foo = document.getElementById("foobar");
//Append the element in page (in span).
alert('i can reach here');
foo.appendChild(element);
alert('i can not reach here');
}
window.onload = function iterator()
{
for (var key in URLobj) {
if (URLobj.hasOwnProperty(key)) {
add(key, URLobj[key])
}
}
}
</script>
Also, does this seem like any good of an approach for this kind of a problem? (Trying to add buttons dynamically) or will my next step prove to be tricky with my current approach (making the buttons control an iframe in the page)?
The main issue here is this line:
var foo = document.getElementById("foobar");
As JS is case sensitive, it should be:
var foo = document.getElementById("fooBar");
Pay close attention to the console when debugging stuff like this. This is the error you should see with your original code:
Uncaught TypeError: Cannot read property 'appendChild' of null
Also, the element type should be input based on your usage, not button. See below.
var URLobj = {
url1: "https://www.lipsum.com/",
url2: "https://www.cnet.com/news/",
url3: "https://stackoverflow.com/"
};
function add(name, URL) {
//Create an input type dynamically.
var element = document.createElement("input");
//Assign different attributes to the element.
element.setAttribute("type", "button");
element.setAttribute("value", URL);
element.setAttribute("name", name);
var foo = document.getElementById("fooBar");
//Append the element in page (in span).
foo.appendChild(element);
}
window.onload = function iterator() {
for (var key in URLobj) {
if (URLobj.hasOwnProperty(key)) {
add(key, URLobj[key])
}
}
}
<HEAD>
<TITLE>Testing stuff</TITLE>
</HEAD>
<BODY onload="script();">
<FORM>
<H2>Dynamically add button to form.</H2>
<span id="fooBar"> </span>
</FORM>
</BODY>
Please check
var foo = document.getElementById("foobar");
To
var foo = document.getElementById("fooBar");

How to add an id to the path of an svg in a webpage?

Here is my webpage:
<html>
<head>
<title>Bin Labeler</title>
</head>
<body>
<embed class="emb" src="racks.svg" style="position: relative;
width:100%;
height:100%"/>
<script>//<![CDATA[
// wait until all the resources are loaded
window.addEventListener("load", findSVGElements, false);
// fetches the document for the given embedding_element
function getSubDocument(embedding_element)
{
if (embedding_element.contentDocument)
{
return embedding_element.contentDocument;
}
else
{
var subdoc = null;
try {
subdoc = embedding_element.getSVGDocument();
} catch(e) {}
return subdoc;
}
}
function findSVGElements()
{
var elm = document.querySelector('.emb');
var subdoc = getSubDocument(elm);
if (subdoc)
var paths = subdoc.querySelectorAll("path");
paths.forEach(function(path){
path.addEventListener('click',function(e){
var bin_id = prompt("What ID belongs to this rack?","Enter here...");
e.target.id=bin_id;
path.setAttribute('fill','green');
console.log(e.target);
})
});
}
//]]>
</script>
</body>
</html>
As you can see, its loading the svg xml into my findSVGElements function and then adding an event listener where for each one, an alert shows up asking for the id. Then I am setting e.target.id hopefully to add the id element to the svg. Then when I do "View Frame source" which gives the svg and all of its paths, I am hoping that the bin_id that the user types in to the alert box becomes the id attribute for that path element. However, it does not seem to do this when I View Frame source, I am simply viewing the original svg that was loaded to the page.
How can I do this?

How to access an iframe from chrome extension?

How can I get my extension to work on all frames like adblock does?
I tried adding "all_frames" : true to my manifest file but it didn't work.
I tried to use this code to get the text with specific ids:
var theId = "starts with something";
var myArray = [];
$('[id^="theId"]').each(function(i, obj) {
myArray.push($(this).text());
});
$.unique(myArray);
console.log(myArray);
but it says my array is empty. When I inspect element on the page, I see a "top" layer, and a "target content" layer. The code only works when I execute it in the console on the "target content" layer. Can I use this code in a content script, or do I need to use background.js somehow?
Continued from SO44122853
I see you figured out that the content was loaded in an iframe. So I have a working demo here PLUNKER, the snippet is here just in case the plunker goes down.
Details are commented in PLUNKER
Demo
Not functional due to the need to run 2 separate pages
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=no">
<style></style>
</head>
<body>
<!--iframe is same as the one on the site, with the exception
of the src-->
<iframe id="ptifrmtgtframe" name="TargetContent" title="Main Content" frameborder="0" scrolling="auto" width='90%' src="tables.html"></iframe>
<!--The data is displayed as a one string-->
<output id='display'></output>
<script>
// Reference the iframe
var iFID = document.getElementById("ptifrmtgtframe");
// Register the load event on iframe
iFID.onload = function(e) {
// Callback is extractText function
return extractText('#ptifrmtgtframe', '#display', '.PSLONGEDITBOX');
}
/* Pass iframe and display as a single selector
|| Pass targets as a multiple selector
*/
function extractText(iframe, display, targets) {
var iArray = [];
var iFrame = document.querySelector(iframe);
var iView = document.querySelector(display);
var iNode = "";
/* .contentWindow is property that refers to content
|| that is in an iframe. This is the heart of the
|| demo.
*/
var iContent = iFrame.contentDocument || iFrame.contentWindow.document;
var iTarget = iContent.querySelectorAll(targets);
/* .map() will call a function on each element
|| and return a new array as well.
*/
Array.from(iTarget).map(function(node, idx) {
iNode = node.textContent;
iView.textContent += iNode;
iArray.push(iNode);
return iArray;
});
console.log(iArray);
}
</script>
</body>
I think your script may be executing before the DOM loads, try putting your function inside:
document.addEventListener('DOMContentLoaded', function() {
});
EDIT
That event seems to do nothing in content scripts, I think that is because they are already loading after DOM is loaded, and never fires.
However this seems to fire but not sure why:
$(function(){
//something
});
This needs jQuery injected aswell

Javascript, I can't with the sun to reach the above items to a iframe

I have to create the effect of a popup using a DIV with DOM, I used an iframe, inside the frame is a form, I can not get rid of the div with Javascript in the submit button because the DOM sees only after the iframe his creation and not the div that contains it ... how should I do?
<html>
<body >
<h1>Title</h1>
</body>
</html>
//Global variable which contain reference to divPopup's element
var divPopup;
function hideDiv() {
window.alert("Content of DIV POPUP " + divPopup );
divPopup.className = "overlayHidden";
}
function load_page() {
var nodoDiv = document.createElement("DIV");
divPopup = nodoDiv;
nodoDiv.className = "overlay";
nodoDiv.setAttribute("id", "popup1");
//nodoDiv.addEventListener("click", function () { hideDiv(); }, false);
document.body.appendChild( nodoDiv );
var nodoDivPopup = document.createElement("DIV");
nodoDivPopup.setAttribute("id", "popup2");
nodoDivPopup.className = "popup";
var elem = document.getElementById("popup1");
divPopup = elem;
elem.appendChild( nodoDivPopup );
var nodoDivEsami= document.createElement("DIV");
nodoDivEsami.setAttribute("id", "contenitoreEsami");
nodoDivEsami.className = "content";
var elem = document.getElementById("popup2");
elem.appendChild( nodoDivEsami );
var nodoIFrame = document.createElement("IFRAME");
nodoIFrame.className = "content";
nodoIFrame.setAttribute("src", "esami_da_importare_TEST.html");
var nodoDivEsami = document.getElementById("contenitoreEsami");
nodoDivEsami.appendChild( nodoIFrame );
//window.alert( document.body.innerHTML );
}
_______file css
.overlayHidden{
visibility:hidden;
opacity:0;
}
the function hideDiv() is in the form, activated onClick on submit button.
the window.alert( ) in function hideDiv return "undefined"...
I think you're trying too hard, as iFrames are notoriously problematic. You don't need to use an iFrame, and you can predefine your DIVs in the HTML (unless you really need to create the DIV dynamically). For example:
<div id="popup1" class="overlayHidden">
<div id="contenitoreEsami" class-"content">
...
</div>
</div>
No code is needed for page load. When you want to display the pop-up, change its class to something that isn't hidden.

Call two different functions on same onclick event in javascript one after another

I have one div content whose height should be 300px when i click on another div name button.
But how can i reset the height, when again clicked on button div?
Here is the javascript code for reference:
function chk()
{
var x = document.getElementById('content').style.height = '300px';
}
This is the HTML code
<div id="content">
This is dummy text.
</div>
<div id="button" onclick="chk()">
click to read
</div>
When button div is click content height increases, but how can i reduce the height by clicking on same div with same onclick event?
Use CSS:
#content {
height: auto;
}
#content.expand {
height: 300px;
}
In your script:
function chk()
{
var node = document.getElementById('content');
node.classList.toggle('expand');
}
This keeps the state local to the element you're working on, which makes for more flexible code.
See also: classList API
You could use a flag:
var isSet = false:
function chk(){
if(!isSet) {
var x = document.getElementById('content').style.height = '300px';
isSet = true;
}
else {
// some other computation
isSet = false;
}
}
Either a flag
var flag;
function chk() {
var height = flag ? '0px' : '300px';
document.getElementById('content').style.height = height;
flag = !flag;
}
or by checking the current height
function chk() {
var currHeight = document.getElementById('content').style.height;
var setHeight = height == '300px' ? '0px' : '300px';
document.getElementById('content').style.height = setHeight;
}
If you are just learning HTML, CSS, and JavaScript you should start by making your code more clear.
// HTML should look more like
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8' />
<style type='text/css'>
#import 'common.css'; #import 'page.css';
</style>
</head>
<body>
<div id='content'>
This is dummy text.
</div>
<input type='button' value='click to read' id='button' />
<script type='text/javascript' src='common.js'></script>
<script type='text/javascript' src='page.js'></script>
</body>
</html>
Notice, your button should be a button, not a div. XHTML is more expandable for scraping and XSLT, and will work on HTML pages, but not the other way around.
// learn to keep your JavaScript separate pages for caching - common.js
//<![CDATA[
// reduce objects to smaller variables and never use `document.getElementById()`
var doc = document, bod = doc.body;
function E(e){
return doc.getElementById(e);
}
//]]>
// page.js
//<![CDATA[
var button = E('button');
/* The self-executing Anonymous Function below creates scope for `var test` and
returns an unexecuted function you can call later. Note that a function is
basically a variable that if you add `()` to will execute. */
var changeHeight = (function(){
var test = false;
return function(id, before, after){
E(id).style.height = test ? before : after;
test = !test;
}
})();
/* This is a backward compatible way of creating an `onclick` function, unlike
`.addEventListener()` and `attachEvent()`, this is assignment, so it will
write over your last `onclick` assiged to this specific Element */
button.onclick = function(){
changeHeight('content', '20px', '300px');
}
// To combat the comment above you could do something like this:
/*
button.onclick = function(){
changeHeight('content', '20px', '300px');
}
function anotherFunction(){
console.log('wow');
}
var before = button.onclick;
button.onclick = function(){
if(before)before();
anotherFunction();
}
*/
/* An executed function, would execute before the event is handled. The only
thing that is automatically passed to your variable function or Anonymous
Function is the Event Object. In this case it is not necessary, because we
are not accessing the Event Object. */
//]]>

Categories

Resources