I have a weird issue that i am hoping someone can help resolve.
Problem
When i load html dynamically via .load() function, if any aspect of html in the loaded fragment tries to access the javascript query functions in original HTML page, it doesn't work. Example code below:
Main HTML page (main.html)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<!--javascript load functions etc... standard header stuff -->
</head>
<body>
<div id="dynamic_section_fragment"></div>
Load Fragment
<script type="text/javascript">
// <![CDATA[
function loadFragment() {
$("#dynamic_section_fragment").load("/api/fragment/");
};
$(".checkvalue").click(function () {
$.getJSON("/api/checkvalue", {term: $(this).attr('value')}, function () {
console.info("submitted for checking");
})
});
// ]]>
</script>
</body>
</html>
FRAGMENT File (fragment.html)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
</head>
<body>
<div th:fragment="check_value">
<br/>
Check the value in the attribute field
<br/>
<a href="javascript:" th:attr="value='123'" class="checkvalue">Check This<a/>
</div>
</body>
</html>
SPRING MVC Controller Method
#RequestMapping("/api/checkvalue")
public String getFragment(Model model) {
return "fragment :: check_value";
}
So a run down of actions:
-Main.html page loads
-User clicks on Load Fragment hyperlink
-Javascript dynamically loads the relevant fragment into the div
-User clicks on Check This hyperlink, nothing happens
Is there something i am missing or something i need to be aware?
It is as if Thymeleaf has preregistered all the possible scenarios of events and doesn't allow any others.
Only way i have been able to get it to work is by injecting the "checkvalue" javascript within the fragment, which as you can agree is a bad way of doing things.
Help is appreciated.
You are applying the click event listener to all existing objects with the checkvalue class.
$(".checkvalue").click(function ()
What you rather wish to do (to make the click event apply to all the existing and any new added, dynamically) is to set a event on a parent in the dom tree (parent both to the existing and to all that will be added).
In your case, the body tag would probably be the safe bet.
The following should suffice:
$('body').on('click', '.checkvalue', function() { ...
Simplified, the code will apply a listener on the body element instead of the .checkvalue objects, and whenever a object with the .checkvalue class is clicked (wether dynamically or statically loaded), the event will fire.
edit
I would also suggest that you, in your javascript, don't use jquery before you know for certain that it is loaded.
The jquery lib have a way of fixing this for you, by using the $( document ).ready() function:
$( document ).ready(function() {
// All jquery dependant code here.
});
Related
Is there any functional difference between using body onload:
<!DOCTYPE html>
<html>
<head>
<title>testing body onload</title>
</head>
<body onload="fu('this is from body onload')">
<h2 id="I1">nothing yet</h2>
<script>
function fu (msg) {
document.getElementById("I1").innerHTML = msg ;
}
</script>
</body>
</html>
on the one hand and executing a script at the end of the body:
<!DOCTYPE html>
<html>
<head>
<title>testing body onload</title>
</head>
<body>
<h2 id="I1">nothing yet</h2>
<script>
function fu (msg){
document.getElementById("I1").innerHTML = msg ;
}
fu('this is from bottom script') ;
</script>
</body>
</html>
The second seems better to me, certainly when there are more actions to do when a page is loaded. But maybe there is a pitfall I don't know?
Yes, there is. Putting your code at the bottom is like putting it in a domready event, not onload.
Domready means that the html code was read (so the dom is ready, or in other words, you can now find dom elements with js selectors), while onload means that all the assets (img, css, etc..) are loaded as well (so, a much longer event).
Edit:
please also refer to MDN docs:
(this is basically like jquery's domready, and it's a document object's event):
https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
this is the onload event, and it's a window object's event:
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onload
onload documentation from Mozilla:
The load event fires at the end of the document loading process. At
this point, all of the objects in the document are in the DOM, and all
the images, scripts, links and sub-frames have finished loading.
Placing scripts at the base of the page will run as soon as the browser has rendered the HTML.
For perception purposes I would combine the two and place your scripts at the bottom of the page in an onload callback, if needed.
I'm developing a single-page web app. What I did is that I have a main page index.html where I have all the skeleton of the app but I have in the body a div that i use to load the contents of the page that I want to show. In the loaded page I have a div whose contents need to loaded as well. The issue is that the contents of the second div doesn't appear and I can't figure out why.
I think you would need an example to better understand.
I have two html files: index.html and browse.html.
First here is browse.html:
<div id="browse_contents">
</div>
Finally here is index.html:
<html>
<head>
//load jquery
<script>
$(document).ready(function(){
$("#browse_page").load("browse.html")
$("#browse_contents").html("<p>The contents.</p>")
});
</script>
</head>
<body>
<div id="browse_page"></div>
</body>
</html
So the problem is that "The contents." doesn't appear and I can't figure out why!
Currently, #browse_contents doesn't exist in the DOM when you are attempting to change its HTML.
.load() is asynchronous, which is why it and other jQuery AJAX methods come with a callback parameter; a function to call when the request is complete:
$(document).ready(function(){
$("#browse_page").load("browse.html", function(){
$("#browse_contents").html("<p>The contents.</p>");
});
});
This thing is driving me mad... I have a simple js script wich checks for all the links tag () in a page and check if two of those links at least correspond to a given href attribute.
If I put the script in the main page as an inline script it works great. If I put it inside an external .js script on the same page, it doesn't find any element. Just like if it's only scanning its internal ones but not the parent document ones.
the script is this
var as,i,islink,l1,l2;
l1 = false
l2 = false
as=document.getElementsByTagName('a');
for(i=0;i<as.length;i++)
{
islink=as[i].href;
alert(islink);
if(islink == 'http://www.linktocheck.com/')
{
if(!as[i].getAttribute('rel')) {l1 = true;}
}
if(islink == 'http://www.linktocheck.com/somedir/somepage.asp')
{
if(!as[i].getAttribute('rel')) {l2 = true;}
}
}
if(!l1 || !l2) {alert('links not found in the page');}
I put alert(islink); for debug purposes to see if some link element has been found in the page or not.
The HTML of the calling page is this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1"><title>page a</title>
<meta name="robots" content="noarchive" />
<meta content="text/html; charset=iso-8859-1" http-equiv="content-type" /></head>
<body>
<script src="externaljstochecklinks.js?PARAMETER=somevalue" id="uniqueid" type="text/javascript"></script><div style="margin-top: 6px;margin-bottom: 4px;text-align: center;">[...] <img src="http://www.linktocheck.com/skins/some/images/some.gif" alt="" style="border: none;vertical-align: middle;" /></div>
Why if I put the link check script inline it finds the elements if I put it as external it doesn't?
You have to wait for the DOM to finish loading before you can query it to find DOM elements.
Your script appears to be at the beginning of the <body> section which means it will execute BEFORE the DOM has been parsed and loaded. Thus, there is nothing yet loaded to find.
The simplest fix would be to move your <script> tag to the end of the body right before the </body> tag. You could also use an event listener and execute your code only when the event fires indicating that the DOM is ready.
Assuming the url to the external.js file is correct, the problem might be with the synchronous loading of the js files.
As soon as the js file is downloaded, it starts running. If this happens before the DOM finished loading, it can't find any <a> tag because they don't exist yet.
To test the hypothesis, include your external js file at the end of the <BODY> tag and see if it works.
To fix this issue permanently (and you don't want to include a JS file at the end of the body, you can defer the loading by either:
using an external library (such as jquery) and place the code inside $(document).ready()
placing your code inside window.onload event
trigger your own "ready" event
I am trying to use jQuery's .load function to dynamically load content into my webpage. This seem so simple, but I cannot make it work. To try and figure it out, I made a test page with just basic structure, but the external content still won't load:
jquery.html
<html>
<head>
<title>JQuery Test</title>
<script src="jquery1.5.min.js"></script>
</head>
<body>
<script>
$('#foo').load('test.html');
</script>
<div id="foo"></div>
</body>
</html>
test.html
<p>Text text</p>
I'm sure I have made a tiny error, but I can't find it anywhere!
You need to encapsulate your script in the $(document).ready() otherwise #foo won't exist when the script is executed:
<script>
$(document).ready(function(){
$('#foo').load('test.html');
});
</script>
You need to wait for the document to be ready before you can access the DOM. Just add a $(document).ready() around your original code:
<html>
<head>
<title>JQuery Test</title>
<script src="jquery1.5.min.js"></script>
</head>
<body>
<script>
$(document).ready( function() {
$('#foo').load('test.html');
});
</script>
<div id="foo"></div>
</body>
</html>
or if you want a shorter code:
$(function() {
$('#foo').load('test.html');
});
Informally, what's happening is that, as your browser reads the code you wrote, it's drawing its contents as it goes along. When it reaches your <script> tag, it executes it. But when $("#foo") gets executed, the browser's still processing the <script> and hasn't reached the part of the code where you told it there's a div called foo, so the browser doesn't know it exists, and jquery will just find nothing.
Of course, the idea that the browser will just sequentially read your code and render it as it goes is naive at best, so while it might seem that just moving the <script> tag to the bottom of the code would work, you're not actually guaranteed it will work. Instead, the browser will notify you when it's done drawing the page by firing a load (and possibly a DOMContentLoaded) event. So all code that depends on the whole html being drawn should be executed in an event handler bound to those events.
jQuery makes waiting for the page to be loaded easy, just use something like this:
$.ready(function() {
doStuff();
});
I'm not sure what I'm doing wrong here:
index.html
<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "XHTML1-s.dtd" >
<html xmlns="http://www.w3.org/TR/1999/REC-html-in-xml" xml:lang="en" lang="en" >
<head>
<script type="text/javascript" src="scripts/eventInit.js"></script>
</head>
<body>
<p id="javascriptWarning">This page will not work with JavaScript disabled.</p>
</body>
</html>
eventInit.js
window.onload = function () {
alert("check"); // works
var jsWarning = document.getElementById("javascriptWarning");
jsWarning.onclick = function () {
alert("hi"); // works
};
jsWarning.onload = function () {
alert("loaded"); // fails
};
}
And yet, nothing happens. What am I doing wrong? I've tried other events, like onmouseover and onload.
I'm doing this in Visual Studio, and intellisense isn't giving me options for setting any event handlers. Is that because I'm doing this wrong?
I have confirmed that JS is working on my setup; just putting alert("hi") in a script and including it does work.
It might be important to note that I'm doing this in JScript, since I'm using Visual Studio 2010, so perhaps event handling is different?
Updated to remove '-' from the ID name, but it still doesn't work.
Updated added the window.onload block. Now onclick works, but onload doesn't.
You are trying to set a load event on a paragraph. Only objects which load external data (window, frame, iframe, img, script, etc) have a load event.
Some JS libraries implement an available event (such as YUI) — but you know the paragraph is available, since you're setting an event on it, and you couldn't do that if it was unavailable.
maybe you forgot to have the code block inside a
window.onload = function() {
// btn click code here
}
You have to wait for the document to be parsed before you can go looking for elements by "id" value. Put your event handling setup into an "onload" function on the window object.
The browser won't fire an "onload" event on your <p> tag. You won't need that anyway if you do your work in the "onload" handler for the window as a whole.
[soapbox] Use a framework.
The script is executed before the desired element exists. Additionally, I don't think, p has an onload-Event. Windows, frames and images, yes, but paragraphs?
You should use <body onload="init();"> or window.onload=function(){ … } or a library function, if you use a library. Example:
index.html
<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "XHTML1-s.dtd" >
<html xmlns="http://www.w3.org/TR/1999/REC-html-in-xml" xml:lang="en" lang="en" >
<head>
<script type="text/javascript" src="scripts/eventInit.js"></script>
</head>
<body>
<p id="javascriptWarning">This page will not work with JavaScript disabled.</p>
</body>
</html>
scripts/eventInit.js
window.onload=function(){
alert('JS is working!');}
Edit: Okay, I am very sure, p makes no use of an onload event handler. And it's no wonder, you don't need it. If you want to execute JS code just after the paragraph is finished, do this:
<p>
<!-- stuff -->
</p>
<script type="text/javascript">
/* stuff */
</script>
Instead of this:
jsWarning.onload = function () {
alert("loaded"); // fails
};
try this
if(jsWarning) alert("loaded");
I think someone above mentioned checking for the existence of the element. At this stage the element should be present but it does no harms to check for it.
I think you have to make sure your JavaScript is binding.
Is your javascript before or after your paragraph element, for some reason my brain is aiming towards that.
I would look into using something like jQuery, it will help.
using jQuery your code would be (with the relevant jQuery files included of course):
$(document).ready(function()
{
$("#javascript-warning").click(function(){
alert("HELLO");
});
});
I don't think hyphens are valid in class names when used in conjunction with JavaScript. Try an underscore instead.
onload is a window event.