'Open a new Window and Close the other one

I'm using IPCMain and IPCRenderer to switch into 3 different Window by opening the New Window and Closing the old one, I'm missing something and I'm having a hard time to figure it out.

Basically the user will select and click on the 3 category and the corresponding window will appear and the current one will close.

switch/case statement during selection:

$('.category a').on('click',function(){
    var cat = $(this).attr('href');
    const {
        ipcRenderer
    } = require('electron');

    switch (cat){
        case 'Window_1':
            ipcRenderer.send('newWindow', 'Window_1');
        break;
        case 'Window_2':
            ipcRenderer.send('newWindow', 'Window_2');
            break;
        case 'Window_3':
            ipcRenderer.send('newWindow', 'Window_3');
            break;
        default:
        break;
    }
});

and here is the code for showing the window

//some code for declaration of library and variables
//....
let {
    ipcMain
} = electron;

var correspondingWindow = null;
let mainWindow;

app.on('ready', function () {
    //Some code for Initialization of Main Window...
});

//function that will be call to show a new window and close the other one
ipcMain.on('newWindow', function (e, category) {

    var height;
    var width; 
    var address;

    //1: focus on the new window
    if (correspondingWindow) {
        correspondingWindow.focus();
        return;
    }

    //2: initialize the height, width and the file address of new Window
    switch (category){
        case 'Window_1':
            height = 600;
            width = 800;
            address = '../html/window_1.html';
        break;
        case 'Window_2':
            height = 600;
            width = 400;
            address = '../html/window_2.html';
            break;
        case 'Window_3':
            height = 600;
            width = 600;
            address = '../html/window_3.html';
            break;
        default:
        break;
    }

    //3: Initialization of new Window
    correspondingWindow = new BrowserWindow({ 
        height: height,
        width: width,
        minHeight: height,
        minWidth: width,
        icon: __dirname + iconPath,
        frame: false,
        backgroundColor: '#FFF',
        show: false
    });

    //4: Load HTML into Window
    correspondingWindow.loadURL(url.format({ 
        pathname: path.join(__dirname, directoryHtml + address),
        protocol: 'file',
        slashes: true
    }));

    //5: Initialization closing event of Window
    correspondingWindow.on('closed', function () {
        correspondingWindow = null;
    });

    //6: finally, show it once its ready
    correspondingWindow.once('ready-to-show', () => {
        correspondingWindow.show();
    });

    //7: Close the Main Window if possible, so that only one window will show at a time.
    if (mainWindow !== null) {
        mainWindow.close();
        mainWindow = null;
    }
});     

I am able to show the new Window and close the MainWindow but not at the second time by calling the ipcMain function again. Nothing's happen at the second time calling it.

I can make it work by making three different ipcMain function but I wanted to find a way to make it only one function.



Solution 1:[1]

From what I understand, you want to open a new BrowserWindow in place of the current BrowserWindow base on the clicked item and you want to shorten your code by making a single function that will do the trick.

Your close enough mate.

You actually don't need a conditional statement in your click event but you can if you choose, I notice your using JQuery so this will be your code on element clicked:

<script src="../js/renderer.js"></script> 
<script>window.$ = window.jQuery = require('jquery');</script>
<script>
$('.category a').on('click',function(){
    const {
        ipcRenderer
    } = require('electron');
    ipcRenderer.send('createBrowserWindow', $(this).attr('href'));

    const remote = require('electron').remote;
    remote.getCurrentWindow().close();
});
</script>

notice that I used the remote function.

here is your main.js

const {
    app,
    BrowserWindow
} = electron;
let {
    ipcMain
} = electron;
let mainWindow;

/*1*/
var toQuit = true; //very important
var category = 'window_1'; //default category

/*2*/
app.on('ready', function () {
    "use strict";
    createWindow(); //call this function to create a BrowserWindow on its lunch
});

app.on('closed', function () {
    "use strict";
    mainWindow = null;
});

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

/*3*/
function createWindow() {
    "use strict";
    var height;
    var width;
    var address;

    switch (category) {
        case 'window_1': 
            height = 600; //Initialize size of BrowserWindow
            width = 400; //Initialize size of BrowserWindow
            address = '../html/window_1.html'; //Initialize the address or the file location of your HTML
            break;
        case 'window_2':
            height = 600; //Initialize size of BrowserWindow
            width = 400; //Initialize size of BrowserWindow
            address = '../html/window_1.html'; //Initialize the address or the file location of your HTML
            break;
        case 'window_3':
            height = 600; //Initialize size of BrowserWindow
            width = 400; //Initialize size of BrowserWindow
            address = '../html/window_1.html'; //Initialize the address or the file location of your HTML
            break;
        default:
            break;
    }

    mainWindow = new BrowserWindow({ 
        height: height, //height and width of BrowserWindow
        width: width, //height and width of BrowserWindow
        minHeight: height, //minimum height and width of BrowserWindow, you can remove this if you want
        minWidth: width, //minimum height and width of BrowserWindow, you can remove this if you want
        icon: __dirname + iconPath,
        frame: false,
        backgroundColor: '#FFF',
        show: false
    });

    mainWindow.loadURL(url.format({ 
        pathname: path.join(__dirname, address), //file location of html
        protocol: 'file',
        slashes: true
    }));

    mainWindow.once('ready-to-show', () => {
        mainWindow.show(); //we only want to show it when its ready to avoid the FLASH WHITE during lunch of BrowserWindow
        mainWindow.focus(); //We make sure to focus on it after showing
    });

    /**The magic start here, **/
    mainWindow.on('closed', (e) => {
        e.preventDefault(); //We have to prevent the closed event from doing it.
        if(toQuit){ //if the value of toQuit is true, then we want to quit the entire application
            mainWindow = null;
            app.exit(); //quit or exit the entire application
        }else{
            mainWindow.hide(); //just hide the BrowserWindow and don't quit the entire application
            toQuit = true;  //reset the value of toQuit to true
        }
    });
}

//call this function from your any Javascript
ipcMain.on('createBrowserWindow', function (e, cat) {
    "use strict";
    category = cat; //get the category of window on which we want to show
    toQuit = false; //set the value to false, meaning we don't want to close the entire application but just hide the current BrowserWindow
    createWindow(); //call this function over and over again
}); 

how it happened:

  • We start a BrowserWindow with the default category which is the window1.

  • From your Javascript, we use ipcMain and ipcRenderer to call the function from your main.js and then we use remote to close the BrowserWindow but during the closed event we prevent it from quitting the BrowserWindow, instead we hide it.

Hope it helps.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Polar