flashtastic 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);