I registered my trigger on Edit->Current Project's Trigger and then made this:
function onEdit(e) {
SpreadsheetApp.getActiveSheet().toast(e.value);
}
I also tried it without registering the trigger in case there's some odd collision thing. Is there something else I need to do to trigger the function?
Either you need to do authorization like tehhowch's comment suggests, or your function has an error. If it has an error and it won't pop up and notify you, try to run the function manually with the debugger and be sure your script is correct.
Here's a bunch of reserved simple trigger functions that you should not use as variable name as they're integral in Apps Script:
onOpen(e) runs when a user opens a spreadsheet, document, or form that he or she has permission to edit.
onEdit(e) runs when a user changes a value in a spreadsheet.
onInstall(e) runs when a user installs an add-on.
doGet(e) runs when a user visits a web app or a program sends an HTTP GET request to a web app.
doPost(e) runs when a program sends an HTTP POST request to a web app.
editing my answer in case I didnt understand what your problem was. I ended up having another issue that was not solved with what I said earlier and I fixed it doing this:
Create a custom menu that runs this:
function addOnEditTrigger(){
var haveTrigger = ScriptApp.getProjectTriggers();
if(haveTrigger.length == 1){ return };
var ss = SpreadsheetApp.getActiveSpreadsheet();
ScriptApp.newTrigger('notifyReportedIssue')
.forSpreadsheet(ss)
.onEdit()
.create();
}
A new user can copy that file, open it, open the menu, run the function and create the needed trigger right there.
OLD answer:
Dont use onEdit(e)
Create another function: myFunctionToRunOnEdit(e) and then set a trigger that runs the function onEdit
image of trigger
Related
I am using OS X JavaScript for Automation (JXA), and I want to be able to capture the "open location" Apple Event.
Per http://www.macosxautomation.com/applescript/linktrigger/ , I have setup a customer URL handler. How do I do the equivalent of
on open location this_URL
...
end open location
with JXA? I tried all of the following, but could not get any of them to execute:
app = Application.currentApplication();
app.includeStandardAdditions = true;
function run() {
app.displayDialog(JSON.stringify(arguments));
}
function openLocation() {
app.displayDialog(JSON.stringify(arguments));
}
function openDocuments() {
app.displayDialog(JSON.stringify(arguments));
}
function onOpenLocation() {
app.displayDialog(JSON.stringify(arguments));
}
Apple's JXA docs (https://developer.apple.com/library/mac/releasenotes/InterapplicationCommunication/RN-JavaScriptForAutomation/Articles/OSX10-10.html#//apple_ref/doc/uid/TP40014508-CH109-SW15 ) don't discuss how to handle the open location event. My script would get opened because I could get an alert to display if I added it outside the functions. I just couldn't get a function to execute and be passed in the URL.
I am working around this by having a AppleScript handler that that then invokes my JXA code, but this is certainly less than ideal.
I also didn't see anything in the JXA Cookbook (https://github.com/dtinth/JXA-Cookbook ) about this.
This question is old, but to any present or future visitors from Google, the correct function name to use is GURLGURL (no, I'm not joking). Your function signature should look something like this:
#!/usr/bin/env osascript -l JavaScript
function GURLGURL(url) {
const App = Application.currentApplication();
App.includeStandardAdditions = true;
App.doShellScript(`echo ${url} > ~/Downloads/url-arg.txt`);
return true;
}
I discovered this after reading through this archived developer document, and then probing my JXA script's applet process with the Console app. The message that gets dispatched is GURLGURL as in get URL.
Cheers to Apple for curating the worst developer experience for the best version of AppleScript.
As you suggest, the trick (for the moment) seems to be to pass control immediately to a second (JavaScript for Automation) script in the same bundle.
on open location strURL
run script (path to resource "jsHandler.scpt" in directory "Scripts") with parameters {{|URL|:strURL}}
end open location
i've gscript inside a spreadsheet, if i add and run a function calling this code :
var conn = Jdbc.getConnection('jdbc:mysql://sql4.freesqldatabase.com:3306/sql427377', 'sql427377', 'my_pass');
it works !
But if i copy/paste the same code in a google app script :
function doGet() {
return HtmlService.createTemplateFromFile('index').evaluate();
}
function getSql(){
var conn = Jdbc.getConnection('jdbc:mysql://sql4.freesqldatabase.com:3306/sql427377', 'sql427377', 'my_pass');
}
even if i don't call the function, i've just paste the code, i ve got this message on execution of my script :
"Vous devez disposer des autorisations requises pour pouvoir effectuer cette action."
"You must have the required permissions to perform this action."
I don't understand why... need help ;)
Permissions in a script project are asked for every service present in this project. Wether you actually call a function using this service or not is not important.
For example, if I have an onOpen() function in a script and another function that sends emails, I will be asked permission for mailApp service even if I simply try to run onOpen().
If your spreadsheet does not ask anything about Jdbc, it means that the project was already authorized for this service (and you probably forgot it) and the behavior you describe in your other project (the doGet one , but it would be the same in any other project) is normal.
If you want to check this, simply add a call to another Google service in a dummy function and try to execute another function that used to work without warning... You'll get the authorization request as expected.
How can you detect the url that I am browsing in chrome/safari/firefox via cocoa (desktop app)?
As a side but related note, are there any security restrictions when developing a desktop app that the user will be alerted and asked if they want to allow? e.g. if the app accesses their contact information etc.
Looking for a cocoa based solution, not javascript.
I would do this as an extension, and because you would like to target Chrome, Safari, and Firefox, I'd use a cross-browser extension framework like Crossrider.
So go to crossrider.com, set up an account and create a new extension. Then open the background.js file and paste in code like this:
appAPI.ready(function($) {
appAPI.message.addListener({channel: "notifyPageUrl"}, function(msg) {
//Do something, like send an xhr post somewhere
// notifying you of the pageUrl that the user visited.
// The url is contained within msg.pageUrl
});
var opts = { listen: true};
// Note: When defining the callback function, the first parameter is an object that
// contains the page URL, and the second parameter contains the data passed
// to the context of the callback function.
appAPI.webRequest.onBeforeNavigate.addListener(function(details, opaqueData) {
// Where:
// * details.pageUrl is the URL of the tab requesting the page
// * opaqueData is the data passed to the context of the callback function
if(opaqueData.listen){
appAPI.message.toBackground({
msg: details.pageUrl
}, {channel: "notifyPageUrl"});
}
}, opts ); // opts is the opaque parameter that is passed to the callback function
});
Then install the extension! In the example above, nothing is being done with the detected pageUrl that the user is visiting, but you can do whatever you like here - you could send a message to the user, you could restrict access utilizing the cancel or redirectTo return parameters, you could log it locally utilizing the crossrider appAPI.db API or you could send the notification elsewhere, cross-domain, to wherever you like utilizing an XHR request from the background directly.
Hope that helps!
And to answer the question on security issues desktop-side, just note that desktop applications will have the permissions of the user under which they run. So if you are thinking of providing a desktop app that your users will run locally, say something that will detect urls they access by tapping into the network stream using something like winpcap on windows or libpcap on *nix varieties, then just be aware of that - and also that libpcap and friends would have to have access to a network card that can be placed in promiscuous mode in the first place, by the user in question.
the pcap / installed desktop app solutions are pretty invasive - most folks don't want you listening in on literally everything and may actually violate some security policies depending on where your users work - their network administrators may not appreciate you "sniffing", whether that is the actual purpose or not. Security guys can get real spooky so-to-speak on these kinds of topics.
The extension via Crossrider is probably the easiest and least intrusive way of accomplishing your goal if I understand the goal correctly.
One last note, you can get the current tab urls for all tabs using Crossrider's tabs API:
// retrieves the array of tabs
appAPI.tabs.getAllTabs(function(allTabInfo) {
// Display the array
for (var i=0; i<allTabInfo.length; i++) {
console.log(
'tabId: ' + allTabInfo[i].tabId +
' tabUrl: ' + allTabInfo[i].tabUrl
);
}
});
For the tab API, refer to:
http://docs.crossrider.com/#!/api/appAPI.tabs
For the background navigation API:
http://docs.crossrider.com/#!/api/appAPI.webRequest.onBeforeNavigate
And for the messaging:
http://docs.crossrider.com/#!/api/appAPI.message
And for the appAPI.db stuff:
http://docs.crossrider.com/#!/api/appAPI.db
Have you looked into the Scripting Bridge? You could have an app that launches, say, an Applescript which verifies if any of the well known browser is opened and ask them which documents (URL) they are viewing.
Note: It doesn't necessarily need to be an applescript; you can access the Scripting Bridge through cocoa.
It would, however, require the browser to support it. I know Safari supports it but ignore if the others do.
Just as a quick note:
There are ways to do it via AppleScript, and you can easily wrap this code into NSAppleScript calls.
Here's gist with AppleScript commands for Safari and Chrome. Firefox seems to not support AE.
Well obviously this is what I had come across on google.
chrome.tabs.
getSelected
(null,
function
(tab) {
alert
(tab.url);
}) ;
in pure javascript we can use
alert(document.URL);
alert(window.location.href)
function to get current url
The Hangout API at https://developers.google.com/+/hangouts/writing includes an example to set a callback function when the hangout state has changed, like this:
gapi.hangout.onStateChanged.add(onStateChange);
When run, this results in an error similar to "gapi.hangout.onStateChanged is undefined". A quick check in Firebug shows that the onStateChanged method belongs to gapi.hangout.data not gapi.hangout.
What is the correct way to add a callback function when the state has changed?
The method that you're looking for is indeed a member of gapi.hangout.data. The writing article you mention seems to be out of date. I fix it :)
To do something when state changes just attach a callback:
gapi.hangout.data.onStateChanged.add(function() {
console.log(gapi.hangout.data.getState());
});
You can find working examples of the code in action on the sample apps page.
I'm looking for a way through AJAX (not via a JS framework!) to real time monitor a file for changes. If changes where made to that file, I need it to give an alert message. I'm a total AJAX noob, so please be gentle. ;-)
Edit: let me explain the purpose a bit more in detail. I'm using a chat script I've written in PHP for a webhop, and what I want is from an admin module monitor the chat requests. The chats are stored in text files, and if someone starts a chat session a new file is created. If that's the case, in the admin module I want to see that in real time.
Makes sense?
To monitor a file for changes with AJAX you could do something like this.
var previous = "";
setInterval(function() {
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function() {
if (ajax.readyState == 4) {
if (ajax.responseText != previous) {
alert("file changed!");
previous = ajax.responseText;
}
}
};
ajax.open("POST", "foo.txt", true); //Use POST to avoid caching
ajax.send();
}, 1000);
I just tested it, and it works pretty well, but I still maintain that AJAX is not the way to go here. Comparing file contents will be slow for big files. Also, you mentionned no framework, but you should use one for AJAX, just to handle the cross-browser inconsistencies.
AJAX is just a javascript, so from its definition you do not have any tool to get access to file unless other service calls an js/AJAX to notify about the change.
I've done that from scratch recently.
I don't know how much of a noob you are with PHP (it's the only server script language I know), but I'll try to be as brief as possible, feel free to ask any doubt.
I'm using long polling, which consists in this (
Create a PHP script that checks the content of the file periodically and only responds when it sees any change (it could include a description of the change in the response)
Create your XHR object
Include your notification code as a callback function (it can use the description)
Make the request
The PHP script will start checking the file, but won't reply until there is a change
When it responds, the callback will be called and your notification code will launch
If you don't care about the content of the file, only that it has been changed, you can check the last-modified time instead of the content in the PHP script.
EDIT: from some comment I see there's something to monitor file changes called FAM, that seems to be the way to go for the PHP script