How to get next element using JavaScript-only? - javascript

Let's say we have this markup:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8" />
<title>project.js</title>
<script src="project.js"></script>
<script>
</script>
</head>
<body>
<h1>some project — javascript & html tests</h1>
<hr />
<p>
testing 123
</p>
</body>
</html>
I know that there are .prependChild(), .appendChild(), .innerHTML, etc, properties and methods, but what I am looking for is how to add (append) contents after the </body> tag closure?
I need this, without using jQuery — is it possible?

If you use 'id'.you can use these property:
document.getElementById('id').nextSibling;
document.getElementById('id').previousSibling;

It won't work in some browser because content after body is not "legal". Anyway, this would be:
document.body.parentNode.appendChild(document.createTextNode('text after body'));
document.body.parentNode.appendChild(document.createComment('comment after body'));
http://jsfiddle.net/yVKk6/ and inspect the Result frame.

Related

Javascript how to prevent adding HTML elements to DOM?

Say I have the following HTML source:
<html>
<head>
<script src="myscript.js"></script>
<meta charset="utf-8">
<script>/*other script*/</script>
<link rel="stylesheet" ...>
</head>
<body>
<div>...</div>
</body>
</html>
What does myscript.js code look like to prevent adding DOM elements as if source code was originally?
<html>
<head>
<script src="myscript.js"></script>
</head>
<body>
</body>
</html>
I already tried overriding javascript DOM manipulation methods such as .append, .prepend, .appendChild, .inserBefore, etc, for all nodes. Still, the browser adds <meta>, <script>, <link>, <div>, and so on. It seems javascript overrides only affects javascript created nodes... which makes sense IMO.
The question is: is there a way to prevent adding DOM items which are part of the download HTML source?
You're looking for Window.stop:
The window.stop() stops further resource loading in the current browsing context, equivalent to the stop button in the browser.
Because of how scripts are executed, this method cannot interrupt its parent document's loading, but it will stop its images, new windows, and other still-loading objects.
Here's an example:
<div>Div #1</div>
<p>Paragraph #1</p>
<div>Div #2</div>
<script>
window.stop();
</script>
<p>Paragraph #2</p><!-- This element is not rendered -->

After getting a page's content from an AJAX request I can select tag element but cannot select body element

