brrd/electron-tabs

Unable to open new page in selected tab

puchenhui opened this issue · 20 comments

Hello, when I want to open a new page in a tab, I don't see anything, is there something wrong with my code?

Below is my code
index.html file

<div class="etabs-tabgroup">
  <div class="etabs-tabs"></div>
   <div class="etabs-buttons"></div>
 </div>
<div class="etabs-views"></div>
<script>
    require('./renderer.js')
</script>

renderer.js file

const TabGroup = require("electron-tabs");
let tabGroup = new TabGroup();
 tabGroup.addTab({
    title: "server",
    src: "./demo.html",
    active: true,
    closable:false,
})

demo.html file

<body>
    <a onClick="window.open('http://www.baidu.com')">click me</a>
</body>
brrd commented

Thank you for the proper issue.

What I understand: electron-tab is working and you are able to display the content of demo.html in a tab. What you want to do is to open baidu.com in a new tab when the user clicks on the "click me" link.

Did I understand well?

Yes, sorry my native language is not English, I need to use Google Translate to communicate with you, the sentence may not be smooth, please forgive me.

Hi this is due popup blocker. Either allow Popups in renderer.js

let tabGroup = new TabGroup();
tabGroup.addTab({
  title: "server",
  src: "./demo.html",
  active: true,
  closable:false,
  webviewAttributes: {
    'allowpopups' : true
  }
})

or better approach to allow special popups in main process (see https://www.electronjs.org/docs/latest/api/window-open)- Therefore you have to make the new tab avaialble in main.
small sample like this
app.js

const {app, BrowserWindow, ipcMain, webContents} = require('electron');

app.on('ready', function () {
  const mainWindow = new BrowserWindow({
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
      webviewTag: true,
    }
  });
  mainWindow.loadURL('file://' + __dirname + '/electron-tabs.html');
  mainWindow.on('ready-to-show', function () {
    mainWindow.show();
    mainWindow.focus();
  });
  ipcMain.on('new-tab', (event, webContentsId) => {
    const tabWebContents = webContents.fromId(webContentsId)
    tabWebContents.setWindowOpenHandler(({ url}) => {
      if (url === 'http://www.baidu.com/') { // or remove this to allow all
        return {
          action: 'allow'
        }
      }
      return { action: 'deny' }
    })
  })
});

renderer.js

const TabGroup = require("../index");
const ipcRenderer = require("electron").ipcRenderer;
let tabGroup = new TabGroup();
let tab = tabGroup.addTab({
  title: "server",
  src: "./demo.html",
  active: true,
  closable:false,
  webviewAttributes: {
    allowpopups: true
  }
})
tab.once("webview-ready", t => ipcRenderer.send('new-tab', t.webview.getWebContentsId()))

Hope it helps you for your needs

@MCMicS @brrd
Thank you very much for your replies, this problem that has been bothering me for a long time has been solved, I can now open new windows in tabs, but at the same time I have another problem that I don't know how to solve. I want to create a new tab automatically after opening the window. Some code is already written, but I'm having trouble creating a new tab.

app.js

	const {getMsg} = require('./renderer');
    mainWindow = new BrowserWindow({
            frame: false, 
            show: false,
            icon: path.join(__dirname, './statics/logoBig.png'),
            webPreferences: {
                nodeIntegration: true,
                enableRemoteModule: true,
                contextIsolation: false,
                webviewTag: true
              }
        })
		mainWindow.webContents.on('new-window', (event, url, frameName, disposition) => {
        if (disposition === 'foreground-tab') {
            getMsg(url);
           event.preventDefault()  
           return false 
        }
    })

renderer.js

exports.getMsg = function (url) {
    tabGroup.addTab({
        title: 'new page',
        src: url,
        active: true,
    });
}

When I write the code like this, Electron will report an error when it starts up:
App threw an error during load
ReferenceError: document is not defined

I don't know why such an error is reported. Is there something wrong with my code? Thank you very much!

@MCMicS
Also, after I added the allowpopups property in renderer.js just now, I can open a new page, but I cannot listen to the event of opening a new window through mainWindow. Sorry, I am new to Electron, I am not very proficient, there may be more questions, thank you very much.

@puchenhui No problem. We try to help each. Th events fired for mainWindow are the Events of the tabs page itself. the listener should be added to the created webview or the webContents of the webview

Do you want to catch all window open and then open it in tabs instead new windows?

I can try to make some samples for you

a Running sample is here: https://github.com/MCMicS/electron-tabs-samples/tree/windowOpenAsTabs

