Website - Is it possible to set links in a central location? - html

I'm currently in the process of redoing a website and all of my pages are going to have a common navigation bar at the top:
Little snippet of the code I'm talking about:
<div id="logoNavContainer">
<nav>
<ul>
<li>Services</li>
<li>Products</li>
<li>Training</li>
<li>Technology</li>
<li>Clients</li>
<li>Publications</li>
<li>Contact Us</li>
</ul>
</nav>
</div>
Initially when I was coding this I was (and still am if it is possible) thinking it would be really convenient if I could have my mainTemplate.html for each page and then for their individual content, create a separate .html page that would be displayed within the correct area on the mainTemplate.
That way any changes to the navBar, links, background etc. Could be done from one location, which is something that I feel might exist due to the purpose of CSS.
But, as it is I simply have identical HTML code at the start of each page for the navbar but at least it is all styled by one CSS form.
So I (and future programmers) can edit the style for all pages from one spot.
Now that I'm implementing each page I am noticing that I have to go through increasingly more pages to change the navBar links, and it is the same action each time.
I was wondering if it is possible to set a variable or something in each html file (like in Java) which is set in one location so that all the links can be swapped out at once?
I'm just trying to make changes easier, and eliminate redundancy. I'm quite new to Html and CSS so I feel like I could be missing a very obvious solution.
Also if the original idea I had IS possible, I would much prefer this solution as it solves more than one problem, and eliminates scores of redundant code.
Thanks in advance.

In pure HTML that's not possible. There are two possible solutions that I can think of right now:
Preprocessing
You can serve your static HTML page using any processor like PHP. This is the best approach in my opinion. It will only require you to call include('header.html') and the header will be included. This is how it's done everywhere.
JavaScript
You can also load the navbar from a different location using JavaScript. The downside here is that it will requiere two requests per page and you'll have to put up some kind of loading animation until the navbar is loaded.
EDIT: I just realized you can use frames/iframes in pure HTML. Bear in mind I didn't come up with frames in the first place because... well, frames suck :)

You can see this article. Pure HTML does not support includes. The article includes a JavaScript solution you can use (see below for an excerpt).
So for your code, you could do:
var navigationDiv = "<div id='logoNavContainer'>" +
"<nav>" +
"<ul>" +
"<li><a href='contentPage.html' class='glow'>Services</a></li>" +
"<li><a href='contentPage.html' class='glow'>Products</a></li>" +
"<li><a href='contentPage.html' class='glow'>Training</a></li>" +
"<li><a href='contentPage.html' class='glow'>Technology</a></li>" +
"<li><a href='contentPage.html' class='glow'>Clients</a></li>" +
"<li><a href='publications.html' class='glow'>Publications</a></li>" +
"<li><a href='contentPage.html' class='glow'>Contact Us</a></li>" +
"</ul>" +
"</nav>" +
"</div>";
document.write(navigationDiv);

The very dirty solution:
Create mymenu.js with the content:
document.write("<div id='logoNavContainer'><nav><ul><li><a href='contentPage.html' class='glow'>Services</a></li></ul></nav></div>");
In all html you want to give navbar include this:
<script src="mymenu.js"></script>
Hope it helps!
Peter

