Google script automatically close UI after clicking link button - user-interface

I have a script that opens a UI which is used to open another spreadsheet
When I click to open the link I would like the UI to close automatically if possible.
function ServiceSetServiceSheets(){
var html = "<a href='https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxx'; target='_blank'>Open The Service Sheet</a>";
var anchor = HtmlService.createHtmlOutput(html).setSandboxMode(HtmlService.SandboxMode.IFRAME).setHeight(60).setWidth(150);
SpreadsheetApp.getUi().showModalDialog(anchor,"Click the link to")
}
Can anyone help please?

In your situation, how about using google.script.host.close() as follows? Please modify your script as follows.
From:
var html = "<a href='https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxx'; target='_blank'>サービス シートを開く";
To:
var html = "<a href='https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxx'; target='_blank' onclick='google.script.host.close()'>サービス シートを開く";
By this modification, when you click the link, the dialog is closed by google.script.host.close().

Example:
Execute launchClickAndClose();
function launchClickAndClose() {
let html = '<!DOCTYPE html><html><head><base target="_top"></head><body>';
html += '<input type="button" value="Doit" onClick="doSomething();" />';
html += '<script>function doSomething(){google.script.run.withSuccessHandler(() => {google.script.host.close()}).doitontheserver();}</script>'
html += '</body></html>';
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html), "Close Automatically")
}
function doitontheserver() {
const ss = SpreadsheetApp.getActive();
ss.toast("Doing it");
return;
}

Related

Laravel file manager standalone iframe to input

I don't know how can't I find any examples on this, like no one used it before..
I want to open file manager in iframe and on images click to insert image url to input. Their example opens new window...
I am using laravel file manager standalone button to change avatar image but by their docs I can do it like this:
<div class="input-group">
<span class="input-group-btn">
<a id="lfm" data-input="thumbnail" data-preview="holder" class="btn btn-primary">
<i class="fa fa-picture-o"></i> Choose
</a>
</span>
<input id="thumbnail" class="form-control" type="text" name="filepath">
</div>
<img id="holder" style="margin-top:15px;max-height:100px;">
And calling $('#lfm').filemanager('image');
Which works but it opens new window because this is .filemanager()
(function( $ ){
$.fn.filemanager = function(type, options) {
type = type || 'file';
this.on('click', function(e) {
var route_prefix = (options && options.prefix) ? options.prefix : '/laravel-filemanager';
localStorage.setItem('target_input', $(this).data('input'));
localStorage.setItem('target_preview', $(this).data('preview'));
window.open(route_prefix + '?type=' + type, 'FileManager', 'width=900,height=600');
window.SetUrl = function (url, file_path) {
//set the value of the desired input to image url
var target_input = $('#' + localStorage.getItem('target_input'));
target_input.val(file_path).trigger('change');
//set or change the preview image src
var target_preview = $('#' + localStorage.getItem('target_preview'));
target_preview.attr('src', url).trigger('change');
};
return false;
});
}
})(jQuery);
Now changing:
window.open(route_prefix + '?type=' + type, 'FileManager', 'width=900,height=600');
To:
$('iframe').attr('src', route_prefix + '?type=' + type);
Will append filemanager to iframe as I want but when I click on image inside iframe it opens image in new tab as it is setting new url but skipping the script?
I think that I could get image url if it was opening in iframe but it is not...
Do you maybe know how to do this?
Thanks
I found out answer for my needs, not finished one tho but it works as needed:
Open up script.js from vendor/..../js folder and change useFIle function if/else statement where it looks up are you using any editor (cke,mce,etc..) and if not it just opens image in new window.
I remove that option and added this:
// parent.document.getElementById(field_name).value = url;
var target_input = parent.document.getElementById(localStorage.getItem('target_input'));
target_input.value = url;
//set or change the preview image src
var target_preview = parent.document.getElementById(localStorage.getItem('target_preview'));
target_preview.src = url;
From my question you can see jquery-plugin for opening laravel-filemanager into iframe and adding elements to localstorage.
I used that elements from localstorage in iframe to append url in input and display image in holder.
Now I will change this a little bit, since I wan't to leave this script as it is for full manager page on that url. I will just add another field as uri to be able to say this url is opened by iframe and use someOtherFUnction instead of useFile function by default.

Google App Scripts Function to Open URL [duplicate]

