Non-invasive Javascript HTML injection - javascript

I'm looking for a non-invasive javascript HTML/CSS/JS injection into page.
I'm ideally looking to use document.write, but keep the original contents that were on the page. So doing the following:
javascript:document.write("blablabla"); - this removes all the content on page, I don't want to use innerHTML += to append the data.
Any suggestions?

If document.write is called after the onload event for the document it needs to re-open the document - effectively truncating it. While you can explicitly call document.write() inline (either with javascript directly embedded in the page or with a tag which does not use defer/async) this is considered bad practice as it blocks all the other processing of the page.
You can inject elements by constructing them in Javascript personally I prefer to set the innerHTML of an existing placeholder to an HTML fragment:
<div id='placeholder/></div>
...
document.getElementById('placeholder').innerHTML="<h2>hello world!</h2>";
(using createElement becomes messy and slow when creating/injecting complex HTML)

document.write will always overwrite the whole page as far I know. One option is to append/prepend your code to a div or to the bottom of your body.
$(elementObj).append(contents);
//or
$(elementObj).prepend(contents);
You can createElement() then use one of the methods above to inject your code into the newly created element.

Related

Removing from DOM content with function (which is attached to resize event) definition - results [duplicate]

As the title says, if I remove a script tag from the DOM using:
$('#scriptid').remove();
Does the javascript itself remain in memory or is it cleaned?
Or... am I completely misunderstanding the way in which browsers treat javascript? Which is quite possible.
For those interested in my reason for asking see below:
I am moving some common javascript interactions from static script files into dynamically generated ones in PHP. Which are loaded on demand when a user requires them.
The reason for doing this is in order to move the logic serverside and and run a small script, returned from the server, clientside. Rather than have a large script which contains a huge amount of logic, clientside.
This is a similar approach to what facebook does...
Facebook talks frontend javascript
If we take a simple dialog for instance. Rather than generating the html in javascript, appending it to the dom, then using jqueryUI's dialog widget to load it, I am now doing the following.
Ajax request is made to dialog.php
Server generates html and javascript that is specific to this dialog then encodes them as JSON
JSON is returned to client.
HTML is appended to the <body> then once this is rendered, the javascript is also appended into the DOM.
The javascript is executed automatically upon insertion and the dynamic dialog opens up.
Doing this has reduced the amount of javasript on my page dramatically however I am concerned about clean up of the inserted javascript.
Obviously once the dialog has been closed it is removed from the DOM using jQuery:
$('#dialog').remove();
The javascript is appended with an ID and I also remove this from the DOM via the same method.
However, as stated above, does using jQuery's .remove() actually clean out the javascript from memory or does it simple remove the <script> element from the DOM?
If so, is there any way to clean this up?
No. Once a script is loaded, the objects and functions it defines are kept in memory. Removing a script element does not remove the objects it defines. This is in contrast to CSS files, where removing the element does remove the styles it defines. That's because the new styles can easily be reflowed. Can you imagine how hard it would be to work out what a script tag created and how to remove it?
EDIT: However, if you have a file that defines myFunction, then you add another script that redefines myFunction to something else, the new value will be kept. You can remove the old script tag if you want to keep the DOM clean, but that's all removing it does.
EDIT2: The only real way to "clean up" functions that I can think of is to have a JS file that basically calls delete window.myFunction for every possible object and function your other script files may define. For obvious reasons, this is a really bad idea.
If your scripts have already executed removing the DOM elements are not going to get rid of them. Go to any page with JavaScript, open up your preferred javascript console and type $("script").remove(). Everything keeps running.
And this demonstrates #Kolink answer:
http://jsfiddle.net/X2mk8/2/
HTML:
<div id="output"></div>
<script id="yourDynamicGeneratedScript">
function test(n) {
$output = $("#output")
$output.append("test " + n + "<br/>")
}
test(1);
</script>
Javascript:
$("script").remove();
// or $("#yourDynamicGeneratedScript").remove();
test(2);
test(3);
test(4);
function test(n) {
$output = $("#output")
$output.append("REDEFINED! " + n + "<br/>")
}
test(5);
test(6);
test(7);

How to reload script tag

