vines-services 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,342 @@
1
+ var SystemsPage;
2
+ var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
3
+ SystemsPage = (function() {
4
+ function SystemsPage(session) {
5
+ this.session = session;
6
+ this.session.onRoster(__bind(function() {
7
+ return this.roster();
8
+ }, this));
9
+ this.session.onMessage(__bind(function(m) {
10
+ return this.message(m);
11
+ }, this));
12
+ this.session.onPresence(__bind(function(p) {
13
+ return this.presence(p);
14
+ }, this));
15
+ this.commands = new Commands;
16
+ this.chats = {};
17
+ this.currentContact = null;
18
+ this.layout = null;
19
+ }
20
+ SystemsPage.prototype.datef = function(millis) {
21
+ var d, hour, meridian, minutes;
22
+ d = new Date(millis);
23
+ meridian = d.getHours() >= 12 ? ' pm' : ' am';
24
+ hour = d.getHours() > 12 ? d.getHours() - 12 : d.getHours();
25
+ if (hour === 0) {
26
+ hour = 12;
27
+ }
28
+ minutes = d.getMinutes() + '';
29
+ if (minutes.length === 1) {
30
+ minutes = '0' + minutes;
31
+ }
32
+ return hour + ':' + minutes + meridian;
33
+ };
34
+ SystemsPage.prototype.groupContacts = function() {
35
+ var contact, group, groups, jid, _i, _len, _ref, _ref2;
36
+ groups = {};
37
+ _ref = this.session.roster;
38
+ for (jid in _ref) {
39
+ contact = _ref[jid];
40
+ _ref2 = contact.groups;
41
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
42
+ group = _ref2[_i];
43
+ (groups[group] || (groups[group] = [])).push(contact);
44
+ }
45
+ }
46
+ return groups;
47
+ };
48
+ SystemsPage.prototype.roster = function() {
49
+ var contact, contacts, group, groups, items, name, optgroup, option, sorted, _i, _len, _results;
50
+ groups = this.groupContacts();
51
+ sorted = (function() {
52
+ var _results;
53
+ _results = [];
54
+ for (group in groups) {
55
+ contacts = groups[group];
56
+ _results.push(group);
57
+ }
58
+ return _results;
59
+ })();
60
+ sorted = sorted.sort(function(a, b) {
61
+ a = a.toLowerCase();
62
+ b = b.toLowerCase();
63
+ if (a > b) {
64
+ return 1;
65
+ } else if (a < b) {
66
+ return -1;
67
+ } else {
68
+ return 0;
69
+ }
70
+ });
71
+ items = $('#roster-items').empty();
72
+ _results = [];
73
+ for (_i = 0, _len = sorted.length; _i < _len; _i++) {
74
+ group = sorted[_i];
75
+ contacts = groups[group];
76
+ optgroup = $('<li class="group"></li>').appendTo(items);
77
+ optgroup.text(group);
78
+ optgroup.attr('data-group', group);
79
+ _results.push((function() {
80
+ var _j, _len2, _results2;
81
+ _results2 = [];
82
+ for (_j = 0, _len2 = contacts.length; _j < _len2; _j++) {
83
+ contact = contacts[_j];
84
+ option = $("<li data-jid=\"" + contact.jid + "\">\n <span class=\"text\"></span>\n <span class=\"unread\" style=\"display:none;\"></span>\n</li>").appendTo(items);
85
+ if (contact.offline()) {
86
+ option.addClass('offline');
87
+ }
88
+ option.click(__bind(function(event) {
89
+ return this.selectContact(event);
90
+ }, this));
91
+ name = contact.name || contact.jid.split('@')[0];
92
+ option.attr('data-name', name);
93
+ option.attr('data-group', group);
94
+ _results2.push($('.text', option).text(name));
95
+ }
96
+ return _results2;
97
+ }).call(this));
98
+ }
99
+ return _results;
100
+ };
101
+ SystemsPage.prototype.message = function(message) {
102
+ var bottom, chat, from, me;
103
+ this.queueMessage(message);
104
+ me = message.from === this.session.jid();
105
+ from = message.from.split('/')[0];
106
+ if (me || from === this.currentContact) {
107
+ bottom = this.atBottom();
108
+ this.appendMessage(message);
109
+ if (bottom) {
110
+ return this.scroll({
111
+ animate: true
112
+ });
113
+ }
114
+ } else {
115
+ chat = this.chat(message.from);
116
+ chat.unread++;
117
+ return this.eachContact(from, function(node) {
118
+ return $('.unread', node).text(chat.unread).show();
119
+ });
120
+ }
121
+ };
122
+ SystemsPage.prototype.eachContact = function(jid, callback) {
123
+ var node, _i, _len, _ref, _results;
124
+ _ref = $("#roster-items li[data-jid='" + jid + "']").get();
125
+ _results = [];
126
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
127
+ node = _ref[_i];
128
+ _results.push(callback($(node)));
129
+ }
130
+ return _results;
131
+ };
132
+ SystemsPage.prototype.appendMessage = function(message) {
133
+ var contact, from, me, name, node, prefix, proxied;
134
+ me = message.from === this.session.jid();
135
+ proxied = $('jid', message.node).text();
136
+ from = (proxied || message.from).split('/')[0];
137
+ contact = this.session.roster[from];
138
+ name = contact ? contact.name || from : from;
139
+ node = $("<li data-jid=\"" + from + "\"><pre></pre></li>").appendTo('#messages');
140
+ prefix = me ? '$ ' : '';
141
+ $('pre', node).text(prefix + message.text);
142
+ if (!me) {
143
+ node.append("<footer>\n <span class=\"author\"></span> @\n <span class=\"time\">" + (this.datef(message.received)) + "</span>\n</footer>");
144
+ return $('.author', node).text(name);
145
+ }
146
+ };
147
+ SystemsPage.prototype.queueMessage = function(message) {
148
+ var chat, full, me;
149
+ me = message.from === this.session.jid();
150
+ full = message[me ? 'to' : 'from'];
151
+ chat = this.chat(full);
152
+ chat.jid = full;
153
+ return chat.messages.push(message);
154
+ };
155
+ SystemsPage.prototype.chat = function(jid) {
156
+ var bare, chat;
157
+ bare = jid.split('/')[0];
158
+ chat = this.chats[bare];
159
+ if (!chat) {
160
+ chat = {
161
+ jid: jid,
162
+ messages: [],
163
+ unread: 0
164
+ };
165
+ this.chats[bare] = chat;
166
+ }
167
+ return chat;
168
+ };
169
+ SystemsPage.prototype.presence = function(presence) {
170
+ var contact, from;
171
+ from = presence.from.split('/')[0];
172
+ if (from === this.session.bareJid()) {
173
+ return;
174
+ }
175
+ if (!presence.type || presence.offline) {
176
+ contact = this.session.roster[from];
177
+ this.eachContact(from, function(node) {
178
+ if (contact.offline()) {
179
+ return node.addClass('offline');
180
+ } else {
181
+ return node.removeClass('offline');
182
+ }
183
+ });
184
+ }
185
+ if (presence.offline) {
186
+ return this.chat(from).jid = from;
187
+ }
188
+ };
189
+ SystemsPage.prototype.selectContact = function(event) {
190
+ var contact, jid, selected;
191
+ $('#blank-slate').fadeOut(200, function() {
192
+ return $(this).remove();
193
+ });
194
+ $('#roster').hide();
195
+ selected = $(event.currentTarget);
196
+ jid = selected.attr('data-jid');
197
+ contact = this.session.roster[jid];
198
+ if (this.currentContact === jid) {
199
+ return;
200
+ }
201
+ this.currentContact = jid;
202
+ $('#message-label').text($('.text', selected).text());
203
+ $('#messages').empty();
204
+ $('#message').focus();
205
+ this.layout.resize();
206
+ return this.restoreChat(jid);
207
+ };
208
+ SystemsPage.prototype.restoreChat = function(jid) {
209
+ var chat, messages, msg, _i, _len;
210
+ chat = this.chats[jid];
211
+ messages = [];
212
+ if (chat) {
213
+ messages = chat.messages;
214
+ chat.unread = 0;
215
+ this.eachContact(jid, function(node) {
216
+ return $('.unread', node).text('').hide();
217
+ });
218
+ }
219
+ for (_i = 0, _len = messages.length; _i < _len; _i++) {
220
+ msg = messages[_i];
221
+ this.appendMessage(msg);
222
+ }
223
+ return this.scroll();
224
+ };
225
+ SystemsPage.prototype.scroll = function(opts) {
226
+ var msgs;
227
+ opts || (opts = {});
228
+ msgs = $('#messages');
229
+ if (opts.animate) {
230
+ return msgs.animate({
231
+ scrollTop: msgs.prop('scrollHeight')
232
+ }, 400);
233
+ } else {
234
+ return msgs.scrollTop(msgs.prop('scrollHeight'));
235
+ }
236
+ };
237
+ SystemsPage.prototype.atBottom = function() {
238
+ var bottom, msgs;
239
+ msgs = $('#messages');
240
+ bottom = msgs.prop('scrollHeight') - msgs.outerHeight();
241
+ return msgs.scrollTop() >= bottom;
242
+ };
243
+ SystemsPage.prototype.send = function() {
244
+ var chat, input, jid, text;
245
+ if (!this.currentContact) {
246
+ return false;
247
+ }
248
+ input = $('#message');
249
+ text = input.val().trim();
250
+ if (text) {
251
+ chat = this.chats[this.currentContact];
252
+ jid = chat ? chat.jid : this.currentContact;
253
+ this.message({
254
+ from: this.session.jid(),
255
+ text: text,
256
+ to: jid,
257
+ received: new Date()
258
+ });
259
+ this.session.sendMessage(jid, text);
260
+ this.commands.push(text);
261
+ }
262
+ input.val('');
263
+ return false;
264
+ };
265
+ SystemsPage.prototype.drawBlankSlate = function() {
266
+ $("<form id=\"blank-slate\" class=\"float\">\n <p>\n Services, and individual systems, can be controlled by sending\n them shell commands through this terminal. Select a system to chat with\n to get started.\n </p>\n <input type=\"submit\" value=\"Select System\"/>\n</form>").appendTo('#alpha');
267
+ return $('#blank-slate').submit(__bind(function() {
268
+ $('#roster').show();
269
+ this.layout.resize();
270
+ return false;
271
+ }, this));
272
+ };
273
+ SystemsPage.prototype.draw = function() {
274
+ var contact, name;
275
+ if (!this.session.connected()) {
276
+ window.location.hash = '';
277
+ return;
278
+ }
279
+ $('body').attr('id', 'systems-page');
280
+ $('#container').hide().empty();
281
+ $("<div id=\"alpha\" class=\"primary column x-fill y-fill\">\n <ul id=\"messages\" class=\"scroll y-fill\"></ul>\n <form id=\"message-form\">\n <label id=\"message-label\"></label>\n <input id=\"message\" name=\"message\" type=\"text\" maxlength=\"1024\" placeholder=\"Type a command and press enter to send\"/>\n </form>\n <div id=\"roster\" class=\"float\" style=\"display:none;\">\n <ul id=\"roster-items\"></ul>\n <div id=\"roster-form\"></div>\n </div>\n</div>").appendTo('#container');
282
+ $('#message-form').submit(__bind(function() {
283
+ return this.send();
284
+ }, this));
285
+ $('#messages').click(function() {
286
+ return $('#roster').hide();
287
+ });
288
+ $('#message').focus(function() {
289
+ return $('#roster').hide();
290
+ });
291
+ this.roster();
292
+ $('#message-label').click(__bind(function() {
293
+ return $('#roster').toggle();
294
+ }, this));
295
+ $('#message').keyup(__bind(function(e) {
296
+ switch (e.keyCode) {
297
+ case 38:
298
+ return $('#message').val(this.commands.prev());
299
+ case 40:
300
+ return $('#message').val(this.commands.next());
301
+ }
302
+ }, this));
303
+ if (this.currentContact) {
304
+ if (this.currentContact) {
305
+ this.restoreChat(this.currentContact);
306
+ }
307
+ contact = this.session.roster[this.currentContact];
308
+ name = contact.name || contact.jid.split('@')[0];
309
+ $('#message-label').text(name);
310
+ $('#message').focus();
311
+ } else {
312
+ this.drawBlankSlate();
313
+ }
314
+ $('#container').show();
315
+ this.layout = this.resize();
316
+ this.scroll();
317
+ new Filter({
318
+ list: '#roster-items',
319
+ form: '#roster-form',
320
+ attrs: ['data-jid', 'data-name']
321
+ });
322
+ return $('form', '#roster-form').show();
323
+ };
324
+ SystemsPage.prototype.resize = function() {
325
+ var container, form, items, label, msg, rform, roster;
326
+ container = $('#container');
327
+ roster = $('#roster');
328
+ items = $('#roster-items');
329
+ rform = $('#roster-form');
330
+ msg = $('#message');
331
+ form = $('#message-form');
332
+ label = $('#message-label');
333
+ return new Layout(function() {
334
+ var height;
335
+ msg.width(form.width() - label.width() - 32);
336
+ height = container.height() - form.height() - 10;
337
+ roster.css('max-height', height);
338
+ return items.css('max-height', height - rform.outerHeight() - 10);
339
+ });
340
+ };
341
+ return SystemsPage;
342
+ })();