Is there a way to write a google apps script so when ran, a second browser window opens to www.google.com (or another site of my choice)?
I am trying to come up with a work-around to my previous question here:
Can I add a hyperlink inside a message box of a Google Apps spreadsheet
This function opens a URL without requiring additional user interaction.
/**
* Open a URL in a new tab.
*/
function openUrl( url ){
var html = HtmlService.createHtmlOutput('<html><script>'
+'window.close = function(){window.setTimeout(function(){google.script.host.close()},9)};'
+'var a = document.createElement("a"); a.href="'+url+'"; a.target="_blank";'
+'if(document.createEvent){'
+' var event=document.createEvent("MouseEvents");'
+' if(navigator.userAgent.toLowerCase().indexOf("firefox")>-1){window.document.body.append(a)}'
+' event.initEvent("click",true,true); a.dispatchEvent(event);'
+'}else{ a.click() }'
+'close();'
+'</script>'
// Offer URL as clickable link in case above code fails.
+'<body style="word-break:break-word;font-family:sans-serif;">Failed to open automatically. Click here to proceed.</body>'
+'<script>google.script.host.setHeight(40);google.script.host.setWidth(410)</script>'
+'</html>')
.setWidth( 90 ).setHeight( 1 );
SpreadsheetApp.getUi().showModalDialog( html, "Opening ..." );
}
This method works by creating a temporary dialog box, so it will not work in contexts where the UI service is not accessible, such as the script editor or a custom G Sheets formula.
You can build a small UI that does the job like this :
function test(){
showURL("http://www.google.com")
}
//
function showURL(href){
var app = UiApp.createApplication().setHeight(50).setWidth(200);
app.setTitle("Show URL");
var link = app.createAnchor('open ', href).setId("link");
app.add(link);
var doc = SpreadsheetApp.getActive();
doc.show(app);
}
If you want to 'show' the URL, just change this line like this :
var link = app.createAnchor(href, href).setId("link");
EDIT : link to a demo spreadsheet in read only because too many people keep writing unwanted things on it (just make a copy to use instead).
EDIT : UiApp was deprecated by Google on 11th Dec 2014, this method could break at any time and needs updating to use HTML service instead!
EDIT :
below is an implementation using html service.
function testNew(){
showAnchor('Stackoverflow','http://stackoverflow.com/questions/tagged/google-apps-script');
}
function showAnchor(name,url) {
var html = '<html><body>'+name+'</body></html>';
var ui = HtmlService.createHtmlOutput(html)
SpreadsheetApp.getUi().showModelessDialog(ui,"demo");
}
There really isn't a need to create a custom click event as suggested in the bountied answer or to show the url as suggested in the accepted answer.
window.open(url)1 does open web pages automatically without user interaction, provided pop- up blockers are disabled(as is the case with Stephen's answer)
openUrl.html
<!DOCTYPE html>
<html>
<head>
<base target="_blank">
<script>
const url1 ='https://stackoverflow.com/a/54675103';
const winRef = window.open(url1);
winRef ? google.script.host.close() : window.alert('Allow popup to redirect you to '+url1) ;
window.onload=function(){document.getElementById('url').href = url1;}
</script>
</head>
<body>
Kindly allow pop ups</br>
Or <a id='url'>Click here </a>to continue!!!
</body>
</html>
code.gs:
function modalUrl(){
SpreadsheetApp.getUi()
.showModalDialog(
HtmlService.createHtmlOutputFromFile('openUrl').setHeight(50),
'Opening StackOverflow'
)
}
Google Apps Script will not open automatically web pages, but it could be used to display a message with links, buttons that the user could click on them to open the desired web pages or even to use the Window object and methods like addEventListener() to open URLs.
It's worth to note that UiApp is now deprecated. From Class UiApp - Google Apps Script - Google Developers
Deprecated. The UI service was deprecated on December 11, 2014. To
create user interfaces, use the HTML service instead.
The example in the HTML Service linked page is pretty simple,
Code.gs
// Use this code for Google Docs, Forms, or new Sheets.
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.createMenu('Dialog')
.addItem('Open', 'openDialog')
.addToUi();
}
function openDialog() {
var html = HtmlService.createHtmlOutputFromFile('index')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.showModalDialog(html, 'Dialog title');
}
A customized version of index.html to show two hyperlinks
<a href='http://stackoverflow.com' target='_blank'>Stack Overflow</a>
<br/>
<a href='http://meta.stackoverflow.com/' target='_blank'>Meta Stack Overflow</a>
Building of off an earlier example, I think there is a cleaner way of doing this. Create an index.html file in your project and using Stephen's code from above, just convert it into an HTML doc.
<!DOCTYPE html>
<html>
<base target="_top">
<script>
function onSuccess(url) {
var a = document.createElement("a");
a.href = url;
a.target = "_blank";
window.close = function () {
window.setTimeout(function() {
google.script.host.close();
}, 9);
};
if (document.createEvent) {
var event = document.createEvent("MouseEvents");
if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1) {
window.document.body.append(a);
}
event.initEvent("click", true, true);
a.dispatchEvent(event);
} else {
a.click();
}
close();
}
function onFailure(url) {
var div = document.getElementById('failureContent');
var link = 'Process';
div.innerHtml = "Failure to open automatically: " + link;
}
google.script.run.withSuccessHandler(onSuccess).withFailureHandler(onFailure).getUrl();
</script>
<body>
<div id="failureContent"></div>
</body>
<script>
google.script.host.setHeight(40);
google.script.host.setWidth(410);
</script>
</html>
Then, in your Code.gs script, you can have something like the following,
function getUrl() {
return 'http://whatever.com';
}
function openUrl() {
var html = HtmlService.createHtmlOutputFromFile("index");
html.setWidth(90).setHeight(1);
var ui = SpreadsheetApp.getUi().showModalDialog(html, "Opening ..." );
}
I liked #Stephen M. Harris's answer, and it worked for me until recently. I'm not sure why it stopped working.
What works for me now on 2021-09-01:
function openUrl( url ){
Logger.log('openUrl. url: ' + url);
const html = `<html>
<a id='url' href="${url}">Click here</a>
<script>
var winRef = window.open("${url}");
winRef ? google.script.host.close() : window.alert('Configure browser to allow popup to redirect you to ${url}') ;
</script>
</html>`;
Logger.log('openUrl. html: ' + html);
var htmlOutput = HtmlService.createHtmlOutput(html).setWidth( 250 ).setHeight( 300 );
Logger.log('openUrl. htmlOutput: ' + htmlOutput);
SpreadsheetApp.getUi().showModalDialog( htmlOutput, `openUrl function in generic.gs is now opening a URL...` ); // https://developers.google.com/apps-script/reference/base/ui#showModalDialog(Object,String) Requires authorization with this scope: https://www.googleapis.com/auth/script.container.ui See https://developers.google.com/apps-script/concepts/scopes#setting_explicit_scopes
}
https://developers.google.com/apps-script/reference/base/ui#showModalDialog(Object,String) Requires authorization with this scope: https://www.googleapis.com/auth/script.container.ui See https://developers.google.com/apps-script/concepts/scopes#setting_explicit_scopes