Okay, I worked at this for a while; researching each of your answers and trying to work it into my code.
The PHP I am completely unfamiliar with, so I didn't get anywhere playing with it and although I worked with javascript I gave up on that as well.
Until I came back and saw Rachel G's updated answer. I used that combined with a discussion on generating html with javascript along with my own piece of javascript I managed to work out a functioning version of exactly what I wanted!
Here is how the HTML that I now include at the beginning of every page:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link href="styleSheet.css" rel="styleSheet" />
<script src="pageFeatures.js" type="text/javascript"></script>
</head>
<body onload="init('tabs')">
<div id="main-container">
<div id="navBar">
<!-- Loaded through Javascript; eliminates repeated code and all navBar Links are now set in one place -->
</div>
.... All page specific code.
And the javascript that creates the navBar:
The Links:
// Links
var servicesPage = 'designAudit.html';
var productsPage = 'pageTemplate.html';
var trainingPage = 'pageTemplate.html';
var technologyPage = 'pageTemplate.html';
var clientsPage = 'pageTemplate.html';
var publicationsPage = 'publications.html';
var contactPage = 'pageTemplate.html';
The Init()
function init(tabs) {
initNavBar();
if (tabs == 'tabs') {
initTabs();
}
}
InitNavBar()
// BEGIN NAVBAR GENERATING CODE
function initNavBar() {
var navBar = document.getElementById("navBar");
var navContainer = document.createElement("div");
navContainer.setAttribute('id','logoNavContainer');
var header = document.createElement("header");
var h1 = document.createElement("h1");
var logo = document.createElement("a");
logo.setAttribute('href','index.html');
h1.appendChild(logo);
var nav = document.createElement("nav");
var ul = document.createElement("ul");
var link1 = createLink(servicesPage, "Services");
var link2 = createLink(productsPage, "Products");
var link3 = createLink(trainingPage, "Training");
var link4 = createLink(technologyPage, "Technology");
var link5 = createLink(clientsPage, "Clients");
var link6 = createLink(publicationsPage, "Publications");
var link7 = createLink(contactPage, "Contact");
ul.appendChild(link1);
ul.appendChild(link2);
ul.appendChild(link3);
ul.appendChild(link4);
ul.appendChild(link5);
ul.appendChild(link6);
ul.appendChild(link7);
nav.appendChild(ul);
header.appendChild(h1);
header.appendChild(nav);
navContainer.appendChild(header);
navBar.appendChild(navContainer);
}
createLink()
// Indented to Represent Html layering.
function createLink(destPage, text) {
var link = document.createElement("li"); // <li>
var linkAnchor = document.createElement("a"); // <a>
linkAnchor.setAttribute('href', destPage); // <a href="">
linkAnchor.setAttribute('class','glow'); // <a href="" class="glow">
var services = document.createTextNode(text); // <a href="" class="glow">Text
linkAnchor.appendChild(services); // </a>
link.appendChild(linkAnchor); // <li>
return link;
}
Anyways, thanks for the assistance. I thought I would post the solution I came up with as it differs quite significantly from what's here.
One question I do have though, if anyone checks over this, is This completely leaves my site to die an aesthetic if the client's browser doesn't have it. Is this something that is likely to happen?
I know I have never personally used a computer without javascript but the world usually isn't that simple.

Related

How to reuse HTML code across multiple pages? [duplicate]

I have several pages on a website that use the same header for each page. I was wondering if there was some way to simply reference a file with the html for the header sort of like in this pseudo code:
<!-- Main Page -->
<body>
<html_import_element src = "myheadertemplate.html">
<body>
Then in a separate file:
<!-- my header template html -->
<div>
<h1>This is my header</h1>
<div id = "navbar">
<div class = "Tab">Home</div>
<div class = "Tab">Contact</div>
</div>
</div>
This way I could write the header html once and just import it in each of my pages where I need it by writing one simple tag. Is this possible? Can I do this with XML?
You could do it in this fashion below.
<head>
<link rel="import" href="myheadertemplate.html">
</head>
where you could have your myheadertemplate.html
<div>
<h1>This is my header</h1>
<div id = "navbar">
<div class = "Tab">Home</div>
<div class = "Tab">Contact</div>
</div>
</div>
You can then use it with JS below
var content = document.querySelector('link[rel="import"]').import;
So, after a long time I actually found a way to do this using AJAX. HTML Imports are a great solution, but the support across browsers is severely lacking as of 04/2017, so I came up with a better solution. Here's my source code:
function HTMLImporter() {}
HTMLImporter.import = function (url) {
var error, http_request, load, script;
script =
document.currentScript || document.scripts[document.scripts.length - 1];
load = function (event) {
var attribute, index, index1, new_script, old_script, scripts, wrapper;
wrapper = document.createElement("div");
wrapper.innerHTML = this.responseText;
scripts = wrapper.getElementsByTagName("SCRIPT");
for (index = scripts.length - 1; index > -1; --index) {
old_script = scripts[index];
new_script = document.createElement("script");
new_script.innerHTML = old_script.innerHTML;
for (index1 = old_script.attributes.length - 1; index1 > -1; --index1) {
attribute = old_script.attributes[index1];
new_script.setAttribute(attribute.name, attribute.value);
}
old_script.parentNode.replaceChild(new_script, old_script);
}
while (wrapper.firstChild) {
script.parentNode.insertBefore(
wrapper.removeChild(wrapper.firstChild),
script
);
}
script.parentNode.removeChild(script);
this.removeEventListener("error", error);
this.removeEventListener("load", load);
};
error = function (event) {
this.removeEventListener("error", error);
this.removeEventListener("load", load);
alert("there was an error!");
};
http_request = new XMLHttpRequest();
http_request.addEventListener("error", error);
http_request.addEventListener("load", load);
http_request.open("GET", url);
http_request.send();
};
Now when I want to import HTML into another document, all I have to do is add a script tag like this:
<script>HTMLImporter.import("my-template.html");</script>
My function will actually replace the script tag used to call the import with the contents of my-template.html and it will execute any scripts found in the template. No special format is required for the template, just write the HTML you want to appear in your code.
As far as I know it's not possible. You can load the header as a webpage in a iframe element though. In the past webpages were built with frame elements to load seperate parts of a webpage, this is not recommended and support in current browsers is due to legacy.
In most cases this is done with server side languages like php with as example include("header.php");.