I'm dynamically changing a script tag's src attribute using JavaScript.
Problem is, that I'd like to "undo" the previous JavaScript before re-executing it.
Any way to do this?
Thanks,
g3
I can describe a method I used to achieve a partial undo in a project. Ugly, but might be useful. First, you may need to refactor your script to work from within an iframe, and/or wrap it in a with statement to give it easy access to some objects in the parent (don't even think of with(opener); you'll want something more precise like with({someObject: opener.someObject}).
When your script runs, it can use the iframe's global scope and DOM freely. Then, instead of reloading the <script> tag, you overwrite the whole iframe, which will reset everything your script did inside the iframe.

Adding a script to a DOM object

I want to add a script that applies to a DOM object of a certain type right after it is loaded/rendered. This type of object always comes together with the javascript script, and I want to put them together within some tag. Is it right to do it as below? If so, I suspect span is not the best tag to be used here because it may interact with the way the element inside will be displayed. What tag should I use?
<span>
<div>the dom object to be modified by the script</div>
<script>theJavascriptFunctionThatModifiesTheDomObject()</script>
</span>
I doubt this is the best way to load your script just after a particular element has been loaded by DOM due to these reasons:-
It makes your page load slower.
User will see your complete page in a discrete way.
Instead you should do this:-
Specify a selector to your element.
Include your single javascript code at the end of body.
Update DOM elements using that script.
EDIT:
Solution1: Append your JS at the end of body so that it has access to all the DOM elements.
Since you are injecting the element in DOM using ajax, you can define a success handler for XHR object which will modify your element in DOM.
Solution2: You can define a separate method in your JS and bind this method on some event. In your HTML markup define a data-event attribute and in your success handler append the element to DOM, extract the data-event using jquery data method and trigger that event.
Atleast it will keep you markup far away from scripting logic.
Some useful Links:
Best practices for speeding up your website - yahoo
Why we should load scripts at end - SO Link
The problem here is the script tag does not know where it is located in the DOM. It would be better to do something like add a class to the element[s] you want to alter. On DOM ready, you look up the element[s] and do your magic.
I would avoid this approach; scripts block the page loading
– so if you did this after several dom elements the page would run slow (or not at all if errors were found)
Try using jquery onready - example here : http://api.jquery.com/ready/
And scripts [usually] need to go on the bottom of the page to allow the page to load first
…there are exceptions to this rule such as the well known modernizer script library that needs to go first so it can evaluate the dom as it loads

When should one use .innerHTML and when document.write in JavaScript

Is there a general rule, when one should use document.write to change the website content and when to use .innerHTML?
So far my rules were:
1) Use document.write when adding new content
2) Use .innerHTML when changing existing content
But I got confused, since someone told me that on the one hand .innerHTML is a strange Microsoft standard, but on the other hand I read that document.write is not allowed in XHTML.
Which structures should I use to manipulate my source code with JavaScript?
innerHTML can be used to change the contents of the DOM by string munging. So if you wanted to add a paragraph with some text at the end of a selected element you could so something like
document.getElementById( 'some-id' ).innerHTML += '<p>here is some text</p>'
Though I'd suggest using as much DOM manipulation specific API as possible (e.g. document.createElement, document.createDocumentFragment, <element>.appendChild, etc.). But that's just my preference.
The only time I've seen applicable use of document.write is in the HTML5 Boilerplate (look at how it checks if jQuery was loaded properly). Other than that, I would stay away from it.
innerHTML and document.write are not really comparable methods to dynamically change/insert content, since their usage is different and for different purposes.
document.write should be tied to specific use cases. When a page has been loaded and the DOM is ready you cannot use that method anymore. That's why is generally most used in conditional statements in which you can use it to syncronously load external javascript file (javascript libraries), including <script> blocks (e.g. when you load jQuery from the CDN in HTML5 Boilerplate).
What you read about this method and XHTML is true when the page is served along with the application/xhtml+xml mime type: From w3.org
document.write (like document.writeln) does not work in XHTML documents (you'll get a "Operation is not supported" (NS_ERROR_DOM_NOT_SUPPORTED_ERR) error on the error console). This is the case if opening a local file with a .xhtml file extension or for any document served with an application/xhtml+xml MIME type
Another difference between these approaches is related on insertion node: when you use .innerHTML method you can choose where to append the content, while using document.write the insertion node is always the part of document in which this method was used.
1) document.write() puts the contents directly to the browser where the user can see it.
this method writes HTML expressions or JavaScript code to a document.
The below example will just print ‘Hello World’ into the document
<html>
<body>
<script>
document.write("Hello World!");
</script>
</body>
</html>
2) document.innerHTML changes the inner content of an element
It changes the existing content of an element
The below code will change the content of p tag
<html>
<body>
<p id="test" onclick="myFun()">Click me to change my HTML content or my inner HTML</p>
<script>
function myFun() {
document.getElementById("test").innerHTML = "I'm replaced by exiesting element";
}
</script>
</body>
</html>
you could use document.write() without any connected HTML, but if you already have HTML that you want to change, then document.innerHTML would be the obvious choice.
I agree with the above comments. Basically:
document.write can be useful while the page is loading, to output new HTML tags or content while the browser is building the document object model. That content is output precisely where the JavaScript statement is embedded.
.innerHTML is useful at any time to insert new HTML tags/content as a string, and can be more easily directed to specific elements in the DOM regardless of when/where the JavaScript is run.
A couple of additional notes...
When document.write is called from a script outside of the body element, its output will be appended to the body element if called while the page is loading; but once the page is loaded, that same document.write will overwrite the entire document object model, effectively erasing your page. It all depends on the timing of document.write with the page load.
If you are using document.write to append new content to the end of the body element, you may be better off using this:
document.body.innerHTML += "A string of new content!";
It's a bit safer.