Ajax and output pdf file are not working together

I have a file named download.php and call getpdf function inside it.
I call download.php via ajax to download pdf file when users click download button. but nothing happend and no download window appears. I checked it in firebug Net tab and download.php are requested on click event. Its size also changes that shows the file is reading from its location,but no download window.
Here's getpdf code:
function getpdf($id) {
header('Content-Type: application/pdf');
readfile('/san/theo-books/PDFs/'.$id.'.pdf');
exit;
}
And here's download.php code:
$pdf_id = $_POST('pdi');
echo getpdf($pdf_id);
What is the problem? Would you help me?
Here is the full postback version. It's not using the jQuery Ajax, because Popup download window needs the full postback:
<a id="pdf-10" href="#">PDF Export</a>
$(document).ready(function () {
$('a[id^="pdf"]').click(function (event) {
event.preventDefault();
var pdfExportPath = "/san/theo-books/PDFs/";
var $a = $(this);
var postId = $a.attr('id').replace("pdf-","");
var form = $('<form action="' + pdfExportPath + '" name="pdf' + postId + '" id="pdf' + postId + '" method="POST"> <input id="id" name="id" type="hidden" value="' + postId + '" /></form>');
$(form).appendTo('body');
form.submit();
});
});

redirect to another page after ajax function