jQuery Mobile and ajax on load

Well I´ve been breaking my head with this problem for some time, I´ve tried tons of solutions online yet none of them work.
What I need is to feed data from a json to a listview on page load and present it yet it only works on index after that I need to reload every page so I can see the listview.
Here´s my jquery code:
$(document).bind("mobileinit", function () {
$.mobile.ajaxEnabled = false;
});
$(document).bind('pageinit',function() {
DrawPageContent();
});
function DrawPageContent() {
$.ajax({
dataType: "json",
url: "js/categorias.json",
success: function(msg){
console.log(msg.categorias[1].nombre);
var categos = '';
for(var i=0;i<msg.categorias.length;i++){
categos += '<li><a href="refrescos.html?id='+ 0 +'"><img src="'
+ msg.categorias[i].logo + '"><h2>'+msg.categorias[i].nombre
+ '</h2><p>' + msg.categorias[i].desc + '</p></a></li> ';
}
$("#categorias").html(categos);
$("#categorias").listview("refresh");
//$("#page").trigger("pagecreate");
}
});}
I've also tried $(document).ready() and some other things.
Here's the HTML for that part:
<div id="page" data-role="page">
<div data-role="header">
<h1>Categorias</h1>
Opciones
</div>
<div data-role="content">
<ul id="categorias" data-role="listview" data-inset="true">
</ul>
Any ideas how to fix this?
If you are trying to append to the id "categorias" each time that is why it only appends to the first page.
In JQuery mobile the pages that are loaded aren't actually removed from the DOM right away. That means that if you load more than one page that has the and element with id categorias in it, it will end up with multiple DOM elements with categorias identifying them. In this case, it will only append to the first one, which would explain why it is not showing up on your other pages until you refresh and the other pages are removed from the DOM.
A good solution here is to give each page a unique identifier and then select the categorias from that page using
$("#categorias", "#pageidentifier");
This selector will search within the specific page you specify to find your categorias element.

HTML/DOM for a page with random image which will post properly in facebook and google+

