Why Electron Remote not working on Electron-Tabs? - javascript

I get these errors in my Electron App Project:
webview logged from Dashboard.html(146): Uncaught TypeError: window.require is not a function
webview logged from dashboard.js(7): Uncaught ReferenceError: require is not defined
and further errors in other files that also use the require function.
Edit: To be more explicit: These errors occur in the tab files that should be opened. Not in the main Window.
These errors occured, because i updated my electron version to the latest one (was on 10 or 11 before) - but needed new version for a new npm module.
I already tried to add nodeIntegration: true, contextIsolation: false, enableRemoteModule: true to webpreferences of main browserwindow and also to each tab in electron-tabs and it didnt work.
I will show here only the main files, because showing the whole project is too much for the question text...
Index.html for Electron:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ExMeX Companion App</title>
<link rel="stylesheet" href="node_modules/electron-tabs/electron-tabs.css">
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<div class="etabs-tabgroup">
<div class="etabs-tabs"></div>
<div class="etabs-buttons"></div>
</div>
<div class="etabs-views"></div>
<script>
// 1. Require the module
const TabGroup = require("electron-tabs");
// 2. Define the instance of the tab group (container)
let tabGroup = new TabGroup({});
let tabDashboard = tabGroup.addTab({
title: "Dashboard",
src: "pages/Dashboard.html",
visible: true,
active: true,
webviewAttributes: {
webSecurity: false,
plugins: true,
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true
}
});
let webviewDashboard = tabDashboard.webview;
webviewDashboard.addEventListener('console-message', function(e) {
var srcFile = e.sourceId.replace(/^.*[\\\/]/, '');
if (srcFile == 'renderer_init.js') {
console.log("Electron Security warning hidden from console.");
} else {
console.log('webview logged from ' + srcFile + '(' + e.line + '): ' + e.message);
}
});
//implementation to get messages from other renderer windows
const {
remote,
ipcRenderer
} = require('electron');
var ExmexGUITabOpened = 'false';
var ExmexGUITabID = 0;
ipcRenderer.on("cardClickedExmexGUI", function(event, arg) {
if (ExmexGUITabOpened == 'false') {
//create new tab
console.log("Tab creation ExmexGUI");
let tabExmexGUI = tabGroup.addTab({
title: "Batch Orchestration",
src: "pages/BatchOrchestration.html",
visible: true,
active: true,
webviewAttributes: {
webSecurity: false,
plugins: true,
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true
}
});
ExmexGUITabOpened = 'true';
ExmexGUITabID = tabExmexGUI.id;
tabExmexGUI.on("close", (tab) => {
ExmexGUITabOpened = 'false';
ExmexGUITabID = 0;
});
let webview2 = tabExmexGUI.webview;
webview2.addEventListener('console-message', function(e) {
var srcFile = e.sourceId.replace(/^.*[\\\/]/, '');
if (srcFile == 'renderer_init.js') {
console.log("Electron Security warning hidden from console.");
} else {
console.log('webview logged from ' + srcFile + '(' + e.line + '): ' + e.message);
}
});
} else {
let activeExmexTab = tabGroup.getTab(ExmexGUITabID);
activeExmexTab.activate();
}
});
var ExmexConfigurationTabOpened = 'false';
var ExmexConfigurationTabID = 0;
ipcRenderer.on("cardClickedExmexConfiguration", function(event, arg) {
if (ExmexConfigurationTabOpened == 'false') {
//create new tab
console.log("Tab creation ExmexConfiguration");
let tabExmexConfig = tabGroup.addTab({
title: "ExMeX Configuration",
src: "pages/ExmexConfiguration.html",
visible: true,
active: true,
webviewAttributes: {
webSecurity: false,
plugins: true,
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true
}
});
ExmexConfigurationTabOpened = 'true';
ExmexConfigurationTabID = tabExmexConfig.id;
tabExmexConfig.on("close", (tab) => {
ExmexConfigurationTabOpened = 'false';
ExmexConfigurationTabID = 0;
});
let webview3 = tabExmexConfig.webview;
webview3.addEventListener('console-message', function(e) {
var srcFile = e.sourceId.replace(/^.*[\\\/]/, '');
if (srcFile == 'renderer_init.js') {
console.log("Electron Security warning hidden from console.");
} else {
console.log('webview logged from ' + srcFile + '(' + e.line + '): ' + e.message);
}
});
} else {
let activeExmexConfigTab = tabGroup.getTab(ExmexConfigurationTabID);
activeExmexConfigTab.activate();
}
});
var ExmexSourceFilterTabOpened = 'false';
var ExmexSourceFilterTabID = 0;
ipcRenderer.on("cardClickedSourceFilter", function(event, arg) {
if (ExmexSourceFilterTabOpened == 'false') {
//create new tab
console.log("Tab creation SourceFilter");
let tabSourceFilter = tabGroup.addTab({
title: "Filter Configuration",
src: "pages/FilterConfiguration.html",
visible: true,
active: true,
webviewAttributes: {
webSecurity: false,
plugins: true,
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true
}
});
ExmexSourceFilterTabOpened = 'true';
ExmexSourceFilterTabID = tabSourceFilter.id;
tabSourceFilter.on("close", (tab) => {
ExmexSourceFilterTabOpened = 'false';
ExmexSourceFilterTabID = 0;
});
let webview4 = tabSourceFilter.webview;
webview4.addEventListener('console-message', function(e) {
var srcFile = e.sourceId.replace(/^.*[\\\/]/, '');
if (srcFile == 'renderer_init.js') {
console.log("Electron Security warning hidden from console.");
} else {
console.log('webview logged from ' + srcFile + '(' + e.line + '): ' + e.message);
}
});
} else {
let activeExmexSourceFilterTab = tabGroup.getTab(ExmexSourceFilterTabID);
activeExmexSourceFilterTab.activate();
}
});
</script>
</body>
</html>
Main.js for electron
/*jshint esversion: 8 */
const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const path = require('path');
const url = require('url');
global.mainWindow = null;
/* Configuration for server is stored in these variables, accessible for all windows or tabs */
/*Test Config*/
const appversion = '0.5.0 Beta';
/*Live Config*/
global.user = 'Not available';
global.password = 'Not Set';
global.server = 'Not available';
global.serverPort = 0;
global.database = 'Not available';
global.serverInfoText = 'Server connection is not configured.';
global.installedExmexVersion = 'ExMeX | Core ? | App ' + appversion + '';
global.trustedConnectionOption = 'no';
global.userDeploy = '';
global.passwordDeploy = '';
global.serverDeploy = '';
global.databaseDeploy = '';
function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 1080,
height: 1000,
webPreferences: {
webviewTag: true,
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true
}
});
// Open the DevTools.
//mainWindow.webContents.openDevTools();
//remove the top menu from electron
//mainWindow.removeMenu();
// load the index.html of the app.
mainWindow.loadFile('index.html');
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
const {
ipcMain
} = require('electron'); // include the ipc module to communicate with render process ie to receive the message from render process
ipcMain.on("setUser", function(event, arg) {
global.user = arg;
});
ipcMain.on("setPassword", function(event, arg) {
global.password = arg;
});
ipcMain.on("setServer", function(event, arg) {
global.server = arg;
});
ipcMain.on("setServerPort", function(event, arg) {
global.serverPort = parseInt(arg, 10);
});
ipcMain.on("setDatabase", function(event, arg) {
global.database = arg;
});
ipcMain.on("setServerInfoText", function(event, arg) {
global.serverInfoText = arg;
});
ipcMain.on("setInstalledExmexVersion", function(event, arg) {
global.installedExmexVersion = 'ExMeX | Core ' + arg + ' | App ' + appversion + '';
});
ipcMain.on("setTrustedConnection", function(event, arg) {
global.trustedConnectionOption = arg;
});
const Store = require('electron-store');
Store.initRenderer();
Dashboard.html
This is the first Tab that should be opened, here the error occurs at the first time
<!doctype html>
<html lang="en" class="no-js">
<!-- <link rel="stylesheet" href="node_modules/electron-tabs/electron-tabs.css"> -->
<link rel="stylesheet" href="../css/dashboard.css">
<link rel="stylesheet" href="../css/sweetalert.css" />
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ExMeX Dashboard App</title>
</head>
<body>
<div class="grid-container-dashboard">
<header class="header">
<div class="header_server_info">
<p style="font-size:16px">Server</p>
<p style="font-size:12px" id="serverInfoText">No server connection.</p>
</div>
<!-- Button to open the serverConfigPopupWindow -->
<div class="header_server_connect">
<button id="myBtn" class="header_button"> Connect</button>
</div>
<div id="serverConfigPopupWindow" class="modal">
<div class="modal-content">
<!-- <span class="close">×</span> -->
<p style="font-size:20px ">Configure the server connection</p>
<br><br>
<div class="box">
<p class="item1">Server Name: </p> <input type="text" id="serverInputField" class="item2" placeholder="Server to connect">
</div>
<div class="box">
<p class="item1">Server Port: </p> <input type="text" id="serverPortInputField" class="item2" placeholder="Port to connect" value="1433">
</div>
<div class="box">
<p class="item1">Database Name: </p> <input type="text" id="databaseInputField" class="item2" placeholder="Your ExMeX database name">
</div>
<div class="box">
<p class="item1">Authentication Mode: </p>
<select class="item2" id="authenticationModeOptionField" onclick="showOrHideUserPWFields()">
<option>Windows Authentication</option>
<option>SQL Server Authentication</option>
</select>
</div>
<div class="box" id="userBox" style="visibility: hidden">
<p class="item1">User: </p> <input type="text" id="userInputField" class="item2" placeholder="Your user login name">
</div>
<div class="box" id="passwordBox" style="visibility: hidden">
<p class="item1">Password: </p> <input type="password" id="passwordInputField" class="item2" placeholder="Your password">
</div>
<br><br>
<textarea type="text" id="OutputTestServerConnection" name="FilterSPOutput" disabled rows="4" cols="70" style="resize: none;">Output will be shown after saving first filter.
</textarea>
<button id="testServerConfig" class="blue_button_big" onclick="testServerConfigFunction()">Connect</button>
<button id="cancelServerConfig" class="blue_button_big" onclick="cancelServerConfigFunction()">Cancel</button>
</div>
</div>
</header>
<aside class="sidenav">
<img src="../img/TedamohLogoFull.png" style=" display: block; margin-left: auto; margin-right: auto; width: 90%; height:80px; object-fit: contain;" alt="Logo" id="spin">
<ul class="sidenav_list">
<p style="font-size:20px">Quick Links</p>
<li class="sidenav_list-item" id="sidenav_Tedamoh" onclick="openTedamohHomepageInBrowser()">TEDAMOH</li>
<li class="sidenav_list-item" id="sidenav_Helpdesk" onclick="openHelpdeskInBrowser()">Helpdesk</li>
<li class="sidenav_list-item" id="sidenav_FAQ" onclick="openFAQInBrowser()">FAQ</li>
<li class="sidenav_list-item" id="sidenav_Documentation" onclick="openDocumentationInBrowser()">Documentation</li>
</ul>
</aside>
<main class="main">
<div class="main-header">
<div class="main-header_heading">
<img src="../img/ExMeX_Banner_Dashboard.png" style="width: 100%; height: 100%; " alt="ExMeX Dashboard">
</div>
<!-- <div class="main-header_updates">A powerful interface component for the Tedamoh ExMeX Framework. <br />We call it ExMeX Companion App!</div> -->
</div>
<div class="main-overview-dashboard">
<div class="overviewcard" id="cardIDExmexConfiguration">
<div class="overviewcard_icon"><img src="../img/dashboard_config.png" style="width:70px;height:70px;" alt="ConfigIcon"></div>
<div class="overviewcard_info">Exmex Configuration</div>
</div>
<div class="overviewcard" id="cardIDExmexGUI">
<div class="overviewcard_icon"><img src="../img/dashboard_threearrows.png" style="width:70px;height:70px;" alt="ThreeArrowIcon"></div>
<div class="overviewcard_info">Batch Orchestration</div>
</div>
<div class="overviewcard" id="cardIDFilterConfig">
<div class="overviewcard_icon"><img src="../img/dashboard_filter.png" style="width:70px;height:70px;" alt="FilterIcon"></div>
<div class="overviewcard_info">Filter Configuration</div>
</div>
<!-- future -->
<div class="overviewcard" id="cardIDFuture4" style=" pointer-events: none;">
<!-- <div class="overviewcard_icon">Icon</div>
<div class="overviewcard_info">Future feature</div> -->
</div>
<div class="overviewcard" id="cardIDFuture5" style=" pointer-events: none;">
<!-- <div class="overviewcard_icon">Icon</div>
<div class="overviewcard_info">Future feature</div> -->
</div>
<div class="overviewcard" id="cardIDFuture6" style=" pointer-events: none;">
<!-- <div class="overviewcard_icon">Icon</div>
<div class="overviewcard_info">Future feature</div> -->
</div>
<div class="overviewcard" id="cardIDFuture7" style=" pointer-events: none;">
<!-- <div class="overviewcard_icon">Icon</div>
<div class="overviewcard_info">Future feature</div> -->
</div>
<div class="overviewcard" id="cardIDFuture8" style=" pointer-events: none;">
<!-- <div class="overviewcard_icon">Icon</div>
<div class="overviewcard_info">Future feature</div> -->
</div>
<div class="overviewcard" id="cardIDFuture9" style=" pointer-events: none;">
<!-- <div class="overviewcard_icon">Icon</div> -->
<!-- <div class="overviewcard_info">Future feature</div> -->
</div>
<!-- future end -->
</div>
</main>
<footer class="footer">
<div class="footer_copyright">© 2019-2022 TEDAMOH GmbH</div>
<div class="footer_signature" id="footer_signature">ExMeX | Core ? | App ?</div>
</footer>
</div>
</body>
<!-- Insert this line above script imports -->
<script>
if (typeof module === 'object') {
window.module = module;
module = undefined;
}
</script>
<!-- normal script imports etc -->
<script src="../js/sweetalert.min.downloaded.js"></script>
<script src="../js/swal-messages.js"></script>
<!-- scripts for opening the links on the dashboard -->
<script>
const {
shell
} = window.require('electron');
function openDocumentationInBrowser() {
shell.openExternal("https://tedamoh.com/de/helpdesk/doc-faq/exmex-framework-book");
}
function openFAQInBrowser() {
shell.openExternal("https://tedamoh.com/de/helpdesk/doc-faq/frequently-asked-questions");
}
function openTedamohHomepageInBrowser() {
shell.openExternal("https://tedamoh.com/de/");
}
function openHelpdeskInBrowser() {
shell.openExternal("https://tedamoh.com/de/helpdesk/my-tickets");
}
</script>
<script src="../js/SQLConnectAndQuery.js"></script>
<script src="../js/dashboard.js"></script>
<!-- Insert this line after script imports -->
<script>
if (window.module) module = window.module;
actualizeVersionInfo('footer_signature');
</script>
</html>
Dashboard.js
This is the javascript for the first tab that should be opened.
/*jshint esversion: 8 */
// include the ipc module to communicate with main process.
const {
remote,
ipcRenderer
} = require('electron');
const Store = require('electron-store');
const store = new Store();
//if store file was never initialized, put defaults in it
if (store.get('serverConfigStore') == undefined) {
store.set('serverConfigStore', {
serverName: "Server to connect",
serverPort: 1433,
databaseName: "Your ExMeX database name",
authenticationMode: "Windows Authentication",
user: ""
});
}
// console.log(store.get('serverConfigStore').serverName);
// console.log(store.get('serverConfigStore').serverPort);
// console.log(store.get('serverConfigStore').databaseName);
let btnclick2 = document.getElementById('cardIDExmexGUI');
btnclick2.addEventListener('click', () => {
var arg2 = "secondparam";
//send the info to main process . we can pass any arguments as second param.
//ipcRenderer.send("btnclick", arg); // ipcRender.send will pass the information to main process
let mainWindowTest2 = remote.getGlobal('mainWindow');
if (mainWindowTest2) mainWindowTest2.webContents.send("cardClickedExmexGUI", arg2);
});
let btnclick3 = document.getElementById('cardIDExmexConfiguration');
btnclick3.addEventListener('click', () => {
var arg3 = "secondparam";
//send the info to main process . we can pass any arguments as second param.
//ipcRenderer.send("btnclick", arg); // ipcRender.send will pass the information to main process
let mainWindowTest3 = remote.getGlobal('mainWindow');
if (mainWindowTest3) mainWindowTest3.webContents.send("cardClickedExmexConfiguration", arg3);
});
let btnclick4 = document.getElementById('cardIDFilterConfig');
btnclick4.addEventListener('click', () => {
var arg4 = "secondparam";
//send the info to main process . we can pass any arguments as second param.
//ipcRenderer.send("btnclick", arg); // ipcRender.send will pass the information to main process
let mainWindowTest4 = remote.getGlobal('mainWindow');
if (mainWindowTest4) mainWindowTest4.webContents.send("cardClickedSourceFilter", arg4);
});
// Get the modal
var modal = document.getElementById("serverConfigPopupWindow");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks on the button, open the modal
btn.onclick = function() {
console.log(store.get('serverConfigStore').serverName);
console.log(store.get('serverConfigStore').serverPort);
console.log(store.get('serverConfigStore').databaseName);
console.log('The connect button clicked and onclickfunction starts');
modal.style.display = "block";
document.getElementById('OutputTestServerConnection').innerHTML = '';
document.getElementById('serverInputField').value = store.get('serverConfigStore').serverName;
document.getElementById('serverPortInputField').value = store.get('serverConfigStore').serverPort;
document.getElementById('databaseInputField').value = store.get('serverConfigStore').databaseName;
document.getElementById('userInputField').value = store.get('serverConfigStore').user;
//Make sure that authentication mode is one of the two possible values (instead a poweruser changes the config file manually...)
if (store.get('serverConfigStore').authenticationMode == "Windows Authentication" || store.get('serverConfigStore').authenticationMode == "SQL Server Authentication") {
document.getElementById('authenticationModeOptionField').value = store.get('serverConfigStore').authenticationMode;
} else {
document.getElementById('authenticationModeOptionField').value = "Windows Authentication";
}
showOrHideUserPWFields();
};
// When the user clicks on <span> (x), close the modal
// span.onclick = function() {
// modal.style.display = "none";
// };
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
};
function testServerConfigFunction() {
console.log("The test server config button was clicked.");
document.getElementById('OutputTestServerConnection').innerHTML = 'Wait for database response...';
const sql = require('mssql/msnodesqlv8');
var authOption = '' + document.getElementById('authenticationModeOptionField').value;
var trustedAuthBool = false;
if (authOption == 'Windows Authentication') {
trustedAuthBool = true;
}
var config;
//if trustedAuthBool is true, then WindowsAuthentification should be used (no User+PW)
if (trustedAuthBool) {
config = {
user: 'Win User',
password: 'Win User',
server: '' + document.getElementById('serverInputField').value,
database: '' + document.getElementById('databaseInputField').value,
port: parseInt(document.getElementById('serverPortInputField').value, 10),
options: {
trustedConnection: "yes"
}
};
}
//else SQL Server Authentification is available (User+PW needed)
else {
config = {
user: '' + document.getElementById('userInputField').value,
password: '' + document.getElementById('passwordInputField').value,
server: '' + document.getElementById('serverInputField').value,
database: '' + document.getElementById('databaseInputField').value,
port: parseInt(document.getElementById('serverPortInputField').value, 10)
};
}
// async function invocation - connect to db and try a query
queryDatabase(config, 'Select TOP(1) ReleaseVersion FROM [MetadataZone].[TEDAMOHExMeXRelease] Order by ReleaseInstalledDate DESC')
.then(result => {
var obj = JSON.parse(JSON.stringify(result.recordsets[0]));
console.log('Connection succesful! Your last installed ExMeX Version is: ' + obj[0].ReleaseVersion);
const {
remote,
ipcRenderer
} = require('electron');
ipcRenderer.send('setInstalledExmexVersion', '' + obj[0].ReleaseVersion);
var s = obj[0].ReleaseVersion;
if ((s.match(/2.12.*/)) || (s.match(/2.11.*/)) || (s.match(/2.10.*/)) || (s.match(/2.9.*/)) || (s.match(/2.8.*/)) || (s.match(/2.7.*/)) || (s.match(/2.6.*/)) || (s.match(/2.5.*/))) {
swal('Old ExMeX Version installed', 'On the connected database the latest installed ExMeX Version is lower than 2.13.* ! The companion App will not work stable in all features! Please install the latest ExMeX release.', 'warning');
}
//document.getElementById('footer_signature').innerHTML = "ExMeX Version: " + obj[0].ReleaseVersion;
actualizeVersionInfo('footer_signature');
})
.catch(err => {
sql.close();
console.log("A connection error happened");
document.getElementById('OutputTestServerConnection').innerHTML = 'An error occurred while trying to query the database. The detailed error message is: ' + err.message;
});
// async function invocation - connect to db and try a query
queryDatabase(config, 'SELECT SUSER_NAME() as LoggedInUser;')
.then(result => {
var obj = JSON.parse(JSON.stringify(result.recordsets[0]));
console.log('Connection succesful! Your SysUsername is: ' + obj[0].LoggedInUser);
const {
remote,
ipcRenderer
} = require('electron');
modal.style.display = "none";
var sysusername = obj[0].LoggedInUser;
saveServerConfigFunction(config, sysusername);
})
.catch(err => {
sql.close();
console.log("A connection error happened");
document.getElementById('OutputTestServerConnection').innerHTML = 'An error occurred while trying to query the database. The detailed error message is: ' + err.message;
});
}
//needed to delete some parts here for question length
I hope this is something where you can follow the code and give me an advise, on how to change my electron code to get the require function working on my tabs.
Best wishes!

