Log in
If you're a student, please log in, so you can get the most from this page.
Lesson contents
Navbar reuse = happiness
On most sites, the same, or a similar, navbar is used on all pages. You can copy-and-paste the same navbar code to each page. Makes sense.
Until you need to change the navbar. Add a new page that needs a navbar link? You need to change every page. All 392 of them, or whatever the number is.
But what if you could have the navbar in a separate HTML file, maybe called top-menu.html
, or something, and insert top-menu.html
into every page on the site? Woohoo! Then, when you want to add a menu item, change that one file top-menu.html
, and every page on the site changes.
That's what this lesson is about. It's a big productivity win.
DoggoLand example
Let's make a site about DoggoLand, a theme park. Follow along on your own PC, if you like.
Here are the pages:
index.html
is the home page. location.html
has a map, and directions to the park. tickets.html
is where you can buy tickets.
rides
is a folder. It has three pages, each one about a different ride.
You can try the site. You'll see that each page has the same navbar:
How it works
We make one file with the navbar code. Then, on each page, we leave a gap, where we want the navbar to appear. Then, when the page loads, we want the navbar code to be injected into the gap.
When the browser loads a page, we want it to run some JavaScript code, that will fetch top-menu.html
, and inject it into the page. You don't need to write JavaScript code. I've done that for you, and put it in a file. All you need to do, is use a script
tag to load the file on each page.
Make a library
folder
To start, we'll need a place for top-menu.html
to live. The file with the JS (JavaScript) will live in the same place. Let's make a library
folder for our new stuff.
Make top-menu.html
with the navbar code
Let's make top-menu.html
, the file with the navbar HTML. This HTML will be inserted into each of your pages.
You learned to make navbar HTML in the previous lesson. Like this:
- <nav class="navbar navbar-expand-lg navbar-light bg-light">
- <a class="navbar-brand" href="index.html" title="Home">DoggoLand</a>
- ...
- </nav>
Make top-menu.html
in library
, and put the navbar code in it:
Copy the JavaScript file
Now, let's add the JavaScript code, in a file called loader.js
in library
.
To get your own copy of loader.js
, right-click on this link and choose "Save link as..." (Firefox and Chrome), "Save target as" (Edge), or whatever on another browser.
You don't need to change the file at all. Just save it into the library
folder.
Preparing the webpages
Remember that we want to inject code into our pages.
We have top-menu.html
. We have the JavaScript code that will do the injection. Now, we need to prep our webpages, like index.html
, dogarium.html
, and tickets.html
.
There are two steps.
- Include the JavaScript code on the page.
- Mark where you want the navbar to be injected.
Including the JavaScript code
We've been using an HTML template for our BS pages. Let's add a line to it:
- <script src="https:// ... /bootstrap.min.js"></script>
- <script src="library/loader.js"></script>
- </head>
The new line adds loader.js
from the library
folder.
Marking the injection point
Recall that BS uses rows and columns. Like this:
- <body>
- <div class="container">
- <div class="row">
- <div class="col-sm-12">
- <!-- Navbar -->
- </div>
- </div>
- <div class="row">
- <div class="col-sm-12">
- <!-- Content -->
- </div>
- </div>
- </div>
- </body>
We want the navbar in the first row. Let's mark the place where we want the navbar to be injected.
- <body>
- <div class="container">
- <div class="row">
- <div class="col">
- <div data-replacement="top-menu.html"></div>
- </div>
- </div>
data-replacement
gives the name of the file to inject. loader.js
(we added that JS file earlier, remember) will look for elements with the data-replacement
property, and replace them with the file given.
Important!
The file being injected has to be in the library
folder, or this won't work.
Georgina
You used a div
there, not a nav
.
- <div data-replacement="top-menu.html"></div>
Does that matter?
No. Elements with data-replacement
attributes get replaced, so it doesn't matter what you use. If you'd rather use nav
to remind yourself what's going on, that's OK.
Actually, this isn't just for navbars. It will inject any HTML. Have a photo of your fave doggo, that you want on your site in lots of different places? Make a file in the library
folder, and inject it as needed.
For example, best-doggo.html
might have this:
- <p>
- <img src="rosie1.jpg" alt="Best doggo!">
- </p>
In your pages:
- <div data-replacement="best-doggo.html"></div>
Use this as many times as you like.
If you get a better photo of your best dog, change the code in best-doggo.html
:
- <p>
- <img src="rosie-blue-ribbon.jpg" alt="Rosie gets the blue!">
- </p>
All of your pages that inject best-doggo.html
will use the new photo.
Summary so far
To reuse some HTML:
- Make a
library
folder. - Make a file there with the HTML you want to reuse.
- Put
loader.js
inlibrary
. - Include
loader.js
in each page (with ascript
tag). - Mark the element you want to replace, with
data-replacement="the-file.html"
.
Changing other site elements
Adela
A question. I'm making a site for a student org. We want to include the name and email of our membership person on the site, on maybe ten different pages. Trouble is, that person changes. Right now, it's Buffy Summers, but next year, it'll be Willow Rosenberg. That means we'll have to go through all the pages, and change the membership contact.
No big deal, but it takes time, and it would be easy to miss one. Could we use this inject-HTML-in-several-files thing, to make the site easier to change?
Yes, you could. You could make a file called membership-questions.html
, or something like that. Put it in library
. It would have HTML, like this:
- <p>
- For membership info, please contact Buffy Summers, at slayer83@sunnydale.edu.
- </p>
When you want to use it on a page, type in this:
- <p data-replacement="membership-questions.html"></p>
Use the data-replacement
thing as many times as you like, on as many pages as you like.
Next semester, update membership-questions.html
with the new contact info. Everything will change across the site, automatically.
Georgina
Wow, that's so useful! I did an internship last summer, updating a website. I kept making the same changes all over the site. This would have saved a lot of time.
Right! And Benjamins. When a large site is set up this way, one person can do a job it might take two or three people to do otherwise.
Ray
Hey, I was thinking. Pretend I'm interviewing for a job, and they asked what I know about making websites. I can talk about HTML, OK. But what might impress them, is if I tell them about productivity hacks I learned.
Like using Bootstrap templates, with good a11y built-in. Making responsive sites, so one site looks good on phones, tablets, and PCs. No duplication of effort.
This reusing HTML thing is another one.
Good thinking, Ray! Talking about productivity is good to do in interviews. The technique we're using here is called code reuse by geeks. Talking about how code reuse makes sites cheaper to maintain, could impress the interviewers.
Georgina
Yeah, that's a good idea, Ray.
It takes a server
Here's part of the code from loader.js
:
- $(replacementElement).load(pathToFile...
The load()
method contacts the server the HTML file is from, and gets the file named in the variable pathToFile
. There has to be a server to respond, for this to work.
If the HTML page is being served from your Reclaim Hosting account, no problem. There is a server. But suppose you opened the HTML file on your PC, by double-clicking on the file name in Explorer. In that case, your browser opens the file directly from your C: or D: drive, or whatever. There is no server involved, and nothing for load()
to send its request to.
Brackets has an "Enable experimental file preview" option in the File menu. If that's on, then when you live preview the file in Brackets, it starts a temporary server for you, running on your PC. load()
works just fine in that case.
I have trouble with the experimental live preview from time to time. It won't start up. In that case, I actually like to use a Chrome extension called Web Server for Chrome. Works well. Try it if you want, or just run your code from your Reclaim Hosting as normal.
Exercise
The subfolder problem
There's just one more wrinkle to deal with. Remember that we have pages in a subfolder:
We want top-menu.html
to work on all of the pages on our site, whether the page is in the root folder, like location.html
is, or whether the page is in a subfolder, like dogarium.html
is.
Here's part of top-menu.html
:
- <nav class="navbar navbar-expand-lg navbar-light bg-light">
- <a class="navbar-brand" href="index.html" title="Home">DoggoLand</a>
- ...
- </nav>
Adela
It looks OK...
No, wait. It says href="index.html"
. That would work for tickets.html
, because tickets.html
and index.html
are in the same folder.
But href="index.html"
wouldn't work for dogarium.html
, because dogarium.html
is in a subfolder. Then the link is in dogarium.html
, it needs to be href="../index.html"
. Go up a level, then look for index.html
.
Right! The links in top-menu.html
need to change, depending on whether the page we're inserting top-menu.html
into is in a subfolder.
Marcus
Argh! That sounds hard!
No worries. loader.js
know how to deal with this. If the page you want to inject the HTML into is in a subfolder, just tell loader.js
the path to the site root. So, dogarium.html
is inside rides
:
The path from dogarium.html
to the site root is ../
, that is, up one level. In dogarium.html
, when you tell loader.js
to inject top-menu.html
, you add something:
- <body>
- <div class="container">
- <div class="row">
- <div class="col">
- <nav data-replacement="top-menu.html" data-path-to-root="../">
- </nav>
- </div>
- </div>
When you use the data-replacement
, you can add the data-path-to-root
(though it's optional). loader.js
will adjust the paths in top-menu.html
, adding ../
to them all.
Well, almost all of the paths. It won't adjust absolute paths, like this:
- <a class="nav-link" href="https://www.google.com/search?tbm=isch&q=cute+goat">Cute goats</a>
This link searches Google for images of cute goats. Adding ../
to the front wouldn't make sense. So, loader.js
won't adjust links that start with http
or https
.
You can also tell loader.js
to not adjust individual links, like this:
- <a class="nav-link" href="monkey-mania.html" data-no-update>Location</a>
data-no-update
tells loader.js
not to change the link. I'm not sure when you would use that, but it lets you skip links, when needed.
One last thing. The pages in the folder need to be able to find loader.js
. So you need to change the line that, er, loads loader.js
into your pages. From this...
- <script src="library/loader.js"></script>
... to this...
- <script src="../library/loader.js"></script>
Why do you need to change the link to loader.js
?
Marcus
Oh, I get it! The pages in the folder need to go up a level, then down into the library, to find loader.js
.
Right! You got it!
Exercise
Code reuse with path adjustment
Log in
If you're a student, please log in, so you can get the most from this page.
Earlier, you made a site about two yummy things. Now make a similar site, about yucky things.
A good way to do it is to copy the folder you made earlier. Then change the bits you need.
Here's my site's home page:
I put three things. You can have two, if you want.
Put your pages about yucky things in the subfolder yucky-things
. Here's my file tree:
Reuse the navbar and footer. For example, here's what happens if I change the text in footer.html
:
Submit your URL as usual.
Up next
We'll end the course by looking at two more useful BS components.