Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Page 1 of 2 12 LastLast
Results 1 to 15 of 20
  1. #1
    New Coder
    Join Date
    Mar 2007
    Posts
    98
    Thanks
    24
    Thanked 4 Times in 4 Posts

    Dynamic Menu from folder tree

    Hi all, it's been a long time since I was last here, however after a lengthy hiatus, I'm back to javascript, so please bear with me.

    Firstly, this is all being done in IE8 on a closed network and all client side, so there are no security or cross-browser issues involved and never will be.

    What I have is a small basic script that scans a particular directory on a local drive. Based on the folder names, it populates an index.html page in the current folder with a listing of subfolders contained within and displays this to the user as hyperlinks (each sub folder also has an index.html to do similar). This is not an issue as I can use activeX and the fso. This function is called from the index pages onload.

    What I'm trying to do, is create a single navigation menu to be loaded on the left of each page that also follows the folder structure. Although the folder structure will go nth layers deep, I only need the nav menu to display 3 layers deep (to keep it readable). I would like it to be dynamic so that regardless of how many folders are added to the parent directory, the menu won't need to be changed at all, it will just pick up the new folders. Obviously, the menu would need to open at the current location (including upper layers), regardless how a user gets to that page (through the menu, direct link from a search). I imagine there would also be breadcrumbs, but not too worried about those right now.

    Is this possible? Does anyone have any pointers, or has it already been done? I'm hoping that jquery or plain JS can do this. I do not have direct server access to do this with ajax or php or the like. As it's based on local folders there isn't any working code.

    Cheers.

  • #2
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,021
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    Pretty trivial, actually.

    Keeping it 3 layers deep would make it fairly easy.

    Only question: What do you mean by "open at the current location"??

    Unless the "current location" is itself an HTML file resident on the local machine, then that is meaningless. Or do you mean that once they click on one of the displayed *folders* (not files?) then the current location is automatically changed to *that* folder?

    And I assume you would want a ".." folder displayed, at all times, to go up one directory level? What about if the user is already at C:\ (or D:\ or...)? Do we then display a list of available drives?
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #3
    New Coder
    Join Date
    Mar 2007
    Posts
    98
    Thanks
    24
    Thanked 4 Times in 4 Posts
    Hi Old Pedant, great to see you're still around, it's been a while since I was last here, however as I recall it was you that helped me.

    I'll try to explain a bit clearer. What I'm trying to do sounds really straight forward in my head.

    On a local drive(lets call it H:/) is a file structure. Each folder will contain any number of subfolders and one index.htm page to act as exactly that, an index page. This page when loaded, will display a table of contents using the names of the subfolders contained in it. For example:

    Folder H:/A/ contents: subfolder B, subfolder C, subfolder D, index.htm

    When index.htm is loaded, the user will see the page. On the right is a content div which will display a listing of the subfolders as hyperlinks (linked to the subsequent index.htm within each folder):

    B
    C
    D

    This part is working correctly. On the left I'm trying to create a nav menu that will also reflect the file structure 3 deep. In the above example, Folder A menu item would be expanded and highlighted as so:

    Folder A
    Subfolder B
    Subfolder C
    Subfolder D

    Each folder and subfolder is setup the same. So if you clicked on subfolder B in either the menu or the index on the right, the menu would expand and highlight Subfolder B. The menu needs to act as a standard menu, that is the can click down the levels and the folder location of the current page (index.htm) will be expanded and highlighted, regardless whether they have navigated through the menu tree or jumped directly to a particular page from a search. Anything over 3rd level will obviously not have it's full path shown in the nav menu, however the lower level items still need to be able to be traced back to their primary/secondary/tertiary levels so these can be highlighted. It is my aim to eventually have the full path displayed as breadcrumbs at the top of the index pages also.

    I realise this is very simple to do with HTML and CSS as a static menu, however as the folder numbers grow, maintenance would become a nightmare. The whole idea of having a single menu function in an external file to build based on the menu structure is to allow new folders to be simply created without having to add individual menu coding to each page.

    I hope I have explained a bit clearer.

  • #4
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,021
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    Well, here's the basic coding, but see below.
    Code:
    <html>
    <head>
    <style type="text/css">
    ul { list-style: none; }
    </style>
    </head>
    <body>
    <h3>Folders</h3>
    <div id="folders"></div>
    
    <script type="text/javascript">
    var dir = location.href.replace(/^file:\/+/,"").replace(/\\/g,"/");
    dir = dir.substring( 0, dir.lastIndexOf("/") );
    
    var putit = document.getElementById("folders");
    putit.appendChild( document.createTextNode("current: " + dir) );
    
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    dir = fso.getFolder(dir);
    
    showSubFolders( dir, putit, 1 );
    
    function showSubFolders( fldr, addto, level )
    {
        var subf = fldr.SubFolders;
        if ( subf.Count == 0 ) return;
    
        var ul = document.createElement( "ul" );
    
        var fc = new Enumerator( subf );
        for ( ; ! fc.atEnd(); fc.moveNext() )
        {
            var fl = fc.item();
            var li = document.createElement("li");
            var link = document.createElement("a");
            link.href = fl.path;
            link.innerHTML = fl.name;
            li.appendChild( link );
            if ( level < 3 )
            {
                showSubFolders( fl, li, level+1 );
            }
            ul.appendChild(li);
        }
        addto.appendChild(ul);
    }
    </script>
    
    </body>
    </html>
    BUT...

    Those links just indeed link to the actual folders. So clicking on one will just (depending on what version of WIndows you are using, perhaps) bring up Windows Explorer showing that directory.

    I *think* what you want, instead, is for clicking on a directory to move it to the "current:" position and then show the 3-level-deep folder for that postion. No?
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    longman (05-09-2013)

  • #5
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,021
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    See, this part of what you wrote doesn't make sense to me:
    ... and the folder location of the current page (index.htm) will be expanded and highlighted,
    That would imply that ever folder in the entire tree would need to contain its own "index.htm" page. Surely you don't mean that?
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #6
    New Coder
    Join Date
    Mar 2007
    Posts
    98
    Thanks
    24
    Thanked 4 Times in 4 Posts
    Hi,

    Thanks again for the response. Unfortunately, yes I mean every folder would have an index.htm page. Sometimes the page will be used to show a TOC of subfolders, or if the current folder has no subfolders, then it will contain some other content to be displayed.

    cheers.

  • #7
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,021
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    Perhaps this is what you want?
    Code:
    <html>
    <head>
    <style type="text/css">
    ul { list-style: none; }
    </style>
    </head>
    <body>
    <h3>Folders</h3>
    <div id="folders"></div>
    
    <script type="text/javascript">
    var startat = location.href.replace(/^file:\/+/,"").replace(/\\/g,"/");
    startat = startat.substring( 0, startat.lastIndexOf("/") );
    
    displayTree( startat );
    
    function displayTree( dir )
    {
        var putit = document.getElementById("folders");
        // clear out existing content, if any:
        while ( putit.lastChild != null )
        {
            putit.removeChild( putit.lastChild );
        }
        // and then get started
        putit.appendChild( document.createTextNode("current: " + dir) );
    
        var fso = new ActiveXObject("Scripting.FileSystemObject");
        dir = fso.getFolder(dir);
    
        showSubFolders( dir, putit, 1 );
    
        function showSubFolders( fldr, addto, level )
        {
            var subf = fldr.SubFolders;
            if ( subf.Count == 0 ) return;
        
            var ul = document.createElement( "ul" );
    
            var fc = new Enumerator( subf );
            for ( ; ! fc.atEnd(); fc.moveNext() )
            {
                var fl = fc.item();
                var li = document.createElement("li");
                var link = document.createElement("a");
                link.href = fl.path;
                link.innerHTML = fl.name;
                link.onclick = changeRoot;
                li.appendChild( link );
                if ( level < 3 )
                {
                    showSubFolders( fl, li, level+1 );
                }
                ul.appendChild(li);
            }
            addto.appendChild(ul);
        }
        return false;
    }
    
    function changeRoot( )
    {
        var newroot = this.href;
        displayTree( newroot );
        return false;
    }
    </script>
    
    </body>
    </html>
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #8
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,021
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    Whoops....no, scratch that last one. I didn't see your post #6,

    Okay, then it's easy.

    Look at my post #4.

    Just change one line:
    Code:
           link.href = fl.path
    is changed to:
    Code:
           link.href = "file://" + fl.path + "/index.htm";
    And I think that does it.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    longman (05-09-2013)

  • #9
    New Coder
    Join Date
    Mar 2007
    Posts
    98
    Thanks
    24
    Thanked 4 Times in 4 Posts
    Another classic example of overthinking. I was thinking it would be a lot more complex. I didn't expect you to write it all for me, so thank you. I'll start playing with getting it how I want. I really appreciate the help!

  • #10
    New Coder
    Join Date
    Mar 2007
    Posts
    98
    Thanks
    24
    Thanked 4 Times in 4 Posts
    Thanks OP, that works a treat. One final question, would there be any issue with using standard CSS to style the elements into a clickable nav menu, with hover highlighting etc and levels hidden until clicked on, or a child page is opened from a search?

  • #11
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,021
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    No, of course not. Style away.

    I'm not sure how you would do "levels hidden until clicked" in CSS, though. But fairly trivial with some added JS.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #12
    New Coder
    Join Date
    Mar 2007
    Posts
    98
    Thanks
    24
    Thanked 4 Times in 4 Posts
    Hi again,

    I've added a screen shot of the page I'm building. You will see the right part has the folder listing with hyperlinks. What I'm working on is the grey menu at the left. It needs to appear on every page and track each pages position in the folder tree. The folder listing in the right has been accomplished successfully. I'm now trying to get your code to resemble the left nav menu. Does this make sense? I probably should have included this screenshot in post #1! apologies for that.
    Attached Thumbnails Attached Thumbnails Dynamic Menu from folder tree-page.jpg  

  • #13
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,021
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    Welll, try this code. Only thing it doesn't do is pre-set the expander/contractor to "-" if there are no children (except on third level). That could be changed if it's important.

    Code:
    <html>
    <head>
    <style type="text/css">
    ul { list-style: none; }
    ul li span { 
        font-family: courier;
        font-size: medium;
        font-weight: bold;
        padding-right: 10px;
        color: red;
        cursor: hand;
    }
    ul.level1 { margin-left: 0px; }
    ul.level2 { display: none; }
    ul.level3 { display: none; }    
    span.level1, span.level2, span.level3 { }
    </style>
    </head>
    <body>
    <h3>Folders</h3>
    <div id="folders"></div>
    
    <script type="text/javascript">
    var dir = location.href.replace(/^file:\/+/,"").replace(/\\/g,"/");
    dir = dir.substring( 0, dir.lastIndexOf("/") );
    
    var putit = document.getElementById("folders");
    putit.appendChild( document.createTextNode("current: " + dir) );
    
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    dir = fso.getFolder(dir);
    
    showSubFolders( dir, putit, 1 );
    
    function showSubFolders( fldr, addto, level )
    {
        var subf = fldr.SubFolders;
        if ( subf.Count == 0 ) return;
    
        var ul = document.createElement( "ul" );
        ul.className = "level" + level;
    
    
        var fc = new Enumerator( subf );
        for ( ; ! fc.atEnd(); fc.moveNext() )
        {
            var fl = fc.item();
            var li = document.createElement("li");
    
            var expand = document.createElement("span");
            expand.appendChild( document.createTextNode( level < 3 ? "+" : "-" ) );
            if ( level < 3 ) expand.onclick = expander;
            li.appendChild(expand);
    
            var link = document.createElement("a");
            link.href = "file://" + fl.path + "/index.htm";
            link.innerHTML = fl.name 
            li.appendChild( link );
    
            if ( level < 3 )
            {
                showSubFolders( fl, li, level+1 );
            }
    
            ul.appendChild(li);
        }
        addto.appendChild(ul);
    }
    
    function expander( )
    {
        // this is a span, so get the enclosing li:
        var li = this.parentNode;
        var ul = li.getElementsByTagName("ul")[0];
        if ( this.innerHTML == "+" )
        {
            if ( ul != null ) ul.style.display = "block";
            this.innerHTML = "-";
        } else {
            if ( ul != null ) ul.style.display = "none";
            this.innerHTML = "+";
        }
    }
    </script>
    
    </body>
    </html>
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    longman (05-13-2013)

  • #14
    New Coder
    Join Date
    Mar 2007
    Posts
    98
    Thanks
    24
    Thanked 4 Times in 4 Posts
    Thanks so much OP for your assistance, I've been styling away and have got it looking the way I want, although the use of spans for the + and - made for some interesting results! I'm hesitant to ask for any more assistance, however the final part of what I'm trying to do is the get the toggle working correctly. That is, if someone loads a page (either from the menu or from a direct link in a search), the menu will automatically open to that pages parent directory and highlight it (if it's within the first 3 levels of the menu) or open the page and highlight the menu item down to the 3rd level (if the page is deeper than 3 levels).

    I've been trying different methods (jquery, location.href etc), however some directories have spaces in the names and this is causing all sorts of grief for some reason, plus I can't figure out how to tie a particular page and directory together and work back along the child/parent relationship. I hope that makes sense.

  • #15
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,021
    Thanks
    75
    Thanked 4,323 Times in 4,289 Posts
    So the page is loaded into the right side and you want to highlight its directory in the left side, right?

    What would you do, pass a message (that is call a function) in the left panel from the code in the right panel?

    Are subdir names unique? Or can you have something lke this:
    Code:
    animals
        mammals
            cougar
    cars
        mercury
            cougar
    ??

    And what would you pass from the right side? Just the path? e.g., "c:\whatever\something\cars\mecury\cougar\motorspecs.html" ??
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.


  •  
    Page 1 of 2 12 LastLast

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •