Search code examples
javascripthta

Can't load HTML into HTA file when click by link inside of the HTML


I have one HTA file, one JS file is enqueued to the HTA file and HTML files with contents are loaded into the HTA file.

For example this is my_hta_file.hta

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="x-ua-compatible" content="ie=9.0" />
</head>
<body></body>
</html>
<script type="text/javascript" src="my_js_file.js"></script>

and this is my_js_file.js

function getFileContent(filePath) {
    var fileStream = new ActiveXObject('ADODB.Stream');
    fileStream.Type = 2;
    fileStream.Charset = 'utf-8';
    fileStream.Open();
    fileStream.loadFromFile(filePath);
    var fileContent = fileStream.ReadText();
    fileStream.Close();
    return fileContent;
}

// initial loading of home page
document.body.innerHTML = getFileContent('index.html');

var pageLinks = document.querySelectorAll('a');
for(i = 0; i < pageLinks.length; i++) {
    var linkHref = pageLinks[i].getAttribute('href');

    pageLinks[i].setAttribute('href','#!'+linkHref);
    // I add this leading prefix to prevent following by the link when click by it

    pageLinks[i].onclick = function() {
        var page = this.getAttribute('href').substring(3);
        if(page == '') {
            var page = 'index';
        }

        // load HTML of the page by link path when click by the link
        document.body.innerHTML = getFileContent(page+'.html');
    }
}

and my HTML files with contents are:

index.html

<a href="/">Home</a>
<a href="/second">Second</a>
<a href="/third">Third</a>
<div>Home page content</div>

second.html

<a href="/">Home</a>
<a href="/second">Second</a>
<a href="/third">Third</a>
<div>Second page content</div>

third.html

<a href="/">Home</a>
<a href="/second">Second</a>
<a href="/third">Third</a>
<div>Third page content</div>

When I click by a link, I need to load all the HTML content from the HTML file by the link path including the very links I click by.

If I open my HTA file and click the link "Second", I get the second page links and content successfully.

But after that if I click the link "Third", I get the error

Cannot find file 'file:///D:/third' ...

How to resolve the problem?


UPDATE 1

If I move my script to the bottom of the HTA body and add a div for loading HTML for example

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="x-ua-compatible" content="ie=9.0" />
</head>
<body>
  <div id="body"></div>
  <script type="text/javascript" src="my_js_file.js"></script>
</body>
</html>

and in my JS file load HTML into div i.e.

document.getElementById('body').innerHTML = ...

instead of

document.body.innerHTML = ...

the problem still remains


Solution

  • As said in the comments, all the links with attached event listeners are replaced by new elements when innerHTML is changed. These new links don't have the listeners which the old elements had.

    The snippet below shows how you can use a function to reinit the listeners. The snippet assumes a content wrapper element is used (as you already seem to use it). I've also simplified the code a bit, and used more modern JS (since IE9 mode is used in the OP).

    function getFileContent (filePath) {
        // As it currently is
    }
    
    // Handles clicks on the links
    function newContent (e) { // e contains information of the current event
        var path = e.target.href || 'index',
            body = document.getElementById('body');
        e.preventDefault(); // Prevents the default action of the clicked link
        body.innerHTML = getFileContent(path + '.html');
        init(); // Initialize the new content
        return;    
    }
    
    // Initializes the page
    function init() {
        var links = document.querySelectorAll('a'),
            i, ei;
        for (i = 0, ei = links.length; i < ei; i++) {
            links[i].addEventListener('click', newContent);
        }
        return;
    }
    
    // Initialize the first page
    init();