It is based on electron-quickstart and use the recommended setWindowOpenHandler method.

There are three ways to open links (as active, in background or new window)

@MCMicS
Thank you very much for your reply and your code, maybe there is some problem with my expressive ability and I didn't express it clearly. I just tried to pull a new branch in your project to make changes, but because of network reasons, I have been unable to submit it, so I can only express it here for you.
Based on your project, I added a demo.html page and modified the two files main.js and renderer.js.

Add demo.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>demo01</title>
</head>
<body>
    <a onClick="window.open('https://www.electronjs.org/')" style="width: 100px;height: 30px;background-color: brown;color: aliceblue;">click me</a>
    
</body>
</html>

main.js

// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
const path = require('path')

function createWindow () {
  const mainWindow = new BrowserWindow({
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false, // needed for Electron >= 12.x
      webviewTag: true
    }
  });

  // and load the index.html of the app.
  mainWindow.maximize()
  mainWindow.show()
  mainWindow.loadFile('index.html')
  
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})

renderer.js

const TabGroup = require('electron-tabs')

let tabGroup = new TabGroup();

tabGroup.addTab({
    title: "Electron",
    src: "./demo.html",
    visible: true,
    active: true,
    webviewAttributes: {
        allowpopups: true,
        id:'foo',
    }
});

const webview = document.getElementById('foo')

webview.addEventListener('new-window', (e) => {
    tabGroup.addTab({
        title: "new page",
        src: e.url,
        active: true,
    });
    
});

When you run the project and click click me on the page, you will find that not only a tab is opened, but also a new window is opened, but in fact, I want to open only the tab instead of the window.

Yes this happens because the new-windowwill be first handled in main process and then anew Window is created. Then your Listener in renderer.js will be fired and a additional tab is opened. The events on renderer process are most async fired after the main process so it is not possible to prevent all Event.

I recommend to use the new-window(deprecated) or the new setWindowOpenHandler event in main process.

you can following to your main.js for deprecated new-window event (see https://github.com/MCMicS/electron-tabs-samples/blob/42b5eaae312efb14f5982d32191316a826edbc5b/main.js#L28)

    app.on('web-contents-created', function (webContentsCreatedEvent, contents) {
        if (contents.getType() === 'webview') {
            contents.on('new-window', function (newWindowEvent, url) {
                console.log('block - handled in renderer.js');
                newWindowEvent.preventDefault();
            });
        }
    });

But as said I would recommend to use the new setWindowOpenHandler in main process

see Sample: https://github.com/MCMicS/electron-tabs-samples/blob/openRenderer2/main.js#L28

@MCMicS
Thank you very much, when I used the method you provided, I achieved the effect I wanted, I am so happy, thank you for your patience and guidance. At this time, it should be night on your side, and it is 13:52 pm on my side.

@puchenhui nice to hear that it works. So this issue can be closed?

@MCMicS I see that new-window event has been deprecated. Will it be considered in subsequent iterations? If I delete it, do I have to use another method?

yes the second sample (https://github.com/MCMicS/electron-tabs-samples/blob/openRenderer2/main.js#L28) show the new handler. But then you have to use ipcRenderer

Try this branch: https://github.com/MCMicS/electron-tabs-samples/tree/openRenderer2

You have been amazing, solved all my problems, I have no problems now, thank you for your very patient guidance.

@MCMicS
Hello, I'm very sorry to bother you again. I encountered another problem in today's development and I don't know how to solve it. Would you like to help me? I would be very happy if you would help me!
The question is this: what should I do when I want to close the current tab after submitting information in an open tab?
My close event is written like this in the project
window.close();

Hi,
you can addEventListener for close event to the webview and then close the tab.

const tab = tabGroup.addTab(
    title: "Electron",
    src: "./demo.html",
    visible: true,
    active: true,
    webviewAttributes: {
        allowpopups: true,
        id:'foo',
    }
});
tab.webview.addEventListener('close', () => t.close())

@MCMicS
Thank you very much for your prompt reply, I have now closed the question.
May I keep in touch with you, please? I think if I encounter problems later, I can ask you. I don't see your email on your github homepage. I guess you don't want others to know. 20849192@qq.com This is my email. If it is convenient for you, I look forward to becoming friends with you.

I'm very sorry to bother you. I now have a new problem. I'm trying to open the tab again through the newly opened tab, but I'm finding no response

brrd commented

@puchenhui Please provide a code sample. Otherwise there is no way to answer your question.

@puchenhui Please provide a code sample. Otherwise there is no way to answer your question.

Thank you very much for your reply, I have resolved this issue and will now close this question