0

I have a web page on which my sidebar links will cause an 'external' HTML document to be loaded into a content div.
However after it is successfully loaded and displayed, the loaded HTML content does not appear in the Page Source.
Regardless, I now need to do a client-side Text Search of that 'external' HTML document using a Javascript function.

My webpage looks like the following:

Page when Contents are displayed

The Search textbox and button are 'outside' of the Content Div (bordered in Red).

And, at the time that one of the link's HTML documents is appearing on-screen the page source looks like:

<!-- Page Content -->
<div id="page-content-wrapper" style="border: thick solid #FF0000; height:660px">
          <!--Loaded content goes here-->
</div>  

Notice that the 'loaded' HTML document is not showing.

I have found a Javascript function findInPage() which looks promising, but it is not finding the 'loaded' HTML document and its text.

// =====================================
function findInPage() {

    var str = document.getElementById("ButtonForm").elements["txtSearch"].value;
    var n = 0;
    var txt, i, found;
    if (str == "")
        return false;

    // Find next occurance of the given string on the page, wrap around to the
    // start of the page if necessary.
    if (window.find) {
        // Look for match starting at the current point. If not found, rewind
        // back to the first match.
        if (!window.find(str)) {
            while (window.find(str, false, true))
                n++;
        } else {
            n++;
        }
        // If not found in either direction, give message.
        if (n == 0)
            alert("Not found.");
    } else if (window.document.body.createTextRange) {

        txt = window.document.body.createTextRange();
        // Find the nth match from the top of the page.
        found = true;
        i = 0;
        while (found === true && i <= n) {

            found = txt.findText(str);
            if (found) {
                txt.moveStart("character", 1);
                txt.moveEnd("textedit");
            }
            i++;
        }
        // If found, mark it and scroll it into view.
        if (found) {
            txt.moveStart("character", -1);
            txt.findText(str);
            txt.select();
            txt.scrollIntoView();
            n++;
        } else {
            // Otherwise, start over at the top of the page and find first match.
            if (n > 0) {
                n = 0;
                findInPage(str);
            }
            // Not found anywhere, give message. else
            alert("Not found.");
        }
    }
    return false;
}

Is there some way to modify the function and/or use a different function such that it can find the 'loaded' HTML document and search it for the entered Text?

YakovL
  • 7,557
  • 12
  • 62
  • 102
Dhugalmac
  • 554
  • 10
  • 20

3 Answers3

0

try selecting the div by id instead of reading the whole window...

document.getElementById('page-content-wrapper').find(str)
Doug
  • 1,435
  • 1
  • 12
  • 26
  • Thanks for the suggestion. I tried it in the Javascript function by replacing everywhere that was "window." with "document.getElementById('page-content-wrapper')." While the script did not crash, it still did not find the text "generate" what I was looking for. – Dhugalmac Sep 27 '17 at 21:07
0

This is a duplicate of How to get html elements from an object tag?.

The answer lies in replacing all instances of window.document with document.getElementById('page-content-wrapper').contentDocument, such that the searched document is the page document.

However, the search function you have there is quite broken, it depends on window.find to search the window instead of searching the document text.

You could build a better search function:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Wrapper</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>
    Body Here
    <object id="page-content-wrapper" type="text/html" data="about.html" name="content"></object>
        <input id="txtSearch" placeholder="Search..." />
        <button onclick="findInPage()">Search</button>
    <script>
        function findInPage() {
            var needle = document.getElementById('txtSearch').value;
            var haystack = document.getElementById('page-content-wrapper').contentDocument.body.innerHTML;
            var match = haystack.indexOf(needle);
            if(match != -1) {
                console.log(match);
            } else {
                console.log('Not Found');
            }
        }
    </script>
    </body>
</html>

Fill about.html with anything you want to load and search in.

Note that this just logs the index of the match. It doesn't scroll it into view or select it. With a little more javascript you can do those though. You just have to go through document.getElementById('page-content-wrapper').contentDocument.body

mmdts
  • 757
  • 6
  • 16
  • Thanks for the suggestion. I tried it, but 'haystack' stays Undefined when that line is executed - thereby causing the rest of the code to be ignored. – Dhugalmac Sep 28 '17 at 13:32
  • On debugging further it seems that .contentDocument.body are not valid – Dhugalmac Sep 28 '17 at 13:44
  • On further testing I find.... *** var Div = document.getElementById('page-content-wrapper'); *** var Obj = document.getElementById('page-content-wrapper').children[0]; *** var innerHTML = document.getElementById('page-content-wrapper').children[0].innerHTML; *** But even when the document shows on-screen in the Div, the innerHTML = "" – Dhugalmac Sep 28 '17 at 16:52
0

I finally found how to access the HTML content of the Object's innerHTML.
Upon clicking on a specific Sidebar link, using Javascript, I build its Object.

function MenuClick(doc) {
var Tutorial = doc;
var DisplayObj = "<object id='ThisObj' type='text/html' data='" + Tutorial + "' style='min-width:100%; min-height: 101%; overflow: hidden'></object>";
        document.getElementById("page-content-wrapper").innerHTML = DisplayObj;
}  

But now I have added an ID to the Object ('ThisObj').

With that ID now defined I was able to 'drill-down' into that Object to get to its innerHTML.

var sourceObj = document.querySelector("#ThisObj");
var sourceBody = sourceObj.contentDocument.body
var haystack = sourceBody.innerHTML;

var match = haystack.indexOf(needle);
if (match != -1) {
  // --- Text match found ---
} else {
  // --- Text match NOT found ---
}  

I still need to create the Javascript to highlight the 'found' text and scroll it into view but I'll ask that question in a separate post.

Thanks for your suggestions/advice.

Dhugalmac
  • 554
  • 10
  • 20
  • On further testing this too did not work. The sourceObj was defined, but it does not have a "contentDocument" element defined and, as a result, no "body". I did find the 'external' HTML defined in the sourceObj.data object, but nothing under that. So I am still without a working solution. – Dhugalmac Oct 20 '17 at 21:48