Below is old; look at the updated text at the bottom.
So my friends and I use google docs to communicate while in school, and we setup the challenge to create a working and "efficient" chat bar to communicate with better results. I've been around JavaScript for quite some time, but have never fooled around with Google Apps Script before. We are using the document app for our chats; the code I came up with is as below, but I have a few problems with it:
- Errors when a user closes it, then goes to Chat -> Open Chat in the toolbar to re-open, saying, "Error encountered: An unexpected error occurred"; does not specify a line or reason
- Needs a hidden element somewhere in the document which can allow users to see what others have typed, but that they can't edit without using the chat box (would add event listener to update chat box when text is ammended)
//Main function, ran when the document first opens.
function onOpen() {
var app = UiApp.createApplication(); //Create a Ui App to use for the chat bar
if(getCurrentUser()=="dev1"||getCurrentUser()=="dev2"){ //user-Id's hidden for privacy
DocumentApp.getUi().createMenu('Chat')
.addItem('AutoColor', 'autoColor')
.addItem('Open Chat', 'createChatBox')
.addItem('Elements', 'displayElements') //Hidden as it is not important for regular use
.addItem('MyID', 'showUser')
.addToUi();
}else{
DocumentApp.getUi().createMenu('Chat')
.addItem('AutoColor', 'autoColor')
.addItem('Open Chat', 'createChatBox')
.addToUi();
}
}
//Creates and returns the chats GUI
function createChatBox(){
var app = UiApp.getActiveApplication()
app.setTitle("Chat Bar (not yet working)");
var vPanel = app.createVerticalPanel().setId('chatPanel').setWidth('100%');
var textArea = app.createTextArea().setId('chatBox').setName('chatBox').setReadOnly(true).setText('').setSize('250px', '450px'); //Read only so they can not edit the text, even if it won't affect overall chat
var textBox = app.createTextBox().setId('messageBox').setName('messageBox').setText('Words');
var chatHandler = app.createServerHandler("sayChat").addCallbackElement(textArea).addCallbackElement(textBox);
var chatButton = app.createButton().setId("sayButton").setText("Say!").addMouseUpHandler(chatHandler);
vPanel.add(textArea);
vPanel.add(textBox);
vPanel.add(chatButton);
app.add(vPanel);
DocumentApp.getUi().showSidebar(app);
return app;
}
//The event handler for when the "Say!" (post) button is pressed. Is probably where the conflict stems from.
function sayChat(eventInfo){
var app = UiApp.getActiveApplication();
var parameter = eventInfo.parameter;
app.getElementById("chatBox").setText(parameter.chatBox+"["+getCurrentUser()+"]: "+parameter.messageBox);
app.getElementById("messageBox").setText("");
return app;
}
//A debug function and a function to tell you the unique part of your email (useless, really)
function showUser(){
DocumentApp.getUi().alert("Your userId is: "+getCurrentUser());
}
//Returns the unique part of a person's email; if their email is "magicuser@gmail.com", it returns "magicuser"
function getCurrentUser(){
var email = Session.getActiveUser().getEmail();
return email.substring(0,email.indexOf("@"));
}
//The Auto-color and displayElements methods are hidden as they contain other user-info. They both work as intended and are not part of the issue.
I do not need someone to rewrite the code (although that'd be greatly appreciated!), but instead point out what I'm doing wrong or suggest something to change/add.
Last, before you suggest it, the google docs chat does not work with our computers. It is not the fault of the document, but probably a compatability error with our browser. It is because of this issue that we are going through this fun yet hasty process of making our own chat method.
Update
I decided to give up on my version of the chat using pure Google Apps Script and help improve my friends version using both G-A-S and HTML. I added image thumbnail/linking support with command /img or /image, along with improved time and counter, and some other behind the scenes updates. Here is a quick screenshot of it:
Magnificent chat programmed from scratch, and no buggy update methods, just a casual refresh database to check for messages and set HTML text-area text. No more buggy getText methods. For each new message in the database, whether targeted toward the user or toward everyone in the chat, we load all the database messages up to a limit (50 messages at a time), then display them. The use of HTML in the messages is key to its appearence and features, such as images.
function getChat() {
var chat = "";
var time = getTime();
var username = getCurrentUsername();
var db = ScriptDb.getMyDb();
var query = db.query({time : db.greaterThan(getJoinTime())}).sortBy('time', db.DESCENDING).limit(50);
var flag = query.getSize() % 2 != 0;
while(query.hasNext()) {
var record = query.next();
if(record.showTo == "all" || record.showTo == getCurrentUsername()) {
var text = record.text;
for(var i = 0; i < text.split(" ").length; i++) {
var substr = text.split(" ")[i];
if(substr.indexOf("http://") == 0 || substr.indexOf("https://") == 0) {
text = text.replace(substr, "<a href='" + substr + "'>" + substr + "</a>");
}
}
var message = "<pre style='display:inline;'><span class='" + (flag? "even" : "odd") + "'><b>[" + record.realTime + "]</b>" + text;
message += "</span></pre>";
chat += message;
flag = !flag;
}
}
//DocumentApp.getUi().alert(getTime() - time);
return chat;
}
I am going to re-do his getChat()
method to only check for new messages, and not load every message at each refresh.