Google App Scripts Function to Open URL [duplicate] - image

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

Related

Google script automatically close UI after clicking link button

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;
}

Google App Script and Html Form not communicating

I need help with Google App Script on a Google Sheet and an Html form. I just cannot get them to connect properly. The form has a text box and two buttons. The user enters a name in the text box and press the start button. The start button records time to a variable. When finished, the user presses finish. The finish button records the time and processes the text box and start button. This info is sent back to the Google App Script to be written to the Sheet. I would like to use an AJAX or JQuery call, but it doesn't seem to be working. Need a little help getting the nice form working. I have tried doGet(e) and doGet() functions, but those aren't working. I have tried lots of different versions of the code. This isn't my final html form, but it has the same point. If I click the button, AJAX should return something to the Google App Script after processing. New to Google App Scripting and need help. Thanks!
code.gs
function doGet(e) {
var result = "";
try {
result = "Hi" + e.queryString;
//should write to the spreadsheet the information here
} catch (f) {
result= "Error" + f.toString();
}
result=JSON.stringify({"result":result});
return ContentService
.createTextOutput( "(" + result + ")")
.setMimeType(ContentService.MimeType.JAVASCRIPT);
}
//where does HtmlService.createHtmlOutput('index.html') go?
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
// Make an AJAX call to Google Script
function callGoogleScript() {
var url = "https://script.google.com/macros/s/" my script id "/exec";
var data = { name: "Tom", city: "Nowhere" };
var request = jQuery.ajax({
url:url+encodeURIComponent(data),
method: "GET",
dataType: "jsonp"
});
}
// print the returned data
function ctrlq(e) {
console.log(e.result)
}
</script>
</head>
<body>
<button id="test" name="test" onclick="callGoogleScript()">Test</script>
</body>
</html>
Edit: This is for a Web App.

jQuery mobile : Linking next page doesn't work on Windows phone using phonegap

Currently im building a application using phonegap & jQuery Mobile
I have done the version which is perfectly working on iOS & Android.But the same code does not work on windows phone.When i click any link,redirection to the respective page is not loading..Its still says "Error Page loading".
<!DOCTYPE html>
Test
<div id="bg">
<div style="padding-top:14%;width:100%;text-align:center">
<div style="float:left;text-align:center;width:50%"><img src="pics/btn_1.png" /></div>
<div style="float:left;text-align:center;width:50%"><img src="pics/btn_2.png" /></div>
</div>
<div style="clear:both"></div>
</div>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<script type="text/javascript">
app.initialize();
</script>
</body>
Need help on this.
Solution
Add data-ajax=false or rel=external to your anchor tag. But, if you do this, you will lose transitions. This tells the framework to do a full page reload to clear out the Ajax hash in the URL. You could enable this if the incoming device is a windows phone if needed :
$(document).on("mobileinit", function () {
//check for windows phone
$.mobile.ajaxEnabled = false;
});
Else, make your code into a single page template. Here's a demo of that : http://jsfiddle.net/hungerpain/aYW2f/
Edit
Currently jQM doesn't support query string parameters. You could use the localStorage API to store the parameters in cache and retrieve them later. Assuming you want to go to index.html from here :
<img src="pics/btn_2.png" />
You'd add a click event for it :
$(document).on("click", "a", function() {
//gets qs=2 and changes it into ["qs",2]
var query = this.href.split["?"][2].split["="];
//construct an array out of that
var paramString = { query[0]: query[1]} ;
//store it in localstorage
locaStorage["query"] = JSON.stringify(paramString);
//continue redirection
return true;
});
In your index.html :
$(document).on("pageinit", "[data-role=page]", function() {
//store it in localstorage
var params = JSON.parse(locaStorage["query"]);
//now params will contain { "qs" : 2 }
//you could access "2" by params["qs"]
});
More info about localStorage here.
I had Also same issue and finally resolve it by using below code
my html page is index.html and i am writtinga all code in one html
Before
$.mobile.changePage( "#second", {});
After
var url = window.location.href;
url = url.split('#').pop().split('?').pop();
url = url.replace(url.substring(url.lastIndexOf('/') + 1),"index.html#second");
$.mobile.changePage(url, { reloadPage : false, changeHash : false });
and suppose you have multiple html page then for more one page to another you can use
var url = window.location.href;
url = url.split('#').pop().split('?').pop();
url = url.replace(url.substring(url.lastIndexOf('/') + 1),"second.html");
$.mobile.changePage(url, { reloadPage : false, changeHash : false });
There is no support of querystring in web application using phonegap for windows phone 7.
However we can replace ? with # or anything else to pass the data,
like convert
Sample.html?id=12312
to
Sample.html#id=12312

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)