I have a website which contains the cute conceit of a random headshot. Every time you load the page (or click the headshot), it gets replaced with a new headshot. It works great until I post a link to the website on Facebook.
What happens then is when Facebook scans the page for images, it doesn't find the random image, I assume because it doesn't run the scripts. I would love for the facebook thumbnail to also have a random image.
Is there any way to solve this without resorting to server side code?
Here's what I do now:
in head-script section
var lastTimeout = 0;
var lastHeadNum = 0;
function headURL(headCount)
{
url = "/public/images/heads/mtoy";
if( headCount < 10 )
url += "0";
url += headCount.toString();
url += ".gif";
return url;
}
function headshotImage()
{
lastHeadNum = Math.floor((Math.random()*87)+1);
document.write('<img id="headshot" src="' + headURL(lastHeadNum) + '" onclick="next_headshot();" width=150 height=150>\n');
lastTimeout = setTimeout("next_headshot();", 12000);
}
function next_headshot()
{
if (lastTimeout != 0)
clearTimeout(lastTimeout);
do {
headNum = Math.floor((Math.random()*87)+1);
} while (headNum == lastHeadNum);
lastHeadNum = headNum;
document.getElementById('headshot').src = headURL(headNum);;
lastTimeout = setTimeout("next_headshot();", 12000);
}
then later in the body-html
<div id="contents">
<script type="text/javascript">headshotImage();</script>
<H1 class="contenthead">Table of Contents</H1>
in a previous incarnation, the body-html looked like:
<div id="contents">
<img id="headshot" src="" onclick="next_headshot();">
<H1 class="contenthead">Table of Contents</H1>
and then i had a body.onload handler to call next_headshot the first time, and that had the same problem with Facebook.
If you really want Facebook to have a random image, then I think you need server-side code. But if you're happy with a fixed image, then look into OpenGraph. You should be able to put this in your <head> section:
<meta property="og:image" content="/public/images/heads/mtoy01.gif"/>
Another approach is to put the <img> tag right into the HTML (instead of generating it procedurally) and hard-code it to one image. It won't give you the initially-random image, though you could probably swap it out immediately on page load.

Make anchor links refer to the current page when using <base>

