nail_polish 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +29 -0
  4. data/Rakefile +23 -0
  5. data/app/assets/javascripts/nail_polish/app.js +58 -0
  6. data/app/assets/javascripts/nail_polish/events/flasher.js +17 -0
  7. data/app/assets/javascripts/nail_polish/events/redirector.js +3 -0
  8. data/app/assets/javascripts/nail_polish/events.js +28 -0
  9. data/app/assets/javascripts/nail_polish/nail_polish.js +25 -0
  10. data/app/assets/javascripts/nail_polish/overrides/auth_token_adder.js +44 -0
  11. data/app/assets/javascripts/nail_polish/overrides/for_backbone.js +14 -0
  12. data/app/assets/javascripts/nail_polish/overrides/function_bind.js +6 -0
  13. data/app/assets/javascripts/nail_polish/overrides/global_publisher_adder.js +28 -0
  14. data/app/assets/javascripts/nail_polish/presenter.js +43 -0
  15. data/app/assets/javascripts/nail_polish/presenters/collection.js +11 -0
  16. data/app/assets/javascripts/nail_polish/router.js +78 -0
  17. data/app/assets/javascripts/nail_polish/utils/text.js +36 -0
  18. data/app/assets/javascripts/nail_polish/view/parent_finder.js +46 -0
  19. data/app/assets/javascripts/nail_polish/view.js +80 -0
  20. data/app/assets/javascripts/nail_polish/widget/flash.js +36 -0
  21. data/app/assets/javascripts/nail_polish/widget/modal.js +40 -0
  22. data/app/assets/javascripts/nail_polish.js +21 -0
  23. data/app/assets/javascripts/nail_polish_legacy_base.js +2 -0
  24. data/app/assets/javascripts/nail_polish_modern_base.js +2 -0
  25. data/app/assets/javascripts/nail_polish_widgets.js +2 -0
  26. data/app/assets/javascripts/vendor/backbone.js +1571 -0
  27. data/app/assets/javascripts/vendor/jquery-1.8.3.js +9472 -0
  28. data/app/assets/javascripts/vendor/jquery.cookie.js +94 -0
  29. data/app/assets/javascripts/vendor/underscore.js +1200 -0
  30. data/app/assets/javascripts/vendor/zepto.cookie.js +22 -0
  31. data/app/assets/javascripts/vendor/zepto.js +1355 -0
  32. data/config/initializers/nail_polish.rb +1 -0
  33. data/config/routes.rb +2 -0
  34. data/lib/nail_polish/engine.rb +4 -0
  35. data/lib/nail_polish/version.rb +3 -0
  36. data/lib/nail_polish.rb +7 -0
  37. data/lib/tasks/nail_polish_tasks.rake +4 -0
  38. metadata +207 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 02093b432326e2623e61fc3bf74ba94d061c9039
