How to send search text to findInPage in Electron - electron

I try using contents.findInPage.
I have code in index.js:
const { webContents } = require('electron')
webContents.on('found-in-page', (event, result) => {
if (result.finalUpdate) webContents.stopFindInPage('clearSelection')
})
const requestId = webContents.findInPage('api')
console.log(requestId)
And code in component:
searchText(value){
this.query = value;
if (this.query.length > 0) {
ipcRenderer.send('api', this.query);
}
}
I wrote this code on the example of this answer.
But function find not work. I do not understand how I can send the text to be searched and the word to be searched.
How I can use function findInPage ?

sorry my answer to the other question wasn't clear enough (it was 2 years ago! I don't remember it that well but I'll give it a shot)
This is the documentation for webcontents and IPCMain
Here's what I have in my main.development.js (globals for the mainWindow and ipc communication):
mainWindow.on('focus', () => {
globalShortcut.register('CmdorCtrl+F', () => {
mainWindow.webContents.send('find_request', '');
});
});
mainWindow.webContents.on('found-in-page', (event, result) => {
if (result.finalUpdate) {
mainWindow.webContents.stopFindInPage('keepSelection');
}
});
ipcMain.on('search-text', (event, arg) => {
mainWindow.webContents.findInPage(arg);
});
mainWindow.on('blur', () => {
globalShortcut.unregister('CmdorCtrl+F');
});
Then I made an ipc listener for CmdorCtrl+F:
ipcRenderer.on('find_request', () => {
const modalbox = document.getElementById('modalbox');
if (modalbox.style.display === 'block') {
modalbox.style.display = 'none';
} else {
modalbox.style.display = 'block';
}
});
Then I made a modal searchbox:
const searchBox = (
<div
id="modalbox"
style={{ display: 'none', position: 'fixed', zIndex: 1 }}
><input type="text" onChange={Calls.searchPage} />
</div>);
The onchange sends the input text to the ipc listener:
static searchPage(event) {
ipcRenderer.send('search-text', event.target.value);
}
I hope this is enough for you to get it fixed :)

Related

contextmenu event not working in webview [Electron]

I'm using Electron with React+Typescript but this can be tested using just Electron+Javascript. The dom-ready event is working, I can see it in the console, but the contextmenu event is not triggered when I right click.
export default Main() {
const browserRef = useRef<WebViewProps>(null);
useEffect(() => {
const domReady = () => {
console.log("Dom is ready!");
};
const contextMenu = () => {
console.log("Context menu is working!");
};
if(browserRef.current) {
browserRef.current.addEventListener("dom-ready", domReady);
browserRef.current.addEventListener("contextmenu", contextMenu);
};
return () => {
if (browserRef.current) {
browserRef.current?.removeEventListener("dom-ready", domReady);
browserRef.current?.removeEventListener("contextmenu", contextMenu);
};
};
}, []);
return (
<webview ref={browserRef} src="https://www.google.com/" />
);
};
My contextmenu is not being called when I right click, this makes me think it doesn't fire when I right click but i don't know...

Using ipcRenderer with contextBridge

I want use contextBridge in my preload.js in electron. Every work as usual when when i send data from the ipcrender-to-ipcmain, but problem arises when i send response from ipcmain-to-ipcrenderer. I have gone through some of there solutions here but i still get the same results.
This is my mainjs code
ipcMain.on('users:load', async function () {
const users = await User.getAll();
win.webContents.send('users:get', users);
});
(async function () {
try {
const rows = await User.getAll();
console.log(rows.length);
win.webContents.send('users:total', rows.length);
} catch (error) {
return console.log(error);
}
})();
This is my preload.js
contextBridge.exposeInMainWorld('UserApi', {
loginuser: (user) => ipcRenderer.invoke('user:login', user),
totalusers: () =>
ipcRenderer.on('user:total', (e, res) => {
return res;
}),
loadUsers: () => {
ipcRenderer.send('users:load', () => {
ipcRenderer.on('users:get', (e, users) => {
return users;
});
});
},
});
In my preload.js ipcRenderer.invoke works perfectly but ipcRenderer.on does not. Any help will be appreciated.

