Thymeleaf fragment expression - javascript

I am using thymeleaf to split my templates in head/main/footer parts. In order to include stylesheets and javascript on some pages (but not on others) I am using fragment expressions as explained here.
So my head.html looks like:
<!DOCTYPE html>
<html>
<head th:fragment="head(title,links,scripts)">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"/>
<title th:replace="${title}">Title placeholder</title>
<!--/* Per-page placeholder for additional links */-->
<th:block th:replace="${links} ?: ~{}" />
<th:block th:replace="${scripts} ?: ~{}" />
</head>
<body>
</body>
</html>
And this is used for instance in my homepage, index.html as follows:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head th:replace="head :: head(~{::title},~{::link},~{::script})">
<title th:text="#{label.pages.home.title}">Homepage</title>
<link rel="stylesheet" href="/assets/css/jumbotron.css"/>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
</head>
<body>
...
</body>
</html>
This works fine as is. Script and link tags appear in the header of the resulting page. However occasionally I want to have scripts at the end of the body (just before </body>. If I put a <script>....</script> in that position two things happen in the resulting page.
the script appears in the head
the script appears a second time in its original position
How can I prevent thymeleaf from putting the script in the head?

Fragment expression has syntax ~{template :: selector}. You reference for original file and syntax reduced to ~{:: selector}. Selector is XPath or CSS like expression. To prevent inclusion of all scripts you should narrow scope to head tag: ~{:: head/script}.

Related

How to import HTML into HTML without duplicate head & body tags? (no frameworks if possible)

I'm playing around with HTML (, JavaScript & CSS) & decided to try to import one HTML from one file into another, the goal is that I can make several modules and just import them into an empty HTML page, so they together create a fully working & content filled HTML page.
I would prefer to use something similar to how scripts or style-sheets are imported:
(ignore the $ signs)
$<script src="file.js"></script>
OR
$<link rel="stylesheet" type="text/css" href="style.css">
The problem is that the $<html>, <head> & <body> tags are inserted again, is there any good way to fix this?
I have tried some methods: $<object> & <embed> &
$<link rel="import" href="file.html">
I don't want to use $<iframe> because I have heard that it's a security problem (yes, it's not relevant right now, but if I'm going to use this method later for real, then it will be important).
I am aware of other similar questions, like this:
Include another HTML file in a HTML file but most of the answers use external frameworks like JQuery or Angular which I don't want to use, I would prefer to use a pure HTML or/and JavaScript solution if possible.
Example code:
File to import:
<p>"The import is working"</p>
Base file to import into:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- Import code here (or in head if it for some reason is required) -->
</body>
</html>
Desired outcome:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>"The import is working"</p>
</body>
</html>
Actual outcome (with $<object> or $<embed>), (at least as the Firefox inspect-element tool shows it):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<embed src="file.html">
#Document <!-- I don't know what this means/function is, can someone explain? -->
<html> <!-- Notice the double: html, head, meta & body -tags -->
<head>
<meta charset="UTF-8">
</head>
<body>
<p>"The import is working"</p>
</body>
</html>
</embed>
</body>
</html>
You can use PHP, by making your file names with a .php extension and use PHP include:
<?php include 'header.php';?>
Read more about it here.
I've been trying to do the same thing for some time and the only solution I've come up with involves some JavaScript. When you import HTML the #document tag means it lives in the shadow DOM which is different than the one rendered (I think, I don't really understand this stuff). In any case, after importing, I ended up having to render the element and append it to the DOM.
<!-- Original HTML file -->
<html>
<head>
<title>Title</title>
</head>
<body>
<p>
Hello from original HTML.
</p>
<link id="importLink" rel="import" href="/path/to/import.html">
</body>
<script src="/path/to/renderImport.js"></script>
</html>
I had the following code in my renderImport.js file:
// renderImport.js
function renderImport() {
let importLink = document.getElementById("importLink");
let importedElement = importLink.import.querySelector('#import');
document.body.appendChild(document.importNode(importedElement, true));
}
renderImport();
And finally, import.html:
<!-- import.html -->
<p id="import">Hello from the imported file</p>
Here it is in Chrome. Though you might have to disable CORS.
Use Angular CDN in Head tag then import html using this code
<body ng-app="">
<ng-include src="'header.html'"></ng-include>
</body>
OR
<body ng-app="">
<header ng-include="'header.html'"></header>
</body>
Use you can change header to footer or content

HTML Tail Tag to complement Head Tag

So typically, in our HTML files, the general structure looks a bit like this:
<!DOCTYPE HTML>
<html lang="en">
<head>
<!-- Favicon -->
<!-- Meta Stuff -->
<!-- Title -->
<!-- CSS Files -->
<!-- JavaScript Files -->
<!-- Other Header Stuff -->
</head>
<header>
<!-- Navbar & Header Stuff -->
</header>
<body>
<!-- Body Stuff -->
</body>
<footer>
<!-- Copyright & Footer Stuff -->
</footer>
</html>
However, I often find myself using JavaScript Files that need to be loaded after the body, or whatever element it interacts with. As such, the body may end up looking like this:
<body>
<!-- Body Stuff -->
<script src="..."></script>
<script src="..."></script>
<script src="..."></script>
...
<script src="..."></script>
</body>
Sure, I could merge all of that stuff into one large Script File, either manually or using some sort of compiler. I could even wrap all of my scripts into a separate div so that I can mark that as "separate" in my mind.
However, all I'm really doing is injecting a bunch of scripts at the end of my document. This stuff shouldn't really go in a body tag, because it's not actual content, just code.
To rectify this, I often use a tail tag, like so:
<!DOCTYPE HTML>
<html lang="en">
<head></head>
<header></header>
<body>
<!-- Body Stuff -->
</body>
<footer></footer>
<tail>
<script src="..."></script>
<script src="..."></script>
<script src="..."></script>
...
<script src="..."></script>
<script>(function() { console.log('Custom code'); })();</script>
</tail>
</html>
Browsers seem to be fine with this, and I'm happy with this solution. However, the tail tag isn't a part of the HTML specifications, and I've seen little to no usage of a tail tag, except old HTML4 stuff that used a tail tag as a footer tag.
So what I'm wondering is: Is this good practice? Are there any downsides to this approach?
I see where you're going with this. I've considered the same concept. There are valid cases for putting <script> tags at the bottom of a document, and they don't really need to be in the <body> tag -- except that there is no other valid place to put them (save the <head>). In lieu of creating invalid tags for organizational purposes, I have done the following:
<section id="tail">
...
</section>
</body>
With some CSS like
section#tail { display: none; }
to ensure there are no errant display effects.
Is this good practice?
No.
Are there any downsides to this approach?
You would have to perform exhaustive browser testing to see whether this worked, including text browsers and screen readers. Also, people may laugh at you, and Steve Faulkner will create an amusing meme about you... which is a downside if that may offend you.
Put all of your content in the body tag, and just place all of the scripts before the </body> tag, not wrapped in anything. They are not displayed, so there is no need to group them in an element.
<!DOCTYPE HTML>
<html lang="en">
<head></head>
<body>
<header></header>
<!-- Body Stuff -->
<footer></footer>
<script src="..."></script>
<script src="..."></script>
<script src="..."></script>
...
<script src="..."></script>
<script>(function() { console.log('Custom code'); })();</script>
</body>
</html>
Not good practice. As an alternative to including scripts within the <body></body> tags, you could leave them in the <head></head> section and the code you want after the page has loaded could be called using the following Jquery:
$( document ).ready(function() {
});
Or the following javascript:
window.onload = function() {
};
HTML Tail defines the HTML code to insert at the bottom of each HTML document, usually to include a link back to your home page or insert a small graphic. It is inserted as a table data element and is right aligned with the page.
Sorry, but I don't agree with your method.
Basic structure:
<!DOCTYPE html>
<html>
<head>
<!-- Some meta data -->
<!-- Title -->
<title></title>
<!-- Link to css script -->
<link rel="stylesheet" type="text/css" href="example.css"/>
</head>
<body>
<!-- Some Content -->
<!-- Script tag to .js source script -->
<script src="example.js"></script>
</body>
</html>
And simple explanation of a proper basic-page load:
When browser goes through that HTML script,
it first recognizes the type of a script defined,
then it runs onto a LINK tag, which directs it to the .css script. Browser reads it and first displays a style on a page,
then it goes through a BODY tag and displays a content,
and let's say at last, it runs onto a SCRIPT tag, which directs the browser to a .js script, reads it, and as last loads the interactivity to a page.
Which gives a user nicer experience when visiting some page.

How to load AngularJS in a div

I have a main page with this structure.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>..:: Test Application ::..</title>
<link rel="stylesheet" href="../bootstrap/css/bootstrap.css" />
<link rel="stylesheet" href="../css/main.css" />
<script src="../js/jquery.js"></script>
<script src="../bootstrap/js/bootstrap.min.js"></script>
<script>
function loadOption(idopt){
if(idopt==1){
var curl = '../view/otherpage.php'
}
$("#mainContainer").load(curl);
}
</script>
<body onLoad=loadOption(<?php echo idopt;?>)>
<div id="mainContainer"></div>
</body>
</html>
otherpage.php
<!DOCTYPE html>
<html ng-app>
<head>
<meta charset="UTF-8">
<title></title>
<script src="../js/angular.min.js"></script>
</head>
<body>
{{1+1}}
</body>
</html>
But, when i load the main page... the AngularJS doesn't run. What could be wrong?
That's because you're loading otherpage.php after the DOMContentLoaded event has finished.
In other words, you're filling in the space inside the mainContainer div with otherpage.php content after the event DOMContentLoaded. And that is where Angular's Automatic Initialization takes place.
So in order to get it to work, you'll have to manually bootstrap Angular.
Here's Angular's documentation about it:
http://docs.angularjs.org/guide/bootstrap
Other options are available and are much better, such as referencing your Angular related files (angular, your controllers, services, directives and what not) at the main page.
Depending on the browser, pulling the script element in otherpage.php out of the head element and into the body element, should correct this.
We can't see all your code, but it may be better to just load Angular.js in the head of the main page. You could do this using your own a script package manager control flow to avoid this type of failure for other dependencies. That would be good style...
make a common includes page and add angular.js file to it and include it in the header so that it is available through out the site or use it in the main page

Head tag in html page closes programatically after page load

My page is located here
As you can see, it doesn't look like it's working properly. This becomes very apparent if you try to open it in an older browser (this is what initially set me off).
I checked the interpreted source code from chrome and it shows me the following:
<html>
<head>
<style type="text/css"></style>
</head>
<body>
<title>Internet adgang - Hurtig opsætning - Ansatte</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
Etc..
Something seems to be closing my head tag which is causing all SORTS of errors:
W3 validator
I have absolutely no idea what is causing this.
You can see my source code here (I've scrambled the PHP):
The code above does not contain my body code, as I am fairly sure that has nothing to do with the head tag closing all of a sudden.
Here is some source of a page that works just fine:
I am completely baffled by this and I have no idea what to do nor what is causing it.
Any ideas?
Solution
With the help of Buttc4k3 and vogomatix I finally found the solution. As buttc4k3 said, there was an illegal "zero-width no-space" character hidden in the file which didn't show in my sublime text editor. It would only show if you opened the file in Notepad++. I could not understand why this character would appear in google chrome, and not in my source, but after googling it, I found that a file saved in UTF-8 WITH BOM (Byte Order Marking) would save the BOM as a zero-width no-space character! This was where vogomatix saved me and told me that my file was saved with BOM and after recoding it without BOM it works fine.
So - if you have the same problem as me - save your file WITHOUT BOM ENCODING (this can be done in notepad++).
I took the page source of your website and pasted it in Notepad++ and found a zero-width no-break space in line 3 column 5. It renders invisible in most editors/viewers, but it breaks the HTML parser of the browser. I don't know how or why it got there since I can't find it in the PHP code, but maybe you can find it by opening your code in Notepad++. It renders this character as a tiny dot. If you can't find it, delete everything from and including <head> to <title> and re-type it.
I hope this works.
PS: Even though it is not the reason why your page is broken, you should add <html> and </html> to the markup. Most browsers can deal with its absence, but it is there for a reason.
It seems like you are missing the <html> tag.
Current HTML-Code:
<!DOCTYPE html>
<head>
<title>Internet adgang - Hurtig opsætning - Ansatte</title>
Must be something like that:
<!DOCTYPE html>
<html>
<head>
<title>Internet adgang - Hurtig opsætning - Ansatte</title>
[...]
</head>
<body>
[...]
</body>
</html>
Edit the first part of your site to be as follows:
<?php
include 'XXXXX';
include 'XXXXX';
if(!isset($_GET['lang'])) {
$lang = "DA";
} else {
$lang = $_GET['lang'];
}
?>
<!DOCTYPE html>
<html lang="<?php $lang; ?>">
<head>
<title><?php echo trans("Internet adgang - Hurtig opsætning - Ansatte", $lang); ?></title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<link rel="stylesheet" href="resources/styles/style.css" media="all">
<script src="resources/js/jquery.min.js" type="text/javascript"></script>
<script src="resources/js/jquery-ui.min.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="resources/styles/au-flowbox-style.css">
<script type="text/javascript" src="resources/js/au-flowbox.js"></script>
<script type="text/javascript" src="resources/js/au-flowbox.data.js"></script>
</head>
<body>
....

DOM's charset different from the displayed on screen

I'm facing a weird problem. The text inside the html has accents, e.g.:
<p>é</p>
It is displayed correctly in the screen (é), but the content inside the DOM instance does not accepts the accents. It is displaying a "?" character instead of the character with accent.
In my case, I'm injecting javascript code in the Kindle (http://read.amazon.com) using a chrome extension, but don't think it is really relevant as I can see the problem just using the chrome console.
A simplified version of the html structure:
<html>
<head>
...
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
...
</head>
<body>
...
<iframe id="KindleReaderIFrame">
<html>
<head>
...
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
...
</head>
<body>
...
<iframe id="column_0_frame_0">
<html>
<head>
<!-- Do not have the Content-Type meta tag -->
</head>
<body>
<!-- Text with accents that I intend to get through DOM -->
</bady>
</html>
</iframe>
...
</body>
</html>
</iframe>
...
</body>
</html>
The text I want is inside the "column_0_frame_0" iframe.
Going through your code, you have not closed the body tag correctly, see below :
<iframe id="column_0_frame_0">
<html>
<head>
<!-- Do not have the Content-Type meta tag -->
</head>
<body>
<!-- Text with accents that I intend to get through DOM ->
</bady>
</html>
</iframe>
Secondly, if you are loading your contents in iFrame or through AJAX, its not enough to set the character set in meta tag, sometimes it depends on the IDE which you used to create your code.
To check:
Open the same code in Notepad++
Save the contents using charset UTF-8 (default ANSI).
Run code on your local server without opening the file in any other IDE.
Now you will be able to render the accents correctly in DOM as well as screen.

Categories