I got an html page through an AJAX request
$.ajax({
async: true,
method: 'GET',
url: linkPage,
// cache: true,
success: function (data) {
console.log(data);
}
});
The data format I get like this:
<!DOCTYPE html>
<html>
<head>
...
</head>
<body id="sustainable" class='sustainable'>
<div id="wrap">
<main class="temp>
<section class="sec01">
...
</section>
</main>
</div>
</body>
</html>
Now I want to get the body id and class (which is "sustainable") via this code:
$(data).find('body').attr('class');
But I have no idea why I can't get that, it returns undefiend. But when I get html content or class of <main> by this code:
$(data).find('main').attr('class');
$(data).find('main').html();
It returns exactly what I want. Can anybody explain me why?
I've tried some solutions so far by create a virtual DOM like this, and I can select <body> and <main> from AJAX data as I want: Cannot get body element from ajax response
But I still wonder why I can't select <body> class and html as first case?
It looks like, when given a string like that, jQuery will only save the contents of the body into its collection:
const data = `<!DOCTYPE html>
<html>
<head>
...
</head>
<body id="sustainable" class='sustainable'>
<div id="wrap">
<main class="temp>
<section class="sec01">
...
</section>
</main>
</div>
</body>
</html>`;
console.log($(data)[0]);
console.log($(data)[1]);
console.log($(data)[2]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
(Check your browser console. It's selecting the text nodes around #wrap, and #wrap itself, but not the <head> or <body>)
You could use DOMParser instead, which will try to turn the whole string into a document, without trying to leave things out:
const data = `<!DOCTYPE html>
<html>
<head>
...
</head>
<body id="sustainable" class='sustainable'>
<div id="wrap">
<main class="temp>
<section class="sec01">
...
</section>
</main>
</div>
</body>
</html>`;
const doc = new DOMParser().parseFromString(data, 'text/html');
console.log(doc.body.className);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Another benefit of using DOMParser is that, unlike jQuery, it won't execute possibly-unsafe code in the HTML string:
const data = `<!DOCTYPE html>
<html>
<head>
...
</head>
<body id="sustainable" class='sustainable'>
<img src onerror="alert('evil')">
</body>
</html>`;
$(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
jQuery version, unsafe
const data = `<!DOCTYPE html>
<html>
<head>
...
</head>
<body id="sustainable" class='sustainable'>
<img src onerror="alert('evil')">
</body>
</html>`;
const doc = new DOMParser().parseFromString(data, 'text/html');
console.log(doc.body.className);
DOMParser version, safe
The reason it doesn't work the way you tried is explained in the jQuery documentation:
If the HTML is more complex than a single tag without attributes, as it is in the above example, the actual creation of the elements is handled by the browser's .innerHTML mechanism. In most cases, jQuery creates a new <div> element and sets the innerHTML property of the element to the HTML snippet that was passed in.
Since you can't have a <body> inside a <div>, the browser ignores the <body> tag.
The documentation goes on to say:
When passing in complex HTML, some browsers may not generate a DOM that exactly replicates the HTML source provided. As mentioned, jQuery uses the browser's .innerHTML property to parse the passed HTML and insert it into the current document. During this process, some browsers filter out certain elements such as <html>, <title>, or <head> elements. As a result, the elements inserted may not be representative of the original string passed.
The following jQuery Won't work:
$(data).find('sustainable');
as the divs are top level elements and data isn't an element but a string, to make it work you need to use .filter
$(data).filter('sustainable.wrap');

How to fix issue HTML1402 with jquery url in IE?

I really don't understand why IE (only, ok for any other browser) gives me HTML1402: Character reference is missing an ending semi-colon “;” with the following code:
<!DOCTYPE HTML>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
</head>
<body>
<span id="here"></span>
<div id="url_iframe">https://www.google.com.br/search?q=ie+html+1402+with+jquery&ie=utf-8&oe=utf-8&client=firefox-b&gws_rd=cr</div>
<script>
var url_iframe = jQuery('#url_iframe').text();
jQuery('#here').append('<iframe src="'+encodeURIComponent(url_iframe)+'" scrolling="no" frameborder="0" width="320" height="300"></iframe>');
</script>
</body>
</html>
Some one know how to fix it, so that stop to appear in console?
I tried without encodeURIComponent and same error.
The URL is just a sample, I konw that won't work, it's a test for an issue of a very big and complex code, all I discover was if I change it to iframe instead of using jquery, no warning shows, but I need to do it with jquery, because of the data before my append in the real web application.
Assuming that the error had to be a MS bug, I discovered that I was right and all I needed was to swap the div for input:
<!DOCTYPE HTML>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
</head>
<body>
<span id="here"></span>
<input type="hidden" id="url_iframe" value="https://www.google.com.br/search?q=ie+html+1402+with+jquery&ie=utf-8&oe=utf-8&client=firefox-b&gws_rd=cr"/>
<script>
var url_iframe = jQuery('#url_iframe').val();
jQuery('#here').append('<iframe src="'+url_iframe+'" scrolling="no" frameborder="0" width="320" height="300"></iframe>');
</script>
</body>
</html>
If someone know how to do it with div, I will be glad if share here...

Client-side Javascript can appear where within an HTML document?

Client-side Javascript can appear where within an HTML document?
A. Between the <head> and </head> tags
B. Between the <body>and </body> tags
C. Both of the above
D. None of the above
Here are codes that are placed in the different parts of the HTML. Ever variation will run no matter where the script tag is placed.
1.
<html>
<head>
<title>Foo</title>
<script type="text/javascript">
alert("hello world");
</script>
</head>
<body>
</body>
</html>
2.
<html>
<head>
<title>Foo</title>
</head>
<body>
<script type="text/javascript">
alert("hello world");
</script>
</body>
</html>
3.
<html>
<head>
<title>Foo</title>
</head>
<body>
</body>
<script type="text/javascript">
alert("hello world");
</script>
</html>
If you try out all these 3 variations where the script tags are placed in different parts of the HTML, you'll see that the alert() call will still run; regardless of their position in the HTML document.
So I think the answer to your question is:
C. Both of the above
Since there is no choice that says "Anywhere within the html document"
It is a good idea to place scripts at the bottom of the element.
This can improve page load, because HTML display is not blocked by scripts loading.
You should prefer here:
I chose "C" both of the above because the "Script" can be placed anywhere between the and < / body> as well as the < head> and < / head> It appears the most logical answer to go with in this situation is "C"

JavaScript: Why is it so with windows.parent?

Why is it so that when you use window.parent.showMessage("Video Is OK"); inside a .js file you've included on a page, it won't work, but only if it's on the page itself..?
Can you fix this?
There are two scenarios that I can think of where you'd want to use window.parent. The first is when you have a window open another window using window.open. The other is where the first window uses an iframe to load a page. In the former case, it appears as though you actually want to use window.opener, as ukostin has said. In the latter case, window.parent works fine. Both methods work properly whether the code is inline or loaded from an external JS file. Here are some tests:
POPUP
parentWindow.htm:
<html>
<head>
<script>function showMsg(msg){alert(msg);}</script>
<body>
Open
</body>
</html>
externalWindow.js:
function showMsgExternal(msg){window.opener.showMsg(msg);}
childWindow.htm:
<html>
<head>
<script>function showMsgInline(msg){window.opener.showMsg(msg);}</script>
<script src="externalWindow.js"></script>
</head>
<body>
Inline
External
</body>
</html>
IFRAME
parentFrame.htm:
<html>
<head>
<script>function showMsg(msg){alert(msg);}</script>
</head>
<body>
<iframe src="childFrame.htm" width="300" height="100"></iframe>
</body>
</html>
externalFrame.js:
function showMsgExternal(msg){window.parent.showMsg(msg);}
childFrame.htm:
<html>
<head>
<script>function showMsgInline(msg){window.parent.showMsg(msg);}</script>
<script src="externalFrame.js"></script>
</head>
<body>
Inline
External
</body>
</html>
Try to use window.opener as link to the parent window.

Categories