mailcatcher-jruby 1.0

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.
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);