Admob reward ads don't work on ios on Expo App

On App.js I have initialized AdMobRewarded as following:
if (Platform.OS === 'ios') {
AdMobRewarded.setAdUnitID('ca-app-pub-xxx/xxx');
} else {
AdMobRewarded.setAdUnitID('ca-app-pub-xxx/xxx');
}
And here is the class:
export default class App extends React.Component {
state = {
fontsLoaded: false,
};
render() {
const { fontsLoaded } = this.state;
if (!fontsLoaded) {
return (
<AppLoading
startAsync={fetchFonts}
onFinish={() => this.setState({ fontsLoaded: true })}
/>
);
}
return (
<Provider store={store}>
<AppContainer
ref={navigatorRef => {
NavigationService.setTopLevelNavigator(navigatorRef);
}}
/>
<CommonComponents />
</Provider>
);
}
}
Inside the CommonComponents I have put the listener for AdMobRewarded:
useEffect(() => {
AdMobRewarded.addEventListener('rewardedVideoDidRewardUser', () => {
setState({
hintModalVisible: true,
adIsLoading: false,
mainMenuVisible: false,
});
});
return () => {
AdMobRewarded.removeAllListeners();
};
}, []);
setState is actually not React setState, it's a redux action I have implemented:
const setStateAction = (obj, sceneName) => {
const type = sceneName ? `${sceneName}_SET_STATE` : 'SET_STATE';
return { ...obj, type };
};
Without the rewardedVideoDidRewardUser listener, calling setState does open the Modal and everything is fine.
hintModalVisible is used for Modal isVisible prop, which opens and closes the Modal.
On Android everything works as expected, but there is a strange behavior on iOS. The ad shows for a second and automatically closes, and the Hint Modal doesn't open.
Here is the function that requests and shows the ad. It is present in all screens of the app:
showHint = async () => {
const { setState } = this.props;
try {
setState({
mainMenuVisible: false,
});
await AdMobRewarded.requestAdAsync();
await AdMobRewarded.showAdAsync();
} catch (e) {
setState({
hintModalVisible: true,
mainMenuVisible: false,
});
}
};
It's an open source project, so you can the code here
The problem was with React Native Modal.
setState({
hintModalVisible: true,
adIsLoading: false,
mainMenuVisible: false,
});
This block of code should have closed the main menu modal and open the hint modal. But it seems that on IOS you cannot do this simultaneously. So this is how I handled it.
useEffect(() => {
AdMobRewarded.addEventListener('rewardedVideoDidRewardUser', () => {
setTimeout(() => {
setState({
hintModalVisible: true,
});
}, 1000);
});
return () => {
AdMobRewarded.removeAllListeners();
};
}, []);
And took the closing of main menu modal in the ad requesting function:
const requestHint = useCallback(async () => {
try {
setState({
mainMenuVisible: false,
});
await AdMobRewarded.requestAdAsync();
await AdMobRewarded.showAdAsync();
} catch (e) {
setState({
mainMenuVisible: false,
});
setTimeout(() => {
setState({
hintModalVisible: true,
});
}, 500);
}
}, [setState, hintModalVisible]);
So this is not concerned to the Admob Rewarded. It is more a React Native Modal bug. https://github.com/react-native-community/react-native-modal/issues/192

electron auto-update on click

