Merge pull request #685 from metamaps/feature/chatview-lint

update ChatView.js eslint style
This commit is contained in:
Devin Howard 2016-09-29 15:21:15 +08:00 committed by GitHub
commit 9af3f04f4d

View file

@ -9,326 +9,346 @@ import Backbone from 'backbone'
import Autolinker from 'autolinker' import Autolinker from 'autolinker'
import _ from 'lodash' import _ from 'lodash'
import underscore from 'underscore' import underscore from 'underscore'
import outdent from 'outdent'
// TODO is this line good or bad // TODO is this line good or bad
// Backbone.$ = window.$ // Backbone.$ = window.$
const linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false, twitter: false }); const linker = new Autolinker({ newWindow: true, truncate: 50, email: false, phone: false, twitter: false })
var Private = { var Private = {
messageHTML: "<div class='chat-message'>" + messageHTML: outdent`
"<div class='chat-message-user'><img src='{{ user_image }}' title='{{user_name }}'/></div>" + <div class='chat-message'>
"<div class='chat-message-text'>{{ message }}</div>" + <div class='chat-message-user'><img src='{{ user_image }}' title='{{user_name }}'/></div>
"<div class='chat-message-time'>{{ timestamp }}</div>" + <div class='chat-message-text'>{{ message }}</div>
"<div class='clearfloat'></div>" + <div class='chat-message-time'>{{ timestamp }}</div>
"</div>", <div class='clearfloat'></div>
participantHTML: "<div class='participant participant-{{ id }} {{ selfClass }}'>" + </div>`,
"<div class='chat-participant-image'><img src='{{ image }}' style='border: 2px solid {{ color }};' /></div>" + participantHTML: outdent`
"<div class='chat-participant-name'>{{ username }} {{ selfName }}</div>" + <div class='participant participant-{{ id }} {{ selfClass }}'>
"<button type='button' class='button chat-participant-invite-call' onclick='Metamaps.Realtime.inviteACall({{ id}});'></button>" + <div class='chat-participant-image'>
"<button type='button' class='button chat-participant-invite-join' onclick='Metamaps.Realtime.inviteToJoin({{ id}});'></button>" + <img src='{{ image }}' style='border: 2px solid {{ color }};' />
"<span class='chat-participant-participating'><div class='green-dot'></div></span>" + </div>
"<div class='clearfloat'></div>" + <div class='chat-participant-name'>
"</div>", {{ username }} {{ selfName }}
templates: function() { </div>
underscore.templateSettings = { <button type='button'
interpolate: /\{\{(.+?)\}\}/g class='button chat-participant-invite-call'
}; onclick='Metamaps.Realtime.inviteACall({{ id}});'
this.messageTemplate = underscore.template(Private.messageHTML); ></button>
<button type='button'
this.participantTemplate = underscore.template(Private.participantHTML); class='button chat-participant-invite-join'
}, onclick='Metamaps.Realtime.inviteToJoin({{ id}});'
createElements: function() { ></button>
this.$unread = $('<div class="chat-unread"></div>'); <span class='chat-participant-participating'>
this.$button = $('<div class="chat-button"><div class="tooltips">Chat</div></div>'); <div class='green-dot'></div>
this.$messageInput = $('<textarea placeholder="Send a message..." class="chat-input"></textarea>'); </span>
this.$juntoHeader = $('<div class="junto-header">PARTICIPANTS</div>'); <div class='clearfloat'></div>
this.$videoToggle = $('<div class="video-toggle"></div>'); </div>`,
this.$cursorToggle = $('<div class="cursor-toggle"></div>'); templates: function () {
this.$participants = $('<div class="participants"></div>'); underscore.templateSettings = {
this.$conversationInProgress = $('<div class="conversation-live">LIVE <span class="call-action leave" onclick="Metamaps.Realtime.leaveCall();">LEAVE</span><span class="call-action join" onclick="Metamaps.Realtime.joinCall();">JOIN</span></div>'); interpolate: /\{\{(.+?)\}\}/g
this.$chatHeader = $('<div class="chat-header">CHAT</div>');
this.$soundToggle = $('<div class="sound-toggle"></div>');
this.$messages = $('<div class="chat-messages"></div>');
this.$container = $('<div class="chat-box"></div>');
},
attachElements: function() {
this.$button.append(this.$unread);
this.$juntoHeader.append(this.$videoToggle);
this.$juntoHeader.append(this.$cursorToggle);
this.$chatHeader.append(this.$soundToggle);
this.$participants.append(this.$conversationInProgress);
this.$container.append(this.$juntoHeader);
this.$container.append(this.$participants);
this.$container.append(this.$chatHeader);
this.$container.append(this.$button);
this.$container.append(this.$messages);
this.$container.append(this.$messageInput);
},
addEventListeners: function() {
var self = this;
this.participants.on('add', function (participant) {
Private.addParticipant.call(self, participant);
});
this.participants.on('remove', function (participant) {
Private.removeParticipant.call(self, participant);
});
this.$button.on('click', function () {
Handlers.buttonClick.call(self);
});
this.$videoToggle.on('click', function () {
Handlers.videoToggleClick.call(self);
});
this.$cursorToggle.on('click', function () {
Handlers.cursorToggleClick.call(self);
});
this.$soundToggle.on('click', function () {
Handlers.soundToggleClick.call(self);
});
this.$messageInput.on('keyup', function (event) {
Handlers.keyUp.call(self, event);
});
this.$messageInput.on('focus', function () {
Handlers.inputFocus.call(self);
});
this.$messageInput.on('blur', function () {
Handlers.inputBlur.call(self);
});
},
initializeSounds: function() {
this.sound = new Howl({
urls: [Metamaps.Erb['sounds/MM_sounds.mp3'], Metamaps.Erb['sounds/MM_sounds.ogg']],
sprite: {
joinmap: [0, 561],
leavemap: [1000, 592],
receivechat: [2000, 318],
sendchat: [3000, 296],
sessioninvite: [4000, 5393, true]
}
});
},
incrementUnread: function() {
this.unreadMessages++;
this.$unread.html(this.unreadMessages);
this.$unread.show();
},
addMessage: function(message, isInitial, wasMe) {
if (!this.isOpen && !isInitial) Private.incrementUnread.call(this);
function addZero(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
var m = _.clone(message.attributes);
var today = new Date();
m.timestamp = new Date(m.created_at);
var date = (m.timestamp.getMonth() + 1) + '/' + m.timestamp.getDate();
date += " " + addZero(m.timestamp.getHours()) + ":" + addZero(m.timestamp.getMinutes());
m.timestamp = date;
m.image = m.user_image || 'http://www.hotpepper.ca/wp-content/uploads/2014/11/default_profile_1_200x200.png'; // TODO: remove
m.message = linker.link(m.message);
var $html = $(this.messageTemplate(m));
this.$messages.append($html);
if (!isInitial) this.scrollMessages(200);
if (!wasMe && !isInitial && this.alertSound) this.sound.play('receivechat');
},
initialMessages: function() {
var messages = this.messages.models;
for (var i = 0; i < messages.length; i++) {
Private.addMessage.call(this, messages[i], true);
}
},
handleInputMessage: function() {
var message = {
message: this.$messageInput.val(),
};
this.$messageInput.val('');
$(document).trigger(ChatView.events.message + '-' + this.room, [message]);
},
addParticipant: function(participant) {
var p = _.clone(participant.attributes);
if (p.self) {
p.selfClass = 'is-self';
p.selfName = '(me)';
} else {
p.selfClass = '';
p.selfName = '';
}
var html = this.participantTemplate(p);
this.$participants.append(html);
},
removeParticipant: function(participant) {
this.$container.find('.participant-' + participant.get('id')).remove();
} }
}; this.messageTemplate = underscore.template(Private.messageHTML)
this.participantTemplate = underscore.template(Private.participantHTML)
},
createElements: function () {
this.$unread = $('<div class="chat-unread"></div>')
this.$button = $('<div class="chat-button"><div class="tooltips">Chat</div></div>')
this.$messageInput = $('<textarea placeholder="Send a message..." class="chat-input"></textarea>')
this.$juntoHeader = $('<div class="junto-header">PARTICIPANTS</div>')
this.$videoToggle = $('<div class="video-toggle"></div>')
this.$cursorToggle = $('<div class="cursor-toggle"></div>')
this.$participants = $('<div class="participants"></div>')
this.$conversationInProgress = $(outdent`
<div class="conversation-live">
LIVE
<span class="call-action leave" onclick="Metamaps.Realtime.leaveCall();">
LEAVE
</span>
<span class="call-action join" onclick="Metamaps.Realtime.joinCall();">
JOIN
</span>
</div>`)
this.$chatHeader = $('<div class="chat-header">CHAT</div>')
this.$soundToggle = $('<div class="sound-toggle"></div>')
this.$messages = $('<div class="chat-messages"></div>')
this.$container = $('<div class="chat-box"></div>')
},
attachElements: function () {
this.$button.append(this.$unread)
this.$juntoHeader.append(this.$videoToggle)
this.$juntoHeader.append(this.$cursorToggle)
this.$chatHeader.append(this.$soundToggle)
this.$participants.append(this.$conversationInProgress)
this.$container.append(this.$juntoHeader)
this.$container.append(this.$participants)
this.$container.append(this.$chatHeader)
this.$container.append(this.$button)
this.$container.append(this.$messages)
this.$container.append(this.$messageInput)
},
addEventListeners: function () {
var self = this
this.participants.on('add', function (participant) {
Private.addParticipant.call(self, participant)
})
this.participants.on('remove', function (participant) {
Private.removeParticipant.call(self, participant)
})
this.$button.on('click', function () {
Handlers.buttonClick.call(self)
})
this.$videoToggle.on('click', function () {
Handlers.videoToggleClick.call(self)
})
this.$cursorToggle.on('click', function () {
Handlers.cursorToggleClick.call(self)
})
this.$soundToggle.on('click', function () {
Handlers.soundToggleClick.call(self)
})
this.$messageInput.on('keyup', function (event) {
Handlers.keyUp.call(self, event)
})
this.$messageInput.on('focus', function () {
Handlers.inputFocus.call(self)
})
this.$messageInput.on('blur', function () {
Handlers.inputBlur.call(self)
})
},
initializeSounds: function () {
this.sound = new Howl({
urls: [Metamaps.Erb['sounds/MM_sounds.mp3'], Metamaps.Erb['sounds/MM_sounds.ogg']],
sprite: {
joinmap: [0, 561],
leavemap: [1000, 592],
receivechat: [2000, 318],
sendchat: [3000, 296],
sessioninvite: [4000, 5393, true]
}
})
},
incrementUnread: function () {
this.unreadMessages++
this.$unread.html(this.unreadMessages)
this.$unread.show()
},
addMessage: function (message, isInitial, wasMe) {
if (!this.isOpen && !isInitial) Private.incrementUnread.call(this)
function addZero (i) {
if (i < 10) {
i = '0' + i
}
return i
}
var m = _.clone(message.attributes)
m.timestamp = new Date(m.created_at)
var date = (m.timestamp.getMonth() + 1) + '/' + m.timestamp.getDate()
date += ' ' + addZero(m.timestamp.getHours()) + ':' + addZero(m.timestamp.getMinutes())
m.timestamp = date
m.image = m.user_image || 'http://www.hotpepper.ca/wp-content/uploads/2014/11/default_profile_1_200x200.png' // TODO: remove
m.message = linker.link(m.message)
var $html = $(this.messageTemplate(m))
this.$messages.append($html)
if (!isInitial) this.scrollMessages(200)
if (!wasMe && !isInitial && this.alertSound) this.sound.play('receivechat')
},
initialMessages: function () {
var messages = this.messages.models
for (var i = 0; i < messages.length; i++) {
Private.addMessage.call(this, messages[i], true)
}
},
handleInputMessage: function () {
var message = {
message: this.$messageInput.val()
}
this.$messageInput.val('')
$(document).trigger(ChatView.events.message + '-' + this.room, [message])
},
addParticipant: function (participant) {
var p = _.clone(participant.attributes)
if (p.self) {
p.selfClass = 'is-self'
p.selfName = '(me)'
} else {
p.selfClass = ''
p.selfName = ''
}
var html = this.participantTemplate(p)
this.$participants.append(html)
},
removeParticipant: function (participant) {
this.$container.find('.participant-' + participant.get('id')).remove()
}
}
var Handlers = { var Handlers = {
buttonClick: function() { buttonClick: function () {
if (this.isOpen) this.close(); if (this.isOpen) this.close()
else if (!this.isOpen) this.open(); else if (!this.isOpen) this.open()
}, },
videoToggleClick: function() { videoToggleClick: function () {
this.$videoToggle.toggleClass('active'); this.$videoToggle.toggleClass('active')
this.videosShowing = !this.videosShowing; this.videosShowing = !this.videosShowing
$(document).trigger(this.videosShowing ? ChatView.events.videosOn : ChatView.events.videosOff); $(document).trigger(this.videosShowing ? ChatView.events.videosOn : ChatView.events.videosOff)
}, },
cursorToggleClick: function() { cursorToggleClick: function () {
this.$cursorToggle.toggleClass('active'); this.$cursorToggle.toggleClass('active')
this.cursorsShowing = !this.cursorsShowing; this.cursorsShowing = !this.cursorsShowing
$(document).trigger(this.cursorsShowing ? ChatView.events.cursorsOn : ChatView.events.cursorsOff); $(document).trigger(this.cursorsShowing ? ChatView.events.cursorsOn : ChatView.events.cursorsOff)
}, },
soundToggleClick: function() { soundToggleClick: function () {
this.alertSound = !this.alertSound; this.alertSound = !this.alertSound
this.$soundToggle.toggleClass('active'); this.$soundToggle.toggleClass('active')
}, },
keyUp: function(event) { keyUp: function (event) {
switch(event.which) { switch (event.which) {
case 13: // enter case 13: // enter
Private.handleInputMessage.call(this); Private.handleInputMessage.call(this)
break; break
}
},
inputFocus: function() {
$(document).trigger(ChatView.events.inputFocus);
},
inputBlur: function() {
$(document).trigger(ChatView.events.inputBlur);
} }
}; },
inputFocus: function () {
$(document).trigger(ChatView.events.inputFocus)
},
inputBlur: function () {
$(document).trigger(ChatView.events.inputBlur)
}
}
const ChatView = function(messages, mapper, room) { const ChatView = function (messages, mapper, room) {
var self = this; this.room = room
this.mapper = mapper
this.messages = messages // backbone collection
this.room = room; this.isOpen = false
this.mapper = mapper; this.alertSound = true // whether to play sounds on arrival of new messages or not
this.messages = messages; // backbone collection this.cursorsShowing = true
this.videosShowing = true
this.unreadMessages = 0
this.participants = new Backbone.Collection()
this.isOpen = false; Private.templates.call(this)
this.alertSound = true; // whether to play sounds on arrival of new messages or not Private.createElements.call(this)
this.cursorsShowing = true; Private.attachElements.call(this)
this.videosShowing = true; Private.addEventListeners.call(this)
this.unreadMessages = 0; Private.initialMessages.call(this)
this.participants = new Backbone.Collection(); Private.initializeSounds.call(this)
this.$container.css({
Private.templates.call(this); right: '-300px'
Private.createElements.call(this); })
Private.attachElements.call(this); }
Private.addEventListeners.call(this);
Private.initialMessages.call(this);
Private.initializeSounds.call(this);
this.$container.css({
right: '-300px'
});
};
ChatView.prototype.conversationInProgress = function (participating) { ChatView.prototype.conversationInProgress = function (participating) {
this.$conversationInProgress.show(); this.$conversationInProgress.show()
this.$participants.addClass('is-live'); this.$participants.addClass('is-live')
if (participating) this.$participants.addClass('is-participating'); if (participating) this.$participants.addClass('is-participating')
this.$button.addClass('active'); this.$button.addClass('active')
// hide invite to call buttons // hide invite to call buttons
} }
ChatView.prototype.conversationEnded = function () { ChatView.prototype.conversationEnded = function () {
this.$conversationInProgress.hide(); this.$conversationInProgress.hide()
this.$participants.removeClass('is-live'); this.$participants.removeClass('is-live')
this.$participants.removeClass('is-participating'); this.$participants.removeClass('is-participating')
this.$button.removeClass('active'); this.$button.removeClass('active')
this.$participants.find('.participant').removeClass('active'); this.$participants.find('.participant').removeClass('active')
this.$participants.find('.participant').removeClass('pending'); this.$participants.find('.participant').removeClass('pending')
} }
ChatView.prototype.leaveConversation = function () { ChatView.prototype.leaveConversation = function () {
this.$participants.removeClass('is-participating'); this.$participants.removeClass('is-participating')
} }
ChatView.prototype.mapperJoinedCall = function (id) { ChatView.prototype.mapperJoinedCall = function (id) {
this.$participants.find('.participant-' + id).addClass('active'); this.$participants.find('.participant-' + id).addClass('active')
} }
ChatView.prototype.mapperLeftCall = function (id) { ChatView.prototype.mapperLeftCall = function (id) {
this.$participants.find('.participant-' + id).removeClass('active'); this.$participants.find('.participant-' + id).removeClass('active')
} }
ChatView.prototype.invitationPending = function (id) { ChatView.prototype.invitationPending = function (id) {
this.$participants.find('.participant-' + id).addClass('pending'); this.$participants.find('.participant-' + id).addClass('pending')
} }
ChatView.prototype.invitationAnswered = function (id) { ChatView.prototype.invitationAnswered = function (id) {
this.$participants.find('.participant-' + id).removeClass('pending'); this.$participants.find('.participant-' + id).removeClass('pending')
} }
ChatView.prototype.addParticipant = function (participant) { ChatView.prototype.addParticipant = function (participant) {
this.participants.add(participant); this.participants.add(participant)
} }
ChatView.prototype.removeParticipant = function (username) { ChatView.prototype.removeParticipant = function (username) {
var p = this.participants.find(function (p) { return p.get('username') === username; }); var p = this.participants.find(p => p.get('username') === username)
if (p) { if (p) {
this.participants.remove(p); this.participants.remove(p)
} }
} }
ChatView.prototype.removeParticipants = function () { ChatView.prototype.removeParticipants = function () {
this.participants.remove(this.participants.models); this.participants.remove(this.participants.models)
} }
ChatView.prototype.open = function () { ChatView.prototype.open = function () {
this.$container.css({ this.$container.css({
right: '0' right: '0'
}); })
this.$messageInput.focus(); this.$messageInput.focus()
this.isOpen = true; this.isOpen = true
this.unreadMessages = 0; this.unreadMessages = 0
this.$unread.hide(); this.$unread.hide()
this.scrollMessages(0); this.scrollMessages(0)
$(document).trigger(ChatView.events.openTray); $(document).trigger(ChatView.events.openTray)
} }
ChatView.prototype.addMessage = function(message, isInitial, wasMe) { ChatView.prototype.addMessage = function (message, isInitial, wasMe) {
this.messages.add(message); this.messages.add(message)
Private.addMessage.call(this, message, isInitial, wasMe); Private.addMessage.call(this, message, isInitial, wasMe)
} }
ChatView.prototype.scrollMessages = function(duration) { ChatView.prototype.scrollMessages = function (duration) {
duration = duration || 0; duration = duration || 0
this.$messages.animate({ this.$messages.animate({
scrollTop: this.$messages[0].scrollHeight scrollTop: this.$messages[0].scrollHeight
}, duration); }, duration)
} }
ChatView.prototype.clearMessages = function () { ChatView.prototype.clearMessages = function () {
this.unreadMessages = 0; this.unreadMessages = 0
this.$unread.hide(); this.$unread.hide()
this.$messages.empty(); this.$messages.empty()
} }
ChatView.prototype.close = function () { ChatView.prototype.close = function () {
this.$container.css({ this.$container.css({
right: '-300px' right: '-300px'
}); })
this.$messageInput.blur(); this.$messageInput.blur()
this.isOpen = false; this.isOpen = false
$(document).trigger(ChatView.events.closeTray); $(document).trigger(ChatView.events.closeTray)
} }
ChatView.prototype.remove = function () { ChatView.prototype.remove = function () {
this.$button.off(); this.$button.off()
this.$container.remove(); this.$container.remove()
} }
/** /**
@ -336,15 +356,15 @@ ChatView.prototype.remove = function () {
* @static * @static
*/ */
ChatView.events = { ChatView.events = {
message: 'ChatView:message', message: 'ChatView:message',
openTray: 'ChatView:openTray', openTray: 'ChatView:openTray',
closeTray: 'ChatView:closeTray', closeTray: 'ChatView:closeTray',
inputFocus: 'ChatView:inputFocus', inputFocus: 'ChatView:inputFocus',
inputBlur: 'ChatView:inputBlur', inputBlur: 'ChatView:inputBlur',
cursorsOff: 'ChatView:cursorsOff', cursorsOff: 'ChatView:cursorsOff',
cursorsOn: 'ChatView:cursorsOn', cursorsOn: 'ChatView:cursorsOn',
videosOff: 'ChatView:videosOff', videosOff: 'ChatView:videosOff',
videosOn: 'ChatView:videosOn' videosOn: 'ChatView:videosOn'
}; }
export default ChatView export default ChatView