Get current page URL from a firefox sidebar extension

I'm writing a sidebar extension for Firefox and need a way to get the URL of the current page so I can check it against a database and display the results. How can I do this?
I stumbled over this post while looking for an answer to the same question.
Actually I think it's as easy as
alert(window.content.location.href)
See also https://developer.mozilla.org/en/DOM/window.content
window.top.getBrowser().selectedBrowser.contentWindow.location.href;
might work, otherwise I think you need to use:
var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
mainWindow.getBrowser().selectedBrowser.contentWindow.location.href;
This seems to work fine for me
function getCurrentURL(){
var currentWindow = Components.classes["#mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow("navigator:browser");
var currBrowser = currentWindow.getBrowser();
var currURL = currBrowser.currentURI.spec;
return currURL;
}
https://developer.mozilla.org/En/Working_with_windows_in_chrome_code
If you need to access the main browser from the code running in a sidebar, you'll something like what Wimmel posted, except the last line could be simplified to
mainWindow.content.location.href
(alternatively you could use 's API returning an nsIURI).
Depending on your task, it might make sense to run the code in the browser window instead (e.g. in a page load handler), then it can access the current page via the content shortcut and the sidebar via document.getElementById("sidebar").contentDocument or .contentWindow.
If you need only domain and subdomain;
Usage;
PageDomain.getDomain(); // stackoverflow.com
PageDomain.getSubDomain(); // abc.stackoverflow.com
Code;
PageDomain = {
getDomain : function() {
var docum = Components.classes["#mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow("navigator:browser");
var domain = PageDomain.extractDomain(new String(docum.location));
return domain;
},
getSubDomain : function() {
var docum = Components.classes["#mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow("navigator:browser");
var subDomain = PageDomain.extractSubDomain(new String(docum.location));
return subDomain;
},
extractDomain: function(host) {
var s;
// Credits to Chris Zarate
host=host.replace('http:\/\/','');
host=host.replace('https:\/\/','');
re=new RegExp("([^/]+)");
host=host.match(re)[1];
host=host.split('.');
if(host[2]!=null) {
s=host[host.length-2]+'.'+host[host.length-1];
domains='ab.ca|ac.ac|ac.at|ac.be|ac.cn|ac.il|ac.in|ac.jp|ac.kr|ac.nz|ac.th|ac.uk|ac.za|adm.br|adv.br|agro.pl|ah.cn|aid.pl|alt.za|am.br|arq.br|art.br|arts.ro|asn.au|asso.fr|asso.mc|atm.pl|auto.pl|bbs.tr|bc.ca|bio.br|biz.pl|bj.cn|br.com|cn.com|cng.br|cnt.br|co.ac|co.at|co.il|co.in|co.jp|co.kr|co.nz|co.th|co.uk|co.za|com.au|com.br|com.cn|com.ec|com.fr|com.hk|com.mm|com.mx|com.pl|com.ro|com.ru|com.sg|com.tr|com.tw|cq.cn|cri.nz|de.com|ecn.br|edu.au|edu.cn|edu.hk|edu.mm|edu.mx|edu.pl|edu.tr|edu.za|eng.br|ernet.in|esp.br|etc.br|eti.br|eu.com|eu.lv|fin.ec|firm.ro|fm.br|fot.br|fst.br|g12.br|gb.com|gb.net|gd.cn|gen.nz|gmina.pl|go.jp|go.kr|go.th|gob.mx|gov.br|gov.cn|gov.ec|gov.il|gov.in|gov.mm|gov.mx|gov.sg|gov.tr|gov.za|govt.nz|gs.cn|gsm.pl|gv.ac|gv.at|gx.cn|gz.cn|hb.cn|he.cn|hi.cn|hk.cn|hl.cn|hn.cn|hu.com|idv.tw|ind.br|inf.br|info.pl|info.ro|iwi.nz|jl.cn|jor.br|jpn.com|js.cn|k12.il|k12.tr|lel.br|ln.cn|ltd.uk|mail.pl|maori.nz|mb.ca|me.uk|med.br|med.ec|media.pl|mi.th|miasta.pl|mil.br|mil.ec|mil.nz|mil.pl|mil.tr|mil.za|mo.cn|muni.il|nb.ca|ne.jp|ne.kr|net.au|net.br|net.cn|net.ec|net.hk|net.il|net.in|net.mm|net.mx|net.nz|net.pl|net.ru|net.sg|net.th|net.tr|net.tw|net.za|nf.ca|ngo.za|nm.cn|nm.kr|no.com|nom.br|nom.pl|nom.ro|nom.za|ns.ca|nt.ca|nt.ro|ntr.br|nx.cn|odo.br|on.ca|or.ac|or.at|or.jp|or.kr|or.th|org.au|org.br|org.cn|org.ec|org.hk|org.il|org.mm|org.mx|org.nz|org.pl|org.ro|org.ru|org.sg|org.tr|org.tw|org.uk|org.za|pc.pl|pe.ca|plc.uk|ppg.br|presse.fr|priv.pl|pro.br|psc.br|psi.br|qc.ca|qc.com|qh.cn|re.kr|realestate.pl|rec.br|rec.ro|rel.pl|res.in|ru.com|sa.com|sc.cn|school.nz|school.za|se.com|se.net|sh.cn|shop.pl|sk.ca|sklep.pl|slg.br|sn.cn|sos.pl|store.ro|targi.pl|tj.cn|tm.fr|tm.mc|tm.pl|tm.ro|tm.za|tmp.br|tourism.pl|travel.pl|tur.br|turystyka.pl|tv.br|tw.cn|uk.co|uk.com|uk.net|us.com|uy.com|vet.br|web.za|web.com|www.ro|xj.cn|xz.cn|yk.ca|yn.cn|za.com';
domains=domains.split('|');
for(var i=0;i<domains.length;i++) {
if(s==domains[i]) {
s=host[host.length-3]+'.'+s;
break;
}
}
} else {
s=host.join('.');
}
// Thanks Chris
return s;
},
extractSubDomain:function(host){
host=host.replace('http:\/\/','');
host=host.replace('https:\/\/','');
re=new RegExp("([^/]+)");
host=host.match(re)[1];
return host;
}
}
From a Firefox extension popup ;
You'll need
"permissions": [
"activeTab"
]
in your manifest or possibly tabs instead of activeTab
async function getCurrentTabUrl(){
let tabs = await browser.tabs.query({active: true, currentWindow: true}) ;
return tabs[0].url ;
}
let hostUrl = await getCurrentTab();
alert(hostUrl);
This works from a firefox "popup" extension.
browser.tabs.query({active: true, windowId: browser.windows.WINDOW_ID_CURRENT})
.then(tabs => browser.tabs.get(tabs[0].id))
.then(tab => {
console.log(tab);
});
Hallo,
I have tried to implement this in JavaScript, because I need that in my project too, but all three possible solutions didn't work. I have also implemented a small site to test it, but this also didn't work.
Here is the source code of the small site:
<html>
<head>
<title>Test</title>
<script type="text/javascript">
function Fall1 () {
alert(window.top.getBrowser().selectedBrowser.contentWindow.location.href);
}
function Fall2() {
var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
alert(mainWindow.getBrowser().selectedBrowser.contentWindow.location.href);
}
function Fall3() {
alert(document.getElementById("sidebar").contentWindow.location.href);
}
</script>
</head>
<body>
<form name="Probe" action="">
<input type="button" value="Fall1"
onclick="Fall1()">
<input type="button" value="Fall2"
onclick="Fall2()">
<input type="button" value="Fall3"
onclick="Fall13()">
</form>
</body>
</html>

Resources