I'm trying to make my electron app auto-updatable, and after searching on google I found nice guide that works. The only problem is that I want to create a button for when update is downloaded so that the user can decide when he wants to update and restart the app. So far I was able to put this code together
renderer.js
const electron = require('electron')
const ipcRenderer = electron.ipcRenderer
let lastMsgId = 0
window.quitAndInstall = function () {
electron.remote.autoUpdater.quitAndInstall()
}
ipcRenderer.on('console', (event, consoleMsg) => {
console.log(consoleMsg)
})
ipcRenderer.on('message', (event, data) => {
showMessage(data.msg, data.hide, data.replaceAll)
})
function showMessage(message, hide = true, replaceAll = false) {
const messagesContainer = document.querySelector('.messages-container')
const msgId = lastMsgId++ + 1
const msgTemplate = `<div id="${msgId}" class="alert alert-info alert-info-message animated fadeIn">${message}</div>`
if (replaceAll) {
messagesContainer.innerHTML = msgTemplate
} else {
messagesContainer.insertAdjacentHTML('afterbegin', msgTemplate)
}
if (hide) {
setTimeout(() => {
const msgEl = document.getElementById(msgId)
msgEl.classList.remove('fadeIn')
msgEl.classList.add('fadeOut')
}, 4000)
}
}
and this is my index.js where messages are storred
const electron = require('electron');
const {autoUpdater} = require('electron-updater');
const log = require('electron-log');
const appVersion = require('./package.json').version
// configure logging
autoUpdater.logger = log;
autoUpdater.logger.transports.file.level = 'info';
log.info('App starting...');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 1020,
height: 800,
});
mainWindow.loadURL('file://' +__dirname + '/public/index.html');
// Open the DevTools.
//mainWindow.webContents.openDevTools();
mainWindow.on('closed', function() {
mainWindow = null;
});
}
app.on('ready', createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', function() {
app.quit();
});
app.on('activate', function() {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow();
}
});
//-------------------------------------------------------------------
// Auto updates
//-------------------------------------------------------------------
const sendStatusToWindow = (text) => {
log.info(text);
if (mainWindow) {
mainWindow.webContents.send('console', `App version: ${appVersion}`)
mainWindow.webContents.send('message', { msg: `App version: ${appVersion}` })
}
};
autoUpdater.on('error', (ev, err) => {
mainWindow.webContents.send('message', { msg: `Error: ${err}` })
})
autoUpdater.once('checking-for-update', (ev, err) => {
mainWindow.webContents.send('message', { msg: 'Checking for updates' })
})
autoUpdater.once('update-available', (ev, err) => {
mainWindow.webContents.send('message', { msg: 'Update available. Downloading ⌛️', hide: false })
})
autoUpdater.once('update-not-available', (ev, err) => {
mainWindow.webContents.send('message', { msg: 'Update not available' })
})
autoUpdater.once('update-downloaded', (ev, err) => {
const msg = 'Update downloaded - <button onclick="quitAndInstall()">Restart</button>'
mainWindow.webContents.send('message', { msg, hide: false, replaceAll: true })
})
autoUpdater.checkForUpdates()
As you can see I added a button to call for function but it doesnt work. When I press the button nothing happens. If I remove button and just say auto.updater.quitAndInstall() it works. It auto close window and install new version. What am I missing?
I think it's that electron.remote.autoUpdater.quitAndInstall() doesn't work when run in the renderer.
In the docs it doesn't say anything against running it in the renderer process but I think sending a message back to the main process to run the quitAndInstall function would work.
Inside of the quitAndInstall function put this instead:
ipcRenderer.send('asynchronous-message', 'quitAndInstall');
Then in the main process put:
electron.ipcMain.on('asynchronous-message', function (evt, message) {
if (message == 'quitAndInstall') {
autoUpdater.quitAndInstall();
}
});

jquery close datepicker when input lose focus

