创建基本聊天栏?

时间:2013-10-29 02:51:53

标签: google-apps-script chat google-docs

下面是旧的;查看底部的更新文本。

所以我的朋友和我在学校时使用谷歌文档进行交流,我们设置了一个挑战,即创建一个工作且“高效”的聊天栏,以便与更好的结果进行交流。我已经使用了很长一段时间的JavaScript,但之前从未使用过 Google Apps脚本。我们正在使用文档应用程序进行聊天;我想出的代码如下,但我遇到了一些问题:

  1. 用户关闭它时出错,然后转到聊天 - >在工具栏中打开聊天重新打开,说“遇到错误:发生意外错误”;未指定行或原因
  2. 在文档的某处需要一个隐藏元素,允许用户查看其他人输入的内容,但是如果不使用聊天框就无法编辑(在修改文本时会添加事件监听器来更新聊天框)

  3. //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.
    

    我不需要有人重写代码(尽管我们非常感激!),但请指出我做错了什么或建议改变/添加的东西。

    最后,在您提出建议之前,Google文档聊天无法与我们的计算机配合使用。这不是文档的错,但可能与我们的浏览器存在兼容性错误。正是由于这个问题,我们正在经历这个有趣而又仓促的过程来制作我们自己的聊天方法。

    更新

    我决定放弃使用纯Google Apps脚本的聊天版本,并使用G-A-S和HTML帮助改善我的朋友版本。我添加了图像缩略图/链接支持与命令/ img或/ image,以及改进的时间和计数器,以及其他一些幕后更新。这是它的快速截图:

    Google Apps Script chat

    从头开始编程的宏伟聊天,没有错误的更新方法,只是一个随意刷新数据库来检查消息和设置HTML文本区域文本。没有更多错误的getText方法。对于数据库中的每个新消息,无论是针对用户还是针对聊天中的每个人,我们都会将所有数据库消息加载到一个限制(一次50条消息),然后显示它们。在消息中使用HTML是其外观和功能的关键,例如图像。

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

    我将重新执行他的getChat()方法,只检查新邮件,而不是在每次刷新时加载每条邮件。

1 个答案:

答案 0 :(得分:2)

要摆脱错误消息,首先要在createChat函数中创建UiApp而不是onOpen

我还使用客户端处理程序清除textBox,因为它更有效。这是修改后的代码:

代码已删除,请参阅下面的更新

至于你的第二个请求,我不确定我到底想要你做什么...你能更准确地解释你期望的行为吗? (这更多是评论而不是答案,但我使用“答案字段”更具可读性)


编辑:我使用这段代码玩了一些东西,并且开始了 - 它几乎起作用......它仍然需要改进,但值得展示它是如何工作的。

我使用scriptProperties来存储会话的常见部分,我认为这是一个很好的方法,但是要知道何时更新其内容的问题。这是我到目前为止的代码,我当然对任何建议/改进持开放态度。

代码已删除,新版本


编辑2 :这是一个自动更新功能非常好的版本,脚本会自动更新聊天区域一段时间...如果没有活动则会停止并等待用户行动。请测试(使用2个帐户)并告诉我们您的想法。

注意我使用了一个checkBox来处理autoUpdate,我将其保持可见以用于测试目的,但当然它可以隐藏在最终版本中。

编辑3:添加了一条消息,警告用户何时离线+将textBox更改为彩色textArea以允许更长的消息+条件清除messageBox以便警告消息不会进去谈话。 (将时间设置为一个非常短的值用于测试目的,更改计数器值以恢复到您的需要)

function onOpen() {

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

function createChatBox(){
  ScriptProperties.setProperty('chatContent','');
  var app = UiApp.createApplication().setWidth(252);
  app.setTitle("Chat Bar");
  var vPanel = app.createVerticalPanel().setId('chatPanel').setWidth('100%');
  var chatHandler = app.createServerHandler("sayChat").addCallbackElement(vPanel);
  var textArea = app.createTextArea().setId('chatBox').setName('chatBox').setReadOnly(true).setText('').setSize('250px', '450px');
  var textBox = app.createTextArea().setId('messageBox').setName('messageBox').setText('Start chat...').setPixelSize(250,100).setStyleAttributes({'padding':'5px','background':'#ffffcc'}).addKeyPressHandler(chatHandler);
  var clearTextBoxClientHandler = app.createClientHandler().forTargets(textBox).setText('');
  textBox.addClickHandler(clearTextBoxClientHandler);
  var chatButton = app.createButton().setId("sayButton").setText("Say!").addMouseUpHandler(chatHandler);
  var chkHandler = app.createServerHandler('autoUpdate').addCallbackElement(vPanel);
  var chk = app.createCheckBox().setId('chk').addValueChangeHandler(chkHandler);
  vPanel.add(textArea);
  vPanel.add(textBox);
  vPanel.add(chatButton);
  vPanel.add(chk);
  app.add(vPanel);
  DocumentApp.getUi().showSidebar(app);
  return app;
}

function sayChat(e){
  var app = UiApp.getActiveApplication();  
  var user = '['+getCurrentUser()+'] : ';
  if(e.parameter.messageBox=="You have been put offline because you didn't type anything for more than 5 minutes..., please click here to refresh the conversation"){
    app.getElementById('messageBox').setText('');// clear messageBox
    ScriptProperties.setProperty('chatTimer',0);// reset counter
    return app;
  }
  if(e.parameter.source=='messageBox'&&e.parameter.keyCode!=13){return app};
  var content = ScriptProperties.getProperty('chatContent');
  ScriptProperties.setProperty('chatContent',content+"\n"+user+e.parameter.messageBox)
  app.getElementById("chatBox").setText(content+"\n"+user+e.parameter.messageBox+'\n');
  app.getElementById('messageBox').setText('');
  app.getElementById('chk').setValue(true,true);
  ScriptProperties.setProperty('chatTimer',0);
  return app;
}

function autoUpdate(){
  var app = UiApp.getActiveApplication();
  var content = ScriptProperties.getProperty('chatContent');
  var counter = Number(ScriptProperties.getProperty('chatTimer'));
  ++counter;
  if(counter>20){
    app.getElementById('chk').setValue(false);
    app.getElementById('messageBox').setText("You have been put offline because you didn't type anything for more than 5 minutes..., please click here to refresh the conversation");
    return app;
  }
  ScriptProperties.setProperty('chatTimer',counter);
  var content = ScriptProperties.getProperty('chatContent');
  app.getElementById("chatBox").setText(content+'*'); // the * is there only for test purpose
  app.getElementById('chk').setValue(false);
  Utilities.sleep(750);
  app.getElementById('chk').setValue(true,true).setText('timer = '+counter);
  return app;
}

function showUser(){
  DocumentApp.getUi().alert("Your userId is: "+getCurrentUser());
}

function getCurrentUser(){
  var email = Session.getEffectiveUser().getEmail();
  return email.substring(0,email.indexOf("@"));
}