Related

If I don't choose a file and press the send button, I will get a popup but it'll break any future popups

If I press Send ☞ without choosing a file, it'll say "No file selected." in a little Bootstrap warning alert but it seems to break all future alerts like file uploaded or file already exists on disk.
If I make an error alert like file already on disk, it'll work and won't break future alerts (meaning it won't stop alerts that popup in the future from showing).
So, why is the "No file selected" alert breaking other alerts?
In this clip, you can see me trying to make more than one of that alert but it just doesn't want to.
Here is my ejs file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Androp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
</head>
<body>
<div class="container-fluid">
<p>
<h1>Androp - Send to [...] MBP</h1>
</p>
<div class="input-group mb-3">
<button class="btn btn-outline-primary" type="button" onclick="send()">Send ☞</button>
<input type="file" class="form-control" id="fileSelector">
</div>
<div id="alerts"></div>
<div class="text-center">
<div id="spinny" class="spinner-border" style="width: 3rem; height: 3rem; visibility: hidden;"></div>
</div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io()
const engine = socket.io.engine
let maxSize = 0
let sending = false
socket.on("disconnect", (reason) => {
alert(`Disconnected from laptop! Check your internet or refresh the page. 💀 (${reason})`, "warning")
})
engine.on("close", reason => {
console.log(reason)
})
socket.emit("getMaxSize", (size) => {
return maxSize = size
})
const alert = (message, type) => {
const wrapper = document.createElement('div')
wrapper.innerHTML = [
`<div class="alert alert-${type} fade show" role="alert">`,
` <div>${message}</div>`,
'</div>'
].join('')
document.getElementById("alerts").append(wrapper)
return bootstrap.Alert.getOrCreateInstance(wrapper)
}
function send() {
if (sending) {
return false
}
sending = true
const file = document.getElementById("fileSelector").files[0] || false
function close(alert) {
setTimeout(() => {
alert.close()
}, 3500)
}
if (!file) { return close(alert("No files to upload.", "warning")) }
if (file.size >= maxSize) { return close(alert(`File is bigger than ${Math.round(maxSize / (1024 ** 2))} MB`, "danger")) }
document.getElementById("spinny").style.visibility = 'visible'
socket.timeout(10000).emit("upload", file, file.name, file.size, (err, status) => {
if(err) {
return close(alert("Could not contact laptop within 10s, laptop might be in sleep mode. 💀", "warning"))
}
document.getElementById("spinny").style.visibility = 'hidden'
sending = false
return close(alert(status.message, status.success ? "success" : "danger"))
})
}
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/#popperjs/core#2.11.5/dist/umd/popper.min.js"
integrity="sha384-Xe+8cL9oJa6tN/veChSP7q+mnSPaj5Bcu9mPX5F5xIGE0DVittaqT5lorf0EI7Vk"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/js/bootstrap.min.js"
integrity="sha384-ODmDIVzN+pFdexxHEHFBQH3/9/vQ9uori45z4JjnFsRydbmQbmL5t1tQ0culUzyK"
crossorigin="anonymous"></script>
</body>
</html>
You should move the flag sending = true when you actually plan to send after validation. I would also place sending = false right when callback returns, even if err
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Androp</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
</head>
<body>
<div class="container-fluid">
<p>
<h1>Androp - Send to [...] MBP</h1>
</p>
<div class="input-group mb-3">
<button class="btn btn-outline-primary" type="button" onclick="send()">Send ☞</button>
<input type="file" class="form-control" id="fileSelector">
</div>
<div id="alerts"></div>
<div class="text-center">
<div id="spinny" class="spinner-border" style="width: 3rem; height: 3rem; visibility: hidden;"></div>
</div>
</div>
<script src="https://cdn.socket.io/4.5.0/socket.io.min.js" integrity="sha384-7EyYLQZgWBi67fBtVxw60/OWl1kjsfrPFcaU0pp0nAh+i8FD068QogUvg85Ewy1k" crossorigin="anonymous"></script>
<script>
const socket = io()
const engine = socket.io.engine
let maxSize = 0
let sending = false
socket.on("disconnect", (reason) => {
alert(`Disconnected from laptop! Check your internet or refresh the page. 💀 (${reason})`, "warning")
})
engine.on("close", reason => {
console.log(reason)
})
socket.emit("getMaxSize", (size) => {
return maxSize = size
})
const alert = (message, type) => {
const wrapper = document.createElement('div')
wrapper.innerHTML = [
`<div class="alert alert-${type} fade show" role="alert">`,
` <div>${message}</div>`,
'</div>'
].join('')
document.getElementById("alerts").append(wrapper)
return bootstrap.Alert.getOrCreateInstance(wrapper)
}
function send() {
if (sending) {
return false
}
const file = document.getElementById("fileSelector").files[0] || false
function close(alert) {
setTimeout(() => {
alert.close()
}, 3500)
}
if (!file) {
return close(alert("No files to upload.", "warning"))
}
if (file.size >= maxSize) {
return close(alert(`File is bigger than ${Math.round(maxSize / (1024 ** 2))} MB`, "danger"))
}
sending = true
document.getElementById("spinny").style.visibility = 'visible'
socket.timeout(10000).emit("upload", file, file.name, file.size, (err, status) => {
if (err) {
return close(alert("Could not contact laptop within 10s, laptop might be in sleep mode. 💀", "warning"))
}
document.getElementById("spinny").style.visibility = 'hidden'
sending = false
return close(alert(status.message, status.success ? "success" : "danger"))
})
}
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
</body>
</html>

How to upload in a particular folder of google drive?

I am having html form and gs.code as shown below. Its working perfect but files are uploaded in root folder of google drive. I want my files to upload in particular folder. Please help me.
Even i want to know how to use uploadView.setIncludeFolders(true) to show particular folder and subfolder for selection and upload.
var config = {
DEVELOPER_KEY: 'xxxx',
UPLOAD_FOLDER_ID: 'xxx',
ACCEPTED_FOLDER_ID: 'xxx',
TIME_ZONE: "GMT",
DATE_FORMAT: "MM/dd/yyyy HH:mm:ss",
ALLOWED_FILES: [
// MimeType.BMP,
// MimeType.GIF,
MimeType.pdf
// MimeType.PNG,
// MimeType.SVG,
// MimeType.PDF,
// MimeType.CSS,
// MimeType.CSV,
// MimeType.HTML,
// MimeType.JAVASCRIPT,
// MimeType.PLAIN_TEXT,
// MimeType.RTF,
// MimeType.OPENDOCUMENT_GRAPHICS,
// MimeType.OPENDOCUMENT_PRESENTATION,
// MimeType.OPENDOCUMENT_SPREADSHEET,
// MimeType.OPENDOCUMENT_TEXT,
// MimeType.MICROSOFT_EXCEL,
// MimeType.MICROSOFT_EXCEL_LEGACY,
// MimeType.MICROSOFT_POWERPOINT,
// MimeType.MICROSOFT_POWERPOINT_LEGACY,
// MimeType.MICROSOFT_WORD,
// MimeType.MICROSOFT_WORD_LEGACY,
// MimeType.ZIP
]
}
function doGet( e ){
return HtmlService.createHtmlOutputFromFile( "Form.html" ).setSandboxMode( HtmlService.SandboxMode.IFRAME )
}
function getConfig(){
DriveApp.getRootFolder();
return {
DEVELOPER_KEY: config.DEVELOPER_KEY,
TOKEN: ScriptApp.getOAuthToken(),
UPLOAD_FOLDER_ID: config.UPLOAD_FOLDER_ID
}
}
function verifyUpload( upload ){
var acceptedFolder = DriveApp.getFolderById( config.ACCEPTED_FOLDER_ID ),
uploadFolder = DriveApp.getFolderById( config.UPLOAD_FOLDER_ID ),
date = Utilities.formatDate( new Date(), config.TIME_ZONE, config.DATE_FORMAT ),
success = [],
fail = [],
doc,
file,
name
for( var i = 0; i < upload.docs.length; i++ ){
doc = upload.docs[ i ];
file = DriveApp.getFileById( doc.id );
name = file.getName();
if ( config.ALLOWED_FILES.indexOf( doc.mimeType ) >= 0 ){
success.push( name );
acceptedFolder.addFile( file );
uploadFolder.removeFile( file );
} else {
fail.push( name );
}
file.setName( upload.username + " - " + date + " - " + name);
}
return {
success: success,
fail: fail
}
}
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
<style>
.app {
margin: 50px 0 0 30px;
}
.formholder {
background-color: #eee;
padding: 25px;
min-width: 400px;
max-width: 40%
}
input[type="text"] {
width: 300px;
}
</style>
</head>
<html>
<body>
<div class="app">
<div class="block formholder">
<div class="block form-group">
<label for="username">Name<span class="current">*</span>
</label>
<input type="text" id="username" class="width-100">
</div>
<div class="block">
<button class="blue" id="run-filepicker-interface">Choose File/s to Upload</button>
</div>
<div class="block">
</a>
</div>
</div>
<div class="block">
<div class="block" id="success-output"></div>
<div class="block error" id="error-output"></div>
</div>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
var fileUploadApp = {
config: {
DIALOG_DIMENSIONS: {
width: 600,
height: 425
}
},
init: function() {
google.script.run
.withSuccessHandler(fileUploadApp.setup)
.withFailureHandler(fileUploadApp.system.outputError)
.getConfig()
},
setup: function(config) {
$.extend(fileUploadApp.config, config)
gapi.load('picker', {
'callback': function() {
$('#run-filepicker-interface').click(fileUploadApp.runFilePickerInterface);
}
});
},
runFilePickerInterface: function(event) {
fileUploadApp.system.clearOutput()
var username = $("#username").val()
if (username) {
var config = fileUploadApp.config
$('#run-filepicker-interface').prop("disabled", false)
var uploadView = new google.picker.DocsUploadView()
uploadView.setIncludeFolders(false)
var picker = new google.picker.PickerBuilder()
.addView(uploadView)
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.hideTitleBar()
.setOAuthToken(config.TOKEN)
.setDeveloperKey(config.DEVELOPER_KEY)
.setCallback(fileUploadApp.pickerCallback)
.setSize(config.DIALOG_DIMENSIONS.width, config.DIALOG_DIMENSIONS.height)
.setOrigin(google.script.host.origin)
.setSelectableMimeTypes('application/vnd.google-apps.folder')
.build();
picker.setVisible(true);
} else {
fileUploadApp.system.outputError("Name is required.")
}
},
pickerCallback: function(data) {
switch (data.action) {
case google.picker.Action.PICKED:
var upload = {
username: $("#username").val(),
docs: []
}
$.each(data.docs, function(index, value) {
if (value.uploadState == "success")
upload.docs.push({
id: value.id,
mimeType: value.mimeType
})
})
google.script.run
.withSuccessHandler(fileUploadApp.verifyUploadSuccess)
.withFailureHandler(function(msg) {
$('#run-filepicker-interface').prop("disabled", false)
fileUploadApp.system.outputError(msg)
})
.verifyUpload(upload)
fileUploadApp.system.outputSuccess("Verifying uploaded files.")
break;
case google.picker.Action.CANCEL:
$('#run-filepicker-interface').prop("disabled", false)
break;
case google.picker.Action.LOADED:
// actions here
break;
}
},
verifyUploadSuccess: function(verifyResult) {
fileUploadApp.system.clearOutput()
if (verifyResult.success.length) {
fileUploadApp.system.outputSuccess(
"Fail:<br />" +
verifyResult.success.join("<br />")
)
}
if (verifyResult.fail.length) {
fileUploadApp.system.outputError(
"Success:<br />" +
verifyResult.fail.join("<br />")
)
}
$('#run-filepicker-interface').prop("disabled", false)
},
system: {
outputError: function(msg) {
$("#error-output").html(msg)
},
outputSuccess: function(msg) {
$("#success-output").html(msg)
},
clearOutput: function() {
$("#error-output, #success-output").html("")
}
}
}
function init() {
fileUploadApp.init()
}
</script>
<script src="https://apis.google.com/js/api.js?onload=init"></script>
</html>

Passing input variable between 2 HTML files using Electron with a login system

I am currently creating an app using Electron which will allow users to communicate with each other via socket.io. I have made a login screen which users input their email and password that they've registered with in order to access the main menu. In this case I have used a dummy account for testing purposes.
Here is the code for login.html along with the login_scripts.js file:
login.html:
<html>
<!--Required JQuery script-->
<script type="text/javascript" src="https://code.jquery.com/jquery-1.7.1.min.js"></script>
<head>
<!--Required meta tags-->
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval';" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--Required CSS-->
<link rel="stylesheet" href="loginstyles.css">
</head>
<body>
<!--Main login box with appropriate classes-->
<div id="Lbox" class="loginBox">
<div class="loginTitle">Welcome!</div>
<h5 id="Etext" class="emailText">EMAIL</h5>
<div id="Einptwrap" class="emailInputWrapper">
<input id="Einput" class="emailInput" type="email"
aria-label="Email" autocomplete="off"
spellcheck="false" maxlength="999">
</div>
<h5 id="Ptext" class="passwordText">PASSWORD</h5>
<div id="Pinptwrap" class="passwordInputWrapper">
<input id="Pinput" class="passwordInput" type="password"
aria-label="Password" autocomplete="off"
spellcheck="false" maxlength="999">
</div>
<button id="Lbutton" type="submit" class="loginButton" onclick="verify()">Login</button>
<h5 class="registerText">Don't have an account?</h5>
<a class="registerLink" href="Register.html">Register</a>
</div>
<!--SQL database connection scripts-->
<script src="./sql_scripts.js"></script>
<!--Login verification scripts-->
<script src="./login_scripts.js"></script>
</body>
</html>
And login_scripts.js:
function verify() {
const electron = require('electron').remote;
const { app, BrowserWindow, ipcMain } = require('electron').remote;
const { ipcRenderer } = require('electron');
//Variable declarations
var EinputFalse = document.getElementById("Einput").value == "";
var EinputTrue = document.getElementById("Einput") &&
document.getElementById("Einput").value;
var PinputFalse = document.getElementById("Pinput").value == "";
var PinputTrue = document.getElementById("Pinput") &&
document.getElementById("Pinput").value;
//Input field checks
if (EinputFalse) {
document.getElementById("Einptwrap").style.cssText =
"border-color: red";
document.getElementById("Etext").innerHTML =
"EMAIL - <small><i>This field is required<i><small>";
document.getElementById("Etext").style.cssText =
"color: red";
}
if (EinputTrue) {
document.getElementById("Einptwrap").style.cssText =
"border-color: #282e2e";
document.getElementById("Etext").innerHTML =
"EMAIL";
document.getElementById("Etext").style.cssText =
"color: #636d6d";
}
if (PinputFalse) {
document.getElementById("Pinptwrap").style.cssText =
"border-color: red";
document.getElementById("Ptext").innerHTML =
"PASSWORD - <small><i>This field is required<i><small>";
document.getElementById("Ptext").style.cssText =
"color: red";
}
if (PinputTrue) {
document.getElementById("Pinptwrap").style.cssText =
"border-color: #282e2e";
document.getElementById("Ptext").innerHTML =
"PASSWORD";
document.getElementById("Ptext").style.cssText =
"color: #636d6d";
}
//Check if both input fields are filled
if (EinputTrue && PinputTrue) {
var einput = document.getElementById("Einput").value;
var einputquery = "SELECT u_email FROM userdetails WHERE u_email = ?";
var pinput = document.getElementById("Pinput").value;
var pinputquery = "SELECT u_password FROM userdetails WHERE u_password = ?";
//SQL database queries
con.query(einputquery, [einput], function(err, result, fields) {
var eResString = JSON.stringify(result);
var eResStringRep = eResString.replace(/[{}":]/g, "").replace("[", "").replace("]", "");
var eResStringVar = eResStringRep.slice(7);
if (eResStringVar == einput) {
console.log("Query success. Result: " + eResStringVar);
}
else {
console.log("Error, query unsuccessful");
}
con.query(pinputquery, [pinput], function(err, result, fields) {
var pResString = JSON.stringify(result);
var pResStringRep = pResString.replace(/[{}";]/g, "").replace("[", "").replace("]", "");
var pResStringVar = pResStringRep.slice(11);
if (pResStringVar == pinput) {
console.log("Query success. Result: " + pResStringVar);
}
else {
console.log("Error, query unsuccessful");
}
//Child window (renderer process) creation in accordance with IF statement
if (eResStringVar == einput
&& pResStringVar == pinput) {
child = new BrowserWindow({
parent: Window,
modal: true,
show: false,
width: 400,
height: 600,
title: "Messaging Service",
center: true,
webPreferences: {
nodeIntegration: true,
defaultEncoding: "UTF-8",
}
})
child.loadFile('menu.html')
child.once('ready-to-show', () => {
child.show()
})
ipcMain.on('einput-send-req', (event, arg) => {
console.log(arg);
child.webContents.send('einput-send-act', arg);
});
ipcRenderer.send('einput-send-act', eResStringVar);
}
else if (eResStringVar != einput) {
document.getElementById("Einptwrap").style.cssText =
"border-color: red";
document.getElementById("Etext").innerHTML =
"EMAIL - <small><i>Email does not exist<i><small>";
document.getElementById("Etext").style.cssText =
"color: red";
}
else if (pResStringVar != pinput) {
document.getElementById("Pinptwrap").style.cssText =
"border-color: red";
document.getElementById("Ptext").innerHTML =
"PASSWORD - <small><i>Password does not match<i><small>";
document.getElementById("Ptext").style.cssText =
"color: red";
}
})
})
}
}
//Event listener for ENTER key
var lgnbox = document.getElementById("Lbox");
lgnbox.addEventListener("keyup", function(event) {
if (event.keyCode == 13) {
event.preventDefault();
verify();
}
});
And menu.html which is the renderer process which will be receiving the desired variable:
<html>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.7.1.min.js"></script>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval';" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="menustyles.css">
</head>
<body>
<script src="./node_modules/socket.io-client/dist/socket.io.js"></script>
<script src="./sql_scripts.js"></script>
<script>
const { ipcRenderer } = require('electron');
ipcRenderer.on('einput-send-act', (event, arg) => {
console.log(arg);
});
</script>
<script>
$(function () {
var socket = io('http://localhost:3000');
});
</script>
<div class="menuHeader">
<button class="settingsButton">Settings</button>
</div>
<ul id="users"></ul>
</body>
</html>
The program compares the input variable to the variable in my SQL database (using phpMyAdmin) via a query and returns the edited and "sliced" variable. In this case, I am testing to see whether the email variable will be passed on using ipcMain and ipcRenderer.
However, this has not worked but there also doesn't seem to be any errors when running the program. I have tried putting the ipcMain function inside of main.js which is the main startup file for Electron and declaring the child window within main.js, but this causes a plethora of errors to crop up.
The code for main.js is here:
//Initialising modules
const electron = require('electron');
const { app, BrowserWindow, ipcMain } = require('electron');
//Server setup and initialisation
const server = require('./serversetup.js').server;
const port = process.env.port || 3000;
server.run(port);
//Creating application window
function createWindow() {
win = new BrowserWindow({
width: 700,
height: 800,
backgroundColor: "#343c3c",
center: true,
title: "Messaging Service",
webPreferences: {
nodeIntegration: true,
defaultEncoding: "UTF-8",
}
})
win.once('ready-to-show', () => {
win.show()
})
win.loadFile('login.html')
win.on('closed', () => {
win = null
})
}
//Application startup processes
app.on('ready', () => {
createWindow()
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win === null) {
createWindow()
}
})
I would like to know what I am doing wrong and whether there is a way to fix this issue.
TL;DR I am trying to pass a variable from a process which uses a login system (login.html) to another process (menu.html), using Electron.
You can use electron's ipc API to communicate between multiple windows.

How do I read the file name and process my html tag?

I tried to make music player with electron and jquery. What I want to do as a first step is open menu, click file and then music title to be changed. I succeeded file open menu but cannot go forward to next step.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>chplayer</title>
<link rel="stylesheet" href=""/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<h1>CH Music Player</h1>
<h1 id="musictitle">[Music Title]</h1>
<h3 id="artistname">[artist name]</h3>
<image src="http://placehold.it/150X90" id="albumimage"/>
<div>
<input type="range" id="musicProgress" min="0" max="100">
</div>
<table>
<tr>
<td>
<button id="previousButton"></button>
<button id="pauseButton"></button>
<button id="nextButton"></button>
</td>
<td>
<input type="range" id="volumeProgess" min="0" max="100">
</td>
</tr>
</table>
</body>
<script>
</script>
</html>
index.html
const { app, BrowserWindow, Menu, dialog } = require('electron')
const path = require('path')
const fs = require('fs')
let win
function createWindow () {
win = new BrowserWindow({ width: 800, height: 600 })
var menu = Menu.buildFromTemplate([
{
label: 'Folders',
accelerator: 'CommandOrControl+o',
click: function () {
openFolderDialog()
}
},
{
label: 'Info',
click: function() {
dialog.showMessageBox(win,{type: "none", title: "Information",
message: "github link"},(response,checkboxChecked) => {
console.log(response)
})
}
}
])
Menu.setApplicationMenu(menu)
win.loadFile('index.html')
win.webContents.openDevTools()
win.on('closed', () => {
win = null
})
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win === null) {
createWindow()
}
})
function openFolderDialog() {
dialog.showOpenDialog(win, {
properties: ['openFile']
} , filepath => {
if (filepath) {
fs.writeFile('path.txt', filepath, function (err, data) {
if (err) console.log(err);
});
scanFile(filepath)
}
})
}
function scanFile(filepath) {
if(!filepath || filepath[0] == 'undefined') return;
console.log(filepath[0])
fs.readFile(filepath[0],"utf8", (err,data) => {
if(err) console.log(err);
var arr = [];
if (data.substr(-4) === '.mp3' || data.substr(-4) === '.m4a'
|| data.substr(-5) === '.webm' || data.substr(-4) === '.wav'
|| data.substr(-4) === '.aac' || data.substr(-4) === '.ogg'
|| data.substr(-5) === '.opus') {
arr.push(data);
}
var objToSend = {};
objToSend.files = arr;
objToSend.path = filepath;
win.webContents.send('selected-files', objToSend)
})
}
main.js
How should I read the file name from file open menu and change h1 musictitle tag?
Seems like there are a few things going on here. Are you trying to allow the user to select one file or a directory of files? Your function is named "openFolderDialog" but you are specifying "openfile". See the showOpenDialog documentation for the various options. On OSX you can specify both: [openfile, openDirectory] but on Windows that doesn't work and openDirectory takes precedence.
If you want the user to select only one file at a time, then your "scanFile" function isn't needed – you can use filters (no period, case doesn't matter):
filters: [
{name: 'Audio', extensions: ['mp3', 'ogg', 'm4a']},
]
Check out this article: Working with HTML5 Audio in Electron
To change the H1 text, since you are already using jquery you could do
$('#musictitle').text(sometext);

TypeError: Cannot read property 'getTime' of undefined

I am getting a problem when trying to use DayPilot Calendar in angularjs.
https://code.daypilot.org/63034/angularjs-event-calendar-open-source
When I downloaded sources and use it it was not working and throwing error
angular.js:9563 TypeError: Cannot read property 'getTime' of undefined
at loadEvents (daypilot-all.min.js:11)
at update (daypilot-all.min.js:11)
at Object.fn (daypilot-all.min.js:11)
at h.$digest (angular.js:12031)
at h.$apply (angular.js:12279)
at g (angular.js:7991)
at C (angular.js:8196)
at XMLHttpRequest.y.onreadystatechange (angular.js:8137)
Source code of the downloaded code is
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>DayPilot: AngularJS Event Calendar</title>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script src="js/daypilot/daypilot-all.min.js" type="text/javascript"></script>
<!-- helper libraries -->
<script src="js/jquery/jquery-1.9.1.min.js" type="text/javascript"></script>
<!-- daypilot libraries -->
<script src="js/daypilot/daypilot-all.min.js" type="text/javascript"></script>
<link type="text/css" rel="stylesheet" href="media/layout.css" />
</head>
<body>
<div id="header">
<div class="bg-help">
<div class="inBox">
<hr class="hidden" />
</div>
</div>
</div>
<div class="shadow"></div>
<div class="hideSkipLink">
</div>
<div class="main">
<div ng-app="main" ng-controller="DemoCtrl" >
<div style="float:left; width: 160px">
<daypilot-navigator id="navi" daypilot-config="navigatorConfig" ></daypilot-navigator>
</div>
<div style="margin-left: 160px">
<div class="space">
<button ng-click="showDay()">Day</button>
<button ng-click="showWeek()">Week</button>
</div>
<daypilot-calendar id="day" daypilot-config="dayConfig" daypilot-events="events" ></daypilot-calendar>
<daypilot-calendar id="week" daypilot-config="weekConfig" daypilot-events="events" ></daypilot-calendar>
</div>
</div>
<script>
var app = angular.module('main', ['daypilot']).controller('DemoCtrl', function($scope, $timeout, $http) {
$scope.events = [];
$scope.navigatorConfig = {
selectMode: "day",
showMonths: 3,
skipMonths: 3,
onTimeRangeSelected: function(args) {
$scope.weekConfig.startDate = args.day;
$scope.dayConfig.startDate = args.day;
loadEvents();
}
};
$scope.dayConfig = {
viewType: "Day",
onTimeRangeSelected: function(args) {
var params = {
start: args.start.toString(),
end: args.end.toString(),
text: "New event"
};
$http.post("backend_create.php", params).success(function(data) {
$scope.events.push({
start: args.start,
end: args.end,
text: "New event",
id: data.id
});
});
},
onEventMove: function(args) {
var params = {
id: args.e.id(),
newStart: args.newStart.toString(),
newEnd: args.newEnd.toString()
};
$http.post("backend_move.php", params);
},
onEventResize: function(args) {
var params = {
id: args.e.id(),
newStart: args.newStart.toString(),
newEnd: args.newEnd.toString()
};
$http.post("backend_move.php", params);
},
onEventClick: function(args) {
var modal = new DayPilot.Modal({
onClosed: function(args) {
if (args.result) { // args.result is empty when modal is closed without submitting
loadEvents();
}
}
});
modal.showUrl("edit.php?id=" + args.e.id());
}
};
$scope.weekConfig = {
visible: false,
viewType: "Week",
onTimeRangeSelected: function(args) {
var params = {
start: args.start.toString(),
end: args.end.toString(),
text: "New event"
};
$http.post("backend_create.php", params).success(function(data) {
$scope.events.push({
start: args.start,
end: args.end,
text: "New event",
id: data.id
});
});
},
onEventMove: function(args) {
var params = {
id: args.e.id(),
newStart: args.newStart.toString(),
newEnd: args.newEnd.toString()
};
$http.post("backend_move.php", params);
},
onEventResize: function(args) {
var params = {
id: args.e.id(),
newStart: args.newStart.toString(),
newEnd: args.newEnd.toString()
};
$http.post("backend_move.php", params);
},
onEventClick: function(args) {
var modal = new DayPilot.Modal({
onClosed: function(args) {
if (args.result) { // args.result is empty when modal is closed without submitting
loadEvents();
}
}
});
modal.showUrl("edit.php?id=" + args.e.id());
}
};
$scope.showDay = function() {
$scope.dayConfig.visible = true;
$scope.weekConfig.visible = false;
$scope.navigatorConfig.selectMode = "day";
};
$scope.showWeek = function() {
$scope.dayConfig.visible = false;
$scope.weekConfig.visible = true;
$scope.navigatorConfig.selectMode = "week";
};
loadEvents();
function loadEvents() {
// using $timeout to make sure all changes are applied before reading visibleStart() and visibleEnd()
$timeout(function() {
var params = {
start: $scope.week.visibleStart().toString(),
end: $scope.week.visibleEnd().toString()
}
$http.post("backend_events.php", params).success(function(data) {
$scope.events = data;
});
});
}
});
</script>
</div>
<div class="clear">
</div>
</body>
</html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
i am still confused why this problem is occurring again and again
You should check the response returned by "backend_events.php". DayPilot expects an array of events in JSON format. If there is any server-side error in the script the response will return an error message instead.
Most likely, there is a problem with permissions on the server side - the PHP script needs read/write permissions for daypilot.sqlite file which is in the application root.

Categories

Resources