I'm using datepicker inside my input , my last field is the datepicker input , after validating it i want to set focus on another input inside my form , but the problem is the datepicker is not closed even taht it does not have the focus..
how can I close the datepicker when i set the focus on another input field?
(I tried .datepicker("hide"); but it did not worked for me).
UPDATE:
this is my code:
$(function()
{ $( "#test_date" ).datepicker({
dateFormat: "dd/mm/yy"
});
});
//when i call my function:
$( "#test_date" ).datepicker("hide"); //---> this does not work!
Thank's In Advance.
Question Edited to work with the latest version of jqueryUI
JqueryUi auto-closes the datepicker when an element loses focus by user interaction, but not when changing focus with JS.
Where you are calling your function which removes focus from the input assigned a datepicker you also need to call:
$("#test_date ~ .ui-datepicker").hide();
This code is hiding the datepicker which is a sibling (~) of #test_date.
To be dynamic, and using the class assigned by jQueryui you can do:
$(".hasDatepicker").on("blur", function(e) { $(this).off("focus").datepicker("hide"); });
;(function() {
function eventOnFocusDP(e, par) {
if (par.ver == $.fn.jquery) {
if (this.tmr) clearTimeout(this.tmr);
par.lbl1.text(par.msgs[1]);
this.tmr = setTimeout(function() { par.inpNP.focus(); }, par.secs*1e3);
}
}
function eventOnFocusNP(e, par) {
if (par.ver == $.fn.jquery) {
par.lbl1.text(par.msgs[0]);
par.lbl2.text(par.msgs[2]);
}
}
function eventOnBlurNP(e, par) {
if (par.ver == $.fn.jquery) par.lbl2.text("");
}
function eventOnBlurHDP(e, par) {
if (par.ver == $.fn.jquery) {
$(this).off("focus").datepicker("hide");
}
}
function test(secs) {
this.ver = $.fn.jquery;
this.secs = (typeof secs)=='number'?secs:2;
this.msgs = [
'This will lose focus to box below '+this.secs+' seconds after it gains focus.',
'Losing focus in '+this.secs+' seconds!',
'Focus now on bottom box.'
];
this.inpDP = $('[name=datePicker]');
this.inpNP = $('[name=nextPicker]');
this.lbl1 = $('#dPMsg').text(this.msgs[0]);
this.lbl2 = $('#dPMsg2');
var par = this;
this.inpDP.datepicker({ dateFormat: "dd/mm/yy" })
.on('focus', function(e) { eventOnFocusDP.apply(this, [e, par]) });
this.inpNP.on('focus', function(e) { eventOnFocusNP.apply(this, [e, par]) });
this.inpNP.on('blur', function(e) { eventOnBlurNP.apply(this, [e, par]) });
$(document).on('blur', '.hasDatepicker', function(e) { eventOnBlurHDP.apply(this, [e, par]) });
return this;
}
function init() {
window.Test = test;
setTimeout(function() {
$(document).on('change', '.switcher, .switcher-ui', function(e) { if (window.Test) new Test(); });
$(jQueryUISwitcher).trigger('change');
}, 1e3);
}
if (document.readyState == "complete") init();
else jQuery(window).on('load', init);
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/JDMcKinstry/cfc32292cbbfa548fb9584db05b2b2fc/raw/4f16f7ee441dfb98aa166a2e84193b14574a46d1/jquery.switcher.js"></script>
<form action="javascript: void 0">
<input type="text" name="datePicker" id="dP" placeholder="mm/dd/yyyy" />
<label for="dP" id="dPMsg"></label>
<hr />
<input type="text" name="nextPicker" placeholder="tab to here" />
<label for="dP" id="dPMsg2"></label>
</form>
<hr />
<hr />
<hr />
Here's a modified solution that worked for me:
$(".hasDatepicker").each(function (index, element) {
var context = $(this);
context.on("blur", function (e) {
// The setTimeout is the key here.
setTimeout(function () {
if (!context.is(':focus')) {
$(context).datepicker("hide");
}
}, 250);
});
});
My version of js:
<script type="text/javascript"> $(function () {
$("#dtp1").on("dp.change", function (e) {
$('#dtp1').data("DateTimePicker").hide();
});
});
I hope it's help you
This worked for me:
$("#datepickerTo").datepicker({
onSelect: function () {
$(this).off( "focus" );
}
});

Resources