I'm writing a static web site that uses JQuery to make some AJAX calls to a RESTful API and populate the page with data.
The site functions correctly (and quickly), everything is good.
As I extend the site and add additional pages, I'm noticing that I'm duplicating certain regions on every page.
For instance, each page shares a common header element.
<header>...Some non-trivial content...</header>
Rather than repeat this definition on each page is there some mechanism, by which, I can define this section once and include it in each document.
Remember that the pages must be served statically but any standard complaint browser functionality can be utilised.
Is there a good way to do this, and what is it or, will I have to abandon DRY principles for this aspect of my client side code?
There's definitely some ways to achieve this. You could either do it using some features of your server-side language that allows to include the content of a page in another page, or if you do not have any server-side technology, you could simply put that code in it's own html document and load it's content using AJAX.
In jQuery it could look like:
$('#header').load('header.html');
However, if the content isin't static for all pages, you could always define a JS module that would be responsible to render this header. You module could make use of a client-side templating engine, like Mustache, Handlebars, etc. However you do not have to use any of these.
Here's a simple example:
DEMO
//in somefile.js, please note that you should namespace your modules
var Header = {
//default config
config: {
el: '#header',
title: 'Some title'
},
init: function (config) {
var cfg = this.config = $.extend({}, this.config, config);
$(cfg.el).html('<h1>' + cfg.title + '</h1>');
}
};
$(function () {
Object.create(Header).init({
title: 'Some other title'
});
Object.create(Header).init({
el: '#header1',
title: 'Yeah'
});
});
As I mentioned in the comment, this is how I do it:
main.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Main page</title>
<sript src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$(function(){
$('#commonsection').load('reusablefile.htm');
// which is eqvivalent to:
//
// $.ajax({
// url: 'reusablefile.htm',
// dataType: 'html',
// success: function(data){
// $('#commonsection').html(data);
// }
// });
});
</script>
</head>
<body>
<div id="commonsection"></div>
</body>
</html>
reusablefile.html:
<script>
(function($){ //separate scope to keep everything "private" for each module
//do additional javascript if required
})(jQuery);
</script>
<p>...Some non-trivial content...</p>
You could use jQuery's ajax as to load the header file. In each file you could load the html like so:
$('#header').load('header.html');
Since you're already using AJAX calls to populate your site with data, you could do the same for the common regions.
Just store the HTML for those regions in a separate file and load it in the page with AJAX. Also, you can work with caching using the Cache-Control headers on that file so you don't reload the entire content from the server with each page load.
If you're using straight HTML, you could do it with a SSI include command or by creating a template page and including it in jQuery. Both of these links might help you
Include another HTML file in a HTML file
and
http://www.htmlgoodies.com/beyond/webmaster/article.php/3473341/SSI-The-Include-Command.htm
It looks like this in modest:
main.xhtml
<?xml version='1.0' encoding='UTF-8'?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<include>reusablePiece</include>
</head>
<body>
<reusablePiece/>
</body>
</html>
reusablePiece.xml
<header>...Some non-trivial content...</header>
Very simple would be the jQuery .clone() function.
If you have more complex content I recommend looking at Handlebars.js which is a full fledged JS templating engine.
Related
I am trying to load an external HTML page (common navigation) into my current HTML page. I tried the load function but it is deprecated. Can you tell me another way to include it? I am not using any server.
Here's my code
<!DOCTYPE html>
<html>
<head>
<script src="ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('#content').load(" nav.html ");
});
</script>
</head>
<body>
<div id="content "></div>
</body>
</html>
Try this
<script>
function loadPage(href) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", href, false);
xmlhttp.send();
return xmlhttp.responseText;
};
document.getElementById('content').innerHTML =
loadPage('your_html_file.html');
</script>
<div id="content">
</div>
Take both file pages in same directory then you can use simple button on link to use external file. for example
<button> External file </button>
Button is your choice it's just example for understanding you can simple use html link.
You should use the SSI-function.
There is several ways but this can solve your problem.
<!--#include virtual="PathToYourFile/YourFile.html" -->
This can be inserted into a <div> for further styling in CSS.
REMEMBER! Due to some limitations in html-doctypes you cannot inlude a .html-file into an .html-file. You have to use another format as .shtml where you can inlude your .html-files. You can include .html into your .shtmlfile. This was also what .shtml was originally created for.
This is because it is part of the XHTML (Dynamic XML HTML)...
To change a file
Your approach on the HTML is correct and also your JS. I include a lot of html-files containing texts there.
My approach is that when a page is loaded some text will be loaded with the <!--#include virtual="" --> inside a <div>. Below JS is used to change the content in the <div>. As Daniel Beck stated below: "...at least in Apache the server needs to be configured to check particular file extensions...".
You configure your file in your .htaccess-file. But ONLY do this if you know what you are doing.
Some (newer?) servers have a default setup of which you don't need to alter the .htaccess-file if you want to be able to include .html-files. At least you are able to include .html-files into .shtml-files.
I have included a Mimetype converter which tells the browser how it should read the file. For txt/html I have told the script that it should use the character encoding ISO-8859-1. Others as UTF-8 could also be used. This depends on your and your receivers native language.
Take into consideration to use the e.preventDefault();. With this i tells the browser NOT to see this as navigation link and will therefore only load the content in the <div>.
$(function() {
$('#ButtonsID').click(function(e) {
$('.DivClass').load('PathToFile/File.shtml');
e.preventDefault();
});
});
$.ajaxSetup({
'beforeSend': function(xhr) {
xhr.overrideMimeType('text/html; charset=ISO-8859-1');
}
});
I'd like to have a Play template that is a JS file (as opposed to having <script> tags inside an HTML template). The reason for this is so that the script can be cached. However, I need to create a differences in the script depending on where it's included and hoped to do this with Play's template system. I can already do so if I use embedded scripts, but those can't be cached.
I found an existing question that also asks the same thing, but the answer is totally different (different goals).
That's easy, just... create view with .js extension, i.e.: views/myDynamicScript.scala.js:
#(message: String)
alert('#message');
//Rest of your javascript...
So you can render it with Scala action as:
def myDynamicScript = Action {
Ok(views.js.myDynamicScript.render(Hello Scala!")).as("text/javascript utf-8")
}
or with Java action:
public static Result myDynamicScript() {
return ok(views.js.myDynamicScript.render("Hello Java!"));
}
Create the route to you action (probably you'll want to add some params to it):
GET /my-dynamic-script.js controllers.Application.myDynamicScript()
So you can include it in HTML templite, just like:
<script type='text/javascript' src='#routes.Application.myDynamicScript()'></script>
Optionally:
You can also render the script into your HTML doc, ie by placing this in your <head>...</head> section:
<script type='text/javascript'>
#Html(views.js.myDynamicScript.render("Find me in the head section of HTML doc!").toString())
</script>
Edit: #See also samples for other templates types
I have recently discovered the new trend of including all .js script at the end of the page.
From what i have read so far seems pretty ok and doable with an exception.
The way I am working is using a template like:
<html>
<head>
<!-- tags, css's -->
</head>
<body>
<!-- header -->
<div id="wrapper">
<?php
include('pages/'.$page.'.php');
?>
</div>
<!-- footer -->
<!-- include all .js -->
</body>
</html>
Now, if I want to use this example on my page http://www.bootply.com/71401 , I would have to add the folowing code under my jquery inclusion.
$('.thumbnail').click(function(){
$('.modal-body').empty();
var title = $(this).parent('a').attr("title");
$('.modal-title').html(title);
$($(this).parents('div').html()).appendTo('.modal-body');
$('#myModal').modal({show:true});
});
But that would mean I either use that in every page - even if I do not have use for it, either generate it with php in the $page.'php' file and echoing it in the template file, after the js inclusion.
I am sure though, better methods exist and I don't want to start off by using a maybe compromised one.
Thanks!
Please avoid using inline scripts as they are not good maintainable and prevent the browser from caching them. Swap your inline scripts in external files.
Fore example you could put all your JavaScript in one file an check the presence of a specific element before initialize the whole code. E.g.:
$(document).ready(function(){
if($('.thumbnail').length) {
// your thumbnail code
}
});
A better way to execute "page specific" JavaScript is to work with a modular library like requirejs. You can modularize your scripts depending on their functionality (like thumbnails.js, gallery.js etc.) and then load the necessary script(s) depending e.g. on the existence of an element:
if($('.thumbnail').length) {
require(['ThumbnailScript'], function(ThumbnailScript){
ThumbnailScript.init();
});
}
The best way you can go is create a separate file for this code.
Let's name it app.js. Now you can include it under the jQuery inclusion.
<script type="text/javascript" src="app.js"></script>
This will prevent code repeat.
One more thing, pull all the code in $(document).ready(). Here is an example. So your app.js file will look like this:
$(document).ready(function(){
$('.thumbnail').click(function(){
$('.modal-body').empty();
var title = $(this).parent('a').attr("title");
$('.modal-title').html(title);
$($(this).parents('div').html()).appendTo('.modal-body');
$('#myModal').modal({show:true});
});
})
I have java script file that reads in a csv file, and has many functions to to visualize the data differently, using d3. I want each visualization to be displayed in different html pages. Ive made every html page, refer to the javascript file. Each page also has its own script that calls functions from the referred javascript file.
The problem, I am facing is that when ever I go to a new page, the function gets called before the data being read. Only works when refreshing the page. I there a way to just read the data in once, and every page can access it.
If you look at the code below, callingFunction() returns undefined (maybe because data is not stored in var data?) The callingFunction() works fine when the page is refreshed.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>D3</title>
**<script src="my.js"></script>** //my script file
</head>
<body>
<script>
callFunction(); //uses var data defined in my.js
</script>
Here is the "my.js":
var data;
function data(file){d3.csv("file", function (error, data) {
ds = data;
callFunction();
}
load your script after the target DOM :
<canvas></canvas>
...........................
<script type="text/javascript"></script>
Use angularJs Js library: it organize your js code according to MVC design pattern.
If you have more than one method to implement a business logic , Use console.time & console.timeEnd to evaluate code performance .
console.time('anID');
// Here your code
console.timeEnd('anID');
I am developing a simple pyramid application where I am using JQuery to do AJAX requests. I have until now had my javascript code within my chameleon templates. Now I want to extract my javascript into another location (e.g. as static resources).
My problem is that I find my javascript code relies on dynamically generated content like so:
$.post("${request.route_url('my_view')}",{'data': 'some data'}, function(html){
$("#destination").html(html);
});
The dynamic element being:
"${request.route_url('my_view')}"
Which is calling the route_url method of the request object within the template.
Is there a recognised pattern for separating such javascript files into their own templates and providing routes and views for them or do I simply keep my javascript in my page template?
Yes; you generally put context-specific information like expanded routes into the templates and access this information from your (static) JavaScript libraries.
Including the context info can be done in various ways, depending on taste:
You could use a data attribute on a tag in your generated HTML:
<body data-viewurl="http://www.example.com/route/to/view">
...
</body>
which you then, in your static JS code load with the jQuery .data() function:
var viewurl = $('body').data('viewurl');
Use a made-up LINK tag relationship to include links in the document head:
<head>
<link rel="ajax-datasource" id="viewurl"
href="http://www.example.com/route/to/view" />
...
</head>
which can be retrieved using $('link#viewurl').attr('href'), or $('link[rel=ajax-datasource]').attr('href'). This only really works for URL information.
Generate JS variables straight in your template, to be referenced from your static code:
<head>
...
<script type="text/javascript">
window.contextVariables = {
viewurl = "http://www.example.com/route/to/view",
...
};
</script>
</head>
and these variables are referable directly with contextVariables.viewurl.