Access an element by id inside Jupyter notebook _repr_javascript_ method - javascript

I cannot retrieve a newly added html object using its id while inside the Jupyter output cell. How can I do it?
EDIT: I have been able to replicate the same behavior in a notebook hosted on Azure:
https://notebooks.azure.com/rickteachey/projects/sandbox/html/js_repr_id_access.ipynb
NOTE: to run this notebook, click Clone at the top right and run it in your own Azure project/notebook.
The javacript first adds a new html button using the Jupyter API (ie, element.html(); in context, element refers to the Jupyter output cell <div>).
Then the code attempts to access the button using document.getElementById():
class C:
def _repr_javascript_(self):
return f'''
element.html(`<button id="clearBtn">Clear</button>`)
var x = document.getElementById("clearBtn")
alert(x)
'''
C()
EXPECTED BEHAVIOR: The alert should show a stringified version of the clearBtn html button object.
ACTUAL BEHAVIOR: The alert shows a null object, which means the script fails to grab the clearBtn - even though I can see it in the DOM when I look at the source.
It's possible I'm using the API incorrectly. If so, how am I supposed to do this?
Another weird issue: when I look at the same notebook on nbviewer, the alert pops up the clearBtn html object as expected. It does NOT behave this way on my local machine(s), or on Azure. Should I report this as a bug?
https://nbviewer.jupyter.org/urls/dl.dropbox.com/s/dwfmnozfn42w0ck/access_by_id_SO_question.ipynb

