1

I'm trying to create a markdown editor.

So far: I have loaded the index page. I'm using fs.readdir to get the titles of all the markdown files and display them in the sidebar. Then, on clicking on of these title #content get's the content.

   module.exports = (win) => { 
        fs.readdir( './data', (err, data) =>{
        data.map(title => {    
          if(title.split('.md').length==2){
            el = document.createElement("li"); // get gave it the title ..
            el.addEventListener('click', function(e){
              fs.readFile(`./data/${title}`, (err, data) => {
                document.getElementById('content').innerHTML = data;
              });
            })
            document.getElementById('titles').appendChild(el) // title are on the page

The problem is when I introduce another page

I have a preferences page

win.loadURL(path.join('file://', __dirname, '../static/preferences.html'))

It has the same sidebar, hence I import the same code to get the titles. But now when I click one of the links, I don't want document.getElementById('content').innerHTML = data; but I want to load the index page and then inject the content

So far I tried this

const checkPageState = (pageName, callback) => {
  if(pageName === "preferences"){
    ipcRenderer.send(GO_TO_PAGE, 'index')
  }
  setTimeout(callback(), 1000);
}
...
el.addEventListener('click', function(e){
    checkPageState(win, ()=>{
      fs.readFile(`./data/${title}`, (err, data) => {
       if (err) throw err;
     fileDir = `./data/${title}`;
     document.getElementById('content').innerHTML = data;
    });
  })
})

My thinking was ipcRenderer.send(GO_TO_PAGE, 'index') would load the index page (which it does) when wait for a bit and then inject the data into the index page. It doesn't!

How can I do this?

relidon
  • 2,142
  • 4
  • 21
  • 37

1 Answers1

1

I recently tried to do this as well and it was kinda tricky but I found something that worked:

In electron when it tries to go to another page I stop it from going to it with:

win.webContents.on('will-navigate', function (evt, url) {
    evt.preventDefault();
    win.webContents.executeJavaScript('makeHiddenPageIframe("' + url + '");');
});

Then it calls the makeHiddenPageIframe function defined on the page.

Then in the page I define the makeHiddenPageIframe function:

function makeHiddenPageIframe (url) {
    var hiddenPage = document.createElement("iframe");
    hiddenPage.setAttribute("src", url);
    hiddenPage.style.display = 'none';
    document.body.appendChild(hiddenPage);
    hiddenPage.onload = function () {
        var frameDocument = hiddenPage.document;
        if (hiddenPage.contentDocument) {
            frameDocument = hiddenPage.contentDocument;
        } else if (hiddenPage.contentWindow) {
            frameDocument = hiddenPage.contentWindow.document;
        }
        document.open();
        document.write(frameDocument.documentElement.innerHTML);
        document.close();
        window.history.pushState("", document.title, url.replace('https://' + window.location.hostname, ''));
    }
}

This then makes a iframe and loads the page in there then once it has loaded copy all the html from the iframe to the parent window so it seems like the switch happened instantly.

Also the window.history.pushState thing at the bottom was when you overwrite the html the url stays the same so when you reload it goes back to the original page but the window.history.pushState changes the url without reloading the page.

Any form of navigation will do the iframe load so you would keep your win.loadURL( to go to another markdown page.

The 'will-navigate' event docs.

window.history.pushState ref.

I hope this helps :)

Joshua
  • 5,032
  • 2
  • 29
  • 45
  • Thanks, where is `makeHiddenPageIframe` defined? in the page I'm going into or in the page I'm trying to leave – relidon Sep 01 '18 at 09:32
  • 1
    In the page you're trying to leave, although to be safe it should probably be defined in both. – Joshua Sep 01 '18 at 09:33
  • I think I understand the code and the logic. I've read the docs on 'will-navigate' but can't seem to get it working. I can seem to even trigger that `will-navigate` event let alone proceed with `makeHiddenPageIframe`. In the root I have `main.js` that's where I declare `win = new BrowserWindow({width: 800, height: 600})` and under it I added `will-navigate` and see if it prevents and logs anything and it doesn't. Never mind, I'll get there. Thanks for getting me in the right direction, it must be my code. – relidon Sep 01 '18 at 10:18
  • huh, that's odd. It might be that the variable name for your window is different and it's just a copy paste error but aside from that I don't know what might be wrong. If you post the code where you're creating the window I might be able to help a bit more. – Joshua Sep 01 '18 at 10:22
  • I found this https://github.com/electron/electron/issues/8841 copied exactly what sebastianseilund has and got the exact same result. `did-navigate` works `will-navigate` doesn't. – relidon Sep 01 '18 at 10:26
  • I'm new at this. Apparently, adding `sandbox: false` get's it working. I'll have to search that later as to why but at least now I got `will-navigate` working as it should – relidon Sep 01 '18 at 10:29
  • Good to hear you found a solution :). Now that it's firing does the delayed page loads work? – Joshua Sep 01 '18 at 10:31
  • I sure I'll get it working, but there seem to be a totally different problem, the moment I add `webPreferences`, `require is not defined` :). I come back to your code late. It clearly works but I don't know why it's acting out at my end. Thanks again – relidon Sep 01 '18 at 10:44
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/179236/discussion-between-mike-and-relidon). – Joshua Sep 01 '18 at 10:49