I am creating a custom modal dialog pop up box in Google Sheets via an Apps Script that is running an onEdit trigger. The idea is, the user clicks on a checkbox in some cell in a column. The trigger detects this edit, and calls a function that utilizes Apps Script UI and HtmlService class. This creates a simple modal dialog box that is built using some html. In the html, I have a button that calls window.print(). However, by calling it, nothing happens. I think it's because of the Same Origin Policy issue. The Html Service is likely using another domain name to launch the dialog box that's different than docs.google.com. So, window calls are likely problematic. Is there another way around this? How does one create customized printing for Google Apps? I've seen some variations of creating a pdf on the fly and printing those, but this seems really inefficient for the end user.
When the checkbox is clicked, the following function is called:
function openDialog() {
var html = HtmlService.createHtmlOutputFromFile('html') ;
SpreadsheetApp.getUi()
.showModalDialog(html, 'Print Receipt');
}
Here is the following html:
<!DOCTYPE html>
<html>
<head><base target="_top">
</head>
<body>
<img src="https://i.imgur.com/someimage.png" alt="Logo" width="100" height="100">
<h3>testing</h3>
<button onclick="print()">Print</button>
</body>
<script>
function print() {
window.print();
}
</script>
</html>');
You should consider renaming the print function to something else, say "printPage" else it may be invoking the native print API. Also, the extra parenthesis in the HTML maybe removed.
<!DOCTYPE html>
<html>
<head><base target="_top">
</head>
<body>
<img src="https://i.imgur.com/someimage.png" />
<h3>testing</h3>
<button onclick="printPage()">Print</button>
</body>
<script>
function printPage() {
window.print();
}
</script>
</html>
Related
I'm wondering if it is possible with google apps script to display the contents of one html file
return HtmlService.createHtmlOutputFromFile('0');
, within the file have a button, and when the button is pressed it will cause the screen to erase the current information and replace itself with a second html file
return HtmlService.createHtmlOutputFromFile('1');
. *note I am NOT wanting to link to a google document nor another webpage. Simply wanting to know if you can switch between html files within the same script document. If it is possible, my reasoning is to have a "menu" page that will display different topics and keep everthing in one document to be more organized.
It's possible to an extent. We will imply have a function to grab the information from an HTML file and then write it on the page. If you want to be able to navigate, then each .html file you have must have the following function in the <script></script>
function changePage(page) {
document.open(); //should work fine without this
document.write(page);
document.close(); //should work fine without this
}
this bit will handle changing the content of the entire page with new content. Now we need to get that content somehow. This will be done with a function inside of a .gs file in your Google Script that looks like this
function newPage(page) {
return HtmlService.createHtmlOutputFromFile(page).getContent()
}
Then inside of your page, whenever you want to change to a new one you need to have let's say a button:
<button onclick="google.script.run.withSuccessHandler(changePage).newPage('success')">Next Page</button>
In this case the newPage() function expects a string that will say what is the name of the html. So following the logic we will do
return HtmlService.createHtmlOutputFromFile('success').getContent()`
once we press that button and once that script finishes and returns the string of an HTML we want, we then use that to set the HTML of the current page.
Here is the full example of how it would work. You can navigate between Index.html and success.html
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function newPage(page) {
return HtmlService.createHtmlOutputFromFile(page).getContent()
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<script>
function changePage(page) {
document.open();
document.write(page);
document.close();
}
</script>
<body>
First Page
<button onclick="google.script.run.withSuccessHandler(changePage).newPage('success')">Next Page</button>
</body>
</html>
success.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<script>
function changePage(page) {
document.open();
document.write(page);
document.close();
}
</script>
<body>
It worked!
<button onclick="google.script.run.withSuccessHandler(changePage).newPage('Index')">First Page</button>
</body>
</html>
In Google chrome web browser
about:blank gives an empty page and F12 gives you access to Developer Tab.
Right-clicking a source in Elements gives Edit as Html Option in Developer Tab
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<div>
<button id="myBtn">Button</button>
</div>
<div id="demo">
</div>
<script>
document.getElementById("myBtn").addEventListener("click", function () {
document.getElementById("demo").innerHTML = "Hello World";
});
</script>
</body>
</html>
Above is a JavaScript snippet which I copied in. But JavaScript code is not executing. Is this work flow of real time html editing not supported in chrome ?
Your script would ran, if it existed there when the page gets loaded. After the page has loaded, no script tags will just run when edited in.
You could wrap everything inside the script tags into a function and call that I think, however.
One other, but kind of a useless and technical trick that might let you run JavaScript, by editing in elements after the page has loaded, looks something like this:
If you add that in to the loaded page's HTML, the script inside that input-element's onfocus-attribute should run. This, however, is no proper way to do anything other than Cross-Site Scripting (XSS).
You can use a template literal, document.write() at console. At about:blank page press F12, at console enter
var html = `<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<div>
<button id="myBtn">Button</button>
</div>
<div id="demo">
</div>
<script>
document.getElementById("myBtn").addEventListener("click", function () {
document.getElementById("demo").innerHTML = "Hello World";
});
</script>
</body>
</html>`;
document.write(html);
then click <button> element.
You can alternatively click Sources -> Snippets, type or paste the above javascript at center window, click right-pointing triangle at right panel to run javascript at Snippets. You can also right-click at Snippets panel to create a new snippet to run.
I am trying to integrate the JavaFx WebView into a Swing application. I am through with the implementation and am finally stuck on just one last missing piece. As part of the requirement, we do need the ability to print certain content. The content is all existing third party html / site and all works fine, except for the embedded print button on the pages. The Print button calls the window.print() and somehow that does not work and am unable to print. This is a needed feature for us and am out of ideas and need some help.
<!DOCTYPE html>
<html>
<body>
<p>Click the button to print the current page.</p>
<button onclick="myFunction()">Print this page</button>
<script>
function myFunction() {
window.print();
}
</script>
</body>
</html>
My web engine initialization is as follows:
Runnable r = () ->
{
WebView view = new WebView();
m_WebEngine = view.getEngine();
//view.setContextMenuEnabled(false);
getWebEngine().setOnStatusChanged(getStatusHandler());
getWebEngine().getLoadWorker().workDoneProperty().addListener(getProgressListener());
getWebEngine().getLoadWorker().exceptionProperty().addListener(getErrorListener());
getWebEngine().titleProperty().addListener(getTitleListener());
getWebEngine().getLoadWorker().stateProperty().addListener(getStatusListener());
getWebEngine().setOnAlert(event -> showAlert(event.getData()));
getWebEngine().setConfirmHandler(message -> showConfirm(message));
getWebEngine().setJavaScriptEnabled(true);
getJfxPanel().setScene(new Scene(view));
};
Platform.runLater(r);
I tried with alert, popup, prompt and all other handlers and just doesn't work.
Any help on handling this properly would be greatly appreciated.
I have a simple HTML code to print the page. Below is the code:
<!DOCTYPE html>
<html>
<head>
<script>
function printPage()
{
var w = window.open("http://www.sigmaaldrich.com/catalog/CofADocRequest.do?symbol=209104&LotNo=MKBP0842V&brandTest=SIGMA","_self");
window.focus();
window.print();
}
</script>
</head>
<body >
<input type="button" onclick="printPage()" value="print a div!" />
</body>
</html>
What the code does is, it displays a button, on clicking that button it calls a function. The function uses open() to open a new URL in the same page by using the “_self ” parameter.
As we can see in the code, the print() is being called after the call to open method. But in my browser IE11, the print pop is being shown befor loading the page.
Due to this I am not printing the correct page.
Can anybody help me on this.
The problem is that window refers to the current window, which is the original.
By opening a new window in self you replace the page, this is basically a redirect.
And if you open it via popup and print it as w.print() than you run into cross-origin security error.
You could use iframe to this with a proxy as shown here
How do print specific content inside the iframe
and
here
How do print specific content inside the iframe
I want to do something when the Modal Dialog (opened using showModalDialog()) is closed from the Spreadsheet App.
However I cannot find the reference of such event, in the API documents provided by Google. I found how to capture this event in a Alert Box, and by using this piece of code I can capture how the user closed the Alert Box, but I cannot use this in a Modal Dialog or a Modeless Dialog.
Is there a way to do this? Please kindly answer if you do.
This is not possible. And you should write your script in a way that this does not matter. For example, by showing a big action button in the dialog, making it clear to the user that he must click there for the script to continue.
But if you really want to make this happen, I guess you could use an HtmlService dialog that make regular async calls to the backend and each call waits for the next one before quitting, then if the "next" call does not get in time, it can assume the dialog got closed and execute your close procedure instead of simply quitting.
Here's an alternative solution. You can use google hosted jquery in the HTML (served by GAS) to track unload events when the page is closed. Here is some sample code:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<!-- page content -->
</body>
<!-- Minified google hosted jquery (see https://developers.google.com/speed/libraries/)-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- And here's where the magic happens -->
<script type="text/javascript">
$(document).ready( e => {
console.log('-- DOM ready --');
/** Add jquery unload listener */
$(window).on('unload', e => {
console.log("Invoked just before unload");
// do pre-unload stuff
});
});
</script>
</html>