Any way to stop JQuery eating my <script> tags

I have inline javascript within my HTML. Each individual component that requires animation or action (sliders, expanding text areas, etc.) each have their own inline script, that sets up the animation and such for that individual component.
The way i have it set up, Each script is position dependent: it references its own position in the DOM, and traverses it to find the component it wants to manipulate (e.g. "add onclick to the parent div"). This is normally an incredibly bad idea for several reasons:
having to repeat the same code all over the place, losing DRY
being very verbose, repeating the same chunk of text over and over, taking up bandwidth
cluttering up your HTML with a bunch of inline scripts, making it hard to read
However, the second problem is easily solved with GZIP, and i have solved the first and last problem.
This has the advantage of locality of reference: the component and the scripts they require are kept in one place, not spread out over separate files. Also, I isolate each set of scripts in a (function(){})(), and avoid polluting the global namespace, so each set of scripts for each component is written once and doesn't interact with scripts written elsewhere at all. Perfect modularity
So the question is, how can i stop JQuery eating my script tags when i do Ajax DOM insertions/replacements? If it didn't eat my scripts, because each component is completely self-contained with it's own scripts, i can simply run every script tag in the new component's DOM and that would be that; everything will be set up. No more fiddling with decided which global scripts need to be re-run depending on which component changed.
However, since JQuery seems to insist on stripping my script tags and moving them somewhere, this no longer works. I could do the insertion by modifying replacing the HTML of the entire document, but that causes the whole screen to flash as it reflows (among other problems). Any ideas?
I don't know about jQuery explicitly, but most libraries will remove script elements from content returned from XHR that they intend to insert using innerHTML. That is because inserting innerHTML does not execute the scripts (in the vast majority of browsers). Looking at the jQuery source, the load method strips out script elements.
So they strip out the script elements, then insert the HTML. This ensures the scripts aren't executed or cause issues.
Some libraries have an "execute script" (or similar) flag that, if set, means they will pass the script element content to eval, but there are pitfalls with that too.
One solution is to put all your script snippets into separate files, then use a src attribute on the script elements. If you can't find a jQuery method that doesn't remove the scripts, it's pretty simple to write your own "get" or "load" or whatever function that doesn't, or use one of the thousands that are already written.
If you are only using script elements, you can simply create a script element, set the src attribute and put it in the DOM (this is one method of doing AJAX).
in your html keep spaces for all the replacements using container divs, so that everything you're replacing through AJAX has a special place in the DOM. jQuery wont eat your script tag.
Alternatively, you can also put an id on your script tags and then access then by using the ids.

Categories