flashtastic 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in flashtastic.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Amit Gaur
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # Flashtastic
2
+
3
+ Flashtastic is a Rails (3.1 and above) gem that replaces rails flash messages with [Messenger](http://github.hubspot.com/messenger/) (Version 1.3.6) javascript library for notifications.
4
+
5
+ ## Features
6
+
7
+ * Adds Messenger js and css into your asset pipeline
8
+ * Out of the box integration with rails flash messages
9
+ * Works for ajax requests
10
+ * Adds a default notification handler for ajax errors
11
+
12
+ ## About Messenger
13
+
14
+ - Show transactional messages in your app.
15
+ - Wrap AJAX requests with progress, success and error messages, and add retry to your failed requests.
16
+ - Add actions (undo, cancel, etc.) to your messages.
17
+ - 4kb minified and compressed.
18
+ - Works in everything modern, and IE7 and above.
19
+
20
+ <a href="http://hubspot.github.com/messenger">
21
+ <img src="https://raw.github.com/HubSpot/messenger/master/promotional-images/messenger.gif" title="Thanks for checking out Messenger!" style="max-width: 100%;padding:30px;"/>
22
+ </a>
23
+
24
+ [Demo and Usage of Messenger](http://hubspot.github.com/messenger)
25
+
26
+ ## Requirement/Dependency:
27
+
28
+ 1. jQuery
29
+
30
+ 2. Plays well with, but doesn't require, Bootstrap
31
+
32
+ ## Installation
33
+
34
+ Add this line to your application's Gemfile:
35
+
36
+ gem 'flashtastic'
37
+
38
+ And then execute:
39
+
40
+ $ bundle
41
+
42
+ Or install it yourself as:
43
+
44
+ $ gem install flashtastic
45
+
46
+ After gem installation do:
47
+
48
+ $ rails g flashtastic:install
49
+
50
+ Thats it!
51
+
52
+ ## Alternative Manual Installation
53
+ After installing the gem, if you don't want to run `rails g flashtastic:install`, do the following:
54
+
55
+ Copy the following coffeescript file in your assets:
56
+
57
+ [flashtastic_initializer.js.coffee](https://github.com/websymphony/flashtastic/blob/master/lib/generators/flashtastic/install/templates/flashtastic_initializer.js.coffee)
58
+
59
+ Add the following directive to your application.coffee / application.js.
60
+
61
+ //= require messenger
62
+ //= require messenger-theme-flat
63
+ //= require flashtastic_initializer // This will add integration with rails flash messages.
64
+
65
+ Add the following directive to your application.scss / application.css.
66
+ There are Five themes/styles provided (flat, future, air, block and ice), change required stylesheet as needed.
67
+
68
+ *= require messenger
69
+ *= require messenger-spinner
70
+ *= require messenger-theme-flat
71
+
72
+ Include Flashtastic module in Application controller
73
+
74
+ include Flashtastic
75
+
76
+ Thats it!
77
+
78
+ ## Usage
79
+
80
+ If you have included [flashtastic_initializer.js.coffee](https://github.com/websymphony/flashtastic/blob/master/lib/generators/flashtastic/install/templates/flashtastic_initializer.js.coffee) in your assets, your regular rails flash messages will show up as messenger messages. Even for ajax requests.
81
+
82
+ Modify [flashtastic_initializer.js.coffee](https://github.com/websymphony/flashtastic/blob/master/lib/generators/flashtastic/install/templates/flashtastic_initializer.js.coffee) as needed.
83
+
84
+ [Demo and Usage of Messenger](http://hubspot.github.com/messenger)
85
+
86
+ ## Contributing
87
+
88
+ 1. Fork it
89
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
90
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
91
+ 4. Push to the branch (`git push origin my-new-feature`)
92
+ 5. Create new Pull Request
93
+
94
+ ## Author
95
+ **Amit Gaur**
96
+
97
+ + [http://websymphony.net](http://websymphony.net)
98
+ + [http://twitter.com/websymphony](http://twitter.com/websymphony)
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'flashtastic/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "flashtastic"
8
+ spec.version = Flashtastic::VERSION
9
+ spec.authors = ["Amit Gaur"]
10
+ spec.email = ["amitgaur.web@gmail.com"]
11
+ spec.description = %q{Adds Hubspot Messenger js and css into your asset pipeline. Integrates seamlessly with rails flash messages, even for ajax requests.}
12
+ spec.summary = %q{Hubspot Messenger for Rails Flash Messages}
13
+ spec.homepage = "https://github.com/websymphony/flashtastic/"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ end
@@ -0,0 +1,21 @@
1
+ require "flashtastic/version"
2
+
3
+ module Flashtastic
4
+ class Engine < ::Rails::Engine
5
+ end
6
+
7
+ def self.included(base)
8
+ base.after_filter :flash_to_cookie
9
+ end
10
+
11
+ def flash_to_cookie
12
+ cookies.delete :flashtastic_cookie #starting with clean slate on each request.
13
+ flash_json = Hash[flash.map{|k,v| [k,ERB::Util.h(v)] }].to_json
14
+ cookies[:flashtastic_cookie] = {
15
+ :value => flash_json,
16
+ :expires => 1.year.from_now
17
+ }
18
+ flash.discard
19
+ end
20
+
21
+ end
@@ -0,0 +1,3 @@
1
+ module Flashtastic
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,40 @@
1
+ module Flashtastic
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ def copy_flashtastic_initializer
7
+ say_status("copying", "flashtastic_initializer.js.coffee file to your assets directory", :green)
8
+ copy_file "flashtastic_initializer.js.coffee", "app/assets/javascripts/flashtastic_initializer.js.coffee"
9
+ end
10
+
11
+ def include_flashtastic_module_in_application_controller
12
+ say_status("inserting", "Flashtastic module in your ApplicationController ", :green)
13
+ inject_into_class "app/controllers/application_controller.rb", ApplicationController, " include Flashtastic\n"
14
+ end
15
+
16
+ def include_messenger_js_references
17
+ say_status("inserting", "messenger js references in your application.js ", :green)
18
+ insert_into_file "app/assets/javascripts/application.js", :after => "//= require jquery\n" do
19
+ <<-JS
20
+ //= require messenger
21
+ //= require messenger-theme-flat
22
+ //= require flashtastic_initializer
23
+ JS
24
+ end
25
+ end
26
+
27
+ def include_messenger_css_references
28
+ say_status("inserting", "messenger css references in your application.css ", :green)
29
+ insert_into_file "app/assets/stylesheets/application.css", :after => "*= require_self\n" do
30
+ <<-CSS
31
+ *= require messenger
32
+ *= require messenger-spinner
33
+ *= require messenger-theme-flat
34
+ CSS
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,74 @@
1
+ # Global Options for Messenger Plugin
2
+ Messenger.options = {
3
+ extraClasses: 'messenger-fixed messenger-on-top messenger-on-right', # define the position of notification
4
+ theme: 'flat' # define styles here
5
+ }
6
+
7
+ $(document).on
8
+ ready: (e) -> # This handles non ajax flash messages
9
+ Flashtastic().showFlashMessage()
10
+
11
+ ajaxSuccess: (e, r) -> # This handles ajax flash messages
12
+ Flashtastic().showFlashMessage()
13
+
14
+ ajaxError: (e) -> # This handles ajax errors
15
+ opts = {
16
+ # Catch All message for all ajax errors. Feel Free to customize.
17
+ message: "There was an error while processing your request. Please try reloading the page."
18
+ type: "error"
19
+ }
20
+ Flashtastic().showFlashMessage(opts)
21
+
22
+
23
+ #==================================================
24
+ # Flashtastic script that handles Rails flash messages
25
+ #==================================================
26
+
27
+ do window.Flashtastic = ->
28
+
29
+ # private
30
+ # This function reads the cookie. duh!
31
+ readCookie = (name, c, C, i) ->
32
+ return cookies[name] if cookies
33
+ c = document.cookie.split("; ")
34
+ cookies = {}
35
+ i = c.length - 1
36
+ while i >= 0
37
+ C = c[i].split("=")
38
+ cookies[C[0]] = C[1]
39
+ i--
40
+ cookies[name]
41
+
42
+ # private
43
+ # This function deletes the cookie. duh!
44
+ deleteCookie = (name) ->
45
+ document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:01 GMT;"
46
+
47
+ # private
48
+ # This function cleans up junk from message.
49
+ cleanUpMessage = (msg) ->
50
+ msg.replace(/\+/g,' ')
51
+
52
+ # private
53
+ # This function uses cookie info
54
+ # and constructs Messenger post
55
+ flashMessageHandler = (opts) ->
56
+ if opts?
57
+ Messenger().post
58
+ type: opts['type']
59
+ message: opts['message']
60
+ hideAfter: 3
61
+ showCloseButton: true
62
+ else
63
+ flash_hash = $.parseJSON(decodeURIComponent(readCookie("flashtastic_cookie")))
64
+ deleteCookie('flashtastic_cookie')
65
+ if flash_hash
66
+ $.each flash_hash, (type, msg) ->
67
+ Messenger().post
68
+ type: type
69
+ message: cleanUpMessage(msg)
70
+ hideAfter: 3
71
+ showCloseButton: true
72
+
73
+
74
+ showFlashMessage: flashMessageHandler # exposed it for public consumption
@@ -0,0 +1,33 @@
1
+ (function() {
2
+ var $, FlatMessage, spinner_template,
3
+ __hasProp = {}.hasOwnProperty,
4
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
5
+
6
+ $ = jQuery;
7
+
8
+ spinner_template = '<div class="messenger-spinner">\n <span class="messenger-spinner-side messenger-spinner-side-left">\n <span class="messenger-spinner-fill"></span>\n </span>\n <span class="messenger-spinner-side messenger-spinner-side-right">\n <span class="messenger-spinner-fill"></span>\n </span>\n</div>';
9
+
10
+ FlatMessage = (function(_super) {
11
+
12
+ __extends(FlatMessage, _super);
13
+
14
+ function FlatMessage() {
15
+ return FlatMessage.__super__.constructor.apply(this, arguments);
16
+ }
17
+
18
+ FlatMessage.prototype.template = function(opts) {
19
+ var $message;
20
+ $message = FlatMessage.__super__.template.apply(this, arguments);
21
+ $message.append($(spinner_template));
22
+ return $message;
23
+ };
24
+
25
+ return FlatMessage;
26
+
27
+ })(window.Messenger.Message);
28
+
29
+ window.Messenger.themes.flat = {
30
+ Message: FlatMessage
31
+ };
32
+
33
+ }).call(this);
@@ -0,0 +1,33 @@
1
+ (function() {
2
+ var $, FutureMessage, spinner_template,
3
+ __hasProp = {}.hasOwnProperty,
4
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
5
+
6
+ $ = jQuery;
7
+
8
+ spinner_template = '<div class="messenger-spinner">\n <span class="messenger-spinner-side messenger-spinner-side-left">\n <span class="messenger-spinner-fill"></span>\n </span>\n <span class="messenger-spinner-side messenger-spinner-side-right">\n <span class="messenger-spinner-fill"></span>\n </span>\n</div>';
9
+
10
+ FutureMessage = (function(_super) {
11
+
12
+ __extends(FutureMessage, _super);
13
+
14
+ function FutureMessage() {
15
+ return FutureMessage.__super__.constructor.apply(this, arguments);
16
+ }
17
+
18
+ FutureMessage.prototype.template = function(opts) {
19
+ var $message;
20
+ $message = FutureMessage.__super__.template.apply(this, arguments);
21
+ $message.append($(spinner_template));
22
+ return $message;
23
+ };
24
+
25
+ return FutureMessage;
26
+
27
+ })(window.Messenger.Message);
28
+
29
+ window.Messenger.themes.future = {
30
+ Message: FutureMessage
31
+ };
32
+
33
+ }).call(this);
@@ -0,0 +1,1228 @@
1
+ /*! messenger 1.3.6 */
2
+ /*
3
+ * This file begins the output concatenated into messenger.js
4
+ *
5
+ * It establishes the Messenger object while preserving whatever it was before
6
+ * (for noConflict), and making it a callable function.
7
+ */
8
+
9
+ (function(){
10
+ var _prevMessenger = window.Messenger;
11
+ var localMessenger;
12
+
13
+ localMessenger = window.Messenger = function(){
14
+ return localMessenger._call.apply(this, arguments);
15
+ }
16
+
17
+ window.Messenger.noConflict = function(){
18
+ window.Messenger = _prevMessenger;
19
+
20
+ return localMessenger;
21
+ }
22
+ })();
23
+
24
+ /*
25
+ * This file contains shims for when Underscore and Backbone
26
+ * are not included.
27
+ *
28
+ * Portions taken from Underscore.js and Backbone.js
29
+ * Both of which are Copyright (c) 2009-2013 Jeremy Ashkenas, DocumentCloud
30
+ */
31
+ window.Messenger._ = (function() {
32
+ if (window._)
33
+ return window._
34
+
35
+ var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
36
+
37
+ // Create quick reference variables for speed access to core prototypes.
38
+ var push = ArrayProto.push,
39
+ slice = ArrayProto.slice,
40
+ concat = ArrayProto.concat,
41
+ toString = ObjProto.toString,
42
+ hasOwnProperty = ObjProto.hasOwnProperty;
43
+
44
+ // All **ECMAScript 5** native function implementations that we hope to use
45
+ // are declared here.
46
+ var
47
+ nativeForEach = ArrayProto.forEach,
48
+ nativeMap = ArrayProto.map,
49
+ nativeReduce = ArrayProto.reduce,
50
+ nativeReduceRight = ArrayProto.reduceRight,
51
+ nativeFilter = ArrayProto.filter,
52
+ nativeEvery = ArrayProto.every,
53
+ nativeSome = ArrayProto.some,
54
+ nativeIndexOf = ArrayProto.indexOf,
55
+ nativeLastIndexOf = ArrayProto.lastIndexOf,
56
+ nativeIsArray = Array.isArray,
57
+ nativeKeys = Object.keys,
58
+ nativeBind = FuncProto.bind;
59
+
60
+ // Create a safe reference to the Underscore object for use below.
61
+ var _ = {};
62
+
63
+ // Establish the object that gets returned to break out of a loop iteration.
64
+ var breaker = {};
65
+
66
+ var each = _.each = _.forEach = function(obj, iterator, context) {
67
+ if (obj == null) return;
68
+ if (nativeForEach && obj.forEach === nativeForEach) {
69
+ obj.forEach(iterator, context);
70
+ } else if (obj.length === +obj.length) {
71
+ for (var i = 0, l = obj.length; i < l; i++) {
72
+ if (iterator.call(context, obj[i], i, obj) === breaker) return;
73
+ }
74
+ } else {
75
+ for (var key in obj) {
76
+ if (_.has(obj, key)) {
77
+ if (iterator.call(context, obj[key], key, obj) === breaker) return;
78
+ }
79
+ }
80
+ }
81
+ };
82
+
83
+ _.result = function(object, property) {
84
+ if (object == null) return null;
85
+ var value = object[property];
86
+ return _.isFunction(value) ? value.call(object) : value;
87
+ };
88
+
89
+ _.once = function(func) {
90
+ var ran = false, memo;
91
+ return function() {
92
+ if (ran) return memo;
93
+ ran = true;
94
+ memo = func.apply(this, arguments);
95
+ func = null;
96
+ return memo;
97
+ };
98
+ };
99
+
100
+ var idCounter = 0;
101
+ _.uniqueId = function(prefix) {
102
+ var id = ++idCounter + '';
103
+ return prefix ? prefix + id : id;
104
+ };
105
+
106
+ _.filter = _.select = function(obj, iterator, context) {
107
+ var results = [];
108
+ if (obj == null) return results;
109
+ if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
110
+ each(obj, function(value, index, list) {
111
+ if (iterator.call(context, value, index, list)) results[results.length] = value;
112
+ });
113
+ return results;
114
+ };
115
+
116
+ // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
117
+ each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
118
+ _['is' + name] = function(obj) {
119
+ return toString.call(obj) == '[object ' + name + ']';
120
+ };
121
+ });
122
+
123
+ _.defaults = function(obj) {
124
+ each(slice.call(arguments, 1), function(source) {
125
+ if (source) {
126
+ for (var prop in source) {
127
+ if (obj[prop] == null) obj[prop] = source[prop];
128
+ }
129
+ }
130
+ });
131
+ return obj;
132
+ };
133
+
134
+ _.extend = function(obj) {
135
+ each(slice.call(arguments, 1), function(source) {
136
+ if (source) {
137
+ for (var prop in source) {
138
+ obj[prop] = source[prop];
139
+ }
140
+ }
141
+ });
142
+ return obj;
143
+ };
144
+
145
+ _.keys = nativeKeys || function(obj) {
146
+ if (obj !== Object(obj)) throw new TypeError('Invalid object');
147
+ var keys = [];
148
+ for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
149
+ return keys;
150
+ };
151
+
152
+ _.bind = function(func, context) {
153
+ if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
154
+ var args = slice.call(arguments, 2);
155
+ return function() {
156
+ return func.apply(context, args.concat(slice.call(arguments)));
157
+ };
158
+ };
159
+
160
+ _.isObject = function(obj) {
161
+ return obj === Object(obj);
162
+ };
163
+
164
+ return _;
165
+ })();
166
+
167
+ window.Messenger.Events = (function() {
168
+ if (window.Backbone && Backbone.Events) {
169
+ return Backbone.Events;
170
+ }
171
+
172
+ var eventsShim = function() {
173
+ var eventSplitter = /\s+/;
174
+
175
+ var eventsApi = function(obj, action, name, rest) {
176
+ if (!name) return true;
177
+ if (typeof name === 'object') {
178
+ for (var key in name) {
179
+ obj[action].apply(obj, [key, name[key]].concat(rest));
180
+ }
181
+ } else if (eventSplitter.test(name)) {
182
+ var names = name.split(eventSplitter);
183
+ for (var i = 0, l = names.length; i < l; i++) {
184
+ obj[action].apply(obj, [names[i]].concat(rest));
185
+ }
186
+ } else {
187
+ return true;
188
+ }
189
+ };
190
+
191
+ var triggerEvents = function(events, args) {
192
+ var ev, i = -1, l = events.length;
193
+ switch (args.length) {
194
+ case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx);
195
+ return;
196
+ case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0]);
197
+ return;
198
+ case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1]);
199
+ return;
200
+ case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1], args[2]);
201
+ return;
202
+ default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
203
+ }
204
+ };
205
+
206
+ var Events = {
207
+
208
+ on: function(name, callback, context) {
209
+ if (!(eventsApi(this, 'on', name, [callback, context]) && callback)) return this;
210
+ this._events || (this._events = {});
211
+ var list = this._events[name] || (this._events[name] = []);
212
+ list.push({callback: callback, context: context, ctx: context || this});
213
+ return this;
214
+ },
215
+
216
+ once: function(name, callback, context) {
217
+ if (!(eventsApi(this, 'once', name, [callback, context]) && callback)) return this;
218
+ var self = this;
219
+ var once = _.once(function() {
220
+ self.off(name, once);
221
+ callback.apply(this, arguments);
222
+ });
223
+ once._callback = callback;
224
+ this.on(name, once, context);
225
+ return this;
226
+ },
227
+
228
+ off: function(name, callback, context) {
229
+ var list, ev, events, names, i, l, j, k;
230
+ if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;
231
+ if (!name && !callback && !context) {
232
+ this._events = {};
233
+ return this;
234
+ }
235
+
236
+ names = name ? [name] : _.keys(this._events);
237
+ for (i = 0, l = names.length; i < l; i++) {
238
+ name = names[i];
239
+ if (list = this._events[name]) {
240
+ events = [];
241
+ if (callback || context) {
242
+ for (j = 0, k = list.length; j < k; j++) {
243
+ ev = list[j];
244
+ if ((callback && callback !== ev.callback &&
245
+ callback !== ev.callback._callback) ||
246
+ (context && context !== ev.context)) {
247
+ events.push(ev);
248
+ }
249
+ }
250
+ }
251
+ this._events[name] = events;
252
+ }
253
+ }
254
+
255
+ return this;
256
+ },
257
+
258
+ trigger: function(name) {
259
+ if (!this._events) return this;
260
+ var args = Array.prototype.slice.call(arguments, 1);
261
+ if (!eventsApi(this, 'trigger', name, args)) return this;
262
+ var events = this._events[name];
263
+ var allEvents = this._events.all;
264
+ if (events) triggerEvents(events, args);
265
+ if (allEvents) triggerEvents(allEvents, arguments);
266
+ return this;
267
+ },
268
+
269
+ listenTo: function(obj, name, callback) {
270
+ var listeners = this._listeners || (this._listeners = {});
271
+ var id = obj._listenerId || (obj._listenerId = _.uniqueId('l'));
272
+ listeners[id] = obj;
273
+ obj.on(name, typeof name === 'object' ? this : callback, this);
274
+ return this;
275
+ },
276
+
277
+ stopListening: function(obj, name, callback) {
278
+ var listeners = this._listeners;
279
+ if (!listeners) return;
280
+ if (obj) {
281
+ obj.off(name, typeof name === 'object' ? this : callback, this);
282
+ if (!name && !callback) delete listeners[obj._listenerId];
283
+ } else {
284
+ if (typeof name === 'object') callback = this;
285
+ for (var id in listeners) {
286
+ listeners[id].off(name, callback, this);
287
+ }
288
+ this._listeners = {};
289
+ }
290
+ return this;
291
+ }
292
+ };
293
+
294
+ Events.bind = Events.on;
295
+ Events.unbind = Events.off;
296
+ return Events;
297
+ };
298
+ return eventsShim();
299
+ })();
300
+
301
+ (function() {
302
+ var $, ActionMessenger, BaseView, Events, RetryingMessage, _, _Message, _Messenger, _ref, _ref1, _ref2,
303
+ __hasProp = {}.hasOwnProperty,
304
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
305
+ __slice = [].slice,
306
+ __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
307
+
308
+ $ = jQuery;
309
+
310
+ _ = (_ref = window._) != null ? _ref : window.Messenger._;
311
+
312
+ Events = (_ref1 = typeof Backbone !== "undefined" && Backbone !== null ? Backbone.Events : void 0) != null ? _ref1 : window.Messenger.Events;
313
+
314
+ BaseView = (function() {
315
+
316
+ function BaseView(options) {
317
+ $.extend(this, Events);
318
+ if (_.isObject(options)) {
319
+ if (options.el) {
320
+ this.setElement(options.el);
321
+ }
322
+ this.model = options.model;
323
+ }
324
+ this.initialize.apply(this, arguments);
325
+ }
326
+
327
+ BaseView.prototype.setElement = function(el) {
328
+ this.$el = $(el);
329
+ return this.el = this.$el[0];
330
+ };
331
+
332
+ BaseView.prototype.delegateEvents = function(events) {
333
+ var delegateEventSplitter, eventName, key, match, method, selector, _results;
334
+ if (!(events || (events = _.result(this, 'events')))) {
335
+ return;
336
+ }
337
+ delegateEventSplitter = /^(\S+)\s*(.*)$/;
338
+ this.undelegateEvents();
339
+ _results = [];
340
+ for (key in events) {
341
+ method = events[key];
342
+ if (!_.isFunction(method)) {
343
+ method = this[events[key]];
344
+ }
345
+ if (!method) {
346
+ throw new Error("Method " + events[key] + " does not exist");
347
+ }
348
+ match = key.match(delegateEventSplitter);
349
+ eventName = match[1];
350
+ selector = match[2];
351
+ method = _.bind(method, this);
352
+ eventName += ".delegateEvents" + this.cid;
353
+ if (selector === '') {
354
+ _results.push(this.jqon(eventName, method));
355
+ } else {
356
+ _results.push(this.jqon(eventName, selector, method));
357
+ }
358
+ }
359
+ return _results;
360
+ };
361
+
362
+ BaseView.prototype.jqon = function(eventName, selector, method) {
363
+ var _ref2;
364
+ if (this.$el.on != null) {
365
+ return (_ref2 = this.$el).on.apply(_ref2, arguments);
366
+ } else {
367
+ if (!(method != null)) {
368
+ method = selector;
369
+ selector = void 0;
370
+ }
371
+ if (selector != null) {
372
+ return this.$el.delegate(selector, eventName, method);
373
+ } else {
374
+ return this.$el.bind(eventName, method);
375
+ }
376
+ }
377
+ };
378
+
379
+ BaseView.prototype.jqoff = function(eventName) {
380
+ var _ref2;
381
+ if (this.$el.off != null) {
382
+ return (_ref2 = this.$el).off.apply(_ref2, arguments);
383
+ } else {
384
+ this.$el.undelegate();
385
+ return this.$el.unbind(eventName);
386
+ }
387
+ };
388
+
389
+ BaseView.prototype.undelegateEvents = function() {
390
+ return this.jqoff(".delegateEvents" + this.cid);
391
+ };
392
+
393
+ BaseView.prototype.remove = function() {
394
+ this.undelegateEvents();
395
+ return this.$el.remove();
396
+ };
397
+
398
+ return BaseView;
399
+
400
+ })();
401
+
402
+ _Message = (function(_super) {
403
+
404
+ __extends(_Message, _super);
405
+
406
+ function _Message() {
407
+ return _Message.__super__.constructor.apply(this, arguments);
408
+ }
409
+
410
+ _Message.prototype.defaults = {
411
+ hideAfter: 10,
412
+ scroll: true
413
+ };
414
+
415
+ _Message.prototype.initialize = function(opts) {
416
+ if (opts == null) {
417
+ opts = {};
418
+ }
419
+ this.shown = false;
420
+ this.rendered = false;
421
+ this.messenger = opts.messenger;
422
+ return this.options = $.extend({}, this.options, opts, this.defaults);
423
+ };
424
+
425
+ _Message.prototype.show = function() {
426
+ var wasShown;
427
+ if (!this.rendered) {
428
+ this.render();
429
+ }
430
+ this.$message.removeClass('messenger-hidden');
431
+ wasShown = this.shown;
432
+ this.shown = true;
433
+ if (!wasShown) {
434
+ return this.trigger('show');
435
+ }
436
+ };
437
+
438
+ _Message.prototype.hide = function() {
439
+ var wasShown;
440
+ if (!this.rendered) {
441
+ return;
442
+ }
443
+ this.$message.addClass('messenger-hidden');
444
+ wasShown = this.shown;
445
+ this.shown = false;
446
+ if (wasShown) {
447
+ return this.trigger('hide');
448
+ }
449
+ };
450
+
451
+ _Message.prototype.cancel = function() {
452
+ return this.hide();
453
+ };
454
+
455
+ _Message.prototype.update = function(opts) {
456
+ var _ref2,
457
+ _this = this;
458
+ if (_.isString(opts)) {
459
+ opts = {
460
+ message: opts
461
+ };
462
+ }
463
+ $.extend(this.options, opts);
464
+ this.lastUpdate = new Date();
465
+ this.rendered = false;
466
+ this.events = (_ref2 = this.options.events) != null ? _ref2 : {};
467
+ this.render();
468
+ this.actionsToEvents();
469
+ this.delegateEvents();
470
+ this.checkClickable();
471
+ if (this.options.hideAfter) {
472
+ this.$message.addClass('messenger-will-hide-after');
473
+ if (this._hideTimeout != null) {
474
+ clearTimeout(this._hideTimeout);
475
+ }
476
+ this._hideTimeout = setTimeout(function() {
477
+ return _this.hide();
478
+ }, this.options.hideAfter * 1000);
479
+ } else {
480
+ this.$message.removeClass('messenger-will-hide-after');
481
+ }
482
+ if (this.options.hideOnNavigate) {
483
+ this.$message.addClass('messenger-will-hide-on-navigate');
484
+ if ((typeof Backbone !== "undefined" && Backbone !== null ? Backbone.history : void 0) != null) {
485
+ Backbone.history.on('route', function() {
486
+ return _this.hide();
487
+ });
488
+ }
489
+ } else {
490
+ this.$message.removeClass('messenger-will-hide-on-navigate');
491
+ }
492
+ return this.trigger('update', this);
493
+ };
494
+
495
+ _Message.prototype.scrollTo = function() {
496
+ if (!this.options.scroll) {
497
+ return;
498
+ }
499
+ return $.scrollTo(this.$el, {
500
+ duration: 400,
501
+ offset: {
502
+ left: 0,
503
+ top: -20
504
+ }
505
+ });
506
+ };
507
+
508
+ _Message.prototype.timeSinceUpdate = function() {
509
+ if (this.lastUpdate) {
510
+ return (new Date) - this.lastUpdate;
511
+ } else {
512
+ return null;
513
+ }
514
+ };
515
+
516
+ _Message.prototype.actionsToEvents = function() {
517
+ var act, name, _ref2, _results,
518
+ _this = this;
519
+ _ref2 = this.options.actions;
520
+ _results = [];
521
+ for (name in _ref2) {
522
+ act = _ref2[name];
523
+ _results.push(this.events["click [data-action=\"" + name + "\"] a"] = (function(act) {
524
+ return function(e) {
525
+ e.preventDefault();
526
+ e.stopPropagation();
527
+ _this.trigger("action:" + name, act, e);
528
+ return act.action.call(_this, e, _this);
529
+ };
530
+ })(act));
531
+ }
532
+ return _results;
533
+ };
534
+
535
+ _Message.prototype.checkClickable = function() {
536
+ var evt, name, _ref2, _results;
537
+ _ref2 = this.events;
538
+ _results = [];
539
+ for (name in _ref2) {
540
+ evt = _ref2[name];
541
+ if (name === 'click') {
542
+ _results.push(this.$message.addClass('messenger-clickable'));
543
+ } else {
544
+ _results.push(void 0);
545
+ }
546
+ }
547
+ return _results;
548
+ };
549
+
550
+ _Message.prototype.undelegateEvents = function() {
551
+ var _ref2;
552
+ _Message.__super__.undelegateEvents.apply(this, arguments);
553
+ return (_ref2 = this.$message) != null ? _ref2.removeClass('messenger-clickable') : void 0;
554
+ };
555
+
556
+ _Message.prototype.parseActions = function() {
557
+ var act, actions, n_act, name, _ref2, _ref3;
558
+ actions = [];
559
+ _ref2 = this.options.actions;
560
+ for (name in _ref2) {
561
+ act = _ref2[name];
562
+ n_act = $.extend({}, act);
563
+ n_act.name = name;
564
+ if ((_ref3 = n_act.label) == null) {
565
+ n_act.label = name;
566
+ }
567
+ actions.push(n_act);
568
+ }
569
+ return actions;
570
+ };
571
+
572
+ _Message.prototype.template = function(opts) {
573
+ var $action, $actions, $cancel, $link, $message, $text, action, _i, _len, _ref2,
574
+ _this = this;
575
+ $message = $("<div class='messenger-message message alert " + opts.type + " message-" + opts.type + " alert-" + opts.type + "'>");
576
+ if (opts.showCloseButton) {
577
+ $cancel = $('<button type="button" class="messenger-close" data-dismiss="alert">&times;</button>');
578
+ $cancel.click(function() {
579
+ _this.cancel();
580
+ return true;
581
+ });
582
+ $message.append($cancel);
583
+ }
584
+ $text = $("<div class=\"messenger-message-inner\">" + opts.message + "</div>");
585
+ $message.append($text);
586
+ if (opts.actions.length) {
587
+ $actions = $('<div class="messenger-actions">');
588
+ }
589
+ _ref2 = opts.actions;
590
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
591
+ action = _ref2[_i];
592
+ $action = $('<span>');
593
+ $action.attr('data-action', "" + action.name);
594
+ $link = $('<a>');
595
+ $link.html(action.label);
596
+ $action.append($('<span class="messenger-phrase">'));
597
+ $action.append($link);
598
+ $actions.append($action);
599
+ }
600
+ $message.append($actions);
601
+ return $message;
602
+ };
603
+
604
+ _Message.prototype.render = function() {
605
+ var opts;
606
+ if (this.rendered) {
607
+ return;
608
+ }
609
+ if (!this._hasSlot) {
610
+ this.setElement(this.messenger._reserveMessageSlot(this));
611
+ this._hasSlot = true;
612
+ }
613
+ opts = $.extend({}, this.options, {
614
+ actions: this.parseActions()
615
+ });
616
+ this.$message = $(this.template(opts));
617
+ this.$el.html(this.$message);
618
+ this.shown = true;
619
+ this.rendered = true;
620
+ return this.trigger('render');
621
+ };
622
+
623
+ return _Message;
624
+
625
+ })(BaseView);
626
+
627
+ RetryingMessage = (function(_super) {
628
+
629
+ __extends(RetryingMessage, _super);
630
+
631
+ function RetryingMessage() {
632
+ return RetryingMessage.__super__.constructor.apply(this, arguments);
633
+ }
634
+
635
+ RetryingMessage.prototype.initialize = function() {
636
+ RetryingMessage.__super__.initialize.apply(this, arguments);
637
+ return this._timers = {};
638
+ };
639
+
640
+ RetryingMessage.prototype.cancel = function() {
641
+ this.clearTimers();
642
+ this.hide();
643
+ if ((this._actionInstance != null) && (this._actionInstance.abort != null)) {
644
+ return this._actionInstance.abort();
645
+ }
646
+ };
647
+
648
+ RetryingMessage.prototype.clearTimers = function() {
649
+ var name, timer, _ref2, _ref3;
650
+ _ref2 = this._timers;
651
+ for (name in _ref2) {
652
+ timer = _ref2[name];
653
+ clearTimeout(timer);
654
+ }
655
+ this._timers = {};
656
+ return (_ref3 = this.$message) != null ? _ref3.removeClass('messenger-retry-soon messenger-retry-later') : void 0;
657
+ };
658
+
659
+ RetryingMessage.prototype.render = function() {
660
+ var action, name, _ref2, _results;
661
+ RetryingMessage.__super__.render.apply(this, arguments);
662
+ this.clearTimers();
663
+ _ref2 = this.options.actions;
664
+ _results = [];
665
+ for (name in _ref2) {
666
+ action = _ref2[name];
667
+ if (action.auto) {
668
+ _results.push(this.startCountdown(name, action));
669
+ } else {
670
+ _results.push(void 0);
671
+ }
672
+ }
673
+ return _results;
674
+ };
675
+
676
+ RetryingMessage.prototype.renderPhrase = function(action, time) {
677
+ var phrase;
678
+ phrase = action.phrase.replace('TIME', this.formatTime(time));
679
+ return phrase;
680
+ };
681
+
682
+ RetryingMessage.prototype.formatTime = function(time) {
683
+ var pluralize;
684
+ pluralize = function(num, str) {
685
+ num = Math.floor(num);
686
+ if (num !== 1) {
687
+ str = str + 's';
688
+ }
689
+ return 'in ' + num + ' ' + str;
690
+ };
691
+ if (Math.floor(time) === 0) {
692
+ return 'now...';
693
+ }
694
+ if (time < 60) {
695
+ return pluralize(time, 'second');
696
+ }
697
+ time /= 60;
698
+ if (time < 60) {
699
+ return pluralize(time, 'minute');
700
+ }
701
+ time /= 60;
702
+ return pluralize(time, 'hour');
703
+ };
704
+
705
+ RetryingMessage.prototype.startCountdown = function(name, action) {
706
+ var $phrase, remaining, tick, _ref2,
707
+ _this = this;
708
+ if (this._timers[name] != null) {
709
+ return;
710
+ }
711
+ $phrase = this.$message.find("[data-action='" + name + "'] .messenger-phrase");
712
+ remaining = (_ref2 = action.delay) != null ? _ref2 : 3;
713
+ if (remaining <= 10) {
714
+ this.$message.removeClass('messenger-retry-later');
715
+ this.$message.addClass('messenger-retry-soon');
716
+ } else {
717
+ this.$message.removeClass('messenger-retry-soon');
718
+ this.$message.addClass('messenger-retry-later');
719
+ }
720
+ tick = function() {
721
+ var delta;
722
+ $phrase.text(_this.renderPhrase(action, remaining));
723
+ if (remaining > 0) {
724
+ delta = Math.min(remaining, 1);
725
+ remaining -= delta;
726
+ return _this._timers[name] = setTimeout(tick, delta * 1000);
727
+ } else {
728
+ _this.$message.removeClass('messenger-retry-soon messenger-retry-later');
729
+ delete _this._timers[name];
730
+ return action.action();
731
+ }
732
+ };
733
+ return tick();
734
+ };
735
+
736
+ return RetryingMessage;
737
+
738
+ })(_Message);
739
+
740
+ _Messenger = (function(_super) {
741
+
742
+ __extends(_Messenger, _super);
743
+
744
+ function _Messenger() {
745
+ return _Messenger.__super__.constructor.apply(this, arguments);
746
+ }
747
+
748
+ _Messenger.prototype.tagName = 'ul';
749
+
750
+ _Messenger.prototype.className = 'messenger';
751
+
752
+ _Messenger.prototype.messageDefaults = {
753
+ type: 'info'
754
+ };
755
+
756
+ _Messenger.prototype.initialize = function(options) {
757
+ this.options = options != null ? options : {};
758
+ this.history = [];
759
+ return this.messageDefaults = $.extend({}, this.messageDefaults, this.options.messageDefaults);
760
+ };
761
+
762
+ _Messenger.prototype.render = function() {
763
+ return this.updateMessageSlotClasses();
764
+ };
765
+
766
+ _Messenger.prototype.findById = function(id) {
767
+ return _.filter(this.history, function(rec) {
768
+ return rec.msg.options.id === id;
769
+ });
770
+ };
771
+
772
+ _Messenger.prototype._reserveMessageSlot = function(msg) {
773
+ var $slot, dmsg,
774
+ _this = this;
775
+ $slot = $('<li>');
776
+ $slot.addClass('messenger-message-slot');
777
+ this.$el.prepend($slot);
778
+ this.history.push({
779
+ msg: msg,
780
+ $slot: $slot
781
+ });
782
+ this._enforceIdConstraint(msg);
783
+ msg.on('update', function() {
784
+ return _this._enforceIdConstraint(msg);
785
+ });
786
+ while (this.options.maxMessages && this.history.length > this.options.maxMessages) {
787
+ dmsg = this.history.shift();
788
+ dmsg.msg.remove();
789
+ dmsg.$slot.remove();
790
+ }
791
+ return $slot;
792
+ };
793
+
794
+ _Messenger.prototype._enforceIdConstraint = function(msg) {
795
+ var entry, _i, _len, _msg, _ref2;
796
+ if (msg.options.id == null) {
797
+ return;
798
+ }
799
+ _ref2 = this.history;
800
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
801
+ entry = _ref2[_i];
802
+ _msg = entry.msg;
803
+ if ((_msg.options.id != null) && _msg.options.id === msg.options.id && msg !== _msg) {
804
+ if (msg.options.singleton) {
805
+ msg.hide();
806
+ return;
807
+ } else {
808
+ _msg.hide();
809
+ }
810
+ }
811
+ }
812
+ };
813
+
814
+ _Messenger.prototype.newMessage = function(opts) {
815
+ var msg, _ref2, _ref3, _ref4,
816
+ _this = this;
817
+ if (opts == null) {
818
+ opts = {};
819
+ }
820
+ opts.messenger = this;
821
+ _Message = (_ref2 = (_ref3 = Messenger.themes[(_ref4 = opts.theme) != null ? _ref4 : this.options.theme]) != null ? _ref3.Message : void 0) != null ? _ref2 : RetryingMessage;
822
+ msg = new _Message(opts);
823
+ msg.on('show', function() {
824
+ if (opts.scrollTo && _this.$el.css('position') !== 'fixed') {
825
+ return msg.scrollTo();
826
+ }
827
+ });
828
+ msg.on('hide show render', this.updateMessageSlotClasses, this);
829
+ return msg;
830
+ };
831
+
832
+ _Messenger.prototype.updateMessageSlotClasses = function() {
833
+ var anyShown, last, rec, willBeFirst, _i, _len, _ref2;
834
+ willBeFirst = true;
835
+ last = null;
836
+ anyShown = false;
837
+ _ref2 = this.history;
838
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
839
+ rec = _ref2[_i];
840
+ rec.$slot.removeClass('messenger-first messenger-last messenger-shown');
841
+ if (rec.msg.shown && rec.msg.rendered) {
842
+ rec.$slot.addClass('messenger-shown');
843
+ anyShown = true;
844
+ last = rec;
845
+ if (willBeFirst) {
846
+ willBeFirst = false;
847
+ rec.$slot.addClass('messenger-first');
848
+ }
849
+ }
850
+ }
851
+ if (last != null) {
852
+ last.$slot.addClass('messenger-last');
853
+ }
854
+ return this.$el["" + (anyShown ? 'remove' : 'add') + "Class"]('messenger-empty');
855
+ };
856
+
857
+ _Messenger.prototype.hideAll = function() {
858
+ var rec, _i, _len, _ref2, _results;
859
+ _ref2 = this.history;
860
+ _results = [];
861
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
862
+ rec = _ref2[_i];
863
+ _results.push(rec.msg.hide());
864
+ }
865
+ return _results;
866
+ };
867
+
868
+ _Messenger.prototype.post = function(opts) {
869
+ var msg;
870
+ if (_.isString(opts)) {
871
+ opts = {
872
+ message: opts
873
+ };
874
+ }
875
+ opts = $.extend(true, {}, this.messageDefaults, opts);
876
+ msg = this.newMessage(opts);
877
+ msg.update(opts);
878
+ return msg;
879
+ };
880
+
881
+ return _Messenger;
882
+
883
+ })(BaseView);
884
+
885
+ ActionMessenger = (function(_super) {
886
+
887
+ __extends(ActionMessenger, _super);
888
+
889
+ function ActionMessenger() {
890
+ return ActionMessenger.__super__.constructor.apply(this, arguments);
891
+ }
892
+
893
+ ActionMessenger.prototype.doDefaults = {
894
+ progressMessage: null,
895
+ successMessage: null,
896
+ errorMessage: "Error connecting to the server.",
897
+ showSuccessWithoutError: true,
898
+ retry: {
899
+ auto: true,
900
+ allow: true
901
+ },
902
+ action: $.ajax
903
+ };
904
+
905
+ ActionMessenger.prototype.hookBackboneAjax = function(msgr_opts) {
906
+ var _ajax,
907
+ _this = this;
908
+ if (msgr_opts == null) {
909
+ msgr_opts = {};
910
+ }
911
+ if (!(window.Backbone != null)) {
912
+ throw 'Expected Backbone to be defined';
913
+ }
914
+ msgr_opts = _.defaults(msgr_opts, {
915
+ id: 'BACKBONE_ACTION',
916
+ errorMessage: false,
917
+ successMessage: "Request completed successfully.",
918
+ showSuccessWithoutError: false
919
+ });
920
+ _ajax = function(options) {
921
+ var sync_msgr_opts;
922
+ sync_msgr_opts = _.extend({}, msgr_opts, options.messenger);
923
+ return _this["do"](sync_msgr_opts, options);
924
+ };
925
+ if (Backbone.ajax != null) {
926
+ if (Backbone.ajax._withoutMessenger) {
927
+ Backbone.ajax = Backbone.ajax._withoutMessenger;
928
+ }
929
+ if (!(msgr_opts.action != null) || msgr_opts.action === this.doDefaults.action) {
930
+ msgr_opts.action = Backbone.ajax;
931
+ }
932
+ _ajax._withoutMessenger = Backbone.ajax;
933
+ return Backbone.ajax = _ajax;
934
+ } else {
935
+ return Backbone.sync = _.wrap(Backbone.sync, function() {
936
+ var args, _old_ajax, _old_sync;
937
+ _old_sync = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
938
+ _old_ajax = $.ajax;
939
+ $.ajax = _ajax;
940
+ _old_sync.call.apply(_old_sync, [this].concat(__slice.call(args)));
941
+ return $.ajax = _old_ajax;
942
+ });
943
+ }
944
+ };
945
+
946
+ ActionMessenger.prototype._getHandlerResponse = function(returnVal) {
947
+ if (returnVal === false) {
948
+ return false;
949
+ }
950
+ if (returnVal === true || !(returnVal != null)) {
951
+ return true;
952
+ }
953
+ return returnVal;
954
+ };
955
+
956
+ ActionMessenger.prototype._parseEvents = function(events) {
957
+ var desc, firstSpace, func, label, out, type, _ref2;
958
+ if (events == null) {
959
+ events = {};
960
+ }
961
+ out = {};
962
+ for (label in events) {
963
+ func = events[label];
964
+ firstSpace = label.indexOf(' ');
965
+ type = label.substring(0, firstSpace);
966
+ desc = label.substring(firstSpace + 1);
967
+ if ((_ref2 = out[type]) == null) {
968
+ out[type] = {};
969
+ }
970
+ out[type][desc] = func;
971
+ }
972
+ return out;
973
+ };
974
+
975
+ ActionMessenger.prototype._normalizeResponse = function() {
976
+ var data, elem, resp, type, xhr, _i, _len;
977
+ resp = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
978
+ type = null;
979
+ xhr = null;
980
+ data = null;
981
+ for (_i = 0, _len = resp.length; _i < _len; _i++) {
982
+ elem = resp[_i];
983
+ if (elem === 'success' || elem === 'timeout' || elem === 'abort') {
984
+ type = elem;
985
+ } else if (((elem != null ? elem.readyState : void 0) != null) && ((elem != null ? elem.responseText : void 0) != null)) {
986
+ xhr = elem;
987
+ } else if (_.isObject(elem)) {
988
+ data = elem;
989
+ }
990
+ }
991
+ return [type, data, xhr];
992
+ };
993
+
994
+ ActionMessenger.prototype.run = function() {
995
+ var args, attr, events, getMessageText, handler, handlers, m_opts, msg, old, opts, promiseAttrs, type, _i, _len, _ref2, _ref3,
996
+ _this = this;
997
+ m_opts = arguments[0], opts = arguments[1], args = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
998
+ if (opts == null) {
999
+ opts = {};
1000
+ }
1001
+ m_opts = $.extend(true, {}, this.messageDefaults, this.doDefaults, m_opts != null ? m_opts : {});
1002
+ events = this._parseEvents(m_opts.events);
1003
+ getMessageText = function(type, xhr) {
1004
+ var message;
1005
+ message = m_opts[type + 'Message'];
1006
+ if (_.isFunction(message)) {
1007
+ return message.call(_this, type, xhr);
1008
+ }
1009
+ return message;
1010
+ };
1011
+ msg = (_ref2 = m_opts.messageInstance) != null ? _ref2 : this.newMessage(m_opts);
1012
+ if (m_opts.id != null) {
1013
+ msg.options.id = m_opts.id;
1014
+ }
1015
+ if (m_opts.progressMessage != null) {
1016
+ msg.update($.extend({}, m_opts, {
1017
+ message: getMessageText('progress', null),
1018
+ type: 'info'
1019
+ }));
1020
+ }
1021
+ handlers = {};
1022
+ _.each(['error', 'success'], function(type) {
1023
+ var originalHandler;
1024
+ originalHandler = opts[type];
1025
+ return handlers[type] = function() {
1026
+ var data, defaultOpts, handlerResp, msgOpts, reason, resp, responseOpts, xhr, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9;
1027
+ resp = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
1028
+ _ref3 = _this._normalizeResponse.apply(_this, resp), reason = _ref3[0], data = _ref3[1], xhr = _ref3[2];
1029
+ if (type === 'success' && !(msg.errorCount != null) && m_opts.showSuccessWithoutError === false) {
1030
+ m_opts['successMessage'] = null;
1031
+ }
1032
+ if (type === 'error') {
1033
+ if ((_ref4 = m_opts.errorCount) == null) {
1034
+ m_opts.errorCount = 0;
1035
+ }
1036
+ m_opts.errorCount += 1;
1037
+ }
1038
+ handlerResp = m_opts.returnsPromise ? resp[0] : typeof originalHandler === "function" ? originalHandler.apply(null, resp) : void 0;
1039
+ responseOpts = _this._getHandlerResponse(handlerResp);
1040
+ if (_.isString(responseOpts)) {
1041
+ responseOpts = {
1042
+ message: responseOpts
1043
+ };
1044
+ }
1045
+ if (type === 'error' && ((xhr != null ? xhr.status : void 0) === 0 || reason === 'abort')) {
1046
+ msg.hide();
1047
+ return;
1048
+ }
1049
+ if (type === 'error' && ((m_opts.ignoredErrorCodes != null) && (_ref5 = xhr != null ? xhr.status : void 0, __indexOf.call(m_opts.ignoredErrorCodes, _ref5) >= 0))) {
1050
+ msg.hide();
1051
+ return;
1052
+ }
1053
+ defaultOpts = {
1054
+ message: getMessageText(type, xhr),
1055
+ type: type,
1056
+ events: (_ref6 = events[type]) != null ? _ref6 : {},
1057
+ hideOnNavigate: type === 'success'
1058
+ };
1059
+ msgOpts = $.extend({}, m_opts, defaultOpts, responseOpts);
1060
+ if (typeof ((_ref7 = msgOpts.retry) != null ? _ref7.allow : void 0) === 'number') {
1061
+ msgOpts.retry.allow--;
1062
+ }
1063
+ if (type === 'error' && (xhr != null ? xhr.status : void 0) >= 500 && ((_ref8 = msgOpts.retry) != null ? _ref8.allow : void 0)) {
1064
+ if (msgOpts.retry.delay == null) {
1065
+ if (msgOpts.errorCount < 4) {
1066
+ msgOpts.retry.delay = 10;
1067
+ } else {
1068
+ msgOpts.retry.delay = 5 * 60;
1069
+ }
1070
+ }
1071
+ if (msgOpts.hideAfter) {
1072
+ if ((_ref9 = msgOpts._hideAfter) == null) {
1073
+ msgOpts._hideAfter = msgOpts.hideAfter;
1074
+ }
1075
+ msgOpts.hideAfter = msgOpts._hideAfter + msgOpts.retry.delay;
1076
+ }
1077
+ msgOpts._retryActions = true;
1078
+ msgOpts.actions = {
1079
+ retry: {
1080
+ label: 'retry now',
1081
+ phrase: 'Retrying TIME',
1082
+ auto: msgOpts.retry.auto,
1083
+ delay: msgOpts.retry.delay,
1084
+ action: function() {
1085
+ msgOpts.messageInstance = msg;
1086
+ return setTimeout(function() {
1087
+ return _this["do"].apply(_this, [msgOpts, opts].concat(__slice.call(args)));
1088
+ }, 0);
1089
+ }
1090
+ },
1091
+ cancel: {
1092
+ action: function() {
1093
+ return msg.cancel();
1094
+ }
1095
+ }
1096
+ };
1097
+ } else if (msgOpts._retryActions) {
1098
+ delete msgOpts.actions.retry;
1099
+ delete msgOpts.actions.cancel;
1100
+ delete m_opts._retryActions;
1101
+ }
1102
+ msg.update(msgOpts);
1103
+ if (responseOpts && msgOpts.message) {
1104
+ Messenger();
1105
+ return msg.show();
1106
+ } else {
1107
+ return msg.hide();
1108
+ }
1109
+ };
1110
+ });
1111
+ if (!m_opts.returnsPromise) {
1112
+ for (type in handlers) {
1113
+ handler = handlers[type];
1114
+ old = opts[type];
1115
+ opts[type] = handler;
1116
+ }
1117
+ }
1118
+ msg._actionInstance = m_opts.action.apply(m_opts, [opts].concat(__slice.call(args)));
1119
+ if (m_opts.returnsPromise) {
1120
+ msg._actionInstance.then(handlers.success, handlers.error);
1121
+ }
1122
+ promiseAttrs = ['done', 'progress', 'fail', 'state', 'then'];
1123
+ for (_i = 0, _len = promiseAttrs.length; _i < _len; _i++) {
1124
+ attr = promiseAttrs[_i];
1125
+ if (msg[attr] != null) {
1126
+ delete msg[attr];
1127
+ }
1128
+ msg[attr] = (_ref3 = msg._actionInstance) != null ? _ref3[attr] : void 0;
1129
+ }
1130
+ return msg;
1131
+ };
1132
+
1133
+ ActionMessenger.prototype["do"] = ActionMessenger.prototype.run;
1134
+
1135
+ ActionMessenger.prototype.ajax = function() {
1136
+ var args, m_opts;
1137
+ m_opts = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
1138
+ m_opts.action = $.ajax;
1139
+ return this.run.apply(this, [m_opts].concat(__slice.call(args)));
1140
+ };
1141
+
1142
+ ActionMessenger.prototype.expectPromise = function(action, m_opts) {
1143
+ m_opts = _.extend({}, m_opts, {
1144
+ action: action,
1145
+ returnsPromise: true
1146
+ });
1147
+ return this.run(m_opts);
1148
+ };
1149
+
1150
+ return ActionMessenger;
1151
+
1152
+ })(_Messenger);
1153
+
1154
+ $.fn.messenger = function() {
1155
+ var $el, args, func, instance, opts, _ref2, _ref3, _ref4;
1156
+ func = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
1157
+ if (func == null) {
1158
+ func = {};
1159
+ }
1160
+ $el = this;
1161
+ if (!(func != null) || !_.isString(func)) {
1162
+ opts = func;
1163
+ if (!($el.data('messenger') != null)) {
1164
+ _Messenger = (_ref2 = (_ref3 = Messenger.themes[opts.theme]) != null ? _ref3.Messenger : void 0) != null ? _ref2 : ActionMessenger;
1165
+ $el.data('messenger', instance = new _Messenger($.extend({
1166
+ el: $el
1167
+ }, opts)));
1168
+ instance.render();
1169
+ }
1170
+ return $el.data('messenger');
1171
+ } else {
1172
+ return (_ref4 = $el.data('messenger'))[func].apply(_ref4, args);
1173
+ }
1174
+ };
1175
+
1176
+ window.Messenger._call = function(opts) {
1177
+ var $el, $parent, choosen_loc, chosen_loc, classes, defaultOpts, inst, loc, locations, _i, _len;
1178
+ defaultOpts = {
1179
+ extraClasses: 'messenger-fixed messenger-on-bottom messenger-on-right',
1180
+ theme: 'future',
1181
+ maxMessages: 9,
1182
+ parentLocations: ['body']
1183
+ };
1184
+ opts = $.extend(defaultOpts, $._messengerDefaults, Messenger.options, opts);
1185
+ if (opts.theme != null) {
1186
+ opts.extraClasses += " messenger-theme-" + opts.theme;
1187
+ }
1188
+ inst = opts.instance || Messenger.instance;
1189
+ if (opts.instance == null) {
1190
+ locations = opts.parentLocations;
1191
+ $parent = null;
1192
+ choosen_loc = null;
1193
+ for (_i = 0, _len = locations.length; _i < _len; _i++) {
1194
+ loc = locations[_i];
1195
+ $parent = $(loc);
1196
+ if ($parent.length) {
1197
+ chosen_loc = loc;
1198
+ break;
1199
+ }
1200
+ }
1201
+ if (!inst) {
1202
+ $el = $('<ul>');
1203
+ $parent.prepend($el);
1204
+ inst = $el.messenger(opts);
1205
+ inst._location = chosen_loc;
1206
+ Messenger.instance = inst;
1207
+ } else if ($(inst._location) !== $(chosen_loc)) {
1208
+ inst.$el.detach();
1209
+ $parent.prepend(inst.$el);
1210
+ }
1211
+ }
1212
+ if (inst._addedClasses != null) {
1213
+ inst.$el.removeClass(inst._addedClasses);
1214
+ }
1215
+ inst.$el.addClass(classes = "" + inst.className + " " + opts.extraClasses);
1216
+ inst._addedClasses = classes;
1217
+ return inst;
1218
+ };
1219
+
1220
+ $.extend(Messenger, {
1221
+ Message: RetryingMessage,
1222
+ Messenger: ActionMessenger,
1223
+ themes: (_ref2 = Messenger.themes) != null ? _ref2 : {}
1224
+ });
1225
+
1226
+ $.globalMessenger = window.Messenger = Messenger;
1227
+
1228
+ }).call(this);