Updated answer, original below:
I've tested this now and think I worked out why the below fixes it. Specifically, when the output cell is generated and inserted in the page, it happens in the following order:
Page receives data from the server.
parses the HTML, including the <script> element.
executes the script, seemingly putting the element in its local scope by some means I haven't yet seen. (This is different from how it happens in the nbviewer page, where the output is already rendered, and the script gets it by using something like var element = $('#ad74eb90-4105-4cc9-83e2-37fb7e953a9f');, which can be seen in the source.)
only then inserts the HTML content in the document.
That means that at the time the script runs, the element is inside a detached DOM node. This can also be checked with the following:
alert(element[0].parentNode.parentNode) -> null
alert(element[0].parentNode.outerHTML) ->
<div class="output_area">
<div class="run_this_cell"></div>
<div class="prompt output_prompt">
<bdi>Out[28]:</bdi>
</div>
<div class="output_subarea output_javascript rendered_html">
<button id="clearBtn">Clear</button>
</div>
</div>
In other words, all manipulation or traversal of the rendered output needs to go through the element variable (such as $("#clearBtn", element) or element.find("#clearBtn") or even element[0].querySelector("#clearBtn")). It can't go through document, because the element isn't yet part of the document when the script runs.
Original answer:
This is just a vague idea: Is it possible the global document in this context is not actually the same document as the one element is in? There might be some iframe stuff going on in the editor, which might explain why it works after being rendered to a single page by nbviewer but not before. (Elements inside iframes are not part of the parent document, even though the browser's DOM viewer nests them as if they were.)
I would suggest using the element you already have to find the button you just inserted in it, instead of trying to find it from the document. (I'm not sure what kind of object element is, but there should be a way to get at the DOM node it's referencing and then use .querySelector("#clearBtn"), right?)
Edit: If the element.html() line is jQuery code, then element is a jQuery object and element.find("#clearBtn")[0] would find the contained button.
(This could also be done with element[0].querySelector("#clearBtn"). Note that the return value of .find() is itself a jQuery object, and that dereferencing [0] on a jQuery object returns the (first) DOM element inside it.)

I see two ways of doing it, by returning HTML or Javascript:
class C:
def _repr_javascript_(self):
alert = "alert('x');"
return f'''
element.html(`<button onclick="{alert}" id="clearBtn">Clear</button>`)
'''
C()
or
class C:
def _repr_html_(self):
return f'''
<button onclick="x()" id="clearBtn">Clear</button>
<script>
{{
var bt = document.getElementById("clearBtn");
bt.onclick = function(){{ alert('hi'); }};;
}}
</script>
'''
C()

Related

DOM manipulation with mathjax

I'm trying to make a button that when pressed at least once, a math symbol/equation made from MathJax appears in a designated spot on my webpage. So far, this is what I have
//in JS
//when button is pressed, then x^2 appears
document.getElementById("button").addEventListener("click", function() {
MathJax.HTML.addElement(document.body, "div", {
id: "sqrt"
}, ["$$x^2$$"]);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.3/MathJax.js"></script>
<!--Press button for x^2 to appear-->
<button id="button">Press</button>
<!--x^2 appears here-->
<p id="sqrt"></p>
but every time I press the button, I don't get x^2, I literally get a string. I know the MathJax.HTML.addElement works when it's outside the event listener, but I'm trying to do this with a button. Any ideas would be helpful.
Thank you
Edit: My question is different because it's asking why, when I submit a button, it's showing my the literal string $$x^2$$ instead of the symbol. I know the document on the MathJax page mentions something about it, but I'm a complete novice and don't understand it. I was hoping someone could help me.
Link to a repl.it showing the problem:
https://mathjax-experiement--dolphinsupreme.repl.co
Edit 2: The x^2 symbol isn't showing up on the repl.it link, I'm not sure why because it's showing up on repl.it built-in page.
Once you have loaded mathJax, you need either a configuration script, or specify options through url:
eg ?config=TeX-AMS-MML_HTMLorMML&dummy=.js
see Loading and Configuring MathJax
MathJax works as a preprocessor, and renders mathematical expressions in the DOM where it's needed.
Everything else that contains mathematical expressions which comes from variables in your script, json or whatever must be interpreted (typesetted) to be properly rendered, once it's appended to the DOM.
MathJax.Hub.Typeset()
Outside the event listener, if MathJax.HTML.addElement(); is immediatly invoked when the DOM is loading, it will first add the element to the DOM, then is processed with the whole document (or the nodes you have specified in your configuration), that's why it works.
Later when you click a button to display a mathematical expression from a variable, you have to invoke Typeset() again:
MathJax.Hub.Typeset(".sqrt");
Indeed, addElement(), won't render your element:
addElement(parent, type[, attributes[, content]])
Creates a DOM element and appends it to the parent node provided. It is equivalent to
parent.appendChild(MathJax.HTML.Element(type,attributes,content))
However, mathjax works asynchronously, as rendering may take a while (otherwise, browser may freeze until it's done), so what will happen if you click while mathjax engine is still occupied to render something elsewhere in your page? To avoid your call to be forgotten, it is safer to enqueue your desired typeset in the mathjax queue:
MathJax.Hub.Queue(["Typeset",MathJax.Hub,".sqrt"]);
If the queue is empty, this will throw immediatly, if not, it will insured you that your action will be thrown at the end of the process.
Everything is exposed here.
Side Note :
In your snippet, you do not configure mathjax properly.
You also add an element with always the same id, which is not valid.
If you just want to replace the content of your div, don't use addElement.
Otherwise you should work with class and create unique ids. See the snippet for details.
// this works as I explain above (don't forget to escape backslash in your string)
//console.log("\\"); as a reminder!
MathJax.HTML.addElement(document.body, "div", {class: "sqrt",id:"sqrt_"+length},["\\begin{equation}x+1\\over\\sqrt{1-x^2}\\end{equation}"]);
document.getElementById("button1").addEventListener("click", function() {
var length = document.getElementsByClassName(".sqrt").length;
var expression = document.getElementById("expression").value || `$$x^2$$`;
MathJax.HTML.addElement(document.body, "div", {class: "sqrt",id:"sqrt_"+length},[expression]);
MathJax.Hub.Queue(["Typeset",MathJax.Hub,"#sqrt_"+length]);
});
document.getElementById("button2").addEventListener("click", function() {
var expression = document.getElementById("expression").value || `$$x^2$$`;
document.getElementsByClassName("sqrt")[0].innerHTML = expression;
MathJax.Hub.Queue(["Typeset",MathJax.Hub,".sqrt"]);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.3/MathJax.js?config=TeX-AMS-MML_HTMLorMML&dummy=.js"></script>
<textarea id="expression"></textarea>
<!--Press button for x^2 to appear-->
<button id="button1">Add</button>
<button id="button2">Replace</button>
<!--x^2 appears here-->
<p class="sqrt">\begin{equation}
x+1\over\sqrt{1-x^2}
\end{equation}</p>

Why doesn't it format the javascript code? [duplicate]

In tutorials I've learnt to use document.write. Now I understand that by many this is frowned upon. I've tried print(), but then it literally sends it to the printer.
So what are alternatives I should use, and why shouldn't I use document.write? Both w3schools and MDN use document.write.
The reason that your HTML is replaced is because of an evil JavaScript function: document.write().
It is most definitely "bad form." It only works with webpages if you use it on the page load; and if you use it during runtime, it will replace your entire document with the input. And if you're applying it as strict XHTML structure it's not even valid code.
the problem:
document.write writes to the document stream. Calling document.write on a closed (or loaded) document automatically calls document.open which will clear the document.
-- quote from the MDN
document.write() has two henchmen, document.open(), and document.close(). When the HTML document is loading, the document is "open". When the document has finished loading, the document has "closed". Using document.write() at this point will erase your entire (closed) HTML document and replace it with a new (open) document. This means your webpage has erased itself and started writing a new page - from scratch.
I believe document.write() causes the browser to have a performance decrease as well (correct me if I am wrong).
an example:
This example writes output to the HTML document after the page has loaded. Watch document.write()'s evil powers clear the entire document when you press the "exterminate" button:
I am an ordinary HTML page. I am innocent, and purely for informational purposes. Please do not <input type="button" onclick="document.write('This HTML page has been succesfully exterminated.')" value="exterminate"/>
me!
the alternatives:
.innerHTML This is a wonderful alternative, but this attribute has to be attached to the element where you want to put the text.
Example: document.getElementById('output1').innerHTML = 'Some text!';
.createTextNode() is the alternative recommended by the W3C.
Example: var para = document.createElement('p');
para.appendChild(document.createTextNode('Hello, '));
NOTE: This is known to have some performance decreases (slower than .innerHTML). I recommend using .innerHTML instead.
the example with the .innerHTML alternative:
I am an ordinary HTML page.
I am innocent, and purely for informational purposes.
Please do not
<input type="button" onclick="document.getElementById('output1').innerHTML = 'There was an error exterminating this page. Please replace <code>.innerHTML</code> with <code>document.write()</code> to complete extermination.';" value="exterminate"/>
me!
<p id="output1"></p>
Here is code that should replace document.write in-place:
document.write=function(s){
var scripts = document.getElementsByTagName('script');
var lastScript = scripts[scripts.length-1];
lastScript.insertAdjacentHTML("beforebegin", s);
}
You can combine insertAdjacentHTML method and document.currentScript property.
The insertAdjacentHTML() method of the Element interface parses the specified text as HTML or XML and inserts the resulting nodes into the DOM tree at a specified position:
'beforebegin': Before the element itself.
'afterbegin': Just inside the element, before its first child.
'beforeend': Just inside the element, after its last child.
'afterend': After the element itself.
The document.currentScript property returns the <script> element whose script is currently being processed. Best position will be beforebegin — new HTML will be inserted before <script> itself. To match document.write's native behavior, one would position the text afterend, but then the nodes from consecutive calls to the function aren't placed in the same order as you called them (like document.write does), but in reverse. The order in which your HTML appears is probably more important than where they're place relative to the <script> tag, hence the use of beforebegin.
document.currentScript.insertAdjacentHTML(
'beforebegin',
'This is a document.write alternative'
)
As a recommended alternative to document.write you could use DOM manipulation to directly query and add node elements to the DOM.
Just dropping a note here to say that, although using document.write is highly frowned upon due to performance concerns (synchronous DOM injection and evaluation), there is also no actual 1:1 alternative if you are using document.write to inject script tags on demand.
There are a lot of great ways to avoid having to do this (e.g. script loaders like RequireJS that manage your dependency chains) but they are more invasive and so are best used throughout the site/application.
I fail to see the problem with document.write. If you are using it before the onload event fires, as you presumably are, to build elements from structured data for instance, it is the appropriate tool to use. There is no performance advantage to using insertAdjacentHTML or explicitly adding nodes to the DOM after it has been built. I just tested it three different ways with an old script I once used to schedule incoming modem calls for a 24/7 service on a bank of 4 modems.
By the time it is finished this script creates over 3000 DOM nodes, mostly table cells. On a 7 year old PC running Firefox on Vista, this little exercise takes less than 2 seconds using document.write from a local 12kb source file and three 1px GIFs which are re-used about 2000 times. The page just pops into existence fully formed, ready to handle events.
Using insertAdjacentHTML is not a direct substitute as the browser closes tags which the script requires remain open, and takes twice as long to ultimately create a mangled page. Writing all the pieces to a string and then passing it to insertAdjacentHTML takes even longer, but at least you get the page as designed. Other options (like manually re-building the DOM one node at a time) are so ridiculous that I'm not even going there.
Sometimes document.write is the thing to use. The fact that it is one of the oldest methods in JavaScript is not a point against it, but a point in its favor - it is highly optimized code which does exactly what it was intended to do and has been doing since its inception.
It's nice to know that there are alternative post-load methods available, but it must be understood that these are intended for a different purpose entirely; namely modifying the DOM after it has been created and memory allocated to it. It is inherently more resource-intensive to use these methods if your script is intended to write the HTML from which the browser creates the DOM in the first place.
Just write it and let the browser and interpreter do the work. That's what they are there for.
PS: I just tested using an onload param in the body tag and even at this point the document is still open and document.write() functions as intended. Also, there is no perceivable performance difference between the various methods in the latest version of Firefox. Of course there is a ton of caching probably going on somewhere in the hardware/software stack, but that's the point really - let the machine do the work. It may make a difference on a cheap smartphone though. Cheers!
The question depends on what you are actually trying to do.
Usually, instead of doing document.write you can use someElement.innerHTML or better, document.createElement with an someElement.appendChild.
You can also consider using a library like jQuery and using the modification functions in there: http://api.jquery.com/category/manipulation/
This is probably the most correct, direct replacement: insertAdjacentHTML.
Try to use getElementById() or getElementsByName() to access a specific element and then to use innerHTML property:
<html>
<body>
<div id="myDiv1"></div>
<div id="myDiv2"></div>
</body>
<script type="text/javascript">
var myDiv1 = document.getElementById("myDiv1");
var myDiv2 = document.getElementById("myDiv2");
myDiv1.innerHTML = "<b>Content of 1st DIV</b>";
myDiv2.innerHTML = "<i>Content of second DIV element</i>";
</script>
</html>
Use
var documentwrite =(value, method="", display="")=>{
switch(display) {
case "block":
var x = document.createElement("p");
break;
case "inline":
var x = document.createElement("span");
break;
default:
var x = document.createElement("p");
}
var t = document.createTextNode(value);
x.appendChild(t);
if(method==""){
document.body.appendChild(x);
}
else{
document.querySelector(method).appendChild(x);
}
}
and call the function based on your requirement as below
documentwrite("My sample text"); //print value inside body
documentwrite("My sample text inside id", "#demoid", "block"); // print value inside id and display block
documentwrite("My sample text inside class", ".democlass","inline"); // print value inside class and and display inline
I'm not sure if this will work exactly, but I thought of
var docwrite = function(doc) {
document.write(doc);
};
This solved the problem with the error messages for me.

What's wrong with document.write? What's a viable alternative? [duplicate]

In tutorials I've learnt to use document.write. Now I understand that by many this is frowned upon. I've tried print(), but then it literally sends it to the printer.
So what are alternatives I should use, and why shouldn't I use document.write? Both w3schools and MDN use document.write.
The reason that your HTML is replaced is because of an evil JavaScript function: document.write().
It is most definitely "bad form." It only works with webpages if you use it on the page load; and if you use it during runtime, it will replace your entire document with the input. And if you're applying it as strict XHTML structure it's not even valid code.
the problem:
document.write writes to the document stream. Calling document.write on a closed (or loaded) document automatically calls document.open which will clear the document.
-- quote from the MDN
document.write() has two henchmen, document.open(), and document.close(). When the HTML document is loading, the document is "open". When the document has finished loading, the document has "closed". Using document.write() at this point will erase your entire (closed) HTML document and replace it with a new (open) document. This means your webpage has erased itself and started writing a new page - from scratch.
I believe document.write() causes the browser to have a performance decrease as well (correct me if I am wrong).
an example:
This example writes output to the HTML document after the page has loaded. Watch document.write()'s evil powers clear the entire document when you press the "exterminate" button:
I am an ordinary HTML page. I am innocent, and purely for informational purposes. Please do not <input type="button" onclick="document.write('This HTML page has been succesfully exterminated.')" value="exterminate"/>
me!
the alternatives:
.innerHTML This is a wonderful alternative, but this attribute has to be attached to the element where you want to put the text.
Example: document.getElementById('output1').innerHTML = 'Some text!';
.createTextNode() is the alternative recommended by the W3C.
Example: var para = document.createElement('p');
para.appendChild(document.createTextNode('Hello, '));
NOTE: This is known to have some performance decreases (slower than .innerHTML). I recommend using .innerHTML instead.
the example with the .innerHTML alternative:
I am an ordinary HTML page.
I am innocent, and purely for informational purposes.
Please do not
<input type="button" onclick="document.getElementById('output1').innerHTML = 'There was an error exterminating this page. Please replace <code>.innerHTML</code> with <code>document.write()</code> to complete extermination.';" value="exterminate"/>
me!
<p id="output1"></p>
Here is code that should replace document.write in-place:
document.write=function(s){
var scripts = document.getElementsByTagName('script');
var lastScript = scripts[scripts.length-1];
lastScript.insertAdjacentHTML("beforebegin", s);
}
You can combine insertAdjacentHTML method and document.currentScript property.
The insertAdjacentHTML() method of the Element interface parses the specified text as HTML or XML and inserts the resulting nodes into the DOM tree at a specified position:
'beforebegin': Before the element itself.
'afterbegin': Just inside the element, before its first child.
'beforeend': Just inside the element, after its last child.
'afterend': After the element itself.
The document.currentScript property returns the <script> element whose script is currently being processed. Best position will be beforebegin — new HTML will be inserted before <script> itself. To match document.write's native behavior, one would position the text afterend, but then the nodes from consecutive calls to the function aren't placed in the same order as you called them (like document.write does), but in reverse. The order in which your HTML appears is probably more important than where they're place relative to the <script> tag, hence the use of beforebegin.
document.currentScript.insertAdjacentHTML(
'beforebegin',
'This is a document.write alternative'
)
As a recommended alternative to document.write you could use DOM manipulation to directly query and add node elements to the DOM.
Just dropping a note here to say that, although using document.write is highly frowned upon due to performance concerns (synchronous DOM injection and evaluation), there is also no actual 1:1 alternative if you are using document.write to inject script tags on demand.
There are a lot of great ways to avoid having to do this (e.g. script loaders like RequireJS that manage your dependency chains) but they are more invasive and so are best used throughout the site/application.
I fail to see the problem with document.write. If you are using it before the onload event fires, as you presumably are, to build elements from structured data for instance, it is the appropriate tool to use. There is no performance advantage to using insertAdjacentHTML or explicitly adding nodes to the DOM after it has been built. I just tested it three different ways with an old script I once used to schedule incoming modem calls for a 24/7 service on a bank of 4 modems.
By the time it is finished this script creates over 3000 DOM nodes, mostly table cells. On a 7 year old PC running Firefox on Vista, this little exercise takes less than 2 seconds using document.write from a local 12kb source file and three 1px GIFs which are re-used about 2000 times. The page just pops into existence fully formed, ready to handle events.
Using insertAdjacentHTML is not a direct substitute as the browser closes tags which the script requires remain open, and takes twice as long to ultimately create a mangled page. Writing all the pieces to a string and then passing it to insertAdjacentHTML takes even longer, but at least you get the page as designed. Other options (like manually re-building the DOM one node at a time) are so ridiculous that I'm not even going there.
Sometimes document.write is the thing to use. The fact that it is one of the oldest methods in JavaScript is not a point against it, but a point in its favor - it is highly optimized code which does exactly what it was intended to do and has been doing since its inception.
It's nice to know that there are alternative post-load methods available, but it must be understood that these are intended for a different purpose entirely; namely modifying the DOM after it has been created and memory allocated to it. It is inherently more resource-intensive to use these methods if your script is intended to write the HTML from which the browser creates the DOM in the first place.
Just write it and let the browser and interpreter do the work. That's what they are there for.
PS: I just tested using an onload param in the body tag and even at this point the document is still open and document.write() functions as intended. Also, there is no perceivable performance difference between the various methods in the latest version of Firefox. Of course there is a ton of caching probably going on somewhere in the hardware/software stack, but that's the point really - let the machine do the work. It may make a difference on a cheap smartphone though. Cheers!
The question depends on what you are actually trying to do.
Usually, instead of doing document.write you can use someElement.innerHTML or better, document.createElement with an someElement.appendChild.
You can also consider using a library like jQuery and using the modification functions in there: http://api.jquery.com/category/manipulation/
This is probably the most correct, direct replacement: insertAdjacentHTML.
Try to use getElementById() or getElementsByName() to access a specific element and then to use innerHTML property:
<html>
<body>
<div id="myDiv1"></div>
<div id="myDiv2"></div>
</body>
<script type="text/javascript">
var myDiv1 = document.getElementById("myDiv1");
var myDiv2 = document.getElementById("myDiv2");
myDiv1.innerHTML = "<b>Content of 1st DIV</b>";
myDiv2.innerHTML = "<i>Content of second DIV element</i>";
</script>
</html>
Use
var documentwrite =(value, method="", display="")=>{
switch(display) {
case "block":
var x = document.createElement("p");
break;
case "inline":
var x = document.createElement("span");
break;
default:
var x = document.createElement("p");
}
var t = document.createTextNode(value);
x.appendChild(t);
if(method==""){
document.body.appendChild(x);
}
else{
document.querySelector(method).appendChild(x);
}
}
and call the function based on your requirement as below
documentwrite("My sample text"); //print value inside body
documentwrite("My sample text inside id", "#demoid", "block"); // print value inside id and display block
documentwrite("My sample text inside class", ".democlass","inline"); // print value inside class and and display inline
I'm not sure if this will work exactly, but I thought of
var docwrite = function(doc) {
document.write(doc);
};
This solved the problem with the error messages for me.

Dynamically change page title from h1 tag using Javascript

First off, thanks for taking the time to read this question. What a great community Stack Overflow has :)
I need to change the title tag of a page based on the text contained in the h1 element on that page.
I've been searching around, and I have found the "document.title" Javascript function. I've been playing around with it, trying to pull the text from my h1 element that has the class of "Category-H1".
<script type="text/javascript">
document.title = document.getElementsByClassName("Category-H1");
</script>
However, it is just setting the page title to "[object HTMLCollection]", which as I understand is a null value. Is JS the best was to do this? I know my code is jacked, any tips?
Thanks in advance! - Alex
Edit
I have been informed that line of code returns a collection object and not a string. It was pointed to a code example of:
setTimeout(function () { document.title = "iFinity User Profile - " + document.getElementById("test").outerText; }, 1000);
However, this code produces a page title of "iFinity User Profile - undefined". I have the h1 element on that page set to the id of "test".
You're almost there.
[object HTMLCollection] is not a null value--it is the string representation of a collection of html elements. You want to choose the first one and then get the inner html from it.
document.getElementsByClassName("Category-H1")[0].innerHTML
Also, make sure you do this after the document has loaded. You can either do this by adding the script at the end of your document, or have it run on the onload event of the body.
This should work:
document.title = document.getElementsByClassName("Category-H1")[0].innerHTML;
The getElementsByClassName() function returns a collections of elements ( [object HTMLCollection], so you need to get an element out of it, I'm assuming the first one.
A better solution may be the following:
<script type="text/javascript">
document.title = document.getElementsByTagName("H1")[0].innerHTML
</script>
This would save from setting a h1 class.
This is very close, but I found that - working with Firefox anyway, when you use the getElementsByTagName("H1") it gives you an array as you have recognized. However, it works better using:
<script type="text/javascript">
document.title = document.getElementsByTagName("H1").item(0).innerHTML;
</script>
Note the addition of the .item(0).innerHTML after getting the element rather than the [0].innerHTML.
I don’t know if you have any experience in it or not, but another alternative that seems to be very popular these days is the use of jQuery. As in the earlier discussions, the code below assumes that you are interested in grabbing the first instance of the “H1” tag or the “Category-H1” class. This is an important point because unless you target an “ID” attribute, you will get a collection of items.
This code also assumes that you have already implemented the inclusion of the jQuery library either directly from your website or by referencing a CDN.
<script type="text/javascript">
$(document).ready(function () {
document.title = $("H1")[0].innerText;
});
</script>
The $(document).ready will call it’s enclosed function only after the Document Object Model (DOM) has finished loading, and before the browser’s rendering engine displays the page.
The content inside the function will grab the inner text of the first instance of the “H1” tag and assign that text value to the document’s title tag in the head section.
I hope this adds another layer of help.

Adding generated content to jQuery object which is not bound to the DOM fails

I am trying to dynamically append an HTML-snippet to an existing Element with .append.
Somehow, the HTML String which was created by the script is not appended to the element.
The element which is appended to is not hooked into the DOM at the moment when the snippet is appended.
All of it is encapsulated in a JavaScript function. Here is the code:
append_content = function() {
var elem = $('<li><div>some text</div></li>');
var somecontent = get_content(); // returns a string: '<div>xx</div>'
elem.append('<div>bleh1</div>');
elem.append(somecontent);
elem.append('<div>bleh2</div>');
console.log(elem);
return elem;
}
The log contains all items correctly, like:
<li>
<div>some text</div>
<div>bleh1</div>
<div>xx</div>
<div>bleh2</div>
</li>
But when im hooking the elem to the DOM later on, the content of the function call is gone. I.e. it is not visible in the computed source (neither in FireBug nor Chrome development tools).
It looks like this:
<li>
<div>some text</div>
<div>bleh1</div>
<div>bleh2</div>
</li>
I am almost convinced that I have some scope issues or something like that here, but I don't get it. There is no error message in the console. Any advice?
Update
Indeed, this was a self-made problem. Striipng down the code for an examle to post here made me realize that i called a similar function wihtout the function call mentioned above - silly me. Thanks for all the comments and help.
It looks correct to me - I'd check the output of the get_content() method to ensure it is in fact returning valid html. Check it using alert("somecontent") as well as console - console.log only writes out the first line of XML in firebug - not sure about chrome...

Categories

Resources