Can anyone help me with, I am trying to create a download counter to my website.
I have a ajax script that counts up by 1 when the users clicks the download link, the issue I am having is on some browsers it goes to the download link before completing the ajax count script.
Is there a way that I can redirect to the download file once the script has completed. At the moment I have as follows
This is the link :-
<a href='downloads/".$downfile."' onclick=\"Counter('$referid');\"'>Download File</a>
This is the counter script:-
<script type="text/javascript">
function Counter(id)
{
$.get("clickcounter.php?id="+id);
{
return false;
}
}
</script>
This is the php script (clickcounter.php)
<?php
include('dbutils.php');
$referid = $_GET['id'];
$q = "SELECT * FROM downloads WHERE downid =".$referid;
$r = mysql_query($q);
while ($row = mysql_fetch_array($r))
{
$click = stripslashes(trim($row['downcount']));
$download = $row['downfile'];
}
$countup = $click + 1;
$qUpdate = "UPDATE downloads
SET downcount=$countup
WHERE downid=$referid";
$rUpdate = mysql_query($qUpdate);
?>
A few relatively small modifications should solve the problem. First, change the onclick to the following:
onclick=\"Counter('$referid', this); return false;\"
What we have done is to send in this as the second argument to the Counter function so we have a reference to the clicked link. Secondly, we have added return false, which blocks the browser from navigating to the url specified in the href.
The modified counter function looks like this:
function Counter(id, link) {
$.get("clickcounter.php?id=" + id, function() {
location.href = $(link).attr("href");
});
}
We now have a reference to the clicked link. A function has now been specified as the second argument to $.get(). This is the success-function, which is called when the ajax call has been successfully called. Inside that function we now redirect to the url specified in the href attribute on the clicked link.
I feel I should point out that the recommended way is to bind the onclick using jQuery separate from the html. The referid can be stored in a data attribute (which I chose to call data-rid):
<a href='downloads/".$downfile."' class='dl' data-rid='$referid'>Download File</a>
Then you bind the onclick for all download links (a elements with a "dl" class):
$(function() {
$("a.dl").click(function() {
var id = $(this).attr("data-rid");
var href = $(this).attr("href");
$.get("clickcounter.php?id=" + id, function() {
location.href = href;
});
return false;
});
});​
(I feel I should point out that the code has not been tested, so it's possible that a typo has snuck in somewhere)

jQuery cleditor plugin: creating a new button

Using cleditor, I'm trying to set up a custom button with the following code:
(function($) {
$.cleditor.buttons.link_species = {
name: "link_species",
image: "fish.gif",
title: "Species Link",
command: "inserthtml",
popupName: "link_species",
popupClass: "cleditorPrompt",
popupContent: "Genus: <input type='text' size='15'> Species: <input type='text' size='15'><br />Remove italics? <input type='checkbox' value='remove'> <input type='button' value='Ok' />",
buttonClick: link_speciesClick
};
// Handle the hello button click event
function link_speciesClick(e, data) {
// Wire up the submit button click event
$(data.popup).children(":button")
.unbind("click")
.bind("click", function(e) {
// Get the editor
var editor = data.editor;
var $text = $(data.popup).find(":text"),
genus = $text[0].value,
species = $text[1].value;
var slug = genus + '-' + species;
slug = htmlEntities(slug);
var link = '/dev/species/' + slug + '/';
var rel = link + '?preview=true';
var display = firstUpper(genus) + ' ' + species;
// Get the entered name
var html = '' + display + '';
if ( !$(data.popup).find(":checkbox").is(':checked') ) {
html = '<em>' + html + '</em>';
}
// Insert some html into the document
editor.execCommand(data.command, html, null, data.button);
// Hide the popup and set focus back to the editor
editor.hidePopups();
editor.focus();
});
}
})(jQuery);
It's a WordPress website, and the directory structure is something like this:
/wp-content/plugins/sf-species-profile/cleditor
Within there I have all the cleditor files and config.js.This file is where the above code is stored.
I also have an images folder containing a 24*24 fish.gif file.
For some reason, when I run this code, I get the following error:
[firefox]
a is undefined
<<myurl>>/wp-content/plugins/sf-species-profiles/cleditor/jquery.cleditor.min.js?ver=3.3.1
Line 17
[chrome]
Uncaught TypeError: Cannot read property 'length' of undefined
If I change the "image" argument to image:"" the same image for "B" appears, but the plugin works without error.
Does anyone have any ideas what may be wrong?
It would be easier to debug with the non minimized version. You can get it from here: http://premiumsoftware.net/cleditor/ (zip)
There are 2 functions that include a length call in the code that ends up in line 17 of the minimized code. One in the function hex(s) that processes color. The other is the the imagePath function.
function imagesPath() {
var cssFile = "jquery.cleditor.css",
href = $("link[href$='" + cssFile +"']").attr("href");
return href.substr(0, href.length - cssFile.length) + "images/";
}
It could throw an error of the type you have if your rendered html doesn't include a line like "<link rel="stylesheet" type="text/css" href="path/to/jquery.cleditor.css" />". (Href would then be undefined.)
For wordpress integration, you may find it easier to setup when using the wordpress plugin version of cleditor.

Resources