I have a quiz app with a series of questions implemented as a slide-deck. The deck is played in a single-page application (SPA). I have the HTML for each slide in a folder and it is loaded into a div container in the index.html file that is the single entry-point.
I use the id of the placeholder div tag in index.html and the innerHTML property to load a slide. The slide is rendered correctly on the page and inspection of the page source shows that the HTML was correctly loaded (i.e. as HTML and not text). However, I am unable to find the HTML elements within the inserted HTML with getElementById() in the application's code. It is as if they don't exist.
Here is the code that loads the HTML to display a slide. It runs when DOMContentLoaded.
fetch('./Slides/Quiz001.html')
.then(data => data.text())
.then(html => document.getElementById("Question").innerHTML = html)
.then([].slice.call(document.getElementsByTagName("div"))
.forEach(div_element => console.log(div_element.id)));
The first line fetches the slide to insert from a local folder. The second line gets the HTML string. The third line inserts the HTML into the page at the DOM insertion point. The fourth line queries all the div elements and converts HTMLCollection to array and the fifth line logs the IDs to console.
The HTML in Quiz001.html is as follows:
<div id="Quiz">
<h3>Patanjali Yoga Sutra</h3>
<div id="Expected" data-answer="asmina"></div>
<p>The five kleshas, the root cause of suffering, are avidya,
<input type="text" id="response" data-binding="response">,
raga, dvesa and abhinivesa.
</p>
</div>
There are two div elements in here, with id's "Quiz" and "Expected". These do not appear in the list logged to console by the javascript. In fact, after the insertion, I am unable to get any element in the inserted HTML by querying with getElementById() or any other method. It is like they are not visible in the code although the HTML is properly inserted and the elements are correctly seen in page source.
I have added a screenshot of the page and console, and highlighted the HTML that is inserted by javascript. Any help is appreciated.
.then([].slice.call(document.getElementsByTagName("div"))
This line is evaluated immediately, not as part of the Promise chain. You forgot the ()=> to make it a callback.
Related
I have an HTML body, and I want to get its full inner HTML code before its loading is completed.
<body someproperties>
<!--- some elements --->
<script>
var html = getFullInnerHTMLsomeWay();
</script>
<!--- some elements --->
</body>
So, the question is, how can I get its full inner HTML code before all its child are loaded?
I have tried many ideas but no success yet.
I also tried to google it but didn't find anything helpful.
Edit: My goal is to replace all instances of a specified text to another text before they displayed to the user.
The first time elements become interactable with (and, for example, viewable from the DOM APIs and by the user) is when the browser inserts them into the DOM.
Given
<body someproperties>
<!--- some elements 1 --->
<script>
console.log(document.body.innerHTML);
</script>
<!--- some elements 2 --->
</body>
you will get the contents of some elements 1, as well as the script tag, but there's no way to get some elements 2 because it hasn't been loaded yet.
You will only be able to get some elements 2 after the <script> tag finishes executing.
The only way I can think of to do something like this would be to completely stop the page from loading, fetch the current page, then parse the response, and then finally load the response into the current page - which would be quite convoluted, and I wouldn't recommend it at all.
It's not exactly what you were asking, but if desirable, you can alter or view the HTML before it gets displayed - use a MutationObserver to watch for appended nodes on the body.
new MutationObserver(() => {
// examine DOM here
// can add and remove nodes as needed, before they get rendered
})
.observe(document.body, { childList: true });
So my website is built using a company's software called Inksoft which leaves me very little to work in the way of customization. So I have to do many workarounds.
Here is my site's homepage.
The header on top of the page only has two links right now. "Products" and "Design Studio". My goal is to add an "About Us" link and "Buyers Guide" to the header as well.
I cannot add new content to the header using Inksoft's backend. So I coded a workaround to replace the content of existing DIV's within the header to say and link to where I want them to go.
The only issue is, the responsive mobile-nav loses functionality when this is implemented. As seen here on this test page.
The test page has the About Us in the top header, added by the use of this code:
<script>
$("#header-nav-designs").html('<document.write="<li id="header-nav-studio"><font color="#000000">About Us</font></li>');
</script>
So, the simplified question is: how do I implement this code without losing the responsive functionality of the nav bar?
The jQuery .html function will replace the HTML inside the target element. If you want to just append the one value, you likely want to .append to the element.
In addition, you aren't setting the HTML to a valid html string. You probably just want to get rid of the <document.write=" at the beginning of the string. The rest of it looks fine with just a cursory glance.
So:
<script>
$("#header-nav-designs").append('<li id="header-nav-studio"><font color="#000000">About Us</font></li>');
</script>
Edit:
After looking at it a little more, it appears as though the $('#header-nav-designs') that you are selecting is already an <li> which means you need to either select the parent <ul> list or you can use the jquery .after function instead.
<script>
$("#header-nav-designs").after('<li id="header-nav-studio"><font color="#000000">About Us</font></li>');
</script>
And as someone else commented above, you are getting an error on the page. It appears as though you are trying to get an element with the id divID and the appending some html to it, but there is no element with the id divID and so you are getting an error saying that you can't read the property innerHTML of null as the call to document.getElementById is returning null (element not found).
Element id header-nav-designs witch your code is referring have CSS style on line 170:
#header-nav-designs {display:none;}
The element will be hidden, and the page will be displayed as if the element is not there. With display:none;
If I understand you correctly your code selector points to wrong element id. It should point $(".header-nav > ul"). Document.write is not needed inside jQuery you need to give only an valid html string as argument.
jQuery html function erase html that is all ready inside element and replace it with html string given as argument. You have to use append if you want to add more html but not remove what is allready in element.
$(".header-nav > ul").append('<li><font color="#000000">About Us</font></li>');
$(".header-nav > ul").append('<li><font color="#000000">Buyers Guide</font></li>');
Having searched the site, I think the issue I'm having may relate to using innerHTML to populate a <div> but I can't quite find a solution that I can map onto my specific issue. Hope someone can help. Basically, I have an HTML page that contains a form with a text field. The page also contains an empty <div> which will be populated with a table-of-contents in a moment. The <div> is defined as:
<div id="toc_menu" class="menu_list">
I've set the onkeyup attribute of the form text field to run a Javascript function (defined in the HTML <head>) which defines a XMLHttpRequest and sends the value entered in the text input field (str) to a PHP page using xmlhttp.open("GET","toc_items.php?filter="+str,true). The PHP page GETS the value of 'filter' and runs a MySQL query. It then produces some results which are echoed back to the empty as a table-of-contents with main headings and subheadings using:
document.getElementById("toc_menu").innerHTML=xmlhttp.responseText;
This works more-or-less as expected. The length of the returned table-of-contents changes as text is entered into the text field. There is, however, a problem. This table-of-contents is supposed to have an accordion effect created using a script which is defined in the HTML <head>. The script was developed by Roshan Bhattarai and works beautifully when the table-of-contents list is hard-coded into the HTML page. The script is as follows:
<script type="text/javascript">
<!--
//---------------------------------+
// Developed by Roshan Bhattarai
// Visit http://roshanbh.com.np for this script and more.
// This notice MUST stay intact for legal use
// --------------------------------->
$(document).ready(function()
{
//slides the element with class "menu_body" when paragraph with class "menu_head" is clicked
$("#toc_menu p.menu_head").click(function()
{
$(this).css({backgroundImage:"url(down.png)"}).next("div.menu_body").slideToggle(300).siblings("div.menu_body").slideUp("slow");
$(this).siblings().css({backgroundImage:"url(left.png)"});
});
});
</script>
The table-of-contents items that are formatted as follows:
<p class="menu_head">HEADING</p>;
<div class="menu_body">;
SubHeading';
</div>;
It appears that the table-of-contents items that are inserted into the <div> don't trigger the Javascript in the HTML page <head> (although the text is formatted correctly using CSS files also defined in <head>). I can manually copy the output from the PHP page and paste it into the <div> and the accordion effect works perfectly.
Any suggestions would be greatly appreciated.
It appears that the code block:
<p class="menu_head">HEADING</p>;
<div class="menu_body">;
SubHeading';
</div>;
is echoed back by PHP from the ajax call. Correct me if I'm wrong on that. If the ajax call builds this html and echos it to the screen, the above script will not work. The ajax call is made via the keyup event on the form as you stated above. However, the script above is run on
$(document).ready. If what I'm understanding is true, the content is placed in the innerhtml of the div when the ajax call is made not when the page loads. Because there are no "p" elements with the class "menu_head" when the page loads on $(document).ready, jquery cannot bind the .click event properly. The script needs to be executed after the ajax call returns and the DOM has been updated with the new elements.
In other words on successful return from the ajax call, run the above script, not on $(document).ready. Once the elements are in the DOM, jquery can find them and bind to them the .click event. The script execution should then complete successfully.
Hope this helps.
I haven't studied your code in detail, but did notice your empty div element has no close tag (unless you've omitted this detail). You should always have a close tag (for div elements) to ensure the DOM doesn't make an invalid assumption as to where this should be inserted, use:
<div id="toc_menu" class="menu_list"></div>
I've been searching for an answer to this and can't seem to find out how to do it...or if it is possible.
I have a JavaScript Program that displays an .HTML page. I have an API from another company that sends us information as well. I would like to be able to change the contents of the .HTML page before the user sees it. Is this possible?
For example, suppose page.html is:
<HTML>
<HEADER>
<TITLE>
The Company Name
</TITLE>
</HEADER>
<BODY>
Some stuff
</BODY>
</<HTML>
page.html is housed on our server and using JavaScript/HTML I would like to change the value of "The Company Name" with the value from the API before the page is rendered to the user. Is this possible?
window.onload would not do the trick if you want to be sure that your users don't see the page before edition, as onload waits for everything to be loaded, including images.
What I recommend is :
to change the title in a block in the head : <script>document.title="test"</script>
to hide initially the page, by enclosing it in a <div id=wholepage style="display:none;">
to change the page content in a standard <script> block included at the end of your body
to render your big div visible at end, using document.getElementById('wholepage').style.display='block';
A simple Javascript function will do the trick:
window.onload = function() { document.getElementByTagNames("title")[0].value = "Yourvalue"; }
You could load the HTML from the page into a string variable. Then you'd use regex on the string and search for the starting expression and ending expression , and do a replace on that content. Javascript has a replace method.
var str="<HTML><HEADER><TITLE>The Company Name</TITLE></HEADER><BODY>Some stuff</BODY></<HTML>";
str=str.replace("<TITLE>","<DUMMY>");
str=str.replace("</TITLE>","</DUMMY><TITLE>your real title</TITLE>");
Essentially you would rename the title tag into a non existent tag like dummy, then append the real title tag to the end of it.
Then you can display the HTML content in the string/variable in a page at runtime.
$('#cart').load('shop.php/ #cart');
So i want to reload the cart section of my page but it is loading it inside the original div id like so:
<div id="cart">
<div id="cart">
// everything loaded fine here
</div>
</div>
I just want it to display the one div, what am i doing wrong?
You do everything correct. However, loading of page fragments in jQuery works as follows:
$('#result').load('ajax/test.html #container');
When this method executes, it retrieves the content of ajax/test.html,
but then jQuery parses the returned document to find the element with
an ID of container. This element, along with its contents, is inserted
into the element with an ID of result, and the rest of the retrieved
document is discarded.
So it will include the container as well. To include the inner contents only use the following:
$("#cart").load("shop.php/ #cart > *");