diff --git a/public/javascripts/application.coffee b/public/javascripts/application.coffee
new file mode 100644
index 0000000..4696906
--- /dev/null
+++ b/public/javascripts/application.coffee
@@ -0,0 +1,95 @@
+class MailCatcher
+ constructor: ->
+ $('#mail tr').live 'click', (e) =>
+ @loadMessage $(e.currentTarget).attr 'data-message-id'
+
+ $('#message .actions ul li.tab').live 'click', (e) =>
+ @loadMessageBody $('#mail tr.selected').attr('data-message-id'), $(e.currentTarget).attr 'data-message-format'
+
+ @refresh()
+ @subscribe()
+
+ haveMessage: (message) ->
+ message = message.id if message.id?
+ $("#mail tbody tr[data-message-id=\"#{message}\"]").length > 0
+
+ addMessage: (message) ->
+ $('#mail tbody').append \
+ $('
').attr('data-message-id', message.id.toString())
+ .append($(' | ').text(message.sender))
+ .append($(' | ').text((message.recipients || []).join(', ')))
+ .append($(' | ').text(message.subject))
+ .append($(' | ').text((new Date(message.created_at)).toString("dddd, d MMM yyyy h:mm:ss tt")))
+
+ loadMessage: (id) ->
+ id = id.id if id?.id?
+ id ||= $('#mail tr.selected').attr 'data-message-id'
+
+ if id?
+ $('#mail tbody tr:not([data-message-id="'+id+'"])').removeClass 'selected'
+ $('#mail tbody tr[data-message-id="'+id+'"]').addClass 'selected'
+
+ $.getJSON '/messages/' + id + '.json', (message) =>
+ $('#message .received span').text (new Date(message.created_at)).toString("dddd, d MMM yyyy h:mm:ss tt")
+ $('#message .from span').text message.sender
+ $('#message .to span').text (message.recipients || []).join(', ')
+ $('#message .subject span').text message.subject
+ $('#message .actions ul li.format').each (i, el) ->
+ $el = $(el)
+ format = $el.attr 'data-message-format'
+ if $.inArray(format, message.formats) >= 0
+ $el.show()
+ else
+ $el.hide()
+
+ if $("#message .actions ul li.tab.selected:not(:visible)").count
+ $("#message .actions ul li.tab.selected").removeClass "selected"
+ $("#message .actions ul li.tab:visible:first").addClass "selected"
+
+ if message.attachments.length
+ $('#message .metadata .attachments ul').empty()
+ $.each message.attachments, (i, attachment) ->
+ $('#message .metadata .attachments ul').append($('').append($('').attr('href', attachment['href']).addClass(attachment['type'].split('/', 1)[0]).addClass(attachment['type'].replace('/', '-')).text(attachment['filename'])));
+ $('#message .metadata .attachments').show()
+ else
+ $('#message .metadata .attachments').hide()
+
+ $('#message .actions ul li.download a').attr 'href', "/messages/#{id}.eml"
+
+ @loadMessageBody()
+
+ loadMessageBody: (id, format) ->
+ id ||= $('#mail tr.selected').attr 'data-message-id'
+ format ||= $('#message .actions ul li.selected').first().attr 'data-message-format'
+ format ||= 'html'
+
+ $("#message .actions ul li.tab[data-message-format=\"#{format}\"]").addClass 'selected'
+ $("#message .actions ul li.tab:not([data-message-format=\"#{format}\"])").removeClass 'selected'
+
+ if id?
+ $('#message iframe').attr "src", "/messages/#{id}.#{format}"
+
+ refresh: ->
+ $.getJSON '/messages', (messages) =>
+ $.each messages, (i, message) =>
+ unless @haveMessage message
+ @addMessage message
+
+ subscribe: ->
+ if WebSocket?
+ @subscribeWebSocket()
+ else
+ @subscribePoll()
+
+ subscribeWebSocket: ->
+ secure = window.location.scheme == 'https'
+ @websocket = new WebSocket("#{if secure then 'wss' else 'ws'}://#{window.location.host}/messages");
+ @websocket.onmessage = (event) =>
+ @addMessage $.parseJSON event.data
+
+ subscribePoll: ->
+ unless @refreshInterval?
+ @refreshInterval = setInterval (=> @refresh()), 1000
+
+
+$ -> window.MailCatcher = new MailCatcher
\ No newline at end of file
diff --git a/public/javascripts/application.js b/public/javascripts/application.js
index 1498221..8b92785 100644
--- a/public/javascripts/application.js
+++ b/public/javascripts/application.js
@@ -1,98 +1,111 @@
-var MailCatcher = {
- init: function() {
- $('#mail tr').live('click', function() {
- MailCatcher.load($(this).attr('data-message-id'));
- });
-
- $('#message .actions ul li.tab').live('click', function() {
- MailCatcher.loadBody($('#mail tr.selected').attr('data-message-id'), $(this).attr('data-message-format'));
- });
-
- MailCatcher.refresh();
-
- MailCatcher.subscribe();
- },
-
- addMessage: function(message) {
- $('#mail tbody').append(
- $('
').attr('data-message-id', message.id.toString())
- .append($(' | ').text(message.sender))
- .append($(' | ').text((message.recipients || []).join(', ')))
- .append($(' | ').text(message.subject))
- .append($(' | ').text((new Date(message.created_at)).toString("dddd, d MMM yyyy h:mm:ss tt")))
- );
- },
-
- refresh: function() {
- $.getJSON('/messages', function(mail) {
- $.each(mail, function(i, message) {
- MailCatcher.addMessage(message);
- });
- });
- },
-
- subscribe: function () {
- if (WebSocket !== undefined) {
- MailCatcher.websocket = new WebSocket("ws" + (window.location.scheme == 'https' ? 's' : '') + "://" + window.location.host + "/messages");
- MailCatcher.websocket.onmessage = function (event) {
- MailCatcher.addMessage($.parseJSON(event.data));
- };
- } else {
- if (!MailCatcher.refreshInterval) {
- MailCatcher.refreshInterval = setInterval(MailCatcher.refresh, 30000);
+(function() {
+ var MailCatcher;
+ var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+ MailCatcher = (function() {
+ function MailCatcher() {
+ $('#mail tr').live('click', __bind(function(e) {
+ return this.loadMessage($(e.currentTarget).attr('data-message-id'));
+ }, this));
+ $('#message .actions ul li.tab').live('click', __bind(function(e) {
+ return this.loadMessageBody($('#mail tr.selected').attr('data-message-id'), $(e.currentTarget).attr('data-message-format'));
+ }, this));
+ this.refresh();
+ this.subscribe();
+ }
+ MailCatcher.prototype.haveMessage = function(message) {
+ if (message.id != null) {
+ message = message.id;
}
- }
- },
-
- load: function(id) {
- id = id || $('#mail tr.selected').attr('data-message-id');
-
- if (id !== null) {
- $('#mail tbody tr:not([data-message-id="'+id+'"])').removeClass('selected');
- $('#mail tbody tr[data-message-id="'+id+'"]').addClass('selected');
-
- $.getJSON('/messages/' + id + '.json', function(message) {
- $('#message .received span').text((new Date(message.created_at)).toString("dddd, d MMM yyyy h:mm:ss tt"));
- $('#message .from span').text(message.sender);
- $('#message .to span').text((message.recipients || []).join(', '));
- $('#message .subject span').text(message.subject);
- $('#message .actions ul li.format').each(function(i, el) {
- var $el = $(el),
+ return $("#mail tbody tr[data-message-id=\"" + message + "\"]").length > 0;
+ };
+ MailCatcher.prototype.addMessage = function(message) {
+ return $('#mail tbody').append($('
').attr('data-message-id', message.id.toString()).append($(' | ').text(message.sender)).append($(' | ').text((message.recipients || []).join(', '))).append($(' | ').text(message.subject)).append($(' | ').text((new Date(message.created_at)).toString("dddd, d MMM yyyy h:mm:ss tt"))));
+ };
+ MailCatcher.prototype.loadMessage = function(id) {
+ if ((id != null ? id.id : void 0) != null) {
+ id = id.id;
+ }
+ id || (id = $('#mail tr.selected').attr('data-message-id'));
+ if (id != null) {
+ $('#mail tbody tr:not([data-message-id="' + id + '"])').removeClass('selected');
+ $('#mail tbody tr[data-message-id="' + id + '"]').addClass('selected');
+ return $.getJSON('/messages/' + id + '.json', __bind(function(message) {
+ $('#message .received span').text((new Date(message.created_at)).toString("dddd, d MMM yyyy h:mm:ss tt"));
+ $('#message .from span').text(message.sender);
+ $('#message .to span').text((message.recipients || []).join(', '));
+ $('#message .subject span').text(message.subject);
+ $('#message .actions ul li.format').each(function(i, el) {
+ var $el, format;
+ $el = $(el);
format = $el.attr('data-message-format');
- if ($.inArray(format, message.formats) >= 0) {
- $el.show();
- } else {
- $el.hide();
- }
- });
- if ($("#message .actions ul li.tab.selected:not(:visible)")) {
- $("#message .actions ul li.tab.selected").removeClass("selected");
- $("#message .actions ul li.tab:visible:first").addClass("selected");
- }
- if (message.attachments.length > 0) {
- $('#message .metadata .attachments ul').empty();
- $.each(message.attachments, function (i, attachment) {
- $('#message .metadata .attachments ul').append($('').append($('').attr('href', attachment['href']).addClass(attachment['type'].split('/', 1)[0]).addClass(attachment['type'].replace('/', '-')).text(attachment['filename'])));
+ if ($.inArray(format, message.formats) >= 0) {
+ return $el.show();
+ } else {
+ return $el.hide();
+ }
});
- $('#message .metadata .attachments').show();
- } else {
- $('#message .metadata .attachments').hide();
- }
- $('#message .actions ul li.download a').attr('href', '/messages/' + id + '.eml');
- MailCatcher.loadBody();
- });
- }
- },
-
- loadBody: function(id, format) {
- id = id || $('#mail tr.selected').attr('data-message-id');
- format = format || $('#message .actions ul li.selected').first().attr('data-message-format') || 'html';
-
- $('#message .actions ul li.tab[data-message-format="'+format+'"]').addClass('selected');
- $('#message .actions ul li.tab:not([data-message-format="'+format+'"])').removeClass('selected');
-
- if (id !== undefined && id !== null) {
- $('#message iframe').attr('src', '/messages/' + id + '.' + format);
- }
- }
-};
\ No newline at end of file
+ if ($("#message .actions ul li.tab.selected:not(:visible)").count) {
+ $("#message .actions ul li.tab.selected").removeClass("selected");
+ $("#message .actions ul li.tab:visible:first").addClass("selected");
+ }
+ if (message.attachments.length) {
+ $('#message .metadata .attachments ul').empty();
+ $.each(message.attachments, function(i, attachment) {
+ return $('#message .metadata .attachments ul').append($('').append($('').attr('href', attachment['href']).addClass(attachment['type'].split('/', 1)[0]).addClass(attachment['type'].replace('/', '-')).text(attachment['filename'])));
+ });
+ $('#message .metadata .attachments').show();
+ } else {
+ $('#message .metadata .attachments').hide();
+ }
+ $('#message .actions ul li.download a').attr('href', "/messages/" + id + ".eml");
+ return this.loadMessageBody();
+ }, this));
+ }
+ };
+ MailCatcher.prototype.loadMessageBody = function(id, format) {
+ id || (id = $('#mail tr.selected').attr('data-message-id'));
+ format || (format = $('#message .actions ul li.selected').first().attr('data-message-format'));
+ format || (format = 'html');
+ $("#message .actions ul li.tab[data-message-format=\"" + format + "\"]").addClass('selected');
+ $("#message .actions ul li.tab:not([data-message-format=\"" + format + "\"])").removeClass('selected');
+ if (id != null) {
+ return $('#message iframe').attr("src", "/messages/" + id + "." + format);
+ }
+ };
+ MailCatcher.prototype.refresh = function() {
+ return $.getJSON('/messages', __bind(function(messages) {
+ return $.each(messages, __bind(function(i, message) {
+ if (!this.haveMessage(message)) {
+ return this.addMessage(message);
+ }
+ }, this));
+ }, this));
+ };
+ MailCatcher.prototype.subscribe = function() {
+ if (typeof WebSocket !== "undefined" && WebSocket !== null) {
+ return this.subscribeWebSocket();
+ } else {
+ return this.subscribePoll();
+ }
+ };
+ MailCatcher.prototype.subscribeWebSocket = function() {
+ var secure;
+ secure = window.location.scheme === 'https';
+ this.websocket = new WebSocket("" + (secure ? 'wss' : 'ws') + "://" + window.location.host + "/messages");
+ return this.websocket.onmessage = __bind(function(event) {
+ return this.addMessage($.parseJSON(event.data));
+ }, this);
+ };
+ MailCatcher.prototype.subscribePoll = function() {
+ if (this.refreshInterval == null) {
+ return this.refreshInterval = setInterval((__bind(function() {
+ return this.refresh();
+ }, this)), 1000);
+ }
+ };
+ return MailCatcher;
+ })();
+ $(function() {
+ return window.MailCatcher = new MailCatcher;
+ });
+}).call(this);
diff --git a/views/index.haml b/views/index.haml
index f0c012a..5a05b44 100644
--- a/views/index.haml
+++ b/views/index.haml
@@ -6,8 +6,6 @@
%script{:src => "/javascripts/jquery.js"}
%script{:src => "/javascripts/date.js"}
%script{:src => "/javascripts/application.js"}
- :javascript
- $(MailCatcher.init);
%body
#mail
%table