I am subscribed to a calendar and sometimes instead of the ' sign it shows '
I tried to make a script that gets the next 100 events (because getting all events doesn't seem to exist in Google Apps script). This works, I can see the events in the log. Now my question is, after it gets these events, how do I make it replace the title?
what I have for now is this:
function listNext100Events() {
var calendarId = 'primary';
var now = new Date();
var events = Calendar.Events.list(calendarId, {
timeMin: now.toISOString(),
singleEvents: true,
orderBy: 'startTime',
maxResults: 100
});
if (events.items && events.items.length > 0) {
for (var i = 0; i < events.items.length; i++) {
var event = events.items[i];
if (event.start.date) {
// All-day event.
var start = parseDate(event.start.date);
Logger.log('%s (%s)', event.summary, start.toLocaleDateString());
} else {
var start = parseDate(event.start.dateTime);
Logger.log('%s (%s)', event.summary, start.toLocaleString());
}
}
} else {
Logger.log('No events found.');
}
}
Also I know that the function to replace a title is
title.replaceText("'", "'");
How do I combine this knowledge into a working script?
Thank you!
Looking at your structure, I'm assuming that the title you're referring to is stored in the event.title attribute. If that's the case, this should work for replacing all instances (using regex because a regular string.replace only gets the first instance)
event.title = event.title.replace(/'/g, "'");
Related
I'm trying to create 7 Javascript shared workers inside a for loop.
My IDE (Pycharm) is giving me a warning for these two variables container-frame and worker:
"Mutable variable is accessible from closure"
Each of these shared worker is communicating with network_worker.js
Below is my JS code:
socket = io.connect('http://' + document.domain + ':4999/layout');
// Set up CSS
for (var i=0; i<player_dict.length; i++) {
var _id = player_dict[i]['_id'];
var container_frame = document.getElementById("container-frame-" + _id);
container_frame.style.display = "none";
setup_communication();
console.log(_id)
var client_id = _id;
var alarm_flag= "";
var alarm_metric="";
if (client_id != null && client_id == 0 && parseInt(location.port) == 4999) { // player_0_hack (for now). Remove and have work properly.
label = "";
} else if (client_id != null){
label = "Service " + (parseInt(location.port) - 5000 + 1);
} else {
label = "Invalid player id";
}
var worker = new SharedWorker('../static/js/network_worker.js', client_id);
console.log(worker);
worker.port.addEventListener('message', worker_callback, false);
window.addEventListener("beforeunload", function () {
worker.port.postMessage('label_close');
});
worker.port.start();
function worker_callback(e) {
console.log(e.data)
if(e.data.type == "update_label") {
console.log(container_frame)
container_frame.style.animationDuration = Math.random() + "s";
}
}
worker.port.postMessage({type: "label_connection", payload: {domain: document.domain, port: location.port, client_id: client_id, label: label}, alarm_flag: alarm_flag, alarm_rate: 1, alarm_metric: alarm_metric});
}
Ultimately what I'm trying to do is animating the container-frame for 7 HTML elements. I'm iterating over these elements using the for loop. These animations happen when an event is triggered from a JS script (update label).
Currently, I have 7 HTML elements. The last element only is having the animation working properly.
My doubt is that when I have put the worker_callback function inside the for loop, the JS compiler became confused about the scope of container_frame but I'm not sure.
Any suggestions please ?
The problem was the two variables container_frame and worker where defined as var not const. Thanks to #Edmund Lee
I wrote the following function to try to get the user that created the gCal event.
To test this I created an event on calendar and tried to run the script. When the script executes it gets error: "TypeError: Cannot find function getCreators in object CalendarEvent. (line 68, file "Code")".
Any ideas why this is happening? I'm fairly certain getCreators() is a function in object CalendarEvent (Ref:https://developers.google.com/apps-script/reference/calendar/calendar-event#getCreators())
function getuser(instr) {
var today = new Date();
var scriptProperties=PropertiesService.getScriptProperties();
var instrcal= scriptProperties.getProperty(instr);
var event=CalendarApp.getCalendarById(instrcal).getEventsForDay(today);
if (event<1) {
var user= 'None'
}
else if (event>1) {
var user= 'Multiple Users'
}
else {
var user= event.getCreators()
}
return user
}
getEventsForDay returns an array of CalendarEvent objects, all events for that day, even if it is just one.
You'll need to go through the events to find the one you want and then call getCreators().
You can verify this by using
var event=CalendarApp.getCalendarById(instrcal).getEventsForDay(today)[0];
Here the call will work.
The method getEventsForDay(date) gets an array all events that occur on a given day.
Check that you are doing: event < 1 instead of event.length < 1.
Code:
function getuser(instr) {
var today = new Date(),
scriptProperties = PropertiesService.getScriptProperties(),
instrcal = scriptProperties.getProperty(instr),
events = CalendarApp.getCalendarById(instrcal).getEventsForDay(today),
user = 'None';
if (events.length === 1) {
user = events[0].getCreators();
} else if (events.length > 1) {
user = 'Multiple Users';
}
return user;
}
I'm getting the following error when attempting to get an enumerator for a collection of lists: "Uncaught Error: The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested."
It happens on the line var listEnumerator = lists.getEnumerator(); it seems to me that there is an issue in my attempt to load lists into the client object with context.load(lists);
Here's the portion of my code that's causing the problem. I've marked the place just before the error is thrown.
//____________________________Required function for accessing the host site's info.___________________________________
function getQueryStringParameter(param) {
var params = document.URL.split("?")[1].split("&");
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == param) {
return singleParam[1];
}
}
}
//____________________________Begin checking for list_________________________
function checkForList(listToFind, typeOfListToCreateIfTheListIsMissing)
{
var hostUrl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
var hostcontext = new SP.AppContextSite(context, hostUrl);
var hostweb = hostcontext.get_web();
var lists = hostweb.get_lists();
context.load(lists);
context.executeQueryAsync(checkIfListExistsUsingEnumerator(listToFind, lists, hostweb, typeOfListToCreateIfTheListIsMissing), onQueryFailed);
}
//Failed to get lists for some reason
function onQueryFailed(sender, args) {
alert('We failed to retrieve lists. \n' + args.get_message() + '\n' + args.get_stackTrace());
}
//____________________________Does list exist?____________________________
function checkIfListExistsUsingEnumerator(listToFind, lists, hostweb, typeOfList)
{
var listExists = false;
//!!!!!!!!!!!!!!! ERROR HERE !!!!!!!!!!!!!!!!
var listEnumerator = lists.getEnumerator();
var title;
while (listEnumerator.moveNext())
{
title = listEnumerator.get_current().get_title();
if (title == listToFind)
{
listExists = true;
}
}
if (!listExists)
{
alert("It appears that a required list does not already exist. \nClick ok, and we'll automatically create one for you.");
//Create a new list
createList(listToFind, hostweb, typeOfList);
}
else if (listExists)
{
//Do nothing.
}
}
//____________________________If it doesn't, create one on the local site____________________________
function createList(nameOfNewList, hostweb, typeOfList) {
var listCreationInfo = new SP.ListCreationInformation();
listCreationInfo.set_title(nameOfNewList);
if (typeOfList === "events")
{
listCreationInfo.set_templateType(SP.ListTemplateType.events);
}
else if (typeOfList === "contacts")
{
listCreationInfo.set_templateType(SP.ListTemplateType.contacts);
}
var lists = hostweb.get_lists();
var newList = lists.add(listCreationInfo);
context.load(newList);
context.executeQueryAsync(onListCreationSuccess, onListCreationFail);
}
function onListCreationSuccess() {
alert('List created successfully!');
}
function onListCreationFail(sender, args) {
alert('Failed to create the list. ' + args.get_message());
}
I've looked at this question sharepoint javascript collection not initialized error which seems to be fairly similar to mine, but I'm having trouble implementing the solution provided there, making me think my error may be have a different cause.
I've also tried querying for the lists inside of the function that is throwing the error, but that doesn't seem to solve anything.
For a little background, these functions are attempting to read all lists from the app's host site, check to see if a specified list exists, and create a list if no matching list exists. If there's a better way of doing that than what I'm attempting, I'd be open to that too.
Any pointers?
Some things I've tried that don't seem to work:
Changing the Asynchronous query
context.executeQueryAsync(checkIfListExists(listToFind, hostweb, typeOfListToCreateIfTheListIsMissing), onQueryFailed);
to a Synchronous one.
context.executeQuery(checkIfListExists(listToFind, hostweb, typeOfListToCreateIfTheListIsMissing), onQueryFailed);
I've figured out an alternate, and shorter way to method of achieving the same goal I was trying to achieve before.
Instead of checking to see if a list does not already exist, I just try to create a list, and the Query fails to create a list if one is already there. (That's good because I don't want to overwrite the list if it is already there.)
I'm not totally sure if there are any undesired side effects of what I'm doing here, but in my tests it produced the desired behavior.
//____________________________Required function for accessing the host site's info.___________________________________
function getQueryStringParameter(param) {
var params = document.URL.split("?")[1].split("&");
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == param) {
return singleParam[1];
}
}
}
//____________________________Create a list if one does not already exist_________________________
function createList(listToCreate, typeOfList)
{
// Create an announcement SharePoint list with the name that the user specifies.
var hostUrl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
var hostContext = new SP.AppContextSite(currentContext, hostUrl);
var hostweb = hostContext.get_web();
var listCreationInfo = new SP.ListCreationInformation();
listCreationInfo.set_title(listToCreate);
if (typeOfList === "events")
{
listCreationInfo.set_templateType(SP.ListTemplateType.events);
}
else if (typeOfList === "contacts")
{
listCreationInfo.set_templateType(SP.ListTemplateType.contacts);
}
var lists = hostweb.get_lists();
var newList = lists.add(listCreationInfo);
currentContext.load(newList);
currentContext.executeQueryAsync(onListCreationSuccess, onListCreationFail);
}
function onListCreationSuccess() {
alert("We've created a list since one doesn't exist yet." );
}
function onListCreationFail(sender, args) {
alert("We didn't create the list. Here's why: " + args.get_message());
}
I've written a Google apps script which first creates and displays a line chart within the UI app and then re-draws the graph based on selected list box values using a Click-button event handler to trigger when the graph "refreshes".
The issue I'm trying to resolve is that when published as a web application when triggering the click event I receive:
Error Encountered: An unexpected error occurred
The code runs perfectly from a spreadsheet (except for some pesky permissions issues where other users are asked to download the panel object; I'll get to that later), and I'm really stuck as to why it won't translate.
Here's the code for what it's worth:
function doGet(){
var app = UiApp.createApplication().setWidth(800).setHeight(650).setTitle('FLEET Chart');
var e = 'undefined';
lb(app);
return click(e, app);
}
function lb(app){
var lb = app.createListBox(true).setId('myId').setName('myLbName');// add items to ListBox
var lb2 = app.createListBox(true).setId('myId2').setName('myLbName2');
var lb3 = app.createListBox(true).setId('myId3').setName('myLbName3');
var bttn = app.createButton('Refresh').setId('myBttn');
lb3.addItem('2011').addItem('2012');
lb2.addItem('January')
.addItem('February')
.addItem('March')
.addItem('April')
.addItem('May')
.addItem('June')
.addItem('July')
.addItem('August')
.addItem('September')
.addItem('October')
.addItem('November')
.addItem('December');
lb.addItem('Drug1')
.addItem('Drug2')
.addItem('Drug3')
.addItem('Drug4');
var mypanel = app.createHorizontalPanel().setVisible(true);
mypanel.add(lb).add(lb2).add(lb3).add(bttn);
app.add(mypanel);
var handler = app.createServerChangeHandler('click').addCallbackElement(mypanel);
handler.addCallbackElement(bttn);
bttn.addClickHandler(handler);
}
function click(e, app) {
var valuelb = new Array('Drug1','Drug2','Drug3','Drug4');
var valuelb2 = new Array ('January','February','March','April','May','June','July','August','September','October','November','December');
var valuelb3 = new Array('2011','2012');
var SS = SpreadsheetApp.openById('0Am8DRqAEaxH7dF9NWFJLSTdWZGRxeEFfMkFjNlFCT2c');
var sheeteff = SS.getSheetByName('Efficiency');
var data = sheeteff.getDataRange().getValues();
if (String(e) != 'undefined') {
app.setWidth(800).setHeight(650).setTitle('FLEET Chart');
var valuelb = String(e.parameter.myLbName);
if (valuelb.indexOf(',') != -1) {
var valuelb = e.parameter.myLbName.split(',');
}
var valuelb2 = String(e.parameter.myLbName2);
if (valuelb2.indexOf(',') != -1) {
var valuelb2 = e.parameter.myLbName2.split(',');
}
var valuelb3 = String(e.parameter.myLbName3);
if (valuelb3.indexOf(',') != -1) {
var valuelb3 = e.parameter.myLbName3.split(',');
}
SS.getSheetByName('Sheet2').getRange(1,1).setValue(String(valuelb2) + ' ' + valuelb.indexOf(','));//for unformation purposes
lb(app);
}else{
SS.getSheetByName('Sheet2').getRange(1,1).setValue(String(e));//for information purposes
}
var usedata = ArrayLib.filterByText(ArrayLib.filterByText(ArrayLib.filterByText(data, 3, valuelb), 1, valuelb2), 0, valuelb3);
//Build data table
var dataTable = Charts.newDataTable();
//Add Column types
dataTable.addColumn(Charts.ColumnType.DATE, data[0][2]);
dataTable.addColumn(Charts.ColumnType.NUMBER, data[0][9]);
dataTable.addColumn(Charts.ColumnType.NUMBER, data[0][8]);
//Add rows
for(var j=0; j<usedata.length; j++){
dataTable.setValue(j, 0, usedata[j][2]);
dataTable.setValue(j, 1, usedata[j][9]);
dataTable.setValue(j, 2, usedata[j][8]);
}
//Create and build chart
var chart = Charts.newLineChart()
.setDataTable(dataTable)
.setTitle('Efficiency over Time \nConfiguration: [' + valuelb + ']\n' + 'Month: [' + valuelb2 + ']\n' + 'Year: [' + valuelb3 + ']')
.setXAxisTitle('Time')
.setYAxisTitle('Percentage')
.setDimensions(750, 600)
.setPointStyle(Charts.PointStyle.MEDIUM)
.build();
app.add(chart);
return app;
}
I've not gone through your entire code but definitely see this wrong - you have set doGet as the function to be called on a handler. No problems with that except you try to call UiApp.createApplication() for the second time which isn't allowed.
I suggest you change the handler to call another function (lb, maybe) instead of doGet.
I also have "Unexpected Errors" in my code. To fix them, I wrote a simple library which helps to find problems in server handlers. Here is an example demonstrating how to use the library. The example source code is here. To add the library to a script is necessary to use the Mr6TKHuVEJGjYr-NnLUNbEkFO7CoOZA03 project key in the Resources->Manage Libraries dialog. The library uses the ScriptProperties Service to store own internal variables.
Update: I guess the subject gave a wrong notion that I'm looking for an existing addon. This is a custom problem and I do NOT want an existing solution.
I wish to WRITE (or more appropriately, modify and existing) Addon.
Here's my requirement:
I want my addon to work for a particular site only
The data on the pages are encoded using a 2 way hash
A good deal of info is loaded by XHR requests, and sometimes
displayed in animated bubbles etc.
The current version of my addon parses the page via XPath
expressions, decodes the data, and replaces them
The issue comes in with those bubblified boxes that are displayed
on mouse-over event
Thus, I realized that it might be a good idea to create an XHR
bridge that could listen to all the data and decode/encode on the fly
After a couple of searches, I came across nsITraceableInterface[1][2][3]
Just wanted to know if I am on the correct path. If "yes", then kindly
provide any extra pointers and suggestions that may be appropriate;
and if "No", then.. well, please help with correct pointers :)
Thanks,
Bipin.
[1]. https://developer.mozilla.org/en/NsITraceableChannel
[2]. http://www.softwareishard.com/blog/firebug/nsitraceablechannel-intercept-http-traffic/
[3]. http://www.ashita.org/howto-xhr-listening-by-a-firefox-addon/
nsITraceableChannel is indeed the way to go here. the blog posts by Jan Odvarko (softwareishard.com) and myself (ashita.org) show how to do this. You may also want to see http://www.ashita.org/implementing-an-xpcom-firefox-interface-and-creating-observers/, however it isn't really necessary to do this in an XPCOM component.
The steps are basically:
Create Object prototype implementing nsITraceableChannel; and create observer to listen to http-on-modify-request and http-on-examine-response
register observer
observer listening to the two request types adds our nsITraceableChannel object into the chain of listeners and make sure that our nsITC knows who is next in the chain
nsITC object provides three callbacks and each will be called at the appropriate stage: onStartRequest, onDataAvailable, and onStopRequest
in each of the callbacks above, our nsITC object must pass on the data to the next item in the chain
Below is actual code from a site-specific add-on I wrote that behaves very similarly to yours from what I can tell.
function TracingListener() {
//this.receivedData = [];
}
TracingListener.prototype =
{
originalListener: null,
receivedData: null, // array for incoming data.
onDataAvailable: function(request, context, inputStream, offset, count)
{
var binaryInputStream = CCIN("#mozilla.org/binaryinputstream;1", "nsIBinaryInputStream");
var storageStream = CCIN("#mozilla.org/storagestream;1", "nsIStorageStream");
binaryInputStream.setInputStream(inputStream);
storageStream.init(8192, count, null);
var binaryOutputStream = CCIN("#mozilla.org/binaryoutputstream;1",
"nsIBinaryOutputStream");
binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));
// Copy received data as they come.
var data = binaryInputStream.readBytes(count);
//var data = inputStream.readBytes(count);
this.receivedData.push(data);
binaryOutputStream.writeBytes(data, count);
this.originalListener.onDataAvailable(request, context,storageStream.newInputStream(0), offset, count);
},
onStartRequest: function(request, context) {
this.receivedData = [];
this.originalListener.onStartRequest(request, context);
},
onStopRequest: function(request, context, statusCode)
{
try
{
request.QueryInterface(Ci.nsIHttpChannel);
if (request.originalURI && piratequesting.baseURL == request.originalURI.prePath && request.originalURI.path.indexOf("/index.php?ajax=") == 0)
{
var data = null;
if (request.requestMethod.toLowerCase() == "post")
{
var postText = this.readPostTextFromRequest(request, context);
if (postText)
data = ((String)(postText)).parseQuery();
}
var date = Date.parse(request.getResponseHeader("Date"));
var responseSource = this.receivedData.join('');
//fix leading spaces bug
responseSource = responseSource.replace(/^\s+(\S[\s\S]+)/, "$1");
piratequesting.ProcessRawResponse(request.originalURI.spec, responseSource, date, data);
}
}
catch (e)
{
dumpError(e);
}
this.originalListener.onStopRequest(request, context, statusCode);
},
QueryInterface: function (aIID) {
if (aIID.equals(Ci.nsIStreamListener) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
readPostTextFromRequest : function(request, context) {
try
{
var is = request.QueryInterface(Ci.nsIUploadChannel).uploadStream;
if (is)
{
var ss = is.QueryInterface(Ci.nsISeekableStream);
var prevOffset;
if (ss)
{
prevOffset = ss.tell();
ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
}
// Read data from the stream..
var charset = "UTF-8";
var text = this.readFromStream(is, charset, true);
// Seek locks the file so, seek to the beginning only if necko hasn't read it yet,
// since necko doesn't seek to 0 before reading (at lest not till 459384 is fixed).
if (ss && prevOffset == 0)
ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
return text;
}
else {
dump("Failed to Query Interface for upload stream.\n");
}
}
catch(exc)
{
dumpError(exc);
}
return null;
},
readFromStream : function(stream, charset, noClose) {
var sis = CCSV("#mozilla.org/binaryinputstream;1", "nsIBinaryInputStream");
sis.setInputStream(stream);
var segments = [];
for (var count = stream.available(); count; count = stream.available())
segments.push(sis.readBytes(count));
if (!noClose)
sis.close();
var text = segments.join("");
return text;
}
}
hRO = {
observe: function(request, aTopic, aData){
try {
if (typeof Cc == "undefined") {
var Cc = Components.classes;
}
if (typeof Ci == "undefined") {
var Ci = Components.interfaces;
}
if (aTopic == "http-on-examine-response") {
request.QueryInterface(Ci.nsIHttpChannel);
if (request.originalURI && piratequesting.baseURL == request.originalURI.prePath && request.originalURI.path.indexOf("/index.php?ajax=") == 0) {
var newListener = new TracingListener();
request.QueryInterface(Ci.nsITraceableChannel);
newListener.originalListener = request.setNewListener(newListener);
}
}
} catch (e) {
dump("\nhRO error: \n\tMessage: " + e.message + "\n\tFile: " + e.fileName + " line: " + e.lineNumber + "\n");
}
},
QueryInterface: function(aIID){
if (typeof Cc == "undefined") {
var Cc = Components.classes;
}
if (typeof Ci == "undefined") {
var Ci = Components.interfaces;
}
if (aIID.equals(Ci.nsIObserver) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
};
var observerService = Cc["#mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.addObserver(hRO,
"http-on-examine-response", false);
In the above code, originalListener is the listener we are inserting ourselves before in the chain. It is vital that you keep that info when creating the Tracing Listener and pass on the data in all three callbacks. Otherwise nothing will work (pages won't even load. Firefox itself is last in the chain).
Note: there are some functions called in the code above which are part of the piratequesting add-on, e.g.: parseQuery() and dumpError()
Tamper Data Add-on. See also the How to Use it page
You could try making a Greasemonkey script and overwriting the XMLHttpRequest.
The code would look something like:
function request () {
};
request.prototype.open = function (type, path, block) {
GM_xmlhttpRequest({
method: type,
url: path,
onload: function (response) {
// some code here
}
});
};
unsafeWindow.XMLHttpRequest = request;
Also note that you can turn a GM script into an addon for Firefox.