When I use the HTML <base> tag to define a base URL for all relative links on a page, anchor links also refer directly to the base URL. Is there a way to set the base URL that would still allow anchor links to refer to the currently open page?
For example, if I have a page at http://example.com/foo/:
Current behaviour:
<base href="http://example.com/" />
bar <!-- Links to "http://example.com/bar/" -->
baz <!-- Links to "http://example.com/#baz" -->
Desired behaviour:
<base href="http://example.com/" />
bar <!-- Links to "http://example.com/bar/" -->
baz <!-- Links to "http://example.com/foo/#baz" -->
I found a solution on this site: using-base-href-with-anchors that doesn't require jQuery, and here is a working snippet:
<base href="https://example.com/">
/test
Anchor
Or without inline JavaScript, something like this:
document.addEventListener('DOMContentLoaded', function(){
var es = document.getElementsByTagName('a')
for(var i=0; i<es.length; i++){
es[i].addEventListener('click', function(e) {
e.preventDefault()
document.location.hash = e.target.getAttribute('href')
})
}
})
Building upon James Tomasino's answer, this one is slightly more efficient, solves a bug with double hashes in the URL and a syntax error.
$(document).ready(function() {
var pathname = window.location.href.split('#')[0];
$('a[href^="#"]').each(function() {
var $this = $(this),
link = $this.attr('href');
$this.attr('href', pathname + link);
});
});
A little bit of jQuery could probably help you with that. Although base href is working as desired, if you want your links beginning with an anchor (#) to be totally relative, you could hijack all links, check the href property for those starting with #, and rebuild them using the current URL.
$(document).ready(function () {
var pathname = window.location.href;
$('a').each(function () {
var link = $(this).attr('href');
if (link.substr(0,1) == "#") {
$(this).attr('href', pathname + link);
}
});
}
Here's an even shorter, jQuery based version I use in a production environment, and it works well for me.
$().ready(function() {
$("a[href^='\#']").each(function() {
this.href = location.href.split("#")[0] + '#' + this.href.substr(this.href.indexOf('#')+1);
});
});
You could also provide an absolute URL:
<base href="https://example.com/">
test
Rather than this
test
I'm afraid there is no way to solve this without any server-side or browser-side script. You can try the following plain JavaScript (without jQuery) implementation:
document.addEventListener("click", function(event) {
var element = event.target;
if (element.tagName.toLowerCase() == "a" &&
element.getAttribute("href").indexOf("#") === 0) {
element.href = location.href + element.getAttribute("href");
}
});
<base href="https://example.com/">
/test
#test
It also works (unlike the other answers) for dynamically generated (i.e. created with JavaScript) a elements.
If you use PHP, you can use following function to generate anchor links:
function generateAnchorLink($anchor) {
$currentURL = "//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
$escaped = htmlspecialchars($currentURL, ENT_QUOTES, 'UTF-8');
return $escaped . '#' . $anchor;
}
Use it in the code like that:
baz
To prevent multiple #s in a URL:
document.addEventListener("click", function(event) {
var element = event.target;
if (element.tagName.toLowerCase() == "a" &&
element.getAttribute("href").indexOf("#") === 0) {
my_href = location.href + element.getAttribute("href");
my_href = my_href.replace(/#+/g, '#');
element.href = my_href;
}
});
My approach is to search for all links to an anchor, and prefix them with the document URL.
This only requires JavaScript on the initial page load and preserves browser features like opening links in a new tab. It also and doesn't depend on jQuery, etc.
document.addEventListener('DOMContentLoaded', function() {
// Get the current URL, removing any fragment
var documentUrl = document.location.href.replace(/#.*$/, '')
// Iterate through all links
var linkEls = document.getElementsByTagName('A')
for (var linkIndex = 0; linkIndex < linkEls.length; linkIndex++) {
var linkEl = linkEls[linkIndex]
// Ignore links that don't begin with #
if (!linkEl.getAttribute('href').match(/^#/)) {
continue;
}
// Convert to an absolute URL
linkEl.setAttribute('href', documentUrl + linkEl.getAttribute('href'))
}
})
You can use some JavaScript code inside the tag that links.
<span onclick="javascript:var mytarget=((document.location.href.indexOf('#')==-1)? document.location.href + '#destination_anchor' : document.location.href);document.location.href=mytarget;return false;" style="display:inline-block;border:1px solid;border-radius:0.3rem"
>Text of link</span>
How does it work when the user clicks?
First it checks if the anchor (#) is already present in the URL. The condition is tested before the "?" sign. This is to avoid the anchor being added twice in the URL if the user clicks again the same link, since the redirection then wouldn't work.
If there is sharp sign (#) in the existing URL, the anchor is appended to it and the result is saved in the mytarget variable. Else, keep the page URL unchanged.
Lastly, go to the (modified or unchanged) URL stored by the mytarget variable.
Instead of <span>, you can also use <div> or even <a> tags.
I would suggest avoiding <a> in order to avoid any unwanted redirection if JavaScript is disabled or not working, and emulate the look of your <a> tag with some CSS styling.
If, despite this, you want to use the <a> tag, don't forget adding return false; at the end of the JavaScript code and set the href attribute like this <a onclick="here the JavaScript code;return false;" href="javascript:return false;">...</a>.
From the example given in the question. To achieve the desired behavior, I do not see the need of using a "base" tag at all.
The page is at http://example.com/foo/
The below code will give the desired behaviour:
bar <!-- Links to "http://example.com/bar/" -->
baz <!-- Links to "http://example.com/foo/#baz" -->
The trick is to use "/" at the beginning of string href="/bar/".
If you're using Angular 2 or later (and just targeting the web), you can do this:
File component.ts
document = document; // Make document available in template
File component.html
<a [href]="document.location.pathname + '#' + anchorName">Click Here</a>

add dynamically data-role pages

I want add dynamically data-role pages in my phonegap application. I thought that I can do this with something like this but isn't working
jQuery(function()
{
var theList = jQuery('#results');
for(i=0; i<mytool_array.length; i++)
{
content = '<div data-role="page" id="page'+i+'"><div data-role="header" data-backbtn="false"></div><div data-role="content"><p>page=+'+i+'</p></div></div>';
theList.append(content);
}
})
Im my HTML:
<div id="results"></div>
As far as I can predict the problems are:
you shouldn't put pages in a div. they should be in body
your function starts at DOMready, so it is after (or partially during) jquery mobile makes its formatting
rethink your idea. putting basic html structure in body and filling them later should work better
Consider making it a list or a set of collapsibles instead of pages.
This said, your current code should look like this:
jQuery(function($)
{
var b = $('body');
for(i=0; i<mytool_array.length; i++)
{
$('<div data-role="page" id="page'+i+'"><div data-role="header" data-backbtn="false"></div><div data-role="content"><p>page=+'+i+'</p></div></div>') //newline added for readability. it shouldn't be here
.appendTo(b).page(); //newline added for readability
}
});