How to load nav menu from an external file? (No Wa

2019-01-20 18:50发布

I have a static HTML web site. I want to store the the nav (top) menu in an external file so when I change the menu, I want to see the change in all pages.
I REALLY REALLY NEED to be able to see the web pages also locally (regular Windows user without the need to install additional software: Apache, PHP, Wamp, specific browsers, etc).

There are two similar StackOverflow questions that partially solves this issue using PHP, SSIand ... frames. None of the solutions is good for me:

  • Frames out of discussion obviously (bad from SEO POV and also obsolete in HTML5).
  • PHP and SSI will only work after the site was uploaded on the server so it won't work locally.

The solution I see is putting ALL the menu in an external JS file. However, all the JS examples I fave found still have some 'parts' of the menu in the HTML file.

So, it is possible to have all menu in a JS file and only a call (and no actual menu items) to that file in my HTML files? I only have basic knowledge of JS. But enough to adapt a generic example for my needs.

5条回答
forever°为你锁心
2楼-- · 2019-01-20 19:25

You can use JsRender/JsViews for this.

查看更多
贪生不怕死
3楼-- · 2019-01-20 19:37

nav.html // you dont need to put html, body or etc. Just the nav itself.

<nav> bla bla </nav>

index.html

<!doctype html>
<html>

  <head>
    <title>onload test</title>
    <script>

    window.onload = function(){
    var xhttp = new XMLHttpRequest();

    xhttp.onreadystatechange = function(){
        if(this.readyState == 4 && this.status == 200){
             document.getElementById('includeNav').innerHTML= '<object type="text/html" data="nav.html"></object>';
        }
    }

    xhttp.open('POST', 'nav.html', true); // method, location, async
    xhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhttp.send(); }
    </script>
  </head>


  <body>
    <p>The load event fires when the document has finished loading!</p>
    <div id="includeNav"></div>
  </body>
</html>

TRY this. this might be the answer of your question.

查看更多
欢心
4楼-- · 2019-01-20 19:38

A copy of my answer on a different thread:

I think this is the easiest way of doing it without a server side language. Use a javascript library like W3Data. All you need to do is add the w3-include-html attribute to your div. Done!

If your menu is in a file called menu.html you'd do something like this.

<div w3-include-html="menu.html"></div> 
查看更多
虎瘦雄心在
5楼-- · 2019-01-20 19:40

You can have a look into HTML Imports.

Option 1: In the simplest case you can do it like that:

index.html (or any other page):

<!DOCTYPE html>
<html>
<head>
    <link rel="import" href="nav.html">
</head>
<body>
    My Page
    <script>
        var link = document.querySelector('link[rel="import"]');
        var nav = link.import.querySelector('nav');
        document.body.appendChild(nav.cloneNode(true));
    </script>
</body>
</html>

nav.html:

<nav>
    <ul>
        <li>link 1</li>
        <li>link 2</li>
        <li>link 3</li>
    </ul>
</nav>

More information at: http://www.html5rocks.com/en/tutorials/webcomponents/imports/

Option 2: Make full usage of the Web Components API and use stuff like your own HTML element, then the usage in all your files gets even easier (although the nav.html gets a little bit more complex).

index.html (or any other page):

<!DOCTYPE html>
<html>
<head>
    <link rel="import" href="nav.html">
</head>
<body>
    My Page
    <my-nav></my-nav>
</body>
</html>

nav.html

<nav>
    <ul>
        <li>link 1</li>
        <li>link 2</li>
        <li>link 3</li>
    </ul>
</nav>
<script>
    var navProto = Object.create(HTMLElement.prototype);
    var navDoc = document.currentScript.ownerDocument;
    navProto.createdCallback = function() {
        var shadow = this.createShadowRoot();
        var nav = navDoc.querySelector('nav');
        var clone = document.importNode(nav, true);
        shadow.appendChild(clone);
    };
    document.registerElement('my-nav', { prototype: navProto });
</script>

EDIT: A mentionable downside of both solution is the browser support:

So mainly it's Chrome (including Android) and Opera which support these features. Unfortunately it's not possible to use HTML imports without a web server because of security settings of the browser. You will get a console error like that:

Imported resource from origin 'file://' has been blocked 
from loading by Cross-Origin Resource Sharing policy: 
Invalid response. Origin 'null' is therefore not allowed access.

So you would need to start a simple web server like the nodejs module http-server or use a Chrome extension like Chrome Dev Editor which brings a built in web server https://chrome.google.com/webstore/detail/chrome-dev-editor/pnoffddplpippgcfjdhbmhkofpnaalpg?utm_source=chrome-app-launcher-info-dialog

查看更多
该账号已被封号
6楼-- · 2019-01-20 19:44

menu.html

<ul>
    <li><a href="index.html">Home</a></li>
    <li><a href="active1.html">Contact</a></li>
    <li><a href="active2.html">About</a></li>
    <li><a href="active3.html">Portfolio</a></li>
</ul>

index.html

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>

<div id="nav"></div>

js file:

$(function() {

    $("#nav").load("menu.html");

    function activeNav() {
        var pgurl = window.location.href.substr(window.location.href.lastIndexOf("/")+1);
         $("#nav ul li a").each(function(){
              if($(this).attr("href") == pgurl || $(this).attr("href") == '' )
              $(this).addClass("active");
         });
    }

    setTimeout(function() {
        activeNav();
    }, 100);

});

The setTimeout lets the page load and then runs the function to see what link is active and then you can add a class in the css:

#nav ul li a.active {
        color: #ff0000;
        font-weight: bold;
    }
查看更多
登录 后发表回答