summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHoussam Haidar <houssam@sdelements.com>2015-04-10 16:21:35 -0400
committerHoussam Haidar <houssam@sdelements.com>2015-04-10 16:21:35 -0400
commitae774d5234e04e77ca14938674346e23c19ee7c9 (patch)
tree44724a77341e24aad9e71d1c3de2a9b7ef368390
parent2a58299b7884ad340ad037cec9f2ca4d7649fc75 (diff)
parent5515052dd7571f0db8492a4c1caf015a5caaef3e (diff)
downloadlets-chat-origin/marionette.zip
lets-chat-origin/marionette.tar.gz
lets-chat-origin/marionette.tar.bz2
Merge branch 'marionette' of github.com:sdelements/lets-chat into marionetteorigin/marionette
Conflicts: templates/chat.html
-rw-r--r--media/js/chat.js1
-rw-r--r--media/js/client.js36
-rw-r--r--media/js/common.js18
-rw-r--r--media/js/models.js83
-rw-r--r--media/js/views/browser.js180
-rw-r--r--media/js/views/client.js133
-rw-r--r--media/js/views/menu.js34
-rw-r--r--media/js/views/modals.js1
-rw-r--r--media/js/views/panes.js264
-rw-r--r--media/js/views/room.js91
-rw-r--r--media/js/views/status.js26
-rw-r--r--media/js/views/upload.js18
-rw-r--r--media/js/views/window.js116
-rw-r--r--media/less/style/chat/tabs.less2
-rw-r--r--templates/chat.html21
-rw-r--r--templates/includes/js/browser-item-user.html4
-rw-r--r--templates/includes/js/browser-item.html38
-rw-r--r--templates/includes/js/browser.html17
-rw-r--r--templates/includes/js/chat.html28
-rw-r--r--templates/includes/js/menu.html41
-rw-r--r--templates/includes/js/room.html171
-rw-r--r--templates/includes/js/status.html11
-rw-r--r--templates/includes/js/tab.html16
-rw-r--r--templates/includes/js/tabs.html7
24 files changed, 831 insertions, 526 deletions
diff --git a/media/js/chat.js b/media/js/chat.js
index 3c43175..c1c9b24 100644
--- a/media/js/chat.js
+++ b/media/js/chat.js
@@ -8,6 +8,7 @@
//= require views/panes.js
//= require views/modals.js
//= require views/upload.js
+//= require views/menu.js
//= require views/client.js
//= require client.js
diff --git a/media/js/client.js b/media/js/client.js
index 867f078..a8d5901 100644
--- a/media/js/client.js
+++ b/media/js/client.js
@@ -35,7 +35,18 @@
this.user = new UserModel();
this.users = new UsersCollection();
this.rooms = new RoomsCollection();
+ this.tabs = new TabCollection();
this.events = _.extend({}, Backbone.Events);
+
+ this.tabs.add(Tab.roomList());
+
+ this.rooms.on('change:joined', function(room, joined) {
+ if (joined) {
+ return this.tabs.add(Tab.room(room));
+ }
+ this.tabs.remove(room.id);
+ }, this);
+
return this;
};
//
@@ -97,9 +108,8 @@
};
Client.prototype.switchRoom = function(id) {
// Make sure we have a last known room ID
- this.rooms.last.set('id', this.rooms.current.get('id'));
if (!id || id === 'list') {
- this.rooms.current.set('id', 'list');
+ this.tabs.selectTab('list');
this.router.navigate('!/', {
replace: true
});
@@ -107,7 +117,7 @@
}
var room = this.rooms.get(id);
if (room && room.get('joined')) {
- this.rooms.current.set('id', id);
+ this.tabs.selectTab(id);
this.router.navigate('!/room/' + room.id, {
replace: true
});
@@ -268,10 +278,7 @@
}
}
this.socket.emit('rooms:leave', id);
- if (id === this.rooms.current.get('id')) {
- var room = this.rooms.get(this.rooms.last.get('id'));
- this.switchRoom(room && room.get('joined') ? room.id : '');
- }
+
// Remove room id from localstorage
RoomStore.remove(id);
};
@@ -298,7 +305,7 @@
var lastMessageOwner = room.get('lastMessageOwner');
var lastMessagePosted = room.get('lastMessagePosted');
- var msg = new MessageModel(_.extend(message, {
+ var model = new MessageModel(_.extend(message, {
paste: /\n/i.test(message.text),
@@ -310,11 +317,11 @@
posted.diff(lastMessagePosted, 'minutes') < 5
}));
- room.messages.add(msg);
+ room.messages.add(model);
room.set('lastMessageOwner', message.owner.id);
room.set('lastMessagePosted', posted);
- room.trigger('messages:new', message);
+ room.trigger('messages:new', model);
};
Client.prototype.addMessages = function(messages, historical) {
_.each(messages, function(message) {
@@ -559,9 +566,14 @@
this.getReplacements();
this.listen();
this.route();
- this.view = new window.LCB.ClientView({
- client: this
+
+ this.view = new window.LCB.RootView({
+ client: this,
+ childView: window.LCB.ClientView
});
+
+ this.view.render();
+
this.passwordModal = new window.LCB.RoomPasswordModalView({
el: $('#lcb-password')
});
diff --git a/media/js/common.js b/media/js/common.js
index ccdd8ba..ef7d3c0 100644
--- a/media/js/common.js
+++ b/media/js/common.js
@@ -1,3 +1,21 @@
+Marionette.Renderer.render = function(template, data) {
+ if (typeof template === 'function') {
+ return template(data);
+ }
+
+ var self = Marionette.Renderer.render;
+
+ if (!self.cache) {
+ self.cache = {};
+ }
+
+ if (!self.cache[template]) {
+ self.cache[template] = Handlebars.compile($(template).html());
+ }
+
+ return self.cache[template](data);
+};
+
// Validator defaults
$.validator.setDefaults({
diff --git a/media/js/models.js b/media/js/models.js
index ff6fac7..7d83a66 100644
--- a/media/js/models.js
+++ b/media/js/models.js
@@ -2,6 +2,62 @@
// LCB Models
//
+var Tab = Backbone.Model.extend({
+ defaults: {
+ id: 'list',
+ type: 'list',
+ name: 'Rooms',
+ model: null
+ },
+
+ initialize: function() {
+ var type = this.get('type');
+
+ if (type === 'room') {
+ var room = this.get('model');
+ this.set('name', room.get('name'));
+ room.on('change:name', function(name) {
+ this.set('name', name);
+ }, this);
+ }
+ }
+
+});
+
+Tab.roomList = function(room) {
+ return new Tab();
+};
+
+Tab.room = function(room) {
+ return new Tab({
+ id: room.id,
+ type: 'room',
+ model: room
+ });
+};
+
+var TabCollection = Backbone.Collection.extend({
+ model: Tab,
+ initialize: function() {
+ this.on('remove', function(model) {
+ if (model.get('selected')) {
+ model.set('selected', false);
+ this.get('list').set('selected', true);
+ }
+ }, this);
+ },
+
+ selectTab: function(id) {
+ var tab = this.get(id);
+ if (tab) {
+ this.forEach(function(x) {
+ x.set('selected', false);
+ });
+ tab.set('selected', true);
+ }
+ }
+});
+
var UserModel = Backbone.Model.extend();
var UsersCollection = Backbone.Collection.extend({
@@ -47,7 +103,30 @@ var RoomModel = Backbone.Model.extend({
var RoomsCollection = Backbone.Collection.extend({
model: RoomModel,
initialize: function() {
- this.current = new Backbone.Model();
- this.last = new Backbone.Model();
+ this.on('users:add users:remove', this.sort);
+ },
+ comparator: function(a, b) {
+ var au = a.users.length,
+ bu = b.users.length,
+ aj = a.get('joined'),
+ bj = b.get('joined');
+
+ if (aj && bj || !aj && !bj) {
+ if (au > bu) {
+ return -1;
+ }
+ if (au < bu) {
+ return 1;
+ }
+ }
+
+ if (aj) {
+ return -1;
+ }
+
+ if (bj) {
+ return 1;
+ }
+ return 0;
}
});
diff --git a/media/js/views/browser.js b/media/js/views/browser.js
index 6235a59..0e47852 100644
--- a/media/js/views/browser.js
+++ b/media/js/views/browser.js
@@ -9,101 +9,120 @@
window.LCB = window.LCB || {};
- window.LCB.BrowserView = Backbone.View.extend({
+ var BrowserItemUser = Marionette.ItemView.extend({
+ tagName: 'li',
+ template:'#template-room-browser-item-user',
+ attributes: function() {
+ return {
+ 'class': 'lcb-rooms-list-user',
+ 'data-id': this.model.get('id'),
+ 'title': this.model.get('displayName')
+ };
+ }
+ });
+
+ var BrowserItem = Marionette.CompositeView.extend({
+ tagName: 'li',
+ template: '#template-room-browser-item',
+ attributes: function() {
+ return {
+ 'class': 'lcb-rooms-list-item',
+ 'data-id': this.model.get('id')
+ };
+ },
+
events: {
- 'submit .lcb-rooms-add': 'create',
- 'keyup .lcb-rooms-browser-filter-input': 'filter',
'change .lcb-rooms-switch': 'toggle',
'click .lcb-rooms-switch-label': 'toggle'
},
- initialize: function(options) {
- this.client = options.client;
- this.template = Handlebars.compile($('#template-room-browser-item').html());
- this.userTemplate = Handlebars.compile($('#template-room-browser-item-user').html());
- this.rooms = options.rooms;
- this.rooms.on('add', this.add, this);
- this.rooms.on('remove', this.remove, this);
- this.rooms.on('change:description change:name', this.update, this);
- this.rooms.on('change:lastActive', _.debounce(this.updateLastActive, 200), this);
- this.rooms.on('change:joined', this.updateToggles, this);
- this.rooms.on('users:add', this.addUser, this);
- this.rooms.on('users:remove', this.removeUser, this);
- this.rooms.on('users:add users:remove add remove', this.sort, this);
- this.rooms.current.on('change:id', function(current, id) {
- // We only care about the list pane
- if (id !== 'list') return;
- this.sort();
- }, this);
+
+ childView: BrowserItemUser,
+ childViewContainer: 'ul',
+ onRender: function() {
+ this.update();
+ this.model.on('change', this.update, this);
},
- updateToggles: function(room, joined) {
- this.$('.lcb-rooms-switch[data-id=' + room.id + ']').prop('checked', joined);
+ update: function() {
+ var room = this.model;
+ this.$('.lcb-rooms-list-item-name')
+ .text(room.get('name'));
+ this.$('.lcb-rooms-list-item-description')
+ .text(room.get('description'));
+ this.$('.lcb-rooms-list-item-last-active .value')
+ .text(moment(room.get('lastActive')).calendar());
+ this.$('.lcb-rooms-switch').prop('checked', room.get('joined'));
},
toggle: function(e) {
e.preventDefault();
- var $target = $(e.currentTarget),
- $input = $target.is(':checkbox') && $target || $target.siblings('[type="checkbox"]'),
- id = $input.data('id'),
- room = this.rooms.get(id);
- if (!room) {
- return;
- }
-
- if (room.get('joined')) {
- this.client.leaveRoom(room.id);
+ if (this.model.get('joined')) {
+ window.client.leaveRoom(this.model.id);
} else {
- this.client.joinRoom(room);
+ window.client.joinRoom(this.model);
}
+ }
+ });
+
+ window.LCB.BrowserView = Marionette.CompositeView.extend({
+ tagName: 'div',
+ template: '#template-room-browser',
+
+ attributes: function() {
+ return {
+ 'class': 'lcb-rooms-browser lcb-pane',
+ 'data-id': 'list'
+ };
},
- add: function(room) {
- var room = room.toJSON ? room.toJSON() : room,
- context = _.extend(room, {
- lastActive: moment(room.lastActive).calendar()
- });
- this.$('.lcb-rooms-list').append(this.template(context));
- },
- remove: function(room) {
- this.$('.lcb-rooms-list-item[data-id=' + room.id + ']').remove();
+
+ events: {
+ 'submit .lcb-rooms-add': 'create',
+ 'keyup .lcb-rooms-browser-filter-input': 'search'
},
- update: function(room) {
- this.$('.lcb-rooms-list-item[data-id=' + room.id + '] .lcb-rooms-list-item-name').text(room.get('name'));
- this.$('.lcb-rooms-list-item[data-id=' + room.id + '] .lcb-rooms-list-item-description').text(room.get('description'));
+
+ ui: {
+ filter: '.lcb-rooms-browser-filter-input'
},
- updateLastActive: function(room) {
- this.$('.lcb-rooms-list-item[data-id=' + room.id + '] .lcb-rooms-list-item-last-active .value').text(moment(room.get('lastActive')).calendar());
+
+ childView: BrowserItem,
+ childViewContainer: 'ul',
+
+ childViewOptions: function(model, index) {
+ return {
+ model: model,
+ collection: model.users
+ };
},
- sort: function(model) {
- var that = this,
- $items = this.$('.lcb-rooms-list-item');
- // We only care about other users
- if (this.$el.hasClass('hide') && model && model.id === this.client.user.id)
- return;
- $items.sort(function(a, b){
- var ar = that.rooms.get($(a).data('id')),
- br = that.rooms.get($(b).data('id')),
- au = ar.users.length,
- bu = br.users.length,
- aj = ar.get('joined'),
- bj = br.get('joined')
- if ((aj && bj) || (!aj && !bj)) {
- if (au > bu) return -1;
- if (au < bu) return 1;
+
+ initialize: function(options) {
+ options.tab.on('change:selected', function(current, selected) {
+ if (selected) {
+ this.$el.show();
+ } else {
+ this.$el.hide();
}
- if (aj) return -1;
- if (bj) return 1;
- return 0;
- });
- $items.detach().appendTo(this.$('.lcb-rooms-list'));
+ }, this);
},
- filter: function(e) {
+
+ search: function(e) {
e.preventDefault();
- var $input = $(e.currentTarget),
- needle = $input.val().toLowerCase();
- this.$('.lcb-rooms-list-item').each(function () {
- var haystack = $(this).find('.lcb-rooms-list-item-name').text().toLowerCase();
- $(this).toggle(haystack.indexOf(needle) >= 0);
- });
+ this._renderChildren();
+ },
+
+ addChild: function (item, ItemView, index) {
+ var val = this.ui.filter.val(); // ????
+
+ if (val) {
+ var needle = val.toLowerCase();
+ var haystack = item.get('name').toLowerCase();
+
+ if (haystack.indexOf(needle) === -1) {
+ return;
+ }
+ }
+
+ Marionette.CollectionView.prototype.addChild.apply(this, arguments);
},
+
create: function(e) {
var that = this;
e.preventDefault();
@@ -160,16 +179,7 @@
}
this.client.events.trigger('rooms:create', data);
- },
- addUser: function(user, room) {
- this.$('.lcb-rooms-list-item[data-id="' + room.id + '"]')
- .find('.lcb-rooms-list-users').prepend(this.userTemplate(user.toJSON()));
- },
- removeUser: function(user, room) {
- this.$('.lcb-rooms-list-item[data-id="' + room.id + '"]')
- .find('.lcb-rooms-list-user[data-id="' + user.id + '"]').remove();
}
-
});
}(window, $, _);
diff --git a/media/js/views/client.js b/media/js/views/client.js
index b14b305..84a122a 100644
--- a/media/js/views/client.js
+++ b/media/js/views/client.js
@@ -9,99 +9,62 @@
window.LCB = window.LCB || {};
- window.LCB.ClientView = Backbone.View.extend({
- el: '#lcb-client',
+ window.LCB.ClientView = Marionette.LayoutView.extend({
+
+ attributes: {
+ 'id': 'lcb-client',
+ 'class': 'lcb-client'
+ },
+
+ template: '#template-chat',
+
events: {
- 'click .lcb-tab': 'toggleSideBar',
+ // 'click .lcb-tab': 'toggleSideBar',
'click .lcb-header-toggle': 'toggleSideBar'
},
- initialize: function(options) {
- this.client = options.client;
- //
- // Subviews
- //
- this.browser = new window.LCB.BrowserView({
- el: this.$el.find('.lcb-rooms-browser'),
- rooms: this.client.rooms,
- client: this.client
- });
- this.tabs = new window.LCB.TabsView({
- el: this.$el.find('.lcb-tabs'),
- rooms: this.client.rooms,
- client: this.client
- });
- this.panes = new window.LCB.PanesView({
- el: this.$el.find('.lcb-panes'),
- rooms: this.client.rooms,
- client: this.client
- });
- this.window = new window.LCB.WindowView({
- rooms: this.client.rooms,
- client: this.client
- });
+
+ regions: {
+ status: '.lcb-status-indicators',
+ menu: '.lcb-menu',
+ tabs: '.lcb-tabs',
+ panes: '.lcb-panes',
+ },
+
+ onRender: function() {
+ this.options.client.status.once('change:connected',
+ this.hideLoadingIndicator, this);
+
+ this.getRegion('status').show(new window.LCB.StatusView({
+ client: this.options.client
+ }));
+
+ this.getRegion('menu').show(new window.LCB.MenuView({
+ model: this.options.client.user,
+ client: this.options.client
+ }));
+
+ this.getRegion('tabs').show(new window.LCB.TabsView({
+ collection: this.options.client.tabs,
+ client: this.options.client
+ }));
+
+ this.getRegion('panes').show(new window.LCB.PanesView({
+ collection: this.options.client.tabs,
+ client: this.options.client
+ }));
+
this.hotKeys = new window.LCB.HotKeysView({
- rooms: this.client.rooms,
- client: this.client
+ rooms: this.options.client.rooms,
+ client: this.options.client
});
- this.status = new window.LCB.StatusView({
- el: this.$el.find('.lcb-status-indicators'),
- client: this.client
- });
- this.accountButton = new window.LCB.AccountButtonView({
- el: this.$el.find('.lcb-account-button'),
- model: this.client.user
- });
- this.desktopNotifications = new window.LCB.DesktopNotificationsView({
- rooms: this.client.rooms,
- client: this.client
- });
- if (this.client.options.filesEnabled) {
- this.upload = new window.LCB.UploadView({
- el: this.$el.find('#lcb-upload'),
- rooms: this.client.rooms
- });
- }
-
- //
- // Modals
- //
- this.profileModal = new window.LCB.ProfileModalView({
- el: this.$el.find('#lcb-profile'),
- model: this.client.user
- });
- this.accountModal = new window.LCB.AccountModalView({
- el: this.$el.find('#lcb-account'),
- model: this.client.user
- });
- this.tokenModal = new window.LCB.AuthTokensModalView({
- el: this.$el.find('#lcb-tokens')
- });
- this.notificationsModal = new window.LCB.NotificationsModalView({
- el: this.$el.find('#lcb-notifications')
- });
- this.giphyModal = new window.LCB.GiphyModalView({
- el: this.$el.find('#lcb-giphy')
- });
- //
- // Misc
- //
- this.client.status.once('change:connected', _.bind(function(status, connected) {
- this.$el.find('.lcb-client-loading').hide(connected);
- }, this));
- return this;
},
- toggleSideBar: function(e) {
- this.$el.toggleClass('lcb-sidebar-opened');
- }
- });
- window.LCB.AccountButtonView = Backbone.View.extend({
- initialize: function() {
- this.model.on('change', this.update, this);
+ hideLoadingIndicator: function(status, connected) {
+ this.$el.find('.lcb-client-loading').hide(connected);
},
- update: function(user){
- this.$('.lcb-account-button-username').text('@' + user.get('username'));
- this.$('.lcb-account-button-name').text(user.get('displayName'));
+
+ toggleSideBar: function(e) {
+ this.$el.toggleClass('lcb-sidebar-opened');
}
});
diff --git a/media/js/views/menu.js b/media/js/views/menu.js
new file mode 100644
index 0000000..7e38c17
--- /dev/null
+++ b/media/js/views/menu.js
@@ -0,0 +1,34 @@
+/*
+ * CLIENT VIEW
+ * The king of all views.
+ */
+
+'use strict';
+
++function(window, $, _) {
+
+ window.LCB = window.LCB || {};
+
+ window.LCB.MenuView = Marionette.ItemView.extend({
+ tagName: 'div',
+
+ attributes: {
+ 'class': 'lcb-menu-inner'
+ },
+
+ template: '#template-menu',
+
+ onRender: function() {
+ this.model.on('change', this.update, this);
+ },
+
+ update: function(user){
+ this.$('.lcb-account-button-username')
+ .text('@' + user.get('username'));
+ this.$('.lcb-account-button-name')
+ .text(user.get('displayName'));
+ }
+ });
+
+
+}(window, $, _);
diff --git a/media/js/views/modals.js b/media/js/views/modals.js
index a6d1c41..1bd48a2 100644
--- a/media/js/views/modals.js
+++ b/media/js/views/modals.js
@@ -221,7 +221,6 @@
}
},
loadGifs: _.throttle(function() {
- console.log(1)
var that = this;
var search = this.$el.find('.search-giphy').val();
diff --git a/media/js/views/panes.js b/media/js/views/panes.js
index 78d5cc0..9104c48 100644
--- a/media/js/views/panes.js
+++ b/media/js/views/panes.js
@@ -8,149 +8,175 @@
window.LCB = window.LCB || {};
- window.LCB.TabsView = Backbone.View.extend({
- events: {
- 'click .lcb-tab-close': 'leave'
+ var TabView = Marionette.ItemView.extend({
+ tagName: 'li',
+
+ template: function() { return ''; },
+
+ attributes: function() {
+ var opts = {
+ 'class': 'lcb-tab',
+ 'data-id': this.model.id,
+
+ };
+
+ if (this.model.get('selected')) {
+ opts.class += ' selected';
+ }
+
+ return opts;
},
- focus: true,
- initialize: function(options) {
- this.client = options.client;
- this.template = Handlebars.compile($('#template-room-tab').html());
- this.rooms = options.rooms;
- // Room joining
- this.rooms.on('change:joined', function(room, joined) {
- if (joined) {
- this.add(room.toJSON());
- return;
- }
- this.remove(room.id);
- }, this);
- // Room meta updates
- this.rooms.on('change:name change:description', this.update, this);
- // Current room switching
- this.rooms.current.on('change:id', function(current, id) {
- this.switch(id);
- this.clearAlerts(id);
- }, this);
- // Alerts
- this.rooms.on('messages:new', this.alert, this);
- // Initial switch since router runs before view is loaded
- this.switch(this.rooms.current.get('id'));
- // Blur/Focus events
- $(window).on('focus blur', _.bind(this.onFocusBlur, this));
- this.render();
+
+ onRender: function() {
+ this.model.on('change:selected', this.onSelect, this);
+ this.options.childView.render();
+ this.$el.append(this.options.childView.el);
},
- add: function(room) {
- this.$el.append(this.template(room));
+
+ onSelect: function(current, selected) {
+ if (selected) {
+ this.$el.addClass('selected');
+ } else {
+ this.$el.removeClass('selected');
+ }
+ }
+ });
+
+ var ListTabView = Marionette.ItemView.extend({
+ tagName: 'a',
+
+ attributes: function() {
+ return {
+ 'href': '#!/'
+ };
},
- remove: function(id) {
- this.$el.find('.lcb-tab[data-id=' + id + ']').remove();
+
+ template: function() {
+ return '<i class="fa fa-th"></i>';
+ }
+ });
+
+ var RoomTabView = Marionette.ItemView.extend({
+ tagName: 'a',
+
+ attributes: function() {
+ return {
+ 'href': '#!/room/' + this.model.id
+ };
+ },
+
+ template: '#template-room-tab',
+
+ events: {
+ 'click .lcb-tab-close': 'leave'
},
- update: function(room) {
- this.$el.find('.lcb-tab[data-id=' + room.id + '] .lcb-tab-title').text(room.get('name'));
+
+ ui: {
+ newMessages: '.lcb-tab-alerts-total',
+ newMentions: '.lcb-tab-alerts-mentions'
},
- switch: function(id) {
- if (!id) {
- id = 'list';
- }
- this.$el.find('.lcb-tab').removeClass('selected')
- .filter('[data-id=' + id + ']').addClass('selected');
+
+ onRender: function() {
+ this.model.messages.on('add', this.alert, this);
+ this.options.tab.on('change:selected', this.removeAlerts, this);
+ },
+
+ update: function() {
+ this.$el.find('.lcb-tab-title').text(
+ this.model.get('name')
+ );
},
+
leave: function(e) {
e.preventDefault();
- var id = $(e.currentTarget).closest('[data-id]').data('id');
- this.client.events.trigger('rooms:leave', id);
+ this.options.client.events
+ .trigger('rooms:leave', this.model.get('id'));
},
+
alert: function(message) {
- var $tab = this.$('.lcb-tab[data-id=' + message.room.id + ']'),
- $total = $tab.find('.lcb-tab-alerts-total'),
- $mentions = $tab.find('.lcb-tab-alerts-mentions');
- if (message.historical || $tab.length === 0
- || ((this.rooms.current.get('id') === message.room.id) && this.focus)) {
- // Nothing to do here!
+ if (message.get('historical') || this.options.tab.get('selected')) {
return;
}
- var total = parseInt($tab.data('count-total')) || 0,
- mentions = parseInt($tab.data('count-mentions')) || 0;
- // All messages
- $tab.data('count-total', ++total);
- $total.text(total);
- // Just mentions
- if (new RegExp('\\B@(' + this.client.user.get('username') + ')(?!@)\\b', 'i').test(message.text)) {
- $tab.data('count-mentions', ++mentions);
- $mentions.text(mentions);
+
+ var $total = this.ui.newMessages;
+ var total = parseInt($total.text() || '0') || 0;
+ $total.text(++total);
+
+ if (!message.get('mentioned')) {
+ return;
}
+
+ var $mentions = this.ui.newMentions;
+ var mentions = parseInt($mentions.text() || '0') || 0;
+ $mentions.text(++mentions);
},
- clearAlerts: function(id) {
- var $tab = this.$('.lcb-tab[data-id=' + id + ']'),
- $total = $tab.find('.lcb-tab-alerts-total'),
- $mentions = $tab.find('.lcb-tab-alerts-mentions');
- $tab.data('count-total', 0).data('count-mentions', 0);
- $total.text('');
- $mentions.text('');
- },
- onFocusBlur: function(e) {
- var that = this;
- this.focus = (e.type === 'focus');
- clearTimeout(this.clearTimer);
- if (this.focus) {
- this.clearTimer = setTimeout(function() {
- that.clearAlerts(that.rooms.current.get('id'));
- }, 9 * 1000);
- return;
+
+ removeAlerts: function(tab, selected) {
+ if (selected) {
+ this.$el.data('count-total', 0).data('count-mentions', 0);
+ this.$el.find('.lcb-tab-alerts-total').text('');
+ this.$el.find('.lcb-tab-alerts-mentions').text('');
}
- that.clearAlerts(that.rooms.current.get('id'));
}
+
});
- window.LCB.PanesView = Backbone.View.extend({
- initialize: function(options) {
- this.client = options.client;
- this.template = Handlebars.compile($('#template-room').html());
- this.rooms = options.rooms;
- this.views = {};
- this.rooms.on('change:joined', function(room, joined) {
- if (joined) {
- this.add(room);
- return;
- }
- this.remove(room.id);
- }, this);
- // Switch room
- this.rooms.current.on('change:id', function(current, id) {
- this.switch(id);
- }, this);
- // Initial switch since router runs before view is loaded
- this.switch(this.rooms.current.get('id'));
+ window.LCB.TabsView = Marionette.CompositeView.extend({
+
+ tagName: 'div',
+ childViewContainer: 'ul',
+
+ template: '#template-tabs',
+
+ buildChildView: function(child, ChildViewClass, childViewOptions) {
+ return new TabView({
+ client: this.options.client,
+ model: child,
+ childView: new ChildViewClass(childViewOptions)
+ });
},
- switch: function(id) {
- if (!id) {
- id = 'list';
+
+ getChildView: function(model) {
+ if (model.get('type') === 'list') {
+ return ListTabView;
}
- var $pane = this.$el.find('.lcb-pane[data-id=' + id + ']');
- $pane.removeClass('hide').siblings().addClass('hide');
- $(window).width() > 767 && $pane.find('[autofocus]').focus();
- // this.views[id] && this.views[id].scrollMessages(true);
+ return RoomTabView;
},
- add: function(room) {
- if (this.views[room.id]) {
- // Nothing to do, this room is already here
- return;
+
+ childViewOptions: function(model, index) {
+ return {
+ client: this.options.client,
+ model: model.get('model'),
+ tab: model
+ };
+ }
+ });
+
+ window.LCB.PanesView = Marionette.CollectionView.extend({
+
+ attributes: {
+ 'class': 'lcb-panes-inner'
+ },
+
+ getChildView: function(model) {
+ if (model.get('type') === 'list') {
+ return window.LCB.BrowserView;
}
- this.views[room.id] = new window.LCB.RoomView({
- client: this.client,
- template: this.template,
- model: room
- });
- this.$el.append(this.views[room.id].$el);
+ return window.LCB.RoomView;
},
- remove: function(id) {
- if (!this.views[id]) {
- // Nothing to do here
- return;
+
+ childViewOptions: function(model, index) {
+ var opts = {
+ model: model.get('model'),
+ tab: model,
+ client: this.options.client
+ };
+
+ if (model.get('type') === 'list') {
+ opts.collection = this.options.client.rooms;
}
- this.views[id].destroy();
- delete this.views[id];
+
+ return opts;
}
});
diff --git a/media/js/views/room.js b/media/js/views/room.js
index 2083702..d9aeb75 100644
--- a/media/js/views/room.js
+++ b/media/js/views/room.js
@@ -9,9 +9,19 @@
window.LCB = window.LCB || {};
- window.LCB.RoomView = Backbone.View.extend({
+ window.LCB.RoomView = Marionette.ItemView.extend({
+
+ attributes: function() {
+ return {
+ 'class': 'lcb-room lcb-pane lcb-pane-' + this.model.id,
+ 'data-id': this.model.id,
+ style: 'display: none;'
+ };
+ },
+
+ template: '#template-room',
+
events: {
- 'DOMCharacterDataModified .lcb-room-heading, .lcb-room-description': 'sendMeta',
'click .lcb-room-toggle-sidebar': 'toggleSidebar',
'click .show-edit-room': 'showEditRoom',
'click .hide-edit-room': 'hideEditRoom',
@@ -23,25 +33,32 @@
initialize: function(options) {
this.client = options.client;
+ options.tab.on('change:selected', function(tab, selected) {
+ if (selected) {
+ this.$el.show();
+ } else {
+ this.$el.hide();
+ }
+ }, this);
+
var iAmOwner = this.model.get('owner') === this.client.user.id;
var iCanEdit = iAmOwner || !this.model.get('hasPassword');
this.model.set('iAmOwner', iAmOwner);
this.model.set('iCanEdit', iCanEdit);
- this.template = options.template;
- this.render();
-
this.model.on('change', this.updateMeta, this);
this.model.on('remove', this.goodbye, this);
this.model.users.on('change', this.updateUser, this);
-
- //
- // Subviews
- //
+ },
+ onRender: function() {
+ // this.$el = $(this.template(_.extend(this.model.toJSON(), {
+ // sidebar: store.get('sidebar')
+ // })));
this.messageView = new window.LCB.MessagesView({
collection: this.model.messages,
- el: this.$('.lcb-messages')
+ el: this.$('.lcb-messages'),
+ tab: this.options.tab
});
this.composeView = new window.LCB.ComposeView({
el: this.$('.lcb-compose'),
@@ -64,11 +81,6 @@
this.$('.lcb-room-sidebar').append(this.usersList.el);
this.$('.lcb-room-sidebar').append(this.filesList.el);
},
- render: function() {
- this.$el = $(this.template(_.extend(this.model.toJSON(), {
- sidebar: store.get('sidebar')
- })));
- },
goodbye: function() {
swal('Archived!', '"' + this.model.get('name') + '" has been archived.', 'warning');
},
@@ -77,17 +89,6 @@
this.$('.lcb-room-heading .slug').text('#' + this.model.get('slug'));
this.$('.lcb-room-description').text(this.model.get('description'));
},
- sendMeta: function(e) {
- this.model.set({
- name: this.$('.lcb-room-heading').text(),
- description: this.$('.lcb-room-description').text()
- });
- this.client.events.trigger('rooms:update', {
- id: this.model.id,
- name: this.model.get('name'),
- description: this.model.get('description')
- });
- },
showEditRoom: function(e) {
if (e) {
e.preventDefault();
@@ -172,7 +173,7 @@
this.$el.siblings('.lcb-room').andSelf().toggleClass('lcb-room-sidebar-opened');
// Save to localstorage
if ($(window).width() > 767) {
- this.scrollMessages();
+ // this.scrollMessages();
store.set('sidebar',
this.$el.hasClass('lcb-room-sidebar-opened'));
}
@@ -208,7 +209,7 @@
});
window.LCB.ComposeView = Marionette.ItemView.extend({
- template: Handlebars.compile($('#template-compose').html()),
+ template: '#template-compose',
tagName: 'form',
attributes: {
'class': 'lcb-entry'
@@ -384,7 +385,7 @@
});
var MessageView = Marionette.ItemView.extend({
- template: Handlebars.compile($('#template-message').html()),
+ template: '#template-message',
tagName: 'li',
attributes: function() {
var attrs = {
@@ -444,10 +445,15 @@
'scroll .lcb-messages': 'updateScrollLock',
},
+ scrollLocked: false,
+
onRender: function() {
- // Scroll Locking
- this.scrollLocked = true;
this.$el.on('scroll', _.bind(this.updateScrollLock, this));
+ this.options.tab.on('change:selected', function(tab, selected) {
+ if (selected) {
+ this.scrollMessages();
+ }
+ }, this);
},
onAddChild: function(childView) {
@@ -456,20 +462,25 @@
updateScrollLock: function() {
this.scrollLocked = this.el.scrollHeight -
- this.$el.scrollTop() - 5 <= this.$el.outerHeight();
+ this.$el.scrollTop() - 5 > this.$el.outerHeight();
return this.scrollLocked;
},
- scrollMessages: function(force) {
- // if ((!force && !this.scrollLocked) || this.$el.hasClass('hide')) {
- // return;
- // }
+ scrollMessages: function() {
+ if (this.scrollLocked) {
+ return;
+ }
+
+ if (!this.options.tab.get('selected')) {
+ return;
+ }
+
this.el.scrollTop = this.el.scrollHeight;
}
});
var UserView = Marionette.ItemView.extend({
- template: Handlebars.compile($('#template-user').html()),
+ template: '#template-user',
tagName: 'li',
attributes: function(model) {
return {
@@ -480,7 +491,7 @@
});
var FileView = Marionette.ItemView.extend({
- template: Handlebars.compile($('#template-file').html()),
+ template: '#template-file',
tagName: 'li',
attributes: function(model) {
return {
@@ -495,7 +506,7 @@
attributes: {
'class': 'lcb-room-sidebar-group lcb-room-sidebar-users'
},
- template: Handlebars.compile($('#template-users').html()),
+ template: '#template-users',
childView: UserView,
childViewContainer: 'ul',
@@ -515,7 +526,7 @@
attributes: {
'class': 'lcb-room-sidebar-group lcb-room-sidebar-files'
},
- template: Handlebars.compile($('#template-files').html()),
+ template: '#template-files',
childView: FileView,
childViewContainer: 'ul'
});
diff --git a/media/js/views/status.js b/media/js/views/status.js
index 0089fe5..ace614d 100644
--- a/media/js/views/status.js
+++ b/media/js/views/status.js
@@ -9,15 +9,23 @@
window.LCB = window.LCB || {};
- window.LCB.StatusView = Backbone.View.extend({
- initialize: function(options) {
- var that = this;
- this.client = options.client;
- this.client.status.on('change:connected', function(status, connected) {
- that.$el.find('[data-status="connected"]').toggle(connected);
- that.$el.find('[data-status="disconnected"]').toggle(!connected);
- });
+ window.LCB.StatusView = Marionette.ItemView.extend({
+
+ attributes: {
+ 'class': 'lcb-status-inner'
+ },
+
+ template: '#template-status',
+
+ onRender: function () {
+ this.options.client.status.on('change:connected',
+ this.update, this);
+ },
+
+ update: function(status, connected) {
+ this.$el.find('[data-status="connected"]').toggle(connected);
+ this.$el.find('[data-status="disconnected"]').toggle(!connected);
}
});
-}(window, $, _); \ No newline at end of file
+}(window, $, _);
diff --git a/media/js/views/upload.js b/media/js/views/upload.js
index 2b9a54c..6743fdc 100644
--- a/media/js/views/upload.js
+++ b/media/js/views/upload.js
@@ -16,20 +16,22 @@ Dropzone && (Dropzone.autoDiscover = false);
'submit form': 'submit'
},
initialize: function(options) {
+ this.dropZone = options.dropZone;
this.template = $('#template-upload').html();
- this.rooms = options.rooms;
- this.rooms.current.on('change:id', this.setRoom, this);
+ this.rooms = options.client.rooms;
+ this.tabs = options.client.tabs;
+
this.rooms.on('add remove', this.populateRooms, this);
this.rooms.on('change:joined', this.populateRooms, this);
this.rooms.on('upload:show', this.show, this);
+ this.tabs.on('change:selected', this.setRoom, this);
this.render();
},
render: function() {
//
// Dropzone
//
- var $ele = this.$el.closest('.lcb-client').get(0);
- this.dropzone = new Dropzone($ele, {
+ this.dropzone = new Dropzone(this.dropZone.get(0), {
url: './files',
autoProcessQueue: false,
clickable: [this.$('.lcb-upload-target').get(0)],
@@ -91,8 +93,12 @@ Dropzone && (Dropzone.autoDiscover = false);
}
this.dropzone.processQueue();
},
- setRoom: function() {
- this.selectize.setValue(this.rooms.current.id);
+ setRoom: function(tab, selected) {
+ if (!selected) {
+ return;
+ }
+
+ this.selectize.setValue(tab.id);
},
populateRooms: function() {
this.selectize.clearOptions();
diff --git a/media/js/views/window.js b/media/js/views/window.js
index e6f3c97..6853482 100644
--- a/media/js/views/window.js
+++ b/media/js/views/window.js
@@ -9,43 +9,78 @@
window.LCB = window.LCB || {};
- window.LCB.WindowView = Backbone.View.extend({
+ window.LCB.RootView = Backbone.View.extend({
el: 'html',
+
focus: true,
count: 0,
mentions: 0,
- initialize: function(options) {
- var that = this;
+ modals: {
+
+ },
+ initialize: function(options) {
this.client = options.client;
- this.rooms = options.rooms;
+ this.rooms = options.client.rooms;
+ this.tabs = options.client.tabs;
+
this.originalTitle = this.$('title').text();
this.title = this.originalTitle;
-
$(window).on('focus blur', _.bind(this.onFocusBlur, this));
- this.rooms.current.on('change:id', function(current, id) {
- var room = this.rooms.get(id),
- title = room ? room.get('name') : 'Rooms';
- this.updateTitle(title);
- }, this);
+ var view = new options.childView({
+ client: options.client,
+ el: this.$el.find('#lcb-client')
+ });
+
+ view.render();
+
+ this.initializeModals(options);
+
+ this.notifications = new window.LCB.DesktopNotificationsView({
+ rooms: options.client.rooms,
+ client: options.client
+ });
- this.rooms.on('change:name', function(room) {
- if (room.id !== this.rooms.current.get('id')) {
+ this.rooms.on('messages:new', this.onNewMessage, this);
+
+ this.tabs.on('change:selected', function(tab, selected) {
+ if (!selected) {
return;
}
- this.updateTitle(room.get('name'));
+ this.updateTitle(tab.get('name'));
}, this);
+ },
- this.rooms.on('messages:new', this.onNewMessage, this);
+ initializeModals: function(options) {
+ if (options.client.options.filesEnabled) {
+ this.modals.upload = new window.LCB.UploadView({
+ el: this.$el.find('#lcb-upload'),
+ dropZone: this.$el.find('#lcb-client'),
+ client: options.client
+ });
+ }
- // Last man standing
- _.defer(function() {
- that.updateTitle();
+ this.modals.profile = new window.LCB.ProfileModalView({
+ el: this.$el.find('#lcb-profile'),
+ model: options.client.user
+ });
+ this.modals.account = new window.LCB.AccountModalView({
+ el: this.$el.find('#lcb-account'),
+ model: options.client.user
+ });
+ this.modals.token = new window.LCB.AuthTokensModalView({
+ el: this.$el.find('#lcb-tokens')
+ });
+ this.modals.notifications = new window.LCB.NotificationsModalView({
+ el: this.$el.find('#lcb-notifications')
+ });
+ this.modals.giphy = new window.LCB.GiphyModalView({
+ el: this.$el.find('#lcb-giphy')
});
-
},
+
onFocusBlur: function(e) {
this.focus = (e.type === 'focus');
if (this.focus) {
@@ -57,19 +92,23 @@
this.updateTitle();
}
},
+
onNewMessage: function(message) {
- if (this.focus || message.historical) {
+ if (this.focus || message.get('historical')) {
return;
}
+
this.countMessage(message);
- this.flashTitle()
+ this.flashTitle();
},
+
countMessage: function(message) {
- var username = this.client.user.get('username'),
- regex = new RegExp('\\B@(' + username + ')(?!@)\\b', 'i');
- ++this.count;
- regex.test(message.text) && ++this.mentions;
+ this.count++;
+ if (message.get('mentioned')) {
+ this.mentions++;
+ }
},
+
flashTitle: function() {
if (!this.titleTimer) {
this._flashTitle();
@@ -77,6 +116,7 @@
this.titleTimer = setInterval(flashTitle, 1 * 1000);
}
},
+
_flashTitle: function() {
var titlePrefix = '';
if (this.count > 0) {
@@ -90,11 +130,8 @@
this.$('title').html(title);
this.titleTimerFlip = !this.titleTimerFlip;
},
+
updateTitle: function(name) {
- if (!name) {
- var room = this.rooms.get(this.rooms.current.get('id'));
- name = (room && room.get('name')) || 'Rooms';
- }
if (name) {
this.title = $('<pre />').text(name).html() +
' &middot; ' + this.originalTitle;
@@ -102,7 +139,7 @@
this.title = this.originalTitle;
}
this.$('title').html(this.title);
- },
+ }
});
window.LCB.HotKeysView = Backbone.View.extend({
@@ -157,7 +194,7 @@
});
},
onNewMessage: function(message) {
- if (this.focus || message.historical) {
+ if (this.focus || message.get('historical')) {
return;
}
this.createDesktopNotification(message);
@@ -171,26 +208,27 @@
return;
}
- var roomID = message.room.id,
- avatar = message.owner.avatar,
- icon = 'https://www.gravatar.com/avatar/' + avatar + '?s=50',
- title = message.owner.displayName + ' in ' + message.room.name,
- mention = message.mentioned;
+ var owner = message.get('owner'),
+ room = message.get('room');
+
+ var icon = 'https://www.gravatar.com/avatar/' + owner.avatar + '?s=50';
+
+ var title = owner.displayName + ' in ' + room.name;
var notification = notify.createNotification(title, {
- body: message.text,
- icon: icon,
+ body: message.get('text'),
+ icon: 'https://www.gravatar.com/avatar/' + owner.avatar + '?s=50',
tag: message.id,
autoClose: 1000,
onclick: function() {
window.focus();
- that.client.events.trigger('rooms:switch', roomID);
+ that.client.events.trigger('rooms:switch', room.id);
}
});
//
// Mentions
//
- if (mention) {
+ if (message.get('mentioned')) {
if (this.openMentions.length > 2) {
this.openMentions[0].close();
this.openMentions.shift();
diff --git a/media/less/style/chat/tabs.less b/media/less/style/chat/tabs.less
index c644b2d..28aa89d 100644
--- a/media/less/style/chat/tabs.less
+++ b/media/less/style/chat/tabs.less
@@ -2,7 +2,7 @@
* Tabs
*********************/
-.lcb-tabs,
+.lcb-tabs-list,
.lab-tab {
padding: 0;
margin: 0;
diff --git a/templates/chat.html b/templates/chat.html
index cffb5d4..ed4b5bb 100644
--- a/templates/chat.html
+++ b/templates/chat.html
@@ -7,6 +7,9 @@
<% endblock %>
<% block templates %>
+ <% include 'includes/js/status.html' %>
+ <% include 'includes/js/menu.html' %>
+ <% include 'includes/js/chat.html' %>
<% include 'includes/js/room.html' %>
<% include 'includes/js/compose.html' %>
<% include 'includes/js/user.html' %>
@@ -14,7 +17,9 @@
<% include 'includes/js/file.html' %>
<% include 'includes/js/files.html' %>
<% include 'includes/js/message.html' %>
+ <% include 'includes/js/tabs.html' %>
<% include 'includes/js/tab.html' %>
+ <% include 'includes/js/browser.html' %>
<% include 'includes/js/browser-item.html' %>
<% include 'includes/js/browser-item-user.html' %>
<% include 'includes/js/upload.html' %>
@@ -114,12 +119,14 @@
<div class="lcb-loading lcb-client-loading">
<img class="lcb-loading-indicator" src="./media/img/loading.svg" alt="Loading..." />
</div>
- <% include 'includes/modals/notifications.html' %>
- <% include 'includes/modals/profile.html' %>
- <% include 'includes/modals/account.html' %>
- <% include 'includes/modals/xmpp.html' %>
- <% include 'includes/modals/tokens.html' %>
- <% include 'includes/modals/upload.html' %>
- <% include 'includes/modals/giphy.html' %>
</div><!-- lcb-client end -->
+ <% include 'includes/modals/add-room.html' %>
+ <% include 'includes/modals/password.html' %>
+ <% include 'includes/modals/notifications.html' %>
+ <% include 'includes/modals/profile.html' %>
+ <% include 'includes/modals/account.html' %>
+ <% include 'includes/modals/xmpp.html' %>
+ <% include 'includes/modals/tokens.html' %>
+ <% include 'includes/modals/upload.html' %>
+ <% include 'includes/modals/giphy.html' %>
<% endblock %>
diff --git a/templates/includes/js/browser-item-user.html b/templates/includes/js/browser-item-user.html
index c7b87ff..a4a77a3 100644
--- a/templates/includes/js/browser-item-user.html
+++ b/templates/includes/js/browser-item-user.html
@@ -1,5 +1,3 @@
<script type="text/x-handlebars-template" id="template-room-browser-item-user">
- <li class="lcb-rooms-list-user" data-id="{{id}}" title="{{displayName}}">
- <img class="lcb-rooms-list-user-avatar" src="https://www.gravatar.com/avatar/{{avatar}}?s=50" alt="{{displayName}}" />
- </li>
+ <img class="lcb-rooms-list-user-avatar" src="https://www.gravatar.com/avatar/{{avatar}}?s=50" alt="{{displayName}}" />
</script>
diff --git a/templates/includes/js/browser-item.html b/templates/includes/js/browser-item.html
index 6c6ba2b..bcb20ac 100644
--- a/templates/includes/js/browser-item.html
+++ b/templates/includes/js/browser-item.html
@@ -1,22 +1,20 @@
<script type="text/x-handlebars-template" id="template-room-browser-item">
- <li class="lcb-rooms-list-item" data-id="{{id}}">
- <div class="lcb-rooms-list-item-top">
- {{#if hasPassword}}
- <span class="lcb-rooms-list-item-password fa fa-lock"></span>
- <a class="lcb-rooms-list-item-name" href="#!/room/{{id}}">{{name}}</a>
- {{else}}
- <a class="lcb-rooms-list-item-name" href="#!/room/{{id}}">{{name}}</a>
- {{/if}}
- <span class="lcb-rooms-list-item-slug">#{{slug}}</span>
- </div>
- <div class="lcb-rooms-list-item-description">{{description}}</div>
- <ul class="lcb-rooms-list-users"></ul>
- <div class="lcb-rooms-list-item-switch onoffswitch">
- <input type="checkbox" class="switch lcb-rooms-switch" id="room-switch-{{id}}" data-id="{{id}}" />
- <label class="switch lcb-rooms-switch-label" for="room-switch-{{id}}"></label>
- </div>
- <div class="lcb-rooms-list-item-last-active">
- <i class="fa fa-clock-o"></i> <span class="value">{{lastActive}}</span>
- </div>
- </li>
+ <div class="lcb-rooms-list-item-top">
+ {{#if hasPassword}}
+ <span class="lcb-rooms-list-item-password fa fa-lock"></span>
+ <a class="lcb-rooms-list-item-name" href="#!/room/{{id}}">{{name}}</a>
+ {{else}}
+ <a class="lcb-rooms-list-item-name" href="#!/room/{{id}}">{{name}}</a>
+ {{/if}}
+ <span class="lcb-rooms-list-item-slug">#{{slug}}</span>
+ </div>
+ <div class="lcb-rooms-list-item-description">{{description}}</div>
+ <ul class="lcb-rooms-list-users"></ul>
+ <div class="lcb-rooms-list-item-switch onoffswitch">
+ <input type="checkbox" class="switch lcb-rooms-switch" id="room-switch-{{id}}" data-id="{{id}}" />
+ <label class="switch lcb-rooms-switch-label" for="room-switch-{{id}}"></label>
+ </div>
+ <div class="lcb-rooms-list-item-last-active">
+ <i class="fa fa-clock-o"></i> <span class="value">{{lastActive}}</span>
+ </div>
</script>
diff --git a/templates/includes/js/browser.html b/templates/includes/js/browser.html
new file mode 100644
index 0000000..5a138bb
--- /dev/null
+++ b/templates/includes/js/browser.html
@@ -0,0 +1,17 @@
+<script type="text/x-handlebars-template" id="template-room-browser">
+ <header class="lcb-rooms-browser-header">
+ <h2 class="lcb-rooms-browser-heading">
+ All Rooms
+ </h2>
+ <div class="lcb-rooms-browser-filter">
+ <label class="lcb-rooms-browser-filter-label" for="lcb-rooms-browser-filter-input">
+ <i class="fa fa-search"></i>
+ </label>
+ <input id="lcb-rooms-browser-filter-input" class="lcb-rooms-browser-filter-input" type="search" autofocus />
+ </div>
+ <a class="btn btn-success lcb-rooms-browser-new" data-toggle="modal" data-target="#lcb-add-room" href="#!/rooms/add">
+ <i class="fa fa-plus"></i>
+ </a>
+ </header>
+ <ul class="lcb-rooms-list"></ul>
+</script>
diff --git a/templates/includes/js/chat.html b/templates/includes/js/chat.html
new file mode 100644
index 0000000..8bcddce
--- /dev/null
+++ b/templates/includes/js/chat.html
@@ -0,0 +1,28 @@
+<script type="text/x-handlebars-template" id="template-chat">
+ <div class="lcb-header">
+ <button type="button" class="btn lcb-header-toggle">
+ <i class="fa fa-bars"></i>
+ </button>
+ <div class="lcb-header-logo">Let's Chat</div>
+ </div>
+ <section class="lcb-sidebar">
+ <div class="lcb-menu"></div>
+ <div class="lcb-status-indicators">
+ <span class="lcb-status-indicator lcb-status-indicator-error lcb-status-connection" data-status="disconnected" style="display: none;">
+ <i class="fa fa-plug"></i> Disconnected
+ </span>
+ <span class="lcb-status-indicator lcb-status-connection" data-status="connected" style="display: none;">
+ <i class="fa fa-refresh"></i> Connected
+ </span>
+ <span class="lcb-status-indicator lcb-status-connection" style="display: none;">
+ <i class="fa fa-bell-slash"></i>
+ </span>
+ </div>
+ <div class="lcb-tabs">
+ </div>
+ </section>
+ <section class="lcb-panes"></section>
+ <div class="lcb-loading lcb-client-loading">
+ <img class="lcb-loading-indicator" src="./media/img/loading.svg" alt="Loading..." />
+ </div>
+</script>
diff --git a/templates/includes/js/menu.html b/templates/includes/js/menu.html
new file mode 100644
index 0000000..8281b9d
--- /dev/null
+++ b/templates/includes/js/menu.html
@@ -0,0 +1,41 @@
+<script type="text/x-handlebars-template" id="template-menu">
+ <div class="dropdown">
+ <a class="lcb-account-button dropdown-toggle" data-toggle="dropdown" href="3">
+ <img class="lcb-account-button-avatar lcb-avatar" src="https://www.gravatar.com/avatar/<$ account.avatar $>?s=50" />
+ <span class="lcb-account-button-name"><$ account.displayName $></span>
+ <span class="lcb-account-button-username">@<$ account.username $></span>
+ <i class="lcb-account-button-chevron fa fa-chevron-down"></i>
+ </a>
+ <ul class="dropdown-menu dropdown-menu-right">
+ <li>
+ <a data-toggle="modal" href="#lcb-profile">
+ <i class="fa fa-fw fa-edit"></i> Edit Profile
+ </a>
+ </li>
+ <li>
+ <a data-toggle="modal" href="#lcb-account">
+ <i class="fa fa-fw fa-cogs"></i> Account Settings
+ </a>
+ </li>
+ <li>
+ <a data-toggle="modal" href="#lcb-notifications">
+ <i class="fa fa-fw fa-bell"></i> Notifications
+ </a>
+ </li>
+ <% if settings.xmpp.enable %>
+ <li>
+ <a data-toggle="modal" href="#lcb-xmpp">
+ <i class="fa fa-fw fa-comments"></i> XMPP/Jabber
+ </a>
+ </li>
+ <% endif %>
+ <li>
+ <a data-toggle="modal" href="#lcb-tokens">
+ <i class="fa fa-fw fa-lock"></i> Auth tokens
+ </a>
+ </li>
+ <li class="divider"></li>
+ <li><a href="./logout"><i class="fa fa-fw fa-sign-out"></i> Logout</a></li>
+ </ul>
+ </div>
+</script>
diff --git a/templates/includes/js/room.html b/templates/includes/js/room.html
index 6782ac2..a5564da 100644
--- a/templates/includes/js/room.html
+++ b/templates/includes/js/room.html
@@ -1,103 +1,100 @@
<script type="text/x-handlebars-template" id="template-room">
- <div class="lcb-room lcb-pane lcb-pane-{{id}} {{#if sidebar}}lcb-room-sidebar-opened{{/if}} hide" data-id="{{id}}">
- <div class="lcb-room-chat ">
- <div class="lcb-room-header">
- <div class="lcb-room-meta">
- <h2 class="lcb-room-heading">
- <span class="name">{{name}}</span>
- <span class="slug">#{{slug}}</span>
- {{#if hasPassword}}
- <span class="fa fa-lock btn password" title="This room require password to enter."></span>
- {{/if}}
- {{#if iCanEdit}}
- <a class="btn hidden-xs show-edit-room"
- title="Edit Room">
- <i class="fa fa-edit"></i>
- </a>
- {{/if}}
- <a class="btn hidden-xs" title="Chat History"
- href="./transcript?room={{ id }}" target="_blank">
- <i class="fa fa-history"></i>
+ <div class="lcb-room-chat ">
+ <div class="lcb-room-header">
+ <div class="lcb-room-meta">
+ <h2 class="lcb-room-heading">
+ <span class="name">{{name}}</span>
+ <span class="slug">#{{slug}}</span>
+ {{#if hasPassword}}
+ <span class="fa fa-lock btn password" title="This room require password to enter."></span>
+ {{/if}}
+ {{#if iCanEdit}}
+ <a class="btn hidden-xs show-edit-room"
+ title="Edit Room">
+ <i class="fa fa-edit"></i>
</a>
- <% if settings.files.enable %>
- <a class="btn hidden-xs lcb-upload-trigger" title="Upload Files" href="#">
- <i class="fa fa-upload"></i>
- </a>
- <% endif %>
- <a class="btn hidden-xs lcb-giphy" href="#lcb-giphy" title="Giphy" data-toggle="modal">
- <i class="fa fa-gift"></i>
- </a>
- </h2>
- <div class="lcb-room-description">
- <p>{{description}}</p>
- </div>
- </div>
- <div class="lcb-room-header-actions">
- <a class="lcb-room-toggle-sidebar" href="#">
- <i class="fa fa-chevron-left"></i>
+ {{/if}}
+ <a class="btn hidden-xs" title="Chat History"
+ href="./transcript?room={{ id }}" target="_blank">
+ <i class="fa fa-history"></i>
+ </a>
+ <% if settings.files.enable %>
+ <a class="btn hidden-xs lcb-upload-trigger" title="Upload Files" href="#">
+ <i class="fa fa-upload"></i>
+ </a>
+ <% endif %>
+ <a class="btn hidden-xs lcb-giphy" href="#lcb-giphy" title="Giphy" data-toggle="modal">
+ <i class="fa fa-gift"></i>
</a>
+ </h2>
+ <div class="lcb-room-description">
+ <p>{{description}}</p>
</div>
- </div><!-- lcb-room-header end -->
- <ul class="lcb-messages">
- </ul>
- <form class="lcb-compose lcb-entry">
- </form>
- </div><!-- lcb-chat end -->
- <div class="lcb-room-sidebar"></div>
- <div class="edit-room modal fade lcb-room-edit">
- <div class="modal-dialog">
- <div class="modal-content">
- <form action="" class="validate form-horizontal" method="post">
- <div class="modal-header">
- <button class="close hide-edit-room" type="button">&times;</button>
- <h4 class="modal-title">Edit Room</h4>
+ </div>
+ <div class="lcb-room-header-actions">
+ <a class="lcb-room-toggle-sidebar" href="#">
+ <i class="fa fa-chevron-left"></i>
+ </a>
+ </div>
+ </div><!-- lcb-room-header end -->
+ <ul class="lcb-messages">
+ </ul>
+ <form class="lcb-compose lcb-entry">
+ </form>
+ </div><!-- lcb-chat end -->
+ <div class="lcb-room-sidebar"></div>
+ <div class="edit-room modal fade lcb-room-edit">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <form action="" class="validate form-horizontal" method="post">
+ <div class="modal-header">
+ <button class="close hide-edit-room" type="button">&times;</button>
+ <h4 class="modal-title">Edit Room</h4>
+ </div>
+ <div class="modal-body">
+ <div class="form-group">
+ <label class="control-label col-sm-4">Name</label>
+ <div class="col-sm-7">
+ <input class="required name form-control" name=
+ "name" type="text" value="{{name}}">
+ </div>
</div>
- <div class="modal-body">
+ <div class="form-group">
+ <label class=
+ "control-label col-sm-4">Description</label>
+ <div class="col-sm-7">
+ <textarea class="form-control" name=
+ "description">{{description}}</textarea>
+ </div>
+ </div>
+ {{#if hasPassword}}
<div class="form-group">
- <label class="control-label col-sm-4">Name</label>
+ <label class=
+ "control-label col-sm-4">Password</label>
<div class="col-sm-7">
- <input class="required name form-control" name=
- "name" type="text" value="{{name}}">
+ <input class="form-control" name=
+ "password" type="password" value="{{password}}">
</div>
</div>
<div class="form-group">
<label class=
- "control-label col-sm-4">Description</label>
+ "control-label col-sm-4">Confirm Password</label>
<div class="col-sm-7">
- <textarea class="form-control" name=
- "description">{{description}}</textarea>
+ <input class="form-control" name=
+ "confirmPassword" type="password" value="{{password}}">
</div>
</div>
- {{#if hasPassword}}
- <div class="form-group">
- <label class=
- "control-label col-sm-4">Password</label>
- <div class="col-sm-7">
- <input class="form-control" name=
- "password" type="password" value="{{password}}">
- </div>
- </div>
- <div class="form-group">
- <label class=
- "control-label col-sm-4">Confirm Password</label>
- <div class="col-sm-7">
- <input class="form-control" name=
- "confirmPassword" type="password" value="{{password}}">
- </div>
- </div>
- {{/if}}
- <p class="response" style="display: none;"></p>
- </div>
- <div class="modal-footer">
- <button class="btn btn-success pull-right submit-edit-room" type=
- "submit"><i class="icon-ok"></i> Save</button>
- <a class="archive-room btn btn-danger pull-left"
- tabindex="-1"><i class="icon-remove icon-white"></i>
- Archive Room</a>
- </div>
- </form>
- </div>
+ {{/if}}
+ <p class="response" style="display: none;"></p>
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-success pull-right submit-edit-room" type=
+ "submit"><i class="icon-ok"></i> Save</button>
+ <a class="archive-room btn btn-danger pull-left"
+ tabindex="-1"><i class="icon-remove icon-white"></i>
+ Archive Room</a>
+ </div>
+ </form>
</div>
- </div><!-- edit room end -->
- </div><!-- lcb-room end -->
+ </div>
</script>
diff --git a/templates/includes/js/status.html b/templates/includes/js/status.html
new file mode 100644
index 0000000..6872029
--- /dev/null
+++ b/templates/includes/js/status.html
@@ -0,0 +1,11 @@
+<script type="text/x-handlebars-template" id="template-status">
+ <span class="lcb-status-indicator lcb-status-indicator-error lcb-status-connection" data-status="disconnected" style="display: none;">
+ <i class="fa fa-plug"></i> Disconnected
+ </span>
+ <span class="lcb-status-indicator lcb-status-connection" data-status="connected" style="display: none;">
+ <i class="fa fa-refresh"></i> Connected
+ </span>
+ <span class="lcb-status-indicator lcb-status-connection" style="display: none;">
+ <i class="fa fa-bell-slash"></i>
+ </span>
+</script>
diff --git a/templates/includes/js/tab.html b/templates/includes/js/tab.html
index f8332b5..687bdd0 100644
--- a/templates/includes/js/tab.html
+++ b/templates/includes/js/tab.html
@@ -1,12 +1,8 @@
<script type="text/x-handlebars-template" id="template-room-tab">
- <li class="lcb-tab lcb-tab-room" data-id="{{id}}">
- <a href="#!/room/{{id}}">
- <span class="lcb-tab-title">{{name}}</span>
- <span class="lcb-tab-alerts">
- <span class="lcb-tab-alerts-mentions"></span>
- <span class="lcb-tab-alerts-total"></span>
- </span>
- <span class="lcb-tab-close">&times;</span>
- </a>
- </li>
+ <span class="lcb-tab-title">{{name}}</span>
+ <span class="lcb-tab-alerts">
+ <span class="lcb-tab-alerts-mentions"></span>
+ <span class="lcb-tab-alerts-total"></span>
+ </span>
+ <span class="lcb-tab-close">&times;</span>
</script>
diff --git a/templates/includes/js/tabs.html b/templates/includes/js/tabs.html
new file mode 100644
index 0000000..44e13c3
--- /dev/null
+++ b/templates/includes/js/tabs.html
@@ -0,0 +1,7 @@
+<script type="text/x-handlebars-template" id="template-tabs">
+ <div class="lcb-tabs-group">
+ <h3 class="lcb-tabs-group-heading">Rooms</h3>
+ <ul class="lcb-tabs-list">
+ </ul>
+ </div>
+</script>