mailcatcher-jruby 1.0

Sign up to get free protection for your applications and to get access to all the features.
Binary file
Binary file
Binary file
@@ -0,0 +1,445 @@
1
+ (function() {
2
+ var MailCatcher,
3
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
4
+
5
+ jQuery.expr[':'].icontains = function(a, i, m) {
6
+ var _ref, _ref1;
7
+ return ((_ref = (_ref1 = a.textContent) != null ? _ref1 : a.innerText) != null ? _ref : "").toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
8
+ };
9
+
10
+ MailCatcher = (function() {
11
+ function MailCatcher() {
12
+ this.nextTab = __bind(this.nextTab, this);
13
+ this.previousTab = __bind(this.previousTab, this);
14
+ this.openTab = __bind(this.openTab, this);
15
+ this.selectedTab = __bind(this.selectedTab, this);
16
+ this.getTab = __bind(this.getTab, this);
17
+ var _this = this;
18
+ $('#messages tr').live('click', function(e) {
19
+ e.preventDefault();
20
+ return _this.loadMessage($(e.currentTarget).attr('data-message-id'));
21
+ });
22
+ $('input[name=search]').keyup(function(e) {
23
+ var query;
24
+ query = $.trim($(e.currentTarget).val());
25
+ if (query) {
26
+ return _this.searchMessages(query);
27
+ } else {
28
+ return _this.clearSearch();
29
+ }
30
+ });
31
+ $('#message .views .format.tab a').live('click', function(e) {
32
+ e.preventDefault();
33
+ return _this.loadMessageBody(_this.selectedMessage(), $($(e.currentTarget).parent('li')).data('message-format'));
34
+ });
35
+ $('#message .views .analysis.tab a').live('click', function(e) {
36
+ e.preventDefault();
37
+ return _this.loadMessageAnalysis(_this.selectedMessage());
38
+ });
39
+ $('#message iframe').load(function() {
40
+ return _this.decorateMessageBody();
41
+ });
42
+ $('#resizer').live({
43
+ mousedown: function(e) {
44
+ var events;
45
+ e.preventDefault();
46
+ return $(window).bind(events = {
47
+ mouseup: function(e) {
48
+ e.preventDefault();
49
+ return $(window).unbind(events);
50
+ },
51
+ mousemove: function(e) {
52
+ e.preventDefault();
53
+ return _this.resizeTo(e.clientY);
54
+ }
55
+ });
56
+ }
57
+ });
58
+ this.resizeToSaved();
59
+ $('nav.app .clear a').live('click', function(e) {
60
+ e.preventDefault();
61
+ if (confirm("You will lose all your received messages.\n\nAre you sure you want to clear all messages?")) {
62
+ return $.ajax({
63
+ url: '/messages',
64
+ type: 'DELETE',
65
+ success: function() {
66
+ return _this.unselectMessage();
67
+ },
68
+ error: function() {
69
+ return alert('Error while clearing all messages.');
70
+ }
71
+ });
72
+ }
73
+ });
74
+ $('nav.app .quit a').live('click', function(e) {
75
+ e.preventDefault();
76
+ if (confirm("You will lose all your received messages.\n\nAre you sure you want to quit?")) {
77
+ return $.ajax({
78
+ type: 'DELETE',
79
+ success: function() {
80
+ return location.replace($('body > header h1 a').attr('href'));
81
+ },
82
+ error: function() {
83
+ return alert('Error while quitting.');
84
+ }
85
+ });
86
+ }
87
+ });
88
+ key('up', function() {
89
+ if (_this.selectedMessage()) {
90
+ _this.loadMessage($('#messages tr.selected').prev().data('message-id'));
91
+ } else {
92
+ _this.loadMessage($('#messages tbody tr[data-message-id]:first').data('message-id'));
93
+ }
94
+ return false;
95
+ });
96
+ key('down', function() {
97
+ if (_this.selectedMessage()) {
98
+ _this.loadMessage($('#messages tr.selected').next().data('message-id'));
99
+ } else {
100
+ _this.loadMessage($('#messages tbody tr[data-message-id]:first').data('message-id'));
101
+ }
102
+ return false;
103
+ });
104
+ key('⌘+up, ctrl+up', function() {
105
+ _this.loadMessage($('#messages tbody tr[data-message-id]:first').data('message-id'));
106
+ return false;
107
+ });
108
+ key('⌘+down, ctrl+down', function() {
109
+ _this.loadMessage($('#messages tbody tr[data-message-id]:last').data('message-id'));
110
+ return false;
111
+ });
112
+ key('left', function() {
113
+ _this.openTab(_this.previousTab());
114
+ return false;
115
+ });
116
+ key('right', function() {
117
+ _this.openTab(_this.nextTab());
118
+ return false;
119
+ });
120
+ key('backspace, delete', function() {
121
+ var id;
122
+ id = _this.selectedMessage();
123
+ if (id != null) {
124
+ $.ajax({
125
+ url: '/messages/' + id,
126
+ type: 'DELETE',
127
+ success: function() {
128
+ var messageRow, switchTo;
129
+ messageRow = $("#messages tbody tr[data-message-id='" + id + "']");
130
+ switchTo = messageRow.next().data('message-id') || messageRow.prev().data('message-id');
131
+ messageRow.remove();
132
+ if (switchTo) {
133
+ return _this.loadMessage(switchTo);
134
+ } else {
135
+ return _this.unselectMessage();
136
+ }
137
+ },
138
+ error: function() {
139
+ return alert('Error while removing message.');
140
+ }
141
+ });
142
+ }
143
+ return false;
144
+ });
145
+ this.refresh();
146
+ this.subscribe();
147
+ }
148
+
149
+ MailCatcher.prototype.parseDateRegexp = /^(\d{4})[-\/\\](\d{2})[-\/\\](\d{2})(?:\s+|T)(\d{2})[:-](\d{2})[:-](\d{2})(?:([ +-]\d{2}:\d{2}|\s*\S+|Z?))?$/;
150
+
151
+ MailCatcher.prototype.parseDate = function(date) {
152
+ var match;
153
+ if (match = this.parseDateRegexp.exec(date)) {
154
+ return new Date(match[1], match[2] - 1, match[3], match[4], match[5], match[6], 0);
155
+ }
156
+ };
157
+
158
+ MailCatcher.prototype.offsetTimeZone = function(date) {
159
+ var offset;
160
+ offset = Date.now().getTimezoneOffset() * 60000;
161
+ date.setTime(date.getTime() - offset);
162
+ return date;
163
+ };
164
+
165
+ MailCatcher.prototype.formatDate = function(date) {
166
+ if (typeof date === "string") {
167
+ date && (date = this.parseDate(date));
168
+ }
169
+ date && (date = this.offsetTimeZone(date));
170
+ return date && (date = date.toString("dddd, d MMM yyyy h:mm:ss tt"));
171
+ };
172
+
173
+ MailCatcher.prototype.messagesCount = function() {
174
+ return $('#messages tr').length - 1;
175
+ };
176
+
177
+ MailCatcher.prototype.tabs = function() {
178
+ return $('#message ul').children('.tab');
179
+ };
180
+
181
+ MailCatcher.prototype.getTab = function(i) {
182
+ return $(this.tabs()[i]);
183
+ };
184
+
185
+ MailCatcher.prototype.selectedTab = function() {
186
+ return this.tabs().index($('#message li.tab.selected'));
187
+ };
188
+
189
+ MailCatcher.prototype.openTab = function(i) {
190
+ return this.getTab(i).children('a').click();
191
+ };
192
+
193
+ MailCatcher.prototype.previousTab = function(tab) {
194
+ var i;
195
+ i = tab || tab === 0 ? tab : this.selectedTab() - 1;
196
+ if (i < 0) {
197
+ i = this.tabs().length - 1;
198
+ }
199
+ if (this.getTab(i).is(":visible")) {
200
+ return i;
201
+ } else {
202
+ return this.previousTab(i - 1);
203
+ }
204
+ };
205
+
206
+ MailCatcher.prototype.nextTab = function(tab) {
207
+ var i;
208
+ i = tab ? tab : this.selectedTab() + 1;
209
+ if (i > this.tabs().length - 1) {
210
+ i = 0;
211
+ }
212
+ if (this.getTab(i).is(":visible")) {
213
+ return i;
214
+ } else {
215
+ return this.nextTab(i + 1);
216
+ }
217
+ };
218
+
219
+ MailCatcher.prototype.haveMessage = function(message) {
220
+ if (message.id != null) {
221
+ message = message.id;
222
+ }
223
+ return $("#messages tbody tr[data-message-id=\"" + message + "\"]").length > 0;
224
+ };
225
+
226
+ MailCatcher.prototype.selectedMessage = function() {
227
+ return $('#messages tr.selected').data('message-id');
228
+ };
229
+
230
+ MailCatcher.prototype.searchMessages = function(query) {
231
+ var $rows, selector, token;
232
+ selector = ((function() {
233
+ var _i, _len, _ref, _results;
234
+ _ref = query.split(/\s+/);
235
+ _results = [];
236
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
237
+ token = _ref[_i];
238
+ _results.push(":icontains('" + token + "')");
239
+ }
240
+ return _results;
241
+ })()).join("");
242
+ $rows = $("#messages tbody tr");
243
+ $rows.not(selector).hide();
244
+ return $rows.filter(selector).show();
245
+ };
246
+
247
+ MailCatcher.prototype.clearSearch = function() {
248
+ return $('#messages tbody tr').show();
249
+ };
250
+
251
+ MailCatcher.prototype.addMessage = function(message) {
252
+ return $('#messages tbody').prepend($('<tr />').attr('data-message-id', message.id.toString()).append($('<td/>').text(message.sender || "No sender").toggleClass("blank", !message.sender)).append($('<td/>').text((message.recipients || []).join(', ') || "No receipients").toggleClass("blank", !message.recipients.length)).append($('<td/>').text(message.subject || "No subject").toggleClass("blank", !message.subject)).append($('<td/>').text(this.formatDate(message.created_at))));
253
+ };
254
+
255
+ MailCatcher.prototype.scrollToRow = function(row) {
256
+ var overflow, relativePosition;
257
+ relativePosition = row.offset().top - $('#messages').offset().top;
258
+ if (relativePosition < 0) {
259
+ return $('#messages').scrollTop($('#messages').scrollTop() + relativePosition - 20);
260
+ } else {
261
+ overflow = relativePosition + row.height() - $('#messages').height();
262
+ if (overflow > 0) {
263
+ return $('#messages').scrollTop($('#messages').scrollTop() + overflow + 20);
264
+ }
265
+ }
266
+ };
267
+
268
+ MailCatcher.prototype.unselectMessage = function() {
269
+ $('#messages tbody, #message .metadata dd').empty();
270
+ $('#message .metadata .attachments').hide();
271
+ $('#message iframe').attr('src', 'about:blank');
272
+ return null;
273
+ };
274
+
275
+ MailCatcher.prototype.loadMessage = function(id) {
276
+ var messageRow,
277
+ _this = this;
278
+ if ((id != null ? id.id : void 0) != null) {
279
+ id = id.id;
280
+ }
281
+ id || (id = $('#messages tr.selected').attr('data-message-id'));
282
+ if (id != null) {
283
+ $("#messages tbody tr:not([data-message-id='" + id + "'])").removeClass('selected');
284
+ messageRow = $("#messages tbody tr[data-message-id='" + id + "']");
285
+ messageRow.addClass('selected');
286
+ this.scrollToRow(messageRow);
287
+ return $.getJSON("/messages/" + id + ".json", function(message) {
288
+ //----- change recipients to array
289
+ if(typeof message.recipients != 'undefined') {
290
+ message.recipients = JSON.parse(message.recipients);
291
+ }
292
+ //--------------------------------
293
+ var $ul;
294
+ $('#message .metadata dd.created_at').text(_this.formatDate(message.created_at));
295
+ $('#message .metadata dd.from').text(message.sender);
296
+ $('#message .metadata dd.to').text((message.recipients || []).join(', '));
297
+ $('#message .metadata dd.subject').text(message.subject);
298
+ $('#message .views .tab.format').each(function(i, el) {
299
+ var $el, format;
300
+ $el = $(el);
301
+ format = $el.attr('data-message-format');
302
+ if ($.inArray(format, message.formats) >= 0) {
303
+ $el.find('a').attr('href', "/messages/" + id + "." + format);
304
+ return $el.show();
305
+ } else {
306
+ return $el.hide();
307
+ }
308
+ });
309
+ if ($("#message .views .tab.selected:not(:visible)").length) {
310
+ $("#message .views .tab.selected").removeClass("selected");
311
+ $("#message .views .tab:visible:first").addClass("selected");
312
+ }
313
+ if (message.attachments.length) {
314
+ $ul = $('<ul/>').appendTo($('#message .metadata dd.attachments').empty());
315
+ $.each(message.attachments, function(i, attachment) {
316
+ return $ul.append($('<li>').append($('<a>').attr('href', attachment['href']).addClass(attachment['type'].split('/', 1)[0]).addClass(attachment['type'].replace('/', '-')).text(attachment['filename'])));
317
+ });
318
+ $('#message .metadata .attachments').show();
319
+ } else {
320
+ $('#message .metadata .attachments').hide();
321
+ }
322
+ $('#message .views .download a').attr('href', "/messages/" + id + ".eml");
323
+ if ($('#message .views .tab.analysis.selected').length) {
324
+ return _this.loadMessageAnalysis();
325
+ } else {
326
+ return _this.loadMessageBody();
327
+ }
328
+ });
329
+ }
330
+ };
331
+
332
+ MailCatcher.prototype.loadMessageBody = function(id, format) {
333
+ var app;
334
+ id || (id = this.selectedMessage());
335
+ format || (format = $('#message .views .tab.format.selected').attr('data-message-format'));
336
+ format || (format = 'html');
337
+ $("#message .views .tab[data-message-format=\"" + format + "\"]:not(.selected)").addClass('selected');
338
+ $("#message .views .tab:not([data-message-format=\"" + format + "\"]).selected").removeClass('selected');
339
+ if (id != null) {
340
+ $('#message iframe').attr("src", "/messages/" + id + "." + format);
341
+ return app = this;
342
+ }
343
+ };
344
+
345
+ MailCatcher.prototype.decorateMessageBody = function() {
346
+ var body, format, message_iframe, text;
347
+ format = $('#message .views .tab.format.selected').attr('data-message-format');
348
+ switch (format) {
349
+ case 'html':
350
+ body = $('#message iframe').contents().find('body');
351
+ return $("a", body).attr("target", "_blank");
352
+ case 'plain':
353
+ message_iframe = $('#message iframe').contents();
354
+ text = message_iframe.text();
355
+ text = text.replace(/((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:\/~\+#]*[\w\-\@?^=%&amp;\/~\+#])?)/g, '<a href="$1" target="_blank">$1</a>');
356
+ text = text.replace(/\n/g, '<br/>');
357
+ return message_iframe.find('html').html('<html><body>' + text + '</html></body>');
358
+ }
359
+ };
360
+
361
+ MailCatcher.prototype.loadMessageAnalysis = function(id) {
362
+ var $form, $iframe;
363
+ id || (id = this.selectedMessage());
364
+ $("#message .views .analysis.tab:not(.selected)").addClass('selected');
365
+ $("#message .views :not(.analysis).tab.selected").removeClass('selected');
366
+ if (id != null) {
367
+ $iframe = $('#message iframe').contents().children().html("<html>\n<head>\n<title>Analysis</title>\n" + ($('link[rel="stylesheet"]')[0].outerHTML) + "\n</head>\n<body class=\"iframe\">\n<h1>Analyse your email with Fractal</h1>\n<p><a href=\"http://getfractal.com/\" target=\"_blank\">Fractal</a> is a really neat service that applies common email design and development knowledge from <a href=\"http://www.email-standards.org/\" target=\"_blank\">Email Standards Project</a> to your HTML email and tells you what you've done wrong or what you should do instead.</p>\n<p>Please note that this <strong>sends your email to the Fractal service</strong> for analysis. Read their <a href=\"https://www.getfractal.com/page/terms\" target=\"_blank\">terms of service</a> if you're paranoid.</p>\n<form>\n<input type=\"submit\" value=\"Analyse\" /><span class=\"loading\" style=\"color: #999; display: none\">Analysing&hellip;</span>\n</form>\n</body>\n</html>");
368
+ return $form = $iframe.find('form').submit(function(e) {
369
+ e.preventDefault();
370
+ $(this).find('input[type="submit"]').attr('disabled', 'disabled').end().find('.loading').show();
371
+ return $('#message iframe').contents().find('body').xslt("/messages/" + id + "/analysis.xml", "/stylesheets/analysis.xsl");
372
+ });
373
+ }
374
+ };
375
+
376
+ MailCatcher.prototype.refresh = function() {
377
+ var _this = this;
378
+ return $.getJSON('/messages', function(messages) {
379
+ return $.each(messages, function(i, message) {
380
+ if (!_this.haveMessage(message)) {
381
+ //----- change recipients to array
382
+ if(typeof message.recipients != 'undefined') {
383
+ message.recipients = JSON.parse(message.recipients);
384
+ }
385
+ //--------------------------------
386
+ return _this.addMessage(message);
387
+ }
388
+ });
389
+ });
390
+ };
391
+
392
+ MailCatcher.prototype.subscribe = function() {
393
+ if (typeof WebSocket !== "undefined" && WebSocket !== null) {
394
+ return this.subscribeWebSocket();
395
+ } else {
396
+ return this.subscribePoll();
397
+ }
398
+ };
399
+
400
+ MailCatcher.prototype.subscribeWebSocket = function() {
401
+ var secure,
402
+ _this = this;
403
+ secure = window.location.scheme === 'https';
404
+ this.websocket = new WebSocket("" + (secure ? 'wss' : 'ws') + "://" + window.location.host + "/messages");
405
+ return this.websocket.onmessage = function(event) {
406
+ return _this.addMessage($.parseJSON(event.data));
407
+ };
408
+ };
409
+
410
+ MailCatcher.prototype.subscribePoll = function() {
411
+ var _this = this;
412
+ if (this.refreshInterval == null) {
413
+ return this.refreshInterval = setInterval((function() {
414
+ return _this.refresh();
415
+ }), 1000);
416
+ }
417
+ };
418
+
419
+ MailCatcher.prototype.resizeToSavedKey = 'mailcatcherSeparatorHeight';
420
+
421
+ MailCatcher.prototype.resizeTo = function(height) {
422
+ var _ref;
423
+ $('#messages').css({
424
+ height: height - $('#messages').offset().top
425
+ });
426
+ return (_ref = window.localStorage) != null ? _ref.setItem(this.resizeToSavedKey, height) : void 0;
427
+ };
428
+
429
+ MailCatcher.prototype.resizeToSaved = function() {
430
+ var height, _ref;
431
+ height = parseInt((_ref = window.localStorage) != null ? _ref.getItem(this.resizeToSavedKey) : void 0);
432
+ if (!isNaN(height)) {
433
+ return this.resizeTo(height);
434
+ }
435
+ };
436
+
437
+ return MailCatcher;
438
+
439
+ })();
440
+
441
+ $(function() {
442
+ return window.MailCatcher = new MailCatcher;
443
+ });
444
+
445
+ }).call(this);