### -------------------------------------------------------------------------------------------------------------------- If a function's last line is the statement false that represents the function returning false A function such as a click handler will continue along with the propogation and default behaivour if not stopped Returning false stops propogation/prevents default. You cannot always use the event object to call these methods Because most Meteor event handlers set the event object to the exact context of the event which does not allow you to simply call these methods. -------------------------------------------------------------------------------------------------------------------- ### @sendMessage = -> message = linkify $('#newMessageInput').val() # get the message from the input box unless (message?.length > 0 and (/\S/.test(message))) # check the message has content and it is not whitespace return # do nothing if invalid message chattingWith = getInSession('inChatWith') if chattingWith isnt "PUBLIC_CHAT" # dest = Meteor.Users.findOne("userId": chattingWith) dest = Meteor.Users.findOne(_id: chattingWith) messageForServer = { # construct message for server "message": message "chat_type": if chattingWith is "PUBLIC_CHAT" then "PUBLIC_CHAT" else "PRIVATE_CHAT" "from_userid": getInSession("DBID") "from_username": getUsersName() "from_tz_offset": "240" "to_username": if chattingWith is "PUBLIC_CHAT" then "public_chat_username" else dest.user.name "to_userid": if chattingWith is "PUBLIC_CHAT" then "public_chat_userid" else chattingWith "from_lang": "en" "from_time": getTime() "from_color": "0x000000" # "from_color": "0x#{getInSession("messageColor")}" } console.log JSON.stringify messageForServer Meteor.call "sendChatMessagetoServer", getInSession("meetingId"), messageForServer, getInSession("userId") $('#newMessageInput').val '' # Clear message box Template.chatInput.events 'click #sendMessageButton': (event) -> sendMessage() 'keypress #newMessageInput': (event) -> # user pressed a button inside the chatbox if event.shiftKey and event.which is 13 $("#newMessageInput").append("\r") # Change newline character return if event.which is 13 # Check for pressing enter to submit message sendMessage() $('#newMessageInput').val("") return false Template.chatInput.rendered = -> $('input[rel=tooltip]').tooltip() $('button[rel=tooltip]').tooltip() Template.chatbar.helpers getChatGreeting: -> greeting = "Welcome to #{getMeetingName()}!\r\r For help on using BigBlueButton see these (short) tutorial videos.\r\r To join the audio bridge click the headset icon (upper-left hand corner). Use a headset to avoid causing background noise for others.\r\r\r This server is running BigBlueButton #{getInSession 'bbbServerVersion'}.\r\r" # This method returns all messages for the user. It looks at the session to determine whether the user is in #private or public chat. If true is passed, messages returned are from before the user joined. Else, the messages are from after the user joined getFormattedMessagesForChat: -> friend = chattingWith = getInSession('inChatWith') # the recipient(s) of the messages after = before = greeting = [] if chattingWith is 'PUBLIC_CHAT' # find all public messages before = Meteor.Chat.find({'message.chat_type': chattingWith, 'message.from_time': {$lt: String(getTimeOfJoining())}}).fetch() after = Meteor.Chat.find({'message.chat_type': chattingWith, 'message.from_time': {$gt: String(getTimeOfJoining())}}).fetch() greeting = [ 'message': 'message': Template.chatbar.getChatGreeting(), 'from_username': 'System', 'from_time': getTimeOfJoining() 'from_color': '0x3399FF' # A nice blue in hex ] else me = getInSession("DBID") after = Meteor.Chat.find({ # find all messages between current user and recipient 'message.chat_type': 'PRIVATE_CHAT', $or: [{'message.from_userid': me, 'message.to_userid': friend},{'message.from_userid': friend, 'message.to_userid': me}] }).fetch() messages = (before.concat greeting).concat after getCombinedMessagesForChat: -> msgs = Template.chatbar.getFormattedMessagesForChat() len = msgs.length # get length of messages i = 0 while i < len # Must be a do while, for loop compiles and stores the length of array which can change inside the loop! if msgs[i].message.from_userid isnt 'System' # skip system messages j = i+1 # Start looking at messages right after the current one while j < len deleted = false if msgs[j].message.from_userid isnt 'System' # Ignore system messages # Check if the time discrepancy between the two messages exceeds window for grouping if (parseFloat(msgs[j].message.from_time)-parseFloat(msgs[i].message.from_time)) >= 60000 # 60 seconds/1 minute break # Messages are too far between, so them seperated and stop joining here if msgs[i].message.from_userid is msgs[j].message.from_userid # Both messages are from the same user msgs[i].message.message += "\\n#{msgs[j].message.message}" # Combine the messages msgs.splice(j,1) # Delete the message from the collection deleted = true else break # Messages are from different people, move on # else break # This is the break point in the chat, don't merge # len = msgs.length ++j if not deleted # ++i len = msgs.length msgs detectUnreadChat: -> #if the current tab is not the same as the tab we just published in Meteor.Chat.find({}).observe({ added: (chatMessage) => findDestinationTab = -> if chatMessage.message?.chat_type is "PUBLIC_CHAT" "PUBLIC_CHAT" else chatMessage.message?.from_userid populateChatTabs() # check if we need to open a new tab destinationTab = findDestinationTab() if destinationTab isnt getInSession "inChatWith" chatTabs.update({userId: destinationTab}, {$set: {gotMail: true}}) }) # When chatbar gets rendered, scroll to the bottom Template.chatbar.rendered = -> Template.chatbar.detectUnreadChat() $('#chatbody').scrollTop($('#chatbody')[0]?.scrollHeight) false # Scrolls the message container to the bottom. The number of pixels to scroll down is the height of the container Handlebars.registerHelper "autoscroll", -> $('#chatbody').scrollTop($('#chatbody')[0]?.scrollHeight) false Template.optionsBar.events 'click .private-chat-user-entry': (event) -> # clicked a user's name to begin private chat setInSession 'display_chatPane', true setInSession "inChatWith", @userId Template.optionsBar.rendered = -> $('div[rel=tooltip]').tooltip() Template.optionsFontSize.events "click .fontSizeSelector": (event) -> selectedFontSize = parseInt(event.target.id) if selectedFontSize setInSession "messageFontSize", selectedFontSize else setInSession "messageFontSize", 12 Template.tabButtons.events 'click .close': (event) -> # user closes private chat setInSession 'inChatWith', 'PUBLIC_CHAT' setInSession 'display_chatPane', true id = chatTabs.findOne({userId: @userId}) console.log "id is:" + JSON.stringify id if id? chatTabs.remove(id) Meteor.call("deletePrivateChatMessages", getInSession("userId"), @userId) return false # stops propogation/prevents default 'click .optionsChatTab': (event) -> setInSession 'display_chatPane', false 'click .privateChatTab': (event) -> setInSession 'display_chatPane', true console.log ".private" 'click .publicChatTab': (event) -> setInSession 'display_chatPane', true 'click .tab': (event) -> setInSession "inChatWith", @userId 'click .gotUnreadMail': (event) -> chatTabs.update({userId: @userId}, {$set: {gotMail: false}}) Template.tabButtons.helpers makeTabButton: -> # create tab button for private chat or other such as options safeClass = @class.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); safeName = @name.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); button = '
  • #{safeName}" button += ' ' if @class is 'privateChatTab' button += '
  • ' button Template.message.helpers activateBreakLines: (str) -> res = str.replace /\\n/gim, '
    ' res = res.replace /\r/gim, '
    ' # make links received from Flash client clickable in HTML toClickable: (str) -> res = str.replace / # First, replace replace all tags with the ascii equivalent (excluding those involved in anchor tags) res = str.replace(/&/g, '&').replace(/<(?![au\/])/g, '<').replace(/\/([^au])>/g, '$1>').replace(/([^=])"(?!>)/g, '$1"'); res = Template.message.toClickable res res = Template.message.activateBreakLines res