4
+ data.tar.gz: 058bc41c0e48b1fa57ab187283305ecdfbbf743e
5
+ SHA512:
6
+ metadata.gz: a01a5e64327c6ce39fd9d4c51833c38a197c34fbe0234ed28d173065dcc3d15f70956f682ddd2d08d84dec73542e0872f11b34db656b8eef1fd1f72806fc34fb
7
+ data.tar.gz: 304b28c76819afe5245e596dd4d96cb1211fbaa9e189b1db34fd583c14e5bc69646aa55654895a4b8d1b97d64f443620804da54771cb1c74a8da5cb179fbef75
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,29 @@
1
+ = NailPolish: SocialChorus/SocialChorus OO FrontEnd
2
+
3
+ NailPolish is a front-end framework used by the SocialCoder's a SocialChorus.
4
+
5
+ SocialCoders use a modified version of OOCSS, and have an set of Backbone
6
+ conventions.
7
+
8
+ == TODO
9
+ * Hogan compilation for performance
10
+ * template in page render to prevent large resources
11
+ * widgets
12
+ * Dropdown menu
13
+ * back button
14
+ * modal
15
+ * form view
16
+ * model view
17
+ * collection view
18
+ * generators
19
+ - view
20
+ - template
21
+ - presenter
22
+ - specs for presenter and view
23
+ * js models
24
+ * simplified CSS
25
+
26
+ == Development
27
+ The current jasmine gem does not play well with engines.
28
+ To modify and test javascript, go into the spec/dummy directory and then
29
+ run `rake jasmine` or `rake jasmine:ci`.
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'NailPolish'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
@@ -0,0 +1,58 @@
1
+ //specs to come
2
+ NailPolish.App = function() {};
3
+ NailPolish.App.extend = Backbone.Model.extend;
4
+
5
+ _.extend(NailPolish.App.prototype, {
6
+ initialize: function(parent, opts) {
7
+ this.parent = parent;
8
+ this.opts = opts;
9
+ this.init(parent, opts);
10
+ },
11
+
12
+ start: function () {
13
+ this.repository = this.bootstrap();
14
+ this.route();
15
+ this.render();
16
+ },
17
+
18
+ route: function() {
19
+ this.router = new (this.routerClass())();
20
+ this.router.repository = this.repository;
21
+ Backbone.history.start();
22
+ },
23
+
24
+ render: function() {
25
+ _.each(this.subViews(), function(view) {
26
+ view.parent = view.parent || this.parent;
27
+ view.render();
28
+ }.bind(this));
29
+ },
30
+
31
+ bootstrapData: function() {
32
+ var data = data || JSON.parse($('#bootstrap-json').text());
33
+ return data;
34
+ },
35
+
36
+ //Stuff for YOU to configure
37
+
38
+ init: function() {
39
+ //your init stuff here
40
+ },
41
+
42
+ bootstrap: function() {
43
+ //override this if you want specific models in your repo
44
+ return this.bootstrapData();
45
+ },
46
+
47
+ subViews: function() {
48
+ //fill me in
49
+
50
+ //return [
51
+ // new View.That.I.Want.To.Render({model: model})
52
+ //]
53
+ },
54
+
55
+ routerClass: function () {
56
+ //set this, yo
57
+ }
58
+ });
@@ -0,0 +1,17 @@
1
+ NailPolish.Events.Flasher = function (view) {
2
+ this.view = view;
3
+ };
4
+
5
+ _.extend(NailPolish.Events.Flasher.prototype, {
6
+ subscribe: function () {
7
+ NailPolish.Events.subscribe('flash', this.perform, this);
8
+ },
9
+
10
+ perform: function (data) {
11
+ this.view.model = data;
12
+ this.view.show();
13
+ }
14
+ });
15
+
16
+ NailPolish.Events.Flasher.extend = Backbone.Model.extend;
17
+
@@ -0,0 +1,3 @@
1
+ NailPolish.Events.Redirector = function (url) {
2
+ window.location = url;
3
+ };
@@ -0,0 +1,28 @@
1
+ NailPolish.Events = {
2
+ isTouch: function() {
3
+ // taken from Modernizr: http://modernizr.com/license
4
+ return (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);
5
+ },
6
+
7
+ isWindowsTouch: function() {
8
+ if (/Windows.NT.6/i.test(navigator.userAgent)){
9
+ return true;
10
+ }
11
+ return false;
12
+ },
13
+ startEvent: 'touchstart',
14
+
15
+ publisher: _.extend({}, Backbone.Events),
16
+
17
+ publish: function (event, args) {
18
+ this.publisher.trigger(event, args);
19
+ },
20
+
21
+ subscribe: function (event, callback, context) {
22
+ this.publisher.on(event, callback, context);
23
+ },
24
+
25
+ unsubscribe: function(event, callback, context) {
26
+ this.publisher.off(event, callback, context);
27
+ }
28
+ };
@@ -0,0 +1,25 @@
1
+ var NailPolish = {
2
+ apps: function () {
3
+ if (this._apps) return this._apps;
4
+ this._apps = [];
5
+ return this._apps;
6
+ },
7
+
8
+ add: function (app) {
9
+ if (this.apps().length <= 0) {
10
+ this.startServices();
11
+ }
12
+ if (!_.include(this.apps(), app)) {
13
+ this.apps().push(app);
14
+ }
15
+ },
16
+
17
+ startServices: function () {
18
+ Backbone.history.start();
19
+ _.each(this.subscriptions, function (callback, event) {
20
+ NailPolish.Events.subscribe(event, callback);
21
+ });
22
+ }
23
+ };
24
+
25
+ NailPolish.Widget = {};
@@ -0,0 +1,44 @@
1
+ // Backbone does not send model data with delete requests ...
2
+ // which means the authenticity token does not go there either.
3
+ // It sucks, but we unpack the data before each request, and send the
4
+ // token along
5
+
6
+ NailPolish.AuthTokenAdder = function (args) {
7
+ this.args = args;
8
+ this.type = args.type.toLowerCase();
9
+ this.data = _.clone(args.data || {});
10
+ this.authenticityToken = $('meta[name="csrf-token"]').attr('content');
11
+ };
12
+
13
+ NailPolish.AuthTokenAdder.prototype.perform = function () {
14
+ this.handlePostPutPatch();
15
+ this.handleDelete();
16
+ return this.args;
17
+ };
18
+
19
+ NailPolish.AuthTokenAdder.prototype.handleDelete = function () {
20
+ if ( this.type != 'delete' ) { return; }
21
+
22
+ this.args.url = this.args.url +
23
+ "?authenticity_token=" +
24
+ encodeURIComponent(this.authenticityToken);
25
+ };
26
+
27
+ NailPolish.AuthTokenAdder.prototype.handlePostPutPatch = function () {
28
+ if ( this.type != 'post' && this.type != 'put' && this.type != 'patch' ) { return; }
29
+
30
+ if ( _.isString(this.data) ) {
31
+ this.repackageStringData();
32
+ }
33
+
34
+ this.addAuthToken();
35
+ };
36
+
37
+ NailPolish.AuthTokenAdder.prototype.repackageStringData = function () {
38
+ this.data = JSON.parse(this.data);
39
+ };
40
+
41
+ NailPolish.AuthTokenAdder.prototype.addAuthToken = function () {
42
+ data = _.extend(this.data, {authenticity_token: this.authenticityToken});
43
+ this.args.data = this.data = JSON.stringify(data);
44
+ }
@@ -0,0 +1,14 @@
1
+ Backbone.ajax = function() {
2
+ // adds the authenticity token
3
+ var args = _.map(arguments, function(a) {
4
+ return new NailPolish.AuthTokenAdder(a).perform();
5
+ });
6
+
7
+ // reads events from data, and does a global publish
8
+ args = _.map(args, function(a) {
9
+ return new NailPolish.GlobalPublisherAdder(a).perform();
10
+ });
11
+
12
+ return Backbone.$.ajax.apply(Backbone.$, args);
13
+ };
14
+
@@ -0,0 +1,6 @@
1
+ Function.prototype.bind = Function.prototype.bind || function(context) {
2
+ var func = this;
3
+ return function() {
4
+ return func.apply(context, arguments);
5
+ };
6
+ };
@@ -0,0 +1,28 @@
1
+ NailPolish.GlobalPublisherAdder = function (args) {
2
+ this.args = args;
3
+ };
4
+
5
+ _.extend(NailPolish.GlobalPublisherAdder.prototype, {
6
+ perform: function () {
7
+ this.args.complete = this.wrapComplete(this.args.complete);
8
+ return this.args;
9
+ },
10
+
11
+ wrapComplete: function (callback) {
12
+ return function(xhr, status) {
13
+ // call the original callback
14
+ callback && callback(xhr, status);
15
+
16
+ // extract the JSON data
17
+
18
+ response = xhr.response || "{}"
19
+ var data = JSON.parse(response);
20
+ var publisher = NailPolish.Events;
21
+
22
+ // publish each event received
23
+ _.each(data.events, function (value, key) {
24
+ publisher.publish(key, value);
25
+ });
26
+ };
27
+ }
28
+ });
@@ -0,0 +1,43 @@
1
+ NailPolish.Presenter = function(presented) {
2
+ this.presented = presented || {};
3
+ this.initialize();
4
+ this.init();
5
+ };
6
+
7
+ NailPolish.Presenter.prototype.initialize = function () {
8
+ //Put your stuff here
9
+ };
10
+
11
+ NailPolish.Presenter.prototype.init = function () {
12
+ //Put your stuff here
13
+ };
14
+
15
+ NailPolish.Presenter.extend = Backbone.Model.extend;
16
+
17
+ NailPolish.Presenter.prototype.presentedToJSON = function () {
18
+ var json;
19
+ if (this.presented && this.presented.toJSON) {
20
+ json = this.presented.toJSON();
21
+ }
22
+ return json || this.presented;
23
+ };
24
+
25
+ NailPolish.Presenter.prototype.inclusions = function () {
26
+ var inclusions = {};
27
+ _.each(this.include || [], function (prop) {
28
+ inclusions[prop] = this.inclusionFor(prop);
29
+ }.bind(this));
30
+ return inclusions;
31
+ };
32
+
33
+ NailPolish.Presenter.prototype.inclusionFor = function (attr) {
34
+ var prop = this[attr];
35
+ return _.isFunction(prop) ? prop.bind(this)() : prop;
36
+ };
37
+
38
+ NailPolish.Presenter.prototype.toJSON = function() {
39
+ var base = this.presentedToJSON();
40
+ var inclusions = this.inclusions();
41
+ return _.extend(base, inclusions);
42
+ };
43
+
@@ -0,0 +1,11 @@
1
+ NailPolish.Presenter.Collection = NailPolish.Presenter.extend({
2
+ presentedToJSON: function () {
3
+ var json;
4
+ if (this.presented && this.presented.toJSON) {
5
+ json = this.presented.toJSON();
6
+ }
7
+ var returnValue = {};
8
+ returnValue[this.name] = (json || this.presented);
9
+ return returnValue;
10
+ }
11
+ })
@@ -0,0 +1,78 @@
1
+ NailPolish.Router = Backbone.Router.extend({
2
+ initialize: function ($layout) {
3
+ this.$layout = $layout;
4
+ this.history = [];
5
+ this.on('route:start', this.storeHistory, this);
6
+
7
+ this.init();
8
+ },
9
+
10
+ init: function () {},
11
+
12
+ // We are overriding this method to add some events before and after
13
+ // a route happens. Unfortunately, the anonymous function in the middle
14
+ // doesn't allow us to call super and change just that behavior.
15
+ route: function (route, name, callback) {
16
+ if (!_.isRegExp(route)) route = this._routeToRegExp(route);
17
+ if (_.isFunction(name)) {
18
+ callback = name;
19
+ name = '';
20
+ }
21
+ if (!callback) callback = this[name];
22
+
23
+ var router = this;
24
+ Backbone.history.route(route, function(fragment) {
25
+ var args = router._extractParameters(route, fragment);
26
+ router.trigger('route:start', fragment, args);
27
+ callback && callback.apply(router, args);
28
+ router.trigger.apply(router, ['route:' + name].concat(args));
29
+ router.trigger('route', name, args);
30
+ Backbone.history.trigger('route', router, name, args);
31
+ });
32
+
33
+ return this;
34
+ },
35
+
36
+ page: function (views) {
37
+ NailPolish.Events.publish('page:new');
38
+ this.$layout.empty();
39
+ this.render(views);
40
+ },
41
+
42
+ render: function (args) {
43
+ _.each(args, function (view) {
44
+ view.parent = view.parent || this.$layout;
45
+ view.repository = view.repository || this.repository;
46
+ view.render();
47
+ }.bind(this));
48
+ this.afterRender();
49
+ },
50
+
51
+ afterRender: function(){
52
+ //put your after render stuff here
53
+ },
54
+
55
+ // this is usually used for NailPolish.Events to publish a redirect event!
56
+ redirect: function (path) {
57
+ window.location = path;
58
+ },
59
+
60
+ go: function(fragment) {
61
+ this.navigate(fragment, {trigger: true});
62
+ },
63
+
64
+ goReplacingLastHistory: function(fragment) {
65
+ this.history.pop();
66
+ this.navigate(fragment, { trigger: true, replace: true });
67
+ },
68
+
69
+ back: function () {
70
+ this.history.pop();
71
+ var fragment = _.last(this.history);
72
+ this.goReplacingLastHistory(fragment);
73
+ },
74
+
75
+ storeHistory: function () {
76
+ this.history.push(Backbone.history.fragment);
77
+ }
78
+ });
@@ -0,0 +1,36 @@
1
+ NailPolish.TextUtils = {
2
+ camelize: function (word) {
3
+ return word
4
+ .replace(/^(\w)/, function(g) {
5
+ return g.toUpperCase();
6
+ }).replace(/(_\w)/g, function(g) {
7
+ return g[1].toUpperCase();
8
+ });
9
+ },
10
+
11
+ underscore: function (word) {
12
+ return word
13
+ .replace(/^(\w)/, function(g) {
14
+ return g.toLowerCase();
15
+ })
16
+ .replace(/([A-Z])/g, function (g) {
17
+ return "_" + g.toLowerCase();
18
+ });
19
+ },
20
+
21
+ shorten: function(text, n) {
22
+ if (!text || !n) { return; }
23
+
24
+ if (text.length > n) {
25
+ text = text.substr(0, n) + '...';
26
+ }
27
+ return text;
28
+ },
29
+
30
+ stripTags: function (text) {
31
+ return text
32
+ .replace(/<(?:.|\n)*?>/gm, ' ')
33
+ .replace(/\s+/g, ' ')
34
+ .replace(/^\s/, '');
35
+ }
36
+ };
@@ -0,0 +1,46 @@
1
+ NailPolish.View.ParentFinder = function (parent, selector, method) {
2
+ this.parent = parent;
3
+ this.selector = selector;
4
+ this.method = method;
5
+ };
6
+
7
+ _.extend(NailPolish.View.ParentFinder.prototype, {
8
+ perform: function () {
9
+ if (this.parent) {
10
+ // If it is a backbone view, use the $el for parent
11
+ if (this.parent.$el) { this.parent = this.parent.$el; }
12
+
13
+ if(this.selector) {
14
+ //pretends it is jquery
15
+ if (this.parentIsAttachable() && this.parentIsFindable()) {
16
+ return this.findLocally()
17
+ }
18
+ } else {
19
+ // is parent, no selector
20
+ return this.parent;
21
+ }
22
+ } else {
23
+ // no parent, but there is a selector
24
+ return this.findGlobally();
25
+ }
26
+ },
27
+
28
+ findLocally: function() {
29
+ var found = this.parent.find(this.selector)
30
+ if (found.length) { return found }
31
+ },
32
+
33
+ findGlobally: function() {
34
+ if (!this.selector || !$(this.selector).length) { return; }
35
+
36
+ return $(this.selector);
37
+ },
38
+
39
+ parentIsAttachable: function () {
40
+ return !!(this.parent && this.parent[this.method]);
41
+ },
42
+
43
+ parentIsFindable: function () {
44
+ return !!(this.parent && this.parent['find']);
45
+ }
46
+ });
@@ -0,0 +1,80 @@
1
+ NailPolish.View = Backbone.View.extend({
2
+ addListeners: {},
3
+ presenterClass: function () {
4
+ return NailPolish.Presenter;
5
+ },
6
+
7
+ initialize: function (opts) {
8
+ opts = opts || {};
9
+ this.parent = opts.parent;
10
+ this.repository = opts.repository;
11
+ this.attachmentMethod = this.attachmentMethod || 'append';
12
+ this.init(opts);
13
+ },
14
+
15
+ init: function (opts) {
16
+ // override in classes
17
+ },
18
+
19
+ render: function () {
20
+ this.renderTemplate();
21
+ this.renderSubviews();
22
+ this.attachToParent();
23
+ this.afterRender();
24
+ },
25
+
26
+ subviews: function () {
27
+ return [];
28
+ },
29
+
30
+ renderSubviews: function () {
31
+ _.each(this.subviews(), function (view) {
32
+ view.parent = this;
33
+ view.render();
34
+ }.bind(this));
35
+ },
36
+
37
+ attachToParent: function () {
38
+ var $parent = new NailPolish.View.ParentFinder(
39
+ this.parent, this.parentSelector, this.attachmentMethod
40
+ ).perform();
41
+ $parent && $parent[this.attachmentMethod](this.el);
42
+ },
43
+
44
+ afterRender: function () { /* template method hook ! */
45
+ },
46
+
47
+ events: function () {
48
+ if (NailPolish.Events.isTouch() && !NailPolish.Events.isWindowsTouch()) {
49
+ var eventSet = {};
50
+
51
+ _.each(_.keys(this.addListeners), function (eventKey) {
52
+ var key = eventKey.replace('click', NailPolish.Events.startEvent);
53
+ eventSet[key] = this.addListeners[eventKey];
54
+ }.bind(this));
55
+
56
+ return eventSet;
57
+ }
58
+ return this.addListeners;
59
+ },
60
+
61
+ renderTemplate: function () {
62
+ var template = HoganTemplates[this.templateName];
63
+ if (!template) {
64
+ return;
65
+ }
66
+ var rendered = template.render(this.presenter(), this.partials());
67
+ this.$el.html(rendered);
68
+ },
69
+
70
+ presenter: function () {
71
+ var presented = this.model || this.collection || {};
72
+ var presenter = new (this.presenterClass())(presented);
73
+ return presenter.toJSON();
74
+ },
75
+
76
+ partials: function () {
77
+ // override with own partials if necessary
78
+ return {};
79
+ }
80
+ });
@@ -0,0 +1,36 @@
1
+ NailPolish.Widget.Flash = NailPolish.View.extend({
2
+ templateName: 'flash',
3
+ className: 'flash',
4
+ parentSelector: '#flash-container',
5
+ attachmentMethod: 'html',
6
+ animationLength: 500,
7
+ showFor: 2000,
8
+
9
+ addListeners: {
10
+ 'click .close': 'hide'
11
+ },
12
+
13
+ perform: function (model) {
14
+ this.model = model;
15
+ this.render();
16
+ },
17
+
18
+ afterRender: function () {
19
+ this.show();
20
+ },
21
+
22
+ show: function () {
23
+ window.scrollTo(0, 0);
24
+ this.$el.css('opacity', 0);
25
+ this.$el.show();
26
+ this.$el.animate({opacity: 1}, this.animationLength);
27
+
28
+ setTimeout(this.hide.bind(this), this.showFor);
29
+ },
30
+
31
+ hide: function () {
32
+ this.$el.animate(
33
+ {opacity: 0}, this.animationLength, this.$el.hide.bind(this.$el)
34
+ );
35
+ }
36
+ });