I'm trying to write a javascript function that adds some DOM nodes to the document in the place it was called, like this:
...
<div>
<script type="text/javascript">
pushStuffToDOMHere(args);
</script>
</div>
...
i try to do it 'cleanly', without using node id property of the div, or innerHTML string manipulation. for that I need to know where in the document the script tag is located.
is there a way to do it?
Talking about cleanly, I don't think your approach is particularly clean. It is a much better idea to give the div a unique id and execute your javascript when the DocumentReady-event fires.
Do you have an overriding reason for doing it this way? If not the suggestion to use a unique id makes the most sense. And you can always use a library like jQuery to make this even easier for yourself.
However, the following quick test shows that if you use document.write() in the function then it writes the value into the place where the function was called from.
<html>
<head>
<script type="text/javascript">
function dosomething(arg){
document.write(arg);
}
</script>
</head>
<body>
<div>The first Div</div>
<div>The
<script type="text/javascript">
dosomething("Second");
</script>
Div
</div>
<div>The
<script type="text/javascript">
dosomething("Third");
</script>
Div
</div>
</body>
</html>
But, again the question, are you sure this is what you want to do?
Although I agree with n3rd and voted him up, I understand what you are saying that you have a specific challenge where you cannot add an id to the html divisions, unless by script.
So this would be my suggestion for inlining a script aware of its place in the DOM hierarchy, in that case:
Add an id to your script tag. (Yes, script tags can have ids, too.)
ex. <script id="specialagent" type="text/javascript">
Add one line to your inline script function that gets the script element by id.
ex. this.script = document.getElementById('specialagent');
...And another that gets the script element's parentNode.
ex. var targetEl = this.script.parentNode;
Consider restructuring your function to a self-executioning function, if you can.
Ideally it executes immediately, without the necessity for an 'onload' call.
see summary example, next.
SUMMARY EXAMPLE:
<script id="specialagent" type="text/javascript">
var callMe = function(arg1,arg2,arg3) {
this.script = document.getElementById('specialagent');
var targetEl = this.script.parentNode.nodeName=="DIV" && this.script.parentNode;
//...your node manipulation here...
}('arg1','arg2','arg3');
</script>
The following TEST code, when run, proves that the function has identified its place in the DOM, and, importantly, its parentNode. The test has division nodes with an id, only for the purpose of the test. They are not necessary for the function to identify them, other than for testing.
TEST CODE:
<html>
<head>
<title>Test In place node creation with JS</title>
</head>
<body>
<div id="one">
<h2>Child of one</h2>
<div id="two">
<h2>Child of two</h2>
<script id="specialagent" type="text/javascript">
var callMe = function(arg1,arg2,arg3) {
this.script = document.getElementById('specialagent');
var targetEl = this.script.parentNode;
/*BEGIN TEST*/
alert('this.script.id: ' + this.script.id);
alert('targetEl.nodeName: ' + targetEl.nodeName + '\ntargetEl.id: '+targetEl.id);
alert('targetEl.childNodes.length: ' + targetEl.childNodes.length);
var i = 0;
while (i < targetEl.childNodes.length) {
alert('targetEl.childNodes.'+i+'.nodeName = ' + targetEl.childNodes[i].nodeName);
++i;
}
/*END TEST - delete when done*/
//...rest of your code here...to manipulate nodes
}('arg1','arg2','etc');
</script>
</div>
</div>
</body>
</html>
Not really sure what your trying to achieve but this would pass the dom element to the function when clicked. You could then use jquery in the function to do what you wanted like so
...
<script type="text/javascript">
function pushStuffToDOMHere(element)
{
$(element).append("<p>Hello</p>"); // or whatever
}
</script>
<div onclick="pushStuffToDOMHere(this);">
</div>
...
my solution is a compbination of the (good) answers posted here:
as the function is called, it will document.write a div with a unique id.
then on document.onload that div's parent node can be easily located and appended new children.
I chose this approach because some unique restrictions: I'm not allowed to touch the HTML code other than adding script elements. really, ask my boss...
another approach that later came to mind:
function whereMI(node){
return (node.nodeName=='SCRIPT')? node : whereMI(node.lastChild);
}
var scriptNode = whereMI(document);
although, this should fail when things like fireBug append themselves as the last element in the HTML node before document is done loading.
Related
I don't know how to declare a variable here in javascript. I have an example situation that if the paragraph is equals to a, the alert will popup.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p id="sample">a</p>
</body>
</html>
<script type="text/javascript">
var sample = getElementById('sample');
if (sample == "a") {
alert("Correct")
};
</script>
You're declaring your variable just fine, however if you want the text within the element, you also need to use the innerHTML property. And when you use the getElementById method, you need to use it on the document object like document.getElementById:
var sample = document.getElementById('sample');
if (sample.innerHTML == "a") {
alert("Correct")
};
<p id="sample">a</p>
sample is a variable and you are correct but it is storing a reference to a DOM Element with id sample. To get the inner html of that you need
var sample = getElementById('sample').innerHTML;
Also, use === over == for no casting etc. Refer here
I will recommend you to have a quick look at JS from w3schools and then move to MDN. Nobody will report you here if you show your efforts, so relax :).
Your declaration is fine, but the assignment part is missing document as the object which has the .getElementById method. Then, once you have the reference to the element, you then need to access its content with .textContent (you can't compare the entire element to a value that the element might contain). As a side note on this, when the string you wish to set/get doesn't contain any HTML, you should use .textContent so that the browser doesn't parse the string for HTML unnecessarily. Often, people will suggest that the content of an element should be gotten/set using .innerHTML and, while that will work, it's wasteful if the string doesn't contain any HTML.
Also, the <script> must be located within the head or the body, not outside of them. I would suggest placing it just prior to the closing body tag so that by the time the processing reaches the script, all of the HTML elements have been parsed into memory and are available.
Lastly (and this is really just a side point), an HTML page also needs the title element to have something in it, otherwise it won't be valid. While browsers don't actually do HTML validation, it's important to strive for valid HTML so that you can be sure that your pages will work consistently across all devices. You can validate your HTML at: http://validator.w3.org.
<!DOCTYPE html>
<html>
<head>
<title>Something Here</title>
</head>
<body>
<p id="sample">a</p>
<script type="text/javascript">
var sample = document.getElementById('sample');
if (sample.textContent == "a") {
alert("Correct")
};
</script>
</body>
</html>
I'm a noob in JQuery, trying my hands on the basic functionality of it
I have a html, like below.
<html>
<head>
<script type="text/javascript" charset="utf-8" src="js/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="js/start.js"></script>
<script>
$(mainFunction());
$('#label1').prop('innerHTML', "test");
</script>
<title></title>
</head>
<body>
<label id="label1"></label>
</body>
</html>
From start.js, i'm trying to manipulate the elements in this html file like below.
function start(name){
this.iam = name;
this.getName = function(user){
return this.iam;
}
}
function mainFunction(){
var label = $('#label1');
var oStart = new start("test");
label.prop("innerHTML" ,oStart.getName("test"));
}
When I try to lookup whats in the 'label' in the above code, i get [] printed on the console. What am I doing wrong here?
$(mainFunction()); is your issue. Instead provide function reference to document.ready.
Like this:
$(mainFunction);
While doing $(mainFunction()); you are invoking the function mainFunction while setting up the handler, which means it gets executed too early before the DOM tree has been constructed.
Or in order to avoid confusion you could do:
$(function(){
mainFunction();
});
Also remember that this issue will not happen if you move your script just before the end of the body tag. You do not have to listen to document ready handler. Plus as a shorthand you could just do label.html(oStart.getName("test"));
You need to wait for the DOM to be ready before using jQuery.
This is done this way:
$(document).ready(function() {
// All your code touching the DOM in here
});
Also note that this line: $(mainFunction()); uses the return value of mainFunction, it does not trigger it when DOM is ready.
<!DOCTYPE HTML>
<html>
<head>
<script src="js/jquery-1.10.2.min.js"></script>
<script>
$(document).ready(function() {
var x="<script>alert('hello world');</script>";
$("#div_one").html(x);
});
</script>
</head>
<body>
<div id="div_one">
</div>
</body>
</html>
Why does this not work? I'd expect the JS code between the script tags to be interpreted and see an alert message ...
What I want to do:
I have written a set of functions that add and delete items from an array depending on the user input (JavaScript). Then, I have a function that draws() a ul-list of the items held in the array. Behind each item, I want to provide a remove link, which calls a JavaScript function that removes the item from the array and then calls drawList() to redraw the list.
If there weren't that security policy, I'd simply do it as in the code shown above.
That is some weird browser bug I believe. For some reason you can't have </script> inside the script block.
Change to
var x="<scr"+"ipt>alert('hello world');</scr"+"ipt>";
Example on jsFiddle
That is not a bug. The problem is here:
<script>
$(document).ready(function() {
var x="<script>alert('hello world');</script>";
$("#div_one").html(x);
});
</script>
The browser thinks the first <script> tag is associated with the </script> inside your code.
As you can see, the code is shown in the DOM instead of executing.
To further prove it, see this example:
http://jsfiddle.net/DerekL/Ah8Qz/
var x = $("<script>").html("alert('hello world');");
$("#div_one").append(x);
If you avoid the </script> closing tag, then there will be no problem because the HTML parser will ignore any open <script> tag inside <script>.
So to sum up,
Browsers does not have security in place to stop scripts being injected into your page.
This is no where near a browser bug.
I would like page.html to ajax-request the content of side.html and extract the content of two of its divs. But I cannot find the correct way to parse the response, despite everything I tried.
Here is side.html:
<!DOCTYPE html>
<html>
<head>
<title>Useless</title>
</head>
<body>
<div id="a">ContentA</div>
<div id="b">ContentB</div>
</body>
</html>
and here is page.html
<!DOCTYPE html>
<html>
<head>
<title>Useless</title>
<script type='text/javascript' src='jquery-1.9.0.min.js'></script>
</head>
<body>
Hello
<script type="text/javascript">
jQuery.ajax({
url: "side.html",
success: function(result) {
html = jQuery(result);
alert(html.find("div#a").attr("id"));
alert(html.find("div#a").html());
alert(html.find("div#a"));
},
});
</script>
</body>
</html>
When I access this page, I get no error, and the three alert()s yield undefined, undefined and [object Object]. What am I doing wrong? Example is live here.
You need to change this line:
html = jQuery(result);
To this:
html = jQuery('<div>').html(result);
And actually, even better you should declare this as a local variable:
var html = jQuery('<div>').html(result);
Explanation
When you do jQuery(result), jQuery pulls the children of the <body> element and returns a wrapper around those elements, as opposed to returning a jQuery wrapper for the <html> element, which I tend to agree would be pretty dumb.
In your case, the <body> of sidebar.html contains several elements and some text nodes. Therefore the jQuery object that is returned is a wrapper for those several elements and text nodes.
When you use .find(), it searches the descendants of the elements wrapped by the jQuery object that you call it on. In your case, the <div id="a"> is not one of these because it is actually one of the selected elements of the wrapper, and cannot be a descendant of itself.
By wrapping it in a <div> of your own, then you push those elements "down" a level. When you call .find() in my fixed code above, it looks for descendants of that <div> and therefore finds your <div id="a">.
Comment
If your <div id="a"> was not at the top level, i.e. an immediate child of the <body>, then your code would have worked. To me this is inconsistent and therefore incorrect behaviour. To solve this, jQuery should generate the container <div> for you, when it is working its <body> content extraction magic.
Try this :
$.get(url,function(content) {
var content = $(content).find('div.contentWrapper').html();
...
}
I want to add a javascript google ad but I can't insert the javascript into the div using jquery. I try to simulate my problem with this test, which is using some advice I found on stackoverflow , but it does not work.
I want <script type='text/javascript'>document.write('hello world');</script> to be inserted in the div, and "hello world" be displayed between the tag_1 and tag_2.
Here is the code :
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var str="<script type='text/javascript'>document.write('hello world');";
str+="<";
str+="/script>";
$('#insert_here').append(str);
});
</script>
</head>
<body>
tag_1<br/>
<div id="insert_here">
</div>
tag_2<br/>
</body>
</html>
Tanks for your answers,
Lucas
See my answer to Are dynamically inserted <script> tags meant to work? for why you can't use innerHTML, which jQuery's functions map to when passed a HTML string, to insert a script element. document.write will also fail when used after the document has been fully parsed.
To work around this, you will have to use DOM functions to insert an element into the div. Google ads are iframes, so it's usually a case of finding the iframe code and appending that instead.
To correctly insert a script element, you need to use DOM functions, for instance:
var txt = 'alert("Hello");';
var scr = document.createElement("script");
scr.type= "text/javascript";
// We have to use .text for IE, .textContent for standards compliance.
if ("textContent" in scr)
scr.textContent = txt;
else
scr.text = txt;
// Finally, insert the script element into the div
document.getElementById("insert_here").appendChild(scr);
I figured out a great solution:
Insert your Google Adsense code anywhere on your page - e.g. if your CMS only allows you to put this on the right hand side then stick it there.
Wrap a div around it with display:none style
Add some jquery code to move the div to the location you desire.
Since the javascript has already run there is no problem then with moving the block of script to wherever you'd like it to be.
e.g. if you wish to put 2 blocks of google adverts interspersed throughout your blog (say after paragraph 1 and after paragraph 4) then this is perfect.
Here's some example code:
<div id="advert1" style="display:none">
<div class="advertbox advertfont">
<div style="float:right;">
<script type="text/javascript"><!--
google_ad_client = "pub-xxxxxxxxxxxxxxxxx";
/* Video box */
google_ad_slot = "xxxxxxxxxxxxxxxxx"
google_ad_width = 300;
google_ad_height = 250;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
</div>
</div>
<script>
$(document).ready(function() {
$('#advert1').appendTo("#content p:eq(1)");
$('#advert1').css("display", "block");
});
</script>
p.s. #content happens to be where the content starts on my CMS (Squarespace) so you can replace that with whatever you have in your CMS. This works a treat and doesn't break Google ToS.
You cannot use document.write after the page has finished loading. Instead, simply insert the contents that you want to be written in.
<script type="text/javascript">
$(function() { // This is equivalent to document.ready
var str="hello world";
$('#insert